Daemon icon indicating copy to clipboard operation
Daemon copied to clipboard

Implement material system

Open VReaperV opened this issue 1 year ago • 110 comments

Base changes for implementing a material system.

The goal of this system is to improve performance by reducing the amount of state changes and data uploads from CPU->GPU.

The system works by generating materials for draw surfaces/shaders/shader stages after the map is loaded, as well as all the necessary data to draw each material in one drawcall. Currently this only works for world BSP surfaces, everything else is drawn the normal way.

Material

A material in this case represents a distinct global OpenGL state: this includes state bits (as used by GL_State(), however without the alphaTest bits), culling mode, shader program, material ordering and VBO/IBO bindings. Each material is also allocated 2 blocks of memory in a buffer, this memory holds the data for each surface.

Material system

The material system holds material packs, which map materials to various shader sorts: depth pre-pass, opaque pass, and translucent pass. It also contains sky shaders and a list of dynamic surfaces.

A dynamic surface is a surface which can have its data changed after the map is loaded. This includes non-constant color, tex matrices, animated and video images, as well as any active expressions used by RB_EvalExpression().

All surface data is held in a shader storage buffer object. This buffer consists of 2 blocks which have the following memory layout: Material0_surface0_stage0: uniform0 // Start of material 0 data .. Material0_surface0_stage0: uniformn Material0_surface0_stage0: optional padding Material0_surface0_stage1: uniform0 .. Material0_surface0_stagex: uniformn Material0_surface0_stagex: optional padding .. Material1: optional padding Material1_surface0_stage0: uniform0 etc.

The optional padding for per-surface data is needed for it to align with std430 layout. The optional padding for materials is needed because each material can have a different data size per surface, but the offset in the shader has to be an integer multiple of its materials size. The shader accesses the buffer using the offset that equals to: bufferOffset / paddedSize, bufferOffset is the offset in components i. e. multiples of 4 bytes because that's the minimum accessible memory in std430, paddedSize is the size of this shaders Material struct in components, aligned under std430.

The buffer is split into a static surface block, followed by a dynamic surface block. The dynamic surface block is updated once per frame. The whole block has to be updated because the BSP is entirely skipped for world surfaces.

There are 4 distinct steps done by the material system:

  1. Shader post-processing. This will move the uniforms around for shaders marked as using the material system, and then generate the memory layout data (offsets and sizes), as well as generate code that will be inserted into the shader code instead of the uniforms. Uniforms marked as global are skipped: these uniforms are set per-shader rather than per-surface because they don't change within a rendered view.
  2. Material generation. This will iterate through all of the world BSP surfaces except sky and portal surfaces using R_AddWorldSurfaces(). Then for each stage material data is obtained and if a matching material doesn't exist it will be added, then the surface data is added to the material. Surfaces will also be marked as either static or dynamic. Portal surfaces are copied so they can be rendered later, but until GPU culling is there it has to be done in an inefficient way.
  3. Buffer generation. This will generate the buffer with all of the per-surface data, and then the command buffer.
  4. Rendering. The material rendering is called from RB_RenderDrawSurfaces() with appropriate shader sorts. All of the materials matching this sort will the nbe rendered in order.

The command buffer contains data for multiDrawIndirect drawcalls. This contains the indexes into vertex and index array buffers, as well as baseInstance, which is used to access the buffer block in the shader. This data is static.

When rendering, all of the surfaces of a rendered material will be rendered with one such call.

While this means that all of the map surfaces are rendered every frame, it ends being much faster than walking the BSP tree and incurring all the state changes for maps with worse vis. Some maps that are good for testing this are https://users.unvanquished.net/~sweet/pkg/map-station12-b7_0.dpk and https://users.unvanquished.net/~kai/map-example_0.1.dpk. The impact may vary depending on the device, but because currently at least on some devices perf can be worse with this system enabled depending on map, it is disabled by default. I expect that to work better or on par with what we currently have once GPU culling is added.

It can also later be extended to entities etc.

Some example performance differences:

map scene FPS(material system on) FPS(master branch)
nova -1896 336 248 0 0 210 170
habitat default spectator view 200 150
station12-b7 -1377 -195 10 6 8 110 70
example 22728 21405 25414 -139 45 170 43

There are a few issues that are out of scope of this pr: proper portal culling, heatHaze stages (the only map that I know of that use heatHaze is usstremor, but there the heatHaze stage is on a non-world entity, so it works fine anyway), quakeFog stage.

To use the material system, do /r_arb_bindless_texture 1; r_useMaterialSystem 1; vid_restart.

VReaperV avatar Apr 27 '24 19:04 VReaperV

I get a lot of those warnings:

Unvanquished/daemon/src/engine/renderer/gl_shader.h:478:37: warning: '&&' within '||' [-Wlogical-op-parentheses]
                if ( _shader->UseMaterialSystem() && _global || !_shader->UseMaterialSystem() ) {
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~ ~~
Unvanquished/daemon/src/engine/renderer/Material.cpp:1503:70: warning: '&&' within '||' [-Wlogical-op-parentheses]
        if ( tr.hasSkybox && ( fromSort <= shaderSort_t::SS_ENVIRONMENT_FOG && toSort >= shaderSort_t::SS_ENVIRONMENT_FOG
                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

illwieckz avatar Apr 27 '24 20:04 illwieckz

"Material" is sometimes used as a synonym or generic term for (q3)shader. Maybe we could call these metamaterials?

slipher avatar Apr 28 '24 02:04 slipher

I get a lot of those warnings:

This shouldbe fixed now.

VReaperV avatar Apr 28 '24 11:04 VReaperV

"Material" is sometimes used as a synonym or generic term for (q3)shader. Maybe we could call these metamaterials?

Yeah, I thought the name might cause some confusion, so a rename might be in order.

VReaperV avatar Apr 28 '24 11:04 VReaperV

Unvanquished/daemon/src/engine/renderer/gl_shader.h:399:3: warning: field '_global' will be initialized after field '_components' [-Wreorder-ctor]
                _global( global ),
                ^~~~~~~~~~~~~~~~~
                _std430Alignment( std430Alignment )
Unvanquished/daemon/src/engine/renderer/tr_backend.cpp:136:7: warning: logical not is only applied to the left hand side of this comparison [-Wlogical-not-parentheses]
        if ( !bundle->numImages == 0 ) {
             ^                  ~~
Unvanquished/daemon/src/engine/renderer/TextureManager.cpp:177:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
Unvanquished/daemon/src/engine/renderer/Material.cpp:1524:74: warning: '&&' within '||' [-Wlogical-op-parentheses]
        if ( tr.hasSkybox && ( ( fromSort <= shaderSort_t::SS_ENVIRONMENT_FOG ) && ( toSort >= shaderSort_t::SS_ENVIRONMENT_FOG )
                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unvanquished/daemon/src/engine/renderer/Material.cpp:1525:64: warning: '&&' within '||' [-Wlogical-op-parentheses]
                                            || ( fromSort <= shaderSort_t::SS_ENVIRONMENT_NOFOG ) && toSort >= ( shaderSort_t::SS_ENVIRONMENT_NOFOG ) ) ) {
                                            ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unvanquished/daemon/src/engine/renderer/tr_backend.cpp:124:18: warning: expression result unused [-Wunused-value]
                bundle->image[0];
                ~~~~~~~~~~~~~ ~^

It's a cherry-picking as I get dozens and dozens of other warnings like unused variables, const type qualifer on return having no effect. They are likely harmless but produces a lot noise making harder to spot the warnings that can be problematic for real.

illwieckz avatar Apr 28 '24 15:04 illwieckz

More details (GCC) on what is probably the same of the first one of the previous comment (Clang):

Unvanquished/daemon/src/engine/renderer/gl_shader.h: In constructor ‘GLUniform::GLUniform(GLShader*, const char*, const char*, GLuint, GLuint, bool, int, bool)’:
/home/illwieckz/dev/buildme-unvanquished/Unvanquished/daemon/src/engine/renderer/gl_shader.h:387:20: warning: ‘GLUniform::_global’ will be initialized after [-Wreorder]
  387 |         const bool _global = false; // This uniform won't go into materials SSBO if true
      |                    ^~~~~~~
Unvanquished/daemon/src/engine/renderer/gl_shader.h:381:19: warning:   ‘const int GLUniform::_components’ [-Wreorder]
  381 |         const int _components;
      |                   ^~~~~~~~~~~
Unvanquished/daemon/src/engine/renderer/gl_shader.h:392:9: warning:   when initialized here [-Wreorder]
  392 |         GLUniform( GLShader *shader, const char *name, const char* type, const GLuint std430Size, const GLuint std430Alignment,
      |         ^~~~

illwieckz avatar Apr 28 '24 15:04 illwieckz

Also this:

diff --git a/src/engine/renderer/TextureManager.h b/src/engine/renderer/TextureManager.h
index d31892774..d28c78cb3 100644
--- a/src/engine/renderer/TextureManager.h
+++ b/src/engine/renderer/TextureManager.h
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef TEXTURE_MANAGER_H
 #define TEXTURE_MANAGER_H
 
+#include <queue>
 #include <vector>
 #include <unordered_set>
 #include "GL/glew.h"

It is caught by older compilers (GCC9, ICC…):

Unvanquished/daemon/src/engine/renderer/TextureManager.h:86:8: error: ‘queue’ in namespace ‘std’ does not name a template type
   86 |   std::queue<Texture*> texQueue;
      |        ^~~~~
Unvanquished/daemon/src/engine/renderer/TextureManager.h:42:1: note: ‘std::queue’ is defined in header ‘<queue>’; did you forget to ‘#include <queue>’?
   41 | #include "GL/glew.h"
  +++ |+#include <queue>
Unvanquished/daemon/src/engine/renderer/TextureManager.h(86): error: qualified name is not allowed
  		std::queue<Texture*> texQueue;
  		^
Unvanquished/daemon/src/engine/renderer/TextureManager.h(86): error #77: this declaration has no storage class or type specifier
  		std::queue<Texture*> texQueue;
  		^

illwieckz avatar Apr 28 '24 16:04 illwieckz

With AMDGPU-PRO OGLP 23.40:

Warn: Compile log:
ERROR: 0:94: 'gl_DrawIDARB' : required extension not requested: GL_ARB_shader_draw_parameters
ERROR: 0:94: '' : missing #endif 
ERROR: 0:94: '' : compilation terminated 
ERROR: 3 compilation errors.  No code generated.
Warn: Unhandled exception (15ShaderException): Couldn't compile vertex shader: generic2D 

https://pastebin.com/JXGTBaky

With Mesa radeonsi 23.2.1:

Warn: Compile log:
0:94(14): error: `gl_DrawIDARB' undeclared
0:95(20): error: `gl_BaseInstanceARB' undeclared
 Warn: Unhandled exception (15ShaderException): Couldn't compile vertex shader: generic2D 

https://pastebin.com/0qNYBnX1

illwieckz avatar Apr 28 '24 16:04 illwieckz

Yeah, I'll fix most of those later, when everything is more ready. I'm not worried about the ones that don't actually change how the code is executed right now. The && within || warn is just bullshit however.

VReaperV avatar Apr 28 '24 16:04 VReaperV

With AMDGPU-PRO OGLP 23.40:

Warn: Compile log:
ERROR: 0:94: 'gl_DrawIDARB' : required extension not requested: GL_ARB_shader_draw_parameters
ERROR: 0:94: '' : missing #endif 
ERROR: 0:94: '' : compilation terminated 
ERROR: 3 compilation errors.  No code generated.
Warn: Unhandled exception (15ShaderException): Couldn't compile vertex shader: generic2D 

https://pastebin.com/JXGTBaky

With Mesa radeonsi 23.2.1:

Warn: Compile log:
0:94(14): error: `gl_DrawIDARB' undeclared
0:95(20): error: `gl_BaseInstanceARB' undeclared
 Warn: Unhandled exception (15ShaderException): Couldn't compile vertex shader: generic2D 

https://pastebin.com/0qNYBnX1

It looks like AddExtension() for GL_ARB_shader_draw_parameters will have to be set as version -1, because it relies on the variables/functions/etc in an extension having the same names as in the core version.

VReaperV avatar Apr 28 '24 16:04 VReaperV

With both drivers case I get this though:

...using GL_ARB_shader_draw_parameters

illwieckz avatar Apr 28 '24 16:04 illwieckz

Most or all of these warns are caught by CI anyway, so they shouldn't be a problem.

VReaperV avatar Apr 28 '24 16:04 VReaperV

With both drivers case I get this though:

...using GL_ARB_shader_draw_parameters

I'm pretty sure it works that way will all extensions that we use. But the shader never declares the extension as required in this case.

VReaperV avatar Apr 28 '24 16:04 VReaperV

Anyway with -1 I got this with Mesa radeonsi:

unvanquished_2024-04-28_183358_000

With OGLP the computer hangs for several minute, then later when the computer becomes usable again the game window blinks forever with some textures painted in the whole window (but behind 2D elements), doing a screenshot just captures black.

Edit: dmesg log: https://pastebin.com/pPpVWza8

illwieckz avatar Apr 28 '24 16:04 illwieckz

Some graphics settings are currently broken on this branch, so might be that.

VReaperV avatar Apr 28 '24 16:04 VReaperV

I get the same with medium preset, and with low preset I get:

Tess_Begin (stageIteratorFunc=0x555555721680 <Tess_StageIteratorSky()>, stageIteratorFunc2=0x0, surfaceShader=<optimized out>, lightShader=0x0, skipTangentSpaces=false, lightmapNum=-1, fogNum=-1, bspSurface=false) at Unvanquished/daemon/src/engine/renderer/tr_shade.cpp:551
551			tess.numSurfaceStages = state->numStages;

Thread 1 (Thread 0x7ffff554ba80 (LWP 3119916) "daemon"):
#0  Tess_Begin (stageIteratorFunc=0x555555721680 <Tess_StageIteratorSky()>, stageIteratorFunc2=0x0, surfaceShader=<optimized out>, lightShader=0x0, skipTangentSpaces=false, lightmapNum=-1, fogNum=-1, bspSurface=false) at Unvanquished/daemon/src/engine/renderer/tr_shade.cpp:551
#1  0x00005555556c0aad in MaterialSystem::RenderMaterials (this=<optimized out>, fromSort=fromSort@entry=shaderSort_t::SS_ENVIRONMENT_FOG, toSort=toSort@entry=shaderSort_t::SS_OPAQUE) at Unvanquished/daemon/src/engine/renderer/Material.cpp:1533
#2  0x00005555556a10ee in RB_RenderView (depthPass=false) at Unvanquished/daemon/src/engine/renderer/tr_backend.cpp:5012
#3  DrawViewCommand::ExecuteSelf (this=0x7fffd7b96354) at Unvanquished/daemon/src/engine/renderer/tr_backend.cpp:5911
#4  0x00005555556930aa in RB_ExecuteRenderCommands (data=<optimized out>) at Unvanquished/daemon/src/engine/renderer/tr_backend.cpp:6166
#5  0x00005555556b22bb in R_SyncRenderThread () at Unvanquished/daemon/src/engine/renderer/tr_cmds.cpp:209
#6  0x00005555556b22f2 in R_SyncRenderThread () at Unvanquished/daemon/src/engine/renderer/tr_cmds.cpp:217
#7  0x00005555556c9ebd in RE_GenerateTexture (pic=<optimized out>, width=256, height=256) at Unvanquished/daemon/src/engine/renderer/tr_image.cpp:3069
#8  0x00005555556002bf in <lambda(std::vector<unsigned char, std::allocator<unsigned char> >, int, int, qhandle_t&)>::operator() (__closure=<optimized out>, handle=@0x7fffffffc3bc: 0, y=<optimized out>, x=<optimized out>, data=...) at Unvanquished/daemon/src/engine/client/cl_cgame.cpp:1297
#9  Util::apply_impl<CGameVM::QVMSyscall(int, Util::Reader&, IPC::Channel&)::<lambda(std::vector<unsigned char>, int, int, qhandle_t&)>, std::tuple<std::vector<unsigned char, std::allocator<unsigned char> >&&, int&&, int&&, int&>, 0, 1, 2, 3> (func=..., tuple=...) at Unvanquished/daemon/src/common/Util.h:125
#10 Util::apply<CGameVM::QVMSyscall(int, Util::Reader&, IPC::Channel&)::<lambda(std::vector<unsigned char>, int, int, qhandle_t&)>, std::tuple<std::vector<unsigned char, std::allocator<unsigned char> >&&, int&&, int&&, int&> > (func=..., tuple=...) at Unvanquished/daemon/src/common/Util.h:130
#11 IPC::detail::HandleMsg<CGameVM::QVMSyscall(int, Util::Reader&, IPC::Channel&)::<lambda(std::vector<unsigned char>, int, int, qhandle_t&)>, IPC::Message<IPC::Id<0, 68>, std::vector<unsigned char, std::allocator<unsigned char> >, int, int>, IPC::Reply<int> > (func=..., reader=..., channel=...) at Unvanquished/daemon/src/common/IPC/Channel.h:217
#12 IPC::HandleMsg<IPC::SyncMessage<IPC::Message<IPC::Id<0, 68>, std::vector<unsigned char, std::allocator<unsigned char> >, int, int>, IPC::Reply<int> >, CGameVM::QVMSyscall(int, Util::Reader&, IPC::Channel&)::<lambda(std::vector<unsigned char>, int, int, qhandle_t&)> >(IPC::Channel &, Util::Reader, <lambda(std::vector<unsigned char, std::allocator<unsigned char> >, int, int, qhandle_t&)> &&) (channel=..., reader=..., func=...) at Unvanquished/daemon/src/common/IPC/Channel.h:241
#13 0x0000555555603d11 in CGameVM::QVMSyscall (this=<optimized out>, syscallNum=<optimized out>, reader=..., channel=...) at Unvanquished/daemon/src/engine/client/cl_cgame.cpp:1296
#14 0x0000555555606065 in CGameVM::Syscall (this=<optimized out>, id=<optimized out>, reader=..., channel=...) at Unvanquished/daemon/src/engine/client/cl_cgame.cpp:1056
#15 0x000055555560f76d in VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}::operator()(unsigned int, Util::Reader) (reader=..., id=68, this=<optimized out>) at Unvanquished/daemon/src/engine/framework/VirtualMachine.h:142
#16 IPC::detail::SendMsg<VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}&, IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<>, cgClientState_t&>(IPC::Channel&, VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}&, IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&) (channel=..., messageHandler=...) at Unvanquished/daemon/src/common/IPC/Channel.h:174
#17 0x00005555555feefc in IPC::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}, cgClientState_t&>(IPC::Channel&, VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}&&, cgClientState_t&) (messageHandler=..., channel=...) at Unvanquished/daemon/src/common/IPC/Channel.h:232
#18 VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&) (this=0x555555ae5840 <cgvm>) at Unvanquished/daemon/src/engine/framework/VirtualMachine.h:140
#19 CGameVM::CGameRocketFrame (this=0x555555ae5840 <cgvm>) at Unvanquished/daemon/src/engine/client/cl_cgame.cpp:1043
#20 0x000055555562a93d in SCR_DrawScreenField () at Unvanquished/daemon/src/engine/client/cl_scrn.cpp:278
#21 0x000055555562a9a3 in SCR_UpdateScreen () at Unvanquished/daemon/src/engine/client/cl_scrn.cpp:318
#22 0x000055555561f0a5 in CL_Frame (msec=msec@entry=4) at Unvanquished/daemon/src/engine/client/cl_main.cpp:2089
#23 0x00005555555b240e in Com_Frame () at Unvanquished/daemon/src/engine/qcommon/common.cpp:1004
#24 0x00005555555ac9bd in Application::ClientApplication::Frame (this=0x555555881e00 <Application::GetApp()::app>) at Unvanquished/daemon/src/engine/client/ClientApplication.cpp:96
#25 0x00005555555abf85 in main (argc=<optimized out>, argv=<optimized out>) at Unvanquished/daemon/src/engine/framework/System.cpp:780

illwieckz avatar Apr 28 '24 17:04 illwieckz

In fact it probably happened on vid_restart, it doesn't crash with low preset after an engine shutdown.

illwieckz avatar Apr 28 '24 17:04 illwieckz

With low preset:

unvanquished_2024-04-28_194354_000

The black lines around the 23 number are blinking (Edit: it's likely part of the 23 texture, probably missing transparency like the blue shield textures).

illwieckz avatar Apr 28 '24 17:04 illwieckz

I get the same with medium preset, and with low preset I get:

Ah, I need to add that to Free(). It's just accessing memory for drawSurfs that isn't there anymore probably.

VReaperV avatar Apr 28 '24 20:04 VReaperV

The black lines around the 23 number are blinking (Edit: it's likely part of the 23 texture, probably missing transparency like the blue shield textures).

I think it's because of polygon offset. I still need to add it as part of the material state.

VReaperV avatar Apr 28 '24 20:04 VReaperV

With low preset:

That looks about right though (ignore the incorrect textures in some places for now, need to fix a thing or two for that).

Also, does the lighting look right to you? I had to invert the sign on u_InverseLightFactor, I'm not sure why it's not working correctly without that.

VReaperV avatar Apr 28 '24 20:04 VReaperV

I got this with llvmpipe, maybe that explains why I get black textures with radeonsi?

Warn: Compile log:
0:164(1): error: image/sampler variables may only be declared as function parameters or uniform-qualified global variables
0:164(1): error: opaque variables must be declared uniform
0:164(24): error: cannot initialize u_ColorMap variable opaque
0:164(24): error: cannot construct opaque type `sampler2D'
0:165(23): warning: `u_ColorMap' used uninitialized
Warn: Unhandled exception (15ShaderException): Couldn't compile fragment shader: genericMaterial

https://pastebin.com/NkEYRiNs

illwieckz avatar Apr 30 '24 01:04 illwieckz

I have no idea how those line happened to be there:

 161: void	main()
 162: {
 163: sampler2D u_ColorMap = sampler2D(u_ColorMap_initial); // <---
 164: 	vec4 color = texture2D(u_ColorMap, var_TexCoords);
 174: #if defined(USE_DEPTH_FADE) || defined(USE_VERTEX_SPRITE)
 175: sampler2D u_DepthMap = sampler2D(u_DepthMap_initial); // <---
 176: 	float depth = texture2D(u_DepthMap, gl_FragCoord.xy / r_FBufSize).x;
 177: 	float fadeDepth = 0.5 * var_FadeDepth.x / var_FadeDepth.y + 0.5;

illwieckz avatar Apr 30 '24 01:04 illwieckz

I got this with llvmpipe, maybe that explains why I get black textures with radeonsi?

Warn: Compile log:
0:164(1): error: image/sampler variables may only be declared as function parameters or uniform-qualified global variables
0:164(1): error: opaque variables must be declared uniform
0:164(24): error: cannot initialize u_ColorMap variable opaque
0:164(24): error: cannot construct opaque type `sampler2D'
0:165(23): warning: `u_ColorMap' used uninitialized
Warn: Unhandled exception (15ShaderException): Couldn't compile fragment shader: genericMaterial

https://pastebin.com/NkEYRiNs

That's because it's lacking the bindless textures extension (it's currently required because there's too many textures to bind them separately, without packing a lot of them into a few larger textures). I'll need to add a check to not load the material shaders if not all of the required extensions are supported.

VReaperV avatar Apr 30 '24 02:04 VReaperV

I have no idea how those line happened to be there:

 161: void	main()
 162: {
 163: sampler2D u_ColorMap = sampler2D(u_ColorMap_initial); // <---
 164: 	vec4 color = texture2D(u_ColorMap, var_TexCoords);
 174: #if defined(USE_DEPTH_FADE) || defined(USE_VERTEX_SPRITE)
 175: sampler2D u_DepthMap = sampler2D(u_DepthMap_initial); // <---
 176: 	float depth = texture2D(u_DepthMap, gl_FragCoord.xy / r_FBufSize).x;
 177: 	float fadeDepth = 0.5 * var_FadeDepth.x / var_FadeDepth.y + 0.5;

That part is auto-generated in ShaderPostProcess(). Initially I just had it use #define uniform samplerType( uniform ), kinda like for the other uniforms, but it was crashing the AMD shader compiler or something. This is effectively the same thing.

VReaperV avatar Apr 30 '24 02:04 VReaperV

I still need to fix a small part of the material rendering code to make textures resident, so that might be why you're seeing black textures there.

VReaperV avatar Apr 30 '24 02:04 VReaperV

With latest commit I got this:

Warn: Assertion failure at Unvanquished/daemon/src/engine/renderer/gl_shader.h:1081 (SetValue): "p == glState.currentProgram" expected: 0x555557148a90, actual: 0x555558325040 

Thread 1 "daemon" received signal SIGTRAP, Trace/breakpoint trap.
0x00005555557385e1 in GLUniformMatrix4f::SetValue (this=0x555557893b90, transpose=0 '\000', m=0x555556492704 <glState+964>) at Unvanquished/daemon/src/engine/renderer/gl_shader.h:1081
1081				ASSERT_EQ( p, glState.currentProgram );

The engine log was:

illwieckz [granger] entered the game 
World bounds: min: -2304.000000 -1216.000000 -240.000000 max: 2240.000000 1216.000000 1088.000000 
Generated 5 materials from 1681 surfaces 
materialPack sort: 2 2 
id: 0, useSync: 0, sync: 0, program: 51, stateBits: 1006764032, totalDrawSurfCount: 835, shader: genericMaterial, vbo: staticWorld_VBO 0, ibo: staticWorld_IBO 0, staticDrawSurfs: 835, dynamicDrawSurfs: 0, culling: 0 
materialPack sort: 3 4 
id: 0, useSync: 0, sync: 0, program: 94, stateBits: 0, totalDrawSurfCount: 831, shader: lightMappingMaterial, vbo: staticWorld_VBO 0, ibo: staticWorld_IBO 0, staticDrawSurfs: 831, dynamicDrawSurfs: 0, culling: 0 
id: 1, useSync: 0, sync: 0, program: 51, stateBits: 0, totalDrawSurfCount: 4, shader: genericMaterial, vbo: staticWorld_VBO 0, ibo: staticWorld_IBO 0, staticDrawSurfs: 4, dynamicDrawSurfs: 0, culling: 0 
materialPack sort: 5 22 
id: 0, useSync: 0, sync: 0, program: 51, stateBits: 1026, totalDrawSurfCount: 8, shader: genericMaterial, vbo: staticWorld_VBO 0, ibo: staticWorld_IBO 0, staticDrawSurfs: 0, dynamicDrawSurfs: 8, culling: 1 
id: 1, useSync: 0, sync: 0, program: 51, stateBits: 8196, totalDrawSurfCount: 4, shader: genericMaterial, vbo: staticWorld_VBO 0, ibo: staticWorld_IBO 0, staticDrawSurfs: 4, dynamicDrawSurfs: 0, culling: 1 
Debug: CmdBuffer size: 2682 

The backtrace:

Thread 1 (Thread 0x7ffff5515a80 (LWP 4065683) "daemon"):
#0  0x00005555557385e1 in GLUniformMatrix4f::SetValue (this=0x555557893b90, transpose=0 '\000', m=0x555556492704 <glState+964>) at Unvanquished/daemon/src/engine/renderer/gl_shader.h:1081
#1  0x000055555573910f in u_ModelViewProjectionMatrix::SetUniform_ModelViewProjectionMatrix (this=0x555557893b90, m=0x555556492704 <glState+964>) at Unvanquished/daemon/src/engine/renderer/gl_shader.h:3005
#2  0x000055555572dfe6 in RB_CameraPostFX () at Unvanquished/daemon/src/engine/renderer/tr_backend.cpp:3513
#3  0x000055555573332b in RB_RenderPostProcess () at Unvanquished/daemon/src/engine/renderer/tr_backend.cpp:5088
#4  0x00005555557360dc in RenderPostProcessCommand::ExecuteSelf (this=0x7fffd7b96c44) at Unvanquished/daemon/src/engine/renderer/tr_backend.cpp:5934
#5  0x0000555555736810 in RB_ExecuteRenderCommands (data=0x7fffd7b9503c) at Unvanquished/daemon/src/engine/renderer/tr_backend.cpp:6166
#6  0x00005555557555f7 in R_IssueRenderCommands (runPerformanceCounters=false) at Unvanquished/daemon/src/engine/renderer/tr_cmds.cpp:183
#7  0x00005555557556a9 in R_SyncRenderThread () at Unvanquished/daemon/src/engine/renderer/tr_cmds.cpp:209
#8  0x0000555555786f73 in RE_GenerateTexture (pic=0x5555614760e0 "\377\377\377", width=128, height=128) at Unvanquished/daemon/src/engine/renderer/tr_image.cpp:3069
#9  0x0000555555618fb8 in operator() (__closure=0x7fffffffc568, data=std::vector of length 65536, capacity 65536 = {...}, x=128, y=128, handle=@0x7fffffffc404: 0) at Unvanquished/daemon/src/engine/client/cl_cgame.cpp:1297
#10 0x000055555562b70b in Util::apply_impl<CGameVM::QVMSyscall(int, Util::Reader&, IPC::Channel&)::<lambda(std::vector<unsigned char>, int, int, qhandle_t&)>, std::tuple<std::vector<unsigned char, std::allocator<unsigned char> >&&, int&&, int&&, int&>, 0, 1, 2, 3>(struct {...} &&, std::tuple<std::vector<unsigned char, std::allocator<unsigned char> >&&, int&&, int&&, int&> &&, Util::seq<0, 1, 2, 3>) (func=..., tuple=...) at Unvanquished/daemon/src/common/Util.h:125
#11 0x000055555562914e in Util::apply<CGameVM::QVMSyscall(int, Util::Reader&, IPC::Channel&)::<lambda(std::vector<unsigned char>, int, int, qhandle_t&)>, std::tuple<std::vector<unsigned char, std::allocator<unsigned char> >&&, int&&, int&&, int&> >(struct {...} &&, std::tuple<std::vector<unsigned char, std::allocator<unsigned char> >&&, int&&, int&&, int&> &&) (func=..., tuple=...) at Unvanquished/daemon/src/common/Util.h:130
#12 0x00005555556250f6 in IPC::detail::HandleMsg<CGameVM::QVMSyscall(int, Util::Reader&, IPC::Channel&)::<lambda(std::vector<unsigned char>, int, int, qhandle_t&)>, IPC::Message<IPC::Id<0, 68>, std::vector<unsigned char, std::allocator<unsigned char> >, int, int>, IPC::Reply<int> >(IPC::Channel &, IPC::SyncMessage<IPC::Message<IPC::Id<0, 68>, std::vector<unsigned char, std::allocator<unsigned char> >, int, int>, IPC::Reply<int> >, Util::Reader, struct {...} &&) (channel=..., reader=..., func=...) at Unvanquished/daemon/src/common/IPC/Channel.h:217
#13 0x000055555561e983 in IPC::HandleMsg<IPC::SyncMessage<IPC::Message<IPC::Id<0, 68>, std::vector<unsigned char, std::allocator<unsigned char> >, int, int>, IPC::Reply<int> >, CGameVM::QVMSyscall(int, Util::Reader&, IPC::Channel&)::<lambda(std::vector<unsigned char>, int, int, qhandle_t&)> >(IPC::Channel &, Util::Reader, struct {...} &&) (channel=..., reader=..., func=...) at Unvanquished/daemon/src/common/IPC/Channel.h:241
#14 0x000055555561a2ce in CGameVM::QVMSyscall (this=0x555556243300 <cgvm>, syscallNum=68, reader=..., channel=...) at Unvanquished/daemon/src/engine/client/cl_cgame.cpp:1296
#15 0x0000555555618438 in CGameVM::Syscall (this=0x555556243300 <cgvm>, id=68, reader=..., channel=...) at Unvanquished/daemon/src/engine/client/cl_cgame.cpp:1056
#16 0x000055555563029f in VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}::operator()(unsigned int, Util::Reader) (__closure=0x7fffffffc880, id=68, reader=...) at Unvanquished/daemon/src/engine/framework/VirtualMachine.h:142
#17 0x0000555555637356 in IPC::detail::SendMsg<VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}&, IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<>, cgClientState_t&>(IPC::Channel&, VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}&, IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&) (channel=..., messageHandler=...) at Unvanquished/daemon/src/common/IPC/Channel.h:174
#18 0x000055555563201a in IPC::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}, cgClientState_t&>(IPC::Channel&, VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&)::{lambda(unsigned int, Util::Reader)#1}&&, cgClientState_t&) (channel=..., messageHandler=...) at Unvanquished/daemon/src/common/IPC/Channel.h:234
#19 0x000055555563038d in VM::VMBase::SendMsg<IPC::SyncMessage<IPC::Message<IPC::Id<(unsigned short)0, (unsigned short)9>, cgClientState_t>, IPC::Reply<> >, cgClientState_t&>(cgClientState_t&) (this=0x555556243300 <cgvm>) at Unvanquished/daemon/src/engine/framework/VirtualMachine.h:140
#20 0x000055555561838a in CGameVM::CGameRocketFrame (this=0x555556243300 <cgvm>) at Unvanquished/daemon/src/engine/client/cl_cgame.cpp:1043
#21 0x00005555556836eb in SCR_DrawScreenField () at Unvanquished/daemon/src/engine/client/cl_scrn.cpp:278
#22 0x0000555555683779 in SCR_UpdateScreen () at Unvanquished/daemon/src/engine/client/cl_scrn.cpp:318
#23 0x0000555555673824 in CL_Frame (msec=200) at Unvanquished/daemon/src/engine/client/cl_main.cpp:2089
#24 0x000055555559994d in Com_Frame () at Unvanquished/daemon/src/engine/qcommon/common.cpp:1004
#25 0x00005555555921f9 in Application::ClientApplication::Frame (this=0x555555a9bfc0 <Application::GetApp()::app>) at Unvanquished/daemon/src/engine/client/ClientApplication.cpp:96
#26 0x000055555589aad3 in Application::Frame () at Unvanquished/daemon/src/engine/framework/Application.cpp:87
#27 0x00005555558dc191 in main (argc=60, argv=0x7fffffffd7c8) at Unvanquished/daemon/src/engine/framework/System.cpp:780

I'm running the lowest graphics preset.

illwieckz avatar May 02 '24 00:05 illwieckz

Oh, that's weird. That commit was mostly meant to just finish up some render stages other than generic and lightMapping, I'll look at this.

VReaperV avatar May 02 '24 02:05 VReaperV

With latest commit I got this:

Which map is that? I've not been able to reproduce it so far.

VReaperV avatar May 02 '24 19:05 VReaperV

Which map is that? I've not been able to reproduce it so far.

atcshd

illwieckz avatar May 02 '24 19:05 illwieckz