From 9241db812ea8c29d8093701e9cd7c5d4d9d4ce5f Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sun, 4 Nov 2018 19:57:53 +0100 Subject: [PATCH] First changes to fix GPU Skinning with Vulkan --- neo/renderer/RenderBackend.cpp | 2 +- neo/renderer/RenderProgs.h | 2 +- neo/renderer/RenderProgs_GLSL.cpp | 55 ++++++++++++++++++++---- neo/renderer/Vulkan/RenderBackend_VK.cpp | 15 ++----- neo/renderer/Vulkan/RenderProgs_VK.cpp | 23 ++++++++-- 5 files changed, 71 insertions(+), 26 deletions(-) diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index f9c4b03a..7c450b98 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -5216,7 +5216,7 @@ void idRenderBackend::ExecuteBackEndCommands( const emptyCommand_t* cmds ) break; case RC_SET_BUFFER: - //SetBuffer( cmds ); + SetBuffer( cmds ); c_setBuffers++; break; diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h index d9748fd6..fde31dd4 100644 --- a/neo/renderer/RenderProgs.h +++ b/neo/renderer/RenderProgs.h @@ -635,7 +635,7 @@ private: void LoadShader( int index, rpStage_t stage ); idStr StripDeadCode( const idStr& in, const char* name, const idStrList& compileMacros, bool builtin ); - idStr ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, idStr& layout, bool vkGLSL ); + idStr ConvertCG2GLSL( const idStr& in, const char* name, rpStage_t stage, idStr& layout, bool vkGLSL, bool hasGPUSkinning ); enum { diff --git a/neo/renderer/RenderProgs_GLSL.cpp b/neo/renderer/RenderProgs_GLSL.cpp index 897f1268..a1db9982 100644 --- a/neo/renderer/RenderProgs_GLSL.cpp +++ b/neo/renderer/RenderProgs_GLSL.cpp @@ -1013,7 +1013,7 @@ void ParseInOutStruct( idLexer& src, int attribType, int attribIgnoreType, idLis ConvertCG2GLSL ======================== */ -idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, idStr& layout, bool vkGLSL ) +idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, rpStage_t stage, idStr& layout, bool vkGLSL, bool hasGPUSkinning ) { idStr program; program.ReAllocate( in.Length() * 2, false ); @@ -1028,7 +1028,7 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, bo bool inMain = false; bool justEnteredMain = false; - const char* uniformArrayName = isVertexProgram ? VERTEX_UNIFORM_ARRAY_NAME : FRAGMENT_UNIFORM_ARRAY_NAME; + const char* uniformArrayName = ( stage == SHADER_STAGE_VERTEX ) ? VERTEX_UNIFORM_ARRAY_NAME : FRAGMENT_UNIFORM_ARRAY_NAME; char newline[128] = { "\n" }; idToken token; @@ -1113,6 +1113,20 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, bo src.ReadToken( &token ); } + + // RB: HACK to add matrices uniform block layer + if( token == "uniform" && src.PeekTokenString( "matrices_ubo" ) ) + { + hasGPUSkinning = true; + + //src.ReadToken( &token ); + + //src.SkipRestOfLine(); + //program += "\nlayout( binding = 1 ) "; + + src.SkipRestOfLine(); + continue; + } } // convert the in/out structs @@ -1276,7 +1290,7 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, bo newline[len - 0] = '\0'; // RB: add this to every vertex shader - if( inMain && !justEnteredMain && isVertexProgram && vkGLSL ) + if( inMain && !justEnteredMain && ( stage == SHADER_STAGE_VERTEX ) && vkGLSL ) { program += "\n\tvec4 position4 = vec4( in_Position, 1.0 );\n"; justEnteredMain = true; @@ -1476,7 +1490,7 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, bo idStr filenameHint = "// filename " + idStr( name ) + "\n"; // RB: changed to allow multiple versions of GLSL - if( isVertexProgram ) + if( ( stage == SHADER_STAGE_VERTEX ) ) { switch( glConfig.driverType ) { @@ -1527,13 +1541,14 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, bo if( vkGLSL ) { out += "\n"; - if( isVertexProgram ) + if( ( stage == SHADER_STAGE_VERTEX ) ) { out += "layout( binding = 0 ) uniform UBOV {\n"; } else { - out += "layout( binding = 1 ) uniform UBOF {\n"; + //out += "layout( binding = 1 ) uniform UBOF {\n"; + out += va( "layout( binding = %i ) uniform UBOF {\n", hasGPUSkinning ? 2 : 1 ); } for( int i = 0; i < uniformList.Num(); i++ ) @@ -1550,6 +1565,13 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, bo out += ";\n"; } out += "};\n"; + + if( hasGPUSkinning && ( stage == SHADER_STAGE_VERTEX ) ) + { + out += "\nlayout( binding = 1 ) uniform UBO_MAT {\n"; + out += "\t vec4 matrices[ 408 ];\n"; + out += "};\n"; + } } else { @@ -1569,7 +1591,17 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, bo // RB: add samplers with layout bindings if( vkGLSL ) { - int bindingOffset = uniformList.Num() > 0 ? 2 : 1; + int bindingOffset = 1; + + if( hasGPUSkinning ) + { + bindingOffset++; + } + + if( uniformList.Num() > 0 ) + { + bindingOffset++; + } for( int i = 0; i < samplerList.Num(); i++ ) { @@ -1589,13 +1621,20 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, bo layout += "]\n"; layout += "bindings [\n"; + if( uniformList.Num() > 0 ) { layout += "\tubo\n"; } + + if( hasGPUSkinning && ( stage == SHADER_STAGE_VERTEX ) ) + { + layout += "\tubo\n"; + } + for( int i = 0; i < samplerList.Num(); i++ ) { - layout += "\t sampler\n"; + layout += "\tsampler\n"; } layout += "]\n"; diff --git a/neo/renderer/Vulkan/RenderBackend_VK.cpp b/neo/renderer/Vulkan/RenderBackend_VK.cpp index 7ca475cb..a3f865d4 100644 --- a/neo/renderer/Vulkan/RenderBackend_VK.cpp +++ b/neo/renderer/Vulkan/RenderBackend_VK.cpp @@ -1502,16 +1502,7 @@ void idRenderBackend::DrawElementsWithCounters( const drawSurf_t* surf ) } } - - if( surf->jointCache ) - { - idUniformBuffer jointBuffer; - if( !vertexCache.GetJointBuffer( surf->jointCache, &jointBuffer ) ) - { - idLib::Warning( "RB_DrawElementsWithCounters, jointBuffer == NULL" ); - return; - } - } + vkcontext.jointCacheHandle = surf->jointCache; renderProgManager.CommitUniforms( glStateBits ); @@ -2252,13 +2243,13 @@ void idRenderBackend::SetBuffer( const void* data ) RENDERLOG_PRINTF( "---------- RB_SetBuffer ---------- to buffer # %d\n", cmd->buffer ); - GL_Scissor( 0, 0, tr.GetWidth(), tr.GetHeight() ); - // clear screen for debugging // automatically enable this with several other debug tools // that might leave unrendered portions of the screen if( r_clear.GetFloat() || idStr::Length( r_clear.GetString() ) != 1 || r_singleArea.GetBool() || r_showOverDraw.GetBool() ) { + GL_Scissor( 0, 0, tr.GetWidth(), tr.GetHeight() ); + float c[3]; if( sscanf( r_clear.GetString(), "%f %f %f", &c[0], &c[1], &c[2] ) == 3 ) { diff --git a/neo/renderer/Vulkan/RenderProgs_VK.cpp b/neo/renderer/Vulkan/RenderProgs_VK.cpp index 476e5896..e56200e1 100644 --- a/neo/renderer/Vulkan/RenderProgs_VK.cpp +++ b/neo/renderer/Vulkan/RenderProgs_VK.cpp @@ -623,9 +623,21 @@ void idRenderProgManager::LoadShader( shader_t& shader ) } } + // FIXME: we should really scan the program source code for using rpEnableSkinning but at this + // point we directly load a binary and the program source code is not available on the consoles + bool hasGPUSkinning = false; + + if( idStr::Icmp( shader.name.c_str(), "heatHaze.vfp" ) == 0 || + idStr::Icmp( shader.name.c_str(), "heatHazeWithMask.vfp" ) == 0 || + idStr::Icmp( shader.name.c_str(), "heatHazeWithMaskAndVertex.vfp" ) == 0 || + ( BIT( USE_GPU_SKINNING ) & shader.shaderFeatures ) ) + { + hasGPUSkinning = true; + } + idStr hlslCode( hlslFileBuffer ); idStr programHLSL = StripDeadCode( hlslCode, inFile, compileMacros, shader.builtin ); - programGLSL = ConvertCG2GLSL( programHLSL, inFile, shader.stage == SHADER_STAGE_VERTEX, programLayout, true ); + programGLSL = ConvertCG2GLSL( programHLSL, inFile, shader.stage, programLayout, true, hasGPUSkinning ); fileSystem->WriteFile( outFileHLSL, programHLSL.c_str(), programHLSL.Length(), "fs_savepath" ); fileSystem->WriteFile( outFileGLSL, programGLSL.c_str(), programGLSL.Length(), "fs_savepath" ); @@ -757,11 +769,11 @@ void idRenderProgManager::LoadGLSLProgram( const int programIndex, const int ver // TODO -#if 0 +#if 1 // RB: removed idStr::Icmp( name, "heatHaze.vfp" ) == 0 hack - for( int i = 0; i < shaders[vertexShaderIndex].uniforms.Num(); i++ ) + for( int i = 0; i < shaders[vertexShaderIndex].parmIndices.Num(); i++ ) { - if( shaders[vertexShaderIndex].uniforms[i] == RENDERPARM_ENABLE_SKINNING ) + if( shaders[vertexShaderIndex].parmIndices[i] == RENDERPARM_ENABLE_SKINNING ) { prog.usesJoints = true; prog.optionalSkinning = true; @@ -834,6 +846,8 @@ idRenderProgManager::AllocParmBlockBuffer */ void idRenderProgManager::AllocParmBlockBuffer( const idList& parmIndices, idUniformBuffer& ubo ) { + // TODO support shadow matrices + 23 float4 + const int numParms = parmIndices.Num(); const int bytes = ALIGN( numParms * sizeof( idVec4 ), vkcontext.gpu->props.limits.minUniformBufferOffsetAlignment ); @@ -1488,6 +1502,7 @@ void idRenderProgManager::CommitUniforms( uint64 stateBits ) write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write.pImageInfo = &imageInfo; + //imageIndex++; break; } }