Marzac / le3d

A straightforward and easy to use 3D software renderer for real-time retro graphics.
https://marzac.github.io/le3d/
MIT License
60 stars 6 forks source link

Fillers ("shaders") organisation #32

Closed Marzac closed 6 years ago

Marzac commented 6 years ago

Hi @m0ppers.

Let me suggest something. I am fed up with current rasterizer classes (rasterizer_integer & rasterizer_float) as they are bloated. I quite liked you separating the ammx filler for FlatTexZC triangles in a separate file. I would like to standardize this model.

What I would suggest is we create a new folder called "fillers" that contain .cpp or .asm files that implements all platform specific fillers routines that are optimized. The C++ reference versions remain into their respective rasterizers classes as weak symbols.

Exemple: /engine/fillers/fillFlatTexZC_float_sse.cpp /engine/fillers/fillFlatTexZC_integer_ammx.cpp /engine/fillers/fillFlatTexAlphaZCFog.cpp

So that would provide us a "shader" model too.

Your thoughts on that? Frédéric

Marzac commented 6 years ago

Apparently weak symbols do not exist with MSVC ... Can be done with the pre-processor though. I don't want to involve vtables here as the information is known at link time.

m0ppers commented 6 years ago

Yeah something needs to be done about this. Don't have a strong opinion yet how to do it. Your initial suggestion sounds fine to me? Why does it need weak symbols?

Marzac commented 6 years ago

The idea behind the weak symbols would be:

But unfortunately MSVC do not support that. GCC, mingw32 & CLang do.

I don't want to use any runtime code branching (vtable, lambdas ...) as it will have both a performance and code size impact in the critical path.

So any idea?

Marzac commented 6 years ago

We could also define some preprocessor defines relative to implemented methods.

Let's implement a basic filler (fillFlatTexZC = floating point, sse, flat textured & perspective corrected triangle). The necessary files would be:

/engine/fillers/float/sse/fillFlatTexZC.cpp (or .s) /engine/fillers/float/sse/fillFlatTexZC.h

In the h file:

if LE_USE_SSE

#define FILL_FLAT_TEX_ZC

endif

In the architecture specific cpp or s file:

include "fillFlatTexZC.h"

ifdef FILL_FLAT_TEX_ZC

inline void LeRasterizer::fillFlatTexZCFog(int y, int x1, int x2, int w1, int w2, int u1, int u2, int v1, int v2) { the code }

endif

...

In the reference cpp file:

include "fillers/float/fillers.h"

ifndef FILL_FLAT_TEX_ZC

inline void LeRasterizer::fillFlatTexZCFog(int y, int x1, int x2, int w1, int w2, int u1, int u2, int v1, int v2) { the reference code }

endif

Marzac commented 6 years ago

Then the reference implementation only needs to include all the h files for all architectures. And define the methods that have not already been defined using the preprocessor definitions.

For that purpose, it would be easy to create:

@m0ppers what do you think?

Reference implementation can also be part of the fillers directory structure so that we would maybe no longer need a rasterizer_integer and a rasterizer_float separated implementations.

m0ppers commented 6 years ago

Why not conditionally select the files in the cmake file? This way we do not need any preprocessor stuff.

Marzac commented 6 years ago

I am not yet sure about this. I love CMake, it helps a lot supporting all the platforms and compilers compatible with le3d. But I would like that developers can still type a raw: gcc *.cpp -o mygame and the shit does compile.

Marzac commented 6 years ago

Please have a look at what I have done. We should discuss how this could be improved (you are probably right, using CMake ...) for more flexibility and to ease developers task when writing custom fillers for one or several platforms.

m0ppers commented 6 years ago

I don't really like the ".inc" extension. the files are just cpp implementations (and editors might be confused). Apart from that I think it is very well organized :)

Marzac commented 6 years ago

Ok, I agree. So let's make these files *.cpp and selectively compiled by cmake. The next question is, how can we force the compiler / linker to inline each filler code into the triangle filler function?

Marzac commented 6 years ago

Also can you transform / update your amiga code so it follows this new standard?

m0ppers commented 6 years ago

yes .... just got back from my trip...should find some time next week

Marzac commented 6 years ago

Hope your trip was great. I have merged your pull request, everything looks fine to me.

m0ppers commented 6 years ago

hmm inlining is indeed a problem. and "including" cpp files is ugly too....hmmm....maybe .h? right now the missing color makes me a bit sad in my ide. I don't see a super nice solution on the table. maybe keep it as it is?

Marzac commented 6 years ago

Let's replace the .inc by .h files. As it seems that this is the only guaranteed way for a C++ compiler to inline the functions.

After having done some researches, unfortunately CMake cannot do much here. The desired inlined function definitions must be in the same compile unit as the code calling them, for the compiler to inline them. So unless CMake concatenate files before compilation, depending on build config, not much can be done there to my understanding.

Maybe you have a better idea.

m0ppers commented 6 years ago

That is something that CMake COULD do but I don't think that is a good idea :S voting to close this issue for now :)

it is good enough now I would say

Marzac commented 6 years ago

Let's close this then.