diff --git a/src/rendering/gl/renderer/gl_renderstate.cpp b/src/rendering/gl/renderer/gl_renderstate.cpp index ee3316f387..4fe2d56033 100644 --- a/src/rendering/gl/renderer/gl_renderstate.cpp +++ b/src/rendering/gl/renderer/gl_renderstate.cpp @@ -99,7 +99,7 @@ bool FGLRenderState::ApplyShader() } else { - activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : SHADER_NoTexture, mAlphaThreshold >= 0.f, mPassType); + activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : SHADER_NoTexture, GetUniform(UniformName::uAlphaThreshold) >= 0.f, mPassType); activeShader->Bind(); } @@ -121,50 +121,13 @@ bool FGLRenderState::ApplyShader() } } - glVertexAttrib4fv(VATTR_COLOR, &mStreamData.uVertexColor.X); - glVertexAttrib4fv(VATTR_NORMAL, &mStreamData.uVertexNormal.X); + glVertexAttrib4fv(VATTR_COLOR, (const float*)GetUniformData(UniformName::uVertexColor)); + glVertexAttrib4fv(VATTR_NORMAL, (const float*)GetUniformData(UniformName::uVertexNormal)); - activeShader->muDesaturation.Set(mStreamData.uDesaturationFactor); - activeShader->muFogEnabled.Set(fogset); - activeShader->muTextureMode.Set(mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode); - activeShader->muLightParms.Set(mLightParms); - activeShader->muFogColor.Set(mStreamData.uFogColor); - activeShader->muObjectColor.Set(mStreamData.uObjectColor); - activeShader->muDynLightColor.Set(&mStreamData.uDynLightColor.X); - activeShader->muInterpolationFactor.Set(mStreamData.uInterpolationFactor); - activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.); - activeShader->muAlphaThreshold.Set(mAlphaThreshold); - activeShader->muLightIndex.Set(-1); - activeShader->muClipSplit.Set(mClipSplit); - activeShader->muSpecularMaterial.Set(mGlossiness, mSpecularLevel); - activeShader->muAddColor.Set(mStreamData.uAddColor); - activeShader->muTextureAddColor.Set(mStreamData.uTextureAddColor); - activeShader->muTextureModulateColor.Set(mStreamData.uTextureModulateColor); - activeShader->muTextureBlendColor.Set(mStreamData.uTextureBlendColor); - - if (mGlowEnabled || activeShader->currentglowstate) - { - activeShader->muGlowTopColor.Set(&mStreamData.uGlowTopColor.X); - activeShader->muGlowBottomColor.Set(&mStreamData.uGlowBottomColor.X); - activeShader->muGlowTopPlane.Set(&mStreamData.uGlowTopPlane.X); - activeShader->muGlowBottomPlane.Set(&mStreamData.uGlowBottomPlane.X); - activeShader->currentglowstate = mGlowEnabled; - } - - if (mGradientEnabled || activeShader->currentgradientstate) - { - activeShader->muObjectColor2.Set(mStreamData.uObjectColor2); - activeShader->muGradientTopPlane.Set(&mStreamData.uGradientTopPlane.X); - activeShader->muGradientBottomPlane.Set(&mStreamData.uGradientBottomPlane.X); - activeShader->currentgradientstate = mGradientEnabled; - } - - if (mSplitEnabled || activeShader->currentsplitstate) - { - activeShader->muSplitTopPlane.Set(&mStreamData.uSplitTopPlane.X); - activeShader->muSplitBottomPlane.Set(&mStreamData.uSplitBottomPlane.X); - activeShader->currentsplitstate = mSplitEnabled; - } + SetUniform(UniformName::uFogEnabled, fogset); + SetUniform(UniformName::uTextureMode, mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode); + SetUniform(UniformName::timer, (double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.); + SetUniform(UniformName::uSpecularMaterial, FVector2{ mGlossiness, mSpecularLevel }); if (mTextureMatrixEnabled) { @@ -192,7 +155,7 @@ bool FGLRenderState::ApplyShader() matrixToGL(identityMatrix, activeShader->normalmodelmatrix_index); } - int index = mLightIndex; + int index = GetUniform(UniformName::uLightIndex); // Mess alert for crappy AncientGL! if (!screen->mLights->GetBufferType() && index >= 0) { @@ -205,8 +168,41 @@ bool FGLRenderState::ApplyShader() static_cast(screen->mLights->GetBuffer())->BindRange(nullptr, start, size); } } + SetUniform(UniformName::uLightIndex, index); + + // Apply uniforms: + + GLuint* locations = activeShader->UniformLocations.data(); + int* lastupdates = activeShader->UniformLastUpdates.data(); + + int count = (int)mUniformInfo.size(); + for (int i = 0; i < count; i++) + { + if (lastupdates[i] != mUniformInfo.data()[i].LastUpdate) + { + const void* data = GetUniformData((UniformName)i); + GLuint location = locations[i]; + switch (mUniformInfo[i].Type) + { + default: + case UniformType::Vec4: glUniform4fv(location, 1, (float*)data); break; + case UniformType::Float: glUniform1fv(location, 1, (float*)data); break; + case UniformType::Int: glUniform1iv(location, 1, (int*)data); break; + case UniformType::Mat4: glUniformMatrix4fv(location, 1, GL_FALSE, (float*)data); break; + case UniformType::UInt: glUniform1iv(location, 1, (int*)data); break; + case UniformType::Vec2: glUniform2fv(location, 1, (float*)data); break; + case UniformType::Vec3: glUniform3fv(location, 1, (float*)data); break; + case UniformType::IVec2: glUniform1iv(location, 1, (int*)data); break; + case UniformType::IVec3: glUniform1iv(location, 1, (int*)data); break; + case UniformType::IVec4: glUniform1iv(location, 1, (int*)data); break; + case UniformType::UVec2: glUniform1iv(location, 1, (int*)data); break; + case UniformType::UVec3: glUniform1iv(location, 1, (int*)data); break; + case UniformType::UVec4: glUniform1iv(location, 1, (int*)data); break; + } + lastupdates[i] = mUniformInfo[i].LastUpdate; + } + } - activeShader->muLightIndex.Set(index); return true; } diff --git a/src/rendering/gl/shaders/gl_shader.cpp b/src/rendering/gl/shaders/gl_shader.cpp index fc8d787204..c338d11588 100644 --- a/src/rendering/gl/shaders/gl_shader.cpp +++ b/src/rendering/gl/shaders/gl_shader.cpp @@ -232,49 +232,19 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * int uShadowmapFilter; }; )"; - - i_data += "uniform int uTextureMode;\n"; - i_data += "uniform vec2 uClipSplit;\n"; - i_data += "uniform float uAlphaThreshold;\n"; - // colors - i_data += "uniform vec4 uObjectColor;\n"; - i_data += "uniform vec4 uObjectColor2;\n"; - i_data += "uniform vec4 uDynLightColor;\n"; - i_data += "uniform vec4 uAddColor;\n"; - i_data += "uniform vec4 uTextureBlendColor;\n"; - i_data += "uniform vec4 uTextureModulateColor;\n"; - i_data += "uniform vec4 uTextureAddColor;\n"; - i_data += "uniform vec4 uBlendColor;\n"; - i_data += "uniform vec4 uFogColor;\n"; - i_data += "uniform float uDesaturationFactor;\n"; - i_data += "uniform float uInterpolationFactor;\n"; + // Generate uniform declarations: - // Glowing walls stuff - i_data += "uniform vec4 uGlowTopPlane;\n"; - i_data += "uniform vec4 uGlowTopColor;\n"; - i_data += "uniform vec4 uGlowBottomPlane;\n"; - i_data += "uniform vec4 uGlowBottomColor;\n"; + int index = 0; + for (const auto& info : gl_RenderState.GetUniformInfo()) + { + if (info.Name.empty()) + I_FatalError("Missing uniform declaration for index %d", index); + index++; - i_data += "uniform vec4 uGradientTopPlane;\n"; - i_data += "uniform vec4 uGradientBottomPlane;\n"; - - i_data += "uniform vec4 uSplitTopPlane;\n"; - i_data += "uniform vec4 uSplitBottomPlane;\n"; - - // Lighting + Fog - i_data += "uniform vec4 uLightAttr;\n"; - i_data += "#define uLightLevel uLightAttr.a\n"; - i_data += "#define uFogDensity uLightAttr.b\n"; - i_data += "#define uLightFactor uLightAttr.g\n"; - i_data += "#define uLightDist uLightAttr.r\n"; - i_data += "uniform int uFogEnabled;\n"; - - // dynamic lights - i_data += "uniform int uLightIndex;\n"; - - // Blinn glossiness and specular level - i_data += "uniform vec2 uSpecularMaterial;\n"; + static const char* glsltype[] = { "int", "uint", "float", "vec2", "vec3", "vec4", "ivec2", "ivec3", "ivec4", "uvec2", "uvec3", "uvec4", "mat4" }; + i_data.AppendFormat("uniform %s %s;\n", glsltype[(int)info.Type], info.Name.c_str()); + } // matrices i_data += "uniform mat4 ModelMatrix;\n"; @@ -303,9 +273,6 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * i_data += "uniform sampler2D texture5;\n"; i_data += "uniform sampler2D texture6;\n"; - // timer data - i_data += "uniform float timer;\n"; - // material types i_data += "#if defined(SPECULAR)\n"; i_data += "#define normaltexture texture2\n"; @@ -518,32 +485,16 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * hFragProg = 0; } - muDesaturation.Init(hShader, "uDesaturationFactor"); - muFogEnabled.Init(hShader, "uFogEnabled"); - muTextureMode.Init(hShader, "uTextureMode"); - muLightParms.Init(hShader, "uLightAttr"); - muClipSplit.Init(hShader, "uClipSplit"); - muLightIndex.Init(hShader, "uLightIndex"); - muFogColor.Init(hShader, "uFogColor"); - muDynLightColor.Init(hShader, "uDynLightColor"); - muObjectColor.Init(hShader, "uObjectColor"); - muObjectColor2.Init(hShader, "uObjectColor2"); - muGlowBottomColor.Init(hShader, "uGlowBottomColor"); - muGlowTopColor.Init(hShader, "uGlowTopColor"); - muGlowBottomPlane.Init(hShader, "uGlowBottomPlane"); - muGlowTopPlane.Init(hShader, "uGlowTopPlane"); - muGradientBottomPlane.Init(hShader, "uGradientBottomPlane"); - muGradientTopPlane.Init(hShader, "uGradientTopPlane"); - muSplitBottomPlane.Init(hShader, "uSplitBottomPlane"); - muSplitTopPlane.Init(hShader, "uSplitTopPlane"); - muInterpolationFactor.Init(hShader, "uInterpolationFactor"); - muAlphaThreshold.Init(hShader, "uAlphaThreshold"); - muSpecularMaterial.Init(hShader, "uSpecularMaterial"); - muAddColor.Init(hShader, "uAddColor"); - muTextureAddColor.Init(hShader, "uTextureAddColor"); - muTextureModulateColor.Init(hShader, "uTextureModulateColor"); - muTextureBlendColor.Init(hShader, "uTextureBlendColor"); - muTimer.Init(hShader, "timer"); + const auto& uniformInfo = gl_RenderState.GetUniformInfo(); + UniformLastUpdates.resize(uniformInfo.size()); + UniformLocations.resize(uniformInfo.size(), (GLuint)-1); + int count = (int)uniformInfo.size(); + for (int i = 0; i < count; i++) + { + const auto& name = uniformInfo[i].Name; + if (!name.empty()) + UniformLocations[i] = glGetUniformLocation(hShader, name.c_str()); + } lights_index = glGetUniformLocation(hShader, "lights"); modelmatrix_index = glGetUniformLocation(hShader, "ModelMatrix"); diff --git a/src/rendering/gl/shaders/gl_shader.h b/src/rendering/gl/shaders/gl_shader.h index e9d638446b..7b51a580a9 100644 --- a/src/rendering/gl/shaders/gl_shader.h +++ b/src/rendering/gl/shaders/gl_shader.h @@ -235,41 +235,14 @@ class FShader unsigned int hFragProg; FName mName; - FBufferedUniform1f muDesaturation; - FBufferedUniform1i muFogEnabled; - FBufferedUniform1i muTextureMode; - FBufferedUniform4f muLightParms; - FBufferedUniform2f muClipSplit; - FBufferedUniform1i muLightIndex; - FBufferedUniformPE muFogColor; - FBufferedUniform4f muDynLightColor; - FBufferedUniformPE muObjectColor; - FBufferedUniformPE muObjectColor2; - FBufferedUniformPE muAddColor; - FBufferedUniformPE muTextureBlendColor; - FBufferedUniformPE muTextureModulateColor; - FBufferedUniformPE muTextureAddColor; - FUniform4f muGlowBottomColor; - FUniform4f muGlowTopColor; - FUniform4f muGlowBottomPlane; - FUniform4f muGlowTopPlane; - FUniform4f muGradientBottomPlane; - FUniform4f muGradientTopPlane; - FUniform4f muSplitBottomPlane; - FUniform4f muSplitTopPlane; - FBufferedUniform1f muInterpolationFactor; - FBufferedUniform1f muAlphaThreshold; - FBufferedUniform2f muSpecularMaterial; - FBufferedUniform1f muTimer; + std::vector UniformLastUpdates; + std::vector UniformLocations; int lights_index; int modelmatrix_index; int normalmodelmatrix_index; int texturematrix_index; - int currentglowstate = 0; - int currentgradientstate = 0; - int currentsplitstate = 0; int currentcliplinestate = 0; int currentfixedcolormap = 0; bool currentTextureMatrixState = true;// by setting the matrix state to 'true' it is guaranteed to be set the first time the render state gets applied. diff --git a/src/rendering/hwrenderer/scene/hw_renderstate.h b/src/rendering/hwrenderer/scene/hw_renderstate.h index d725d820d3..783296704e 100644 --- a/src/rendering/hwrenderer/scene/hw_renderstate.h +++ b/src/rendering/hwrenderer/scene/hw_renderstate.h @@ -7,6 +7,7 @@ #include "hw_drawlist.h" #include "matrix.h" #include "hwrenderer/textures/hw_material.h" +#include "hwrenderer/data/shaderuniforms.h" struct FColormap; class IVertexBuffer; @@ -172,38 +173,217 @@ struct FVector4PalEntry }; -struct StreamData +enum class UniformName { - FVector4PalEntry uObjectColor; - FVector4PalEntry uObjectColor2; - FVector4 uDynLightColor; - FVector4PalEntry uAddColor; - FVector4PalEntry uTextureAddColor; - FVector4PalEntry uTextureModulateColor; - FVector4PalEntry uTextureBlendColor; - FVector4PalEntry uFogColor; - float uDesaturationFactor; - float uInterpolationFactor; - float timer; - int useVertexData; - FVector4 uVertexColor; - FVector4 uVertexNormal; + uObjectColor, + uObjectColor2, + uDynLightColor, + uAddColor, + uTextureAddColor, + uTextureModulateColor, + uTextureBlendColor, + uFogColor, + uDesaturationFactor, + uInterpolationFactor, + timer, + useVertexData, + uVertexColor, + uVertexNormal, - FVector4 uGlowTopPlane; - FVector4 uGlowTopColor; - FVector4 uGlowBottomPlane; - FVector4 uGlowBottomColor; + uGlowTopPlane, + uGlowTopColor, + uGlowBottomPlane, + uGlowBottomColor, - FVector4 uGradientTopPlane; - FVector4 uGradientBottomPlane; + uGradientTopPlane, + uGradientBottomPlane, - FVector4 uSplitTopPlane; - FVector4 uSplitBottomPlane; + uSplitTopPlane, + uSplitBottomPlane, + + uObjectBlendMode, + uObjectDesaturationFactor, + uObjectColorizeFactor, + uObjectInvertColor, + + uTextureMode, + uAlphaThreshold, + uClipSplit, + uLightLevel, + uFogDensity, + uLightFactor, + uLightDist, + uFogEnabled, + uLightIndex, + uSpecularMaterial, + uDataIndex, + uPadding1, + uPadding2, + uPadding3 +}; + +enum class UniformFamily +{ + Normal, + //Matrix, + PushConstant, + NumFamilies }; class FRenderState { protected: + FRenderState() + { + // Important: the following declarations must be compatible with the GLSL std140 layout rules. + // DeclareUniform does not automatically insert padding to enforce this. + + DeclareUniform(UniformName::uObjectColor, "uObjectColor", UniformType::Vec4); + DeclareUniform(UniformName::uObjectColor2, "uObjectColor2", UniformType::Vec4); + DeclareUniform(UniformName::uDynLightColor, "uDynLightColor", UniformType::Vec4); + DeclareUniform(UniformName::uAddColor, "uAddColor", UniformType::Vec4); + DeclareUniform(UniformName::uTextureAddColor, "uTextureAddColor", UniformType::Vec4); + DeclareUniform(UniformName::uTextureModulateColor, "uTextureModulateColor", UniformType::Vec4); + DeclareUniform(UniformName::uTextureBlendColor, "uTextureBlendColor", UniformType::Vec4); + DeclareUniform(UniformName::uFogColor, "uFogColor", UniformType::Vec4); + + DeclareUniform(UniformName::uDesaturationFactor, "uDesaturationFactor", UniformType::Float); + DeclareUniform(UniformName::uInterpolationFactor, "uInterpolationFactor", UniformType::Float); + DeclareUniform(UniformName::timer, "timer", UniformType::Float); + DeclareUniform(UniformName::useVertexData, "useVertexData", UniformType::Int); + + DeclareUniform(UniformName::uVertexColor, "uVertexColor", UniformType::Vec4); + DeclareUniform(UniformName::uVertexNormal, "uVertexNormal", UniformType::Vec4); + + DeclareUniform(UniformName::uGlowTopPlane, "uGlowTopPlane", UniformType::Vec4); + DeclareUniform(UniformName::uGlowTopColor, "uGlowTopColor", UniformType::Vec4); + DeclareUniform(UniformName::uGlowBottomPlane, "uGlowBottomPlane", UniformType::Vec4); + DeclareUniform(UniformName::uGlowBottomColor, "uGlowBottomColor", UniformType::Vec4); + + DeclareUniform(UniformName::uGradientTopPlane, "uGradientTopPlane", UniformType::Vec4); + DeclareUniform(UniformName::uGradientBottomPlane, "uGradientBottomPlane", UniformType::Vec4); + + DeclareUniform(UniformName::uSplitTopPlane, "uSplitTopPlane", UniformType::Vec4); + DeclareUniform(UniformName::uSplitBottomPlane, "uSplitBottomPlane", UniformType::Vec4); + + DeclareUniform(UniformName::uObjectBlendMode, "uObjectBlendMode", UniformType::Float); + DeclareUniform(UniformName::uObjectInvertColor, "uObjectInvertColor", UniformType::Float); + DeclareUniform(UniformName::uObjectDesaturationFactor, "uObjectDesaturationFactor", UniformType::Float); + DeclareUniform(UniformName::uObjectColorizeFactor, "uObjectColorizeFactor", UniformType::Float); + + DeclareUniform(UniformName::uTextureMode, "uTextureMode", UniformType::Int, UniformFamily::PushConstant); + DeclareUniform(UniformName::uAlphaThreshold, "uAlphaThreshold", UniformType::Float, UniformFamily::PushConstant); + DeclareUniform(UniformName::uClipSplit, "uClipSplit", UniformType::Vec2, UniformFamily::PushConstant); + + DeclareUniform(UniformName::uLightLevel, "uLightLevel", UniformType::Float, UniformFamily::PushConstant); + DeclareUniform(UniformName::uFogDensity, "uFogDensity", UniformType::Float, UniformFamily::PushConstant); + DeclareUniform(UniformName::uLightFactor, "uLightFactor", UniformType::Float, UniformFamily::PushConstant); + DeclareUniform(UniformName::uLightDist, "uLightDist", UniformType::Float, UniformFamily::PushConstant); + DeclareUniform(UniformName::uFogEnabled, "uFogEnabled", UniformType::Int, UniformFamily::PushConstant); + + DeclareUniform(UniformName::uLightIndex, "uLightIndex", UniformType::Int, UniformFamily::PushConstant); + + DeclareUniform(UniformName::uSpecularMaterial, "uSpecularMaterial", UniformType::Vec2, UniformFamily::PushConstant); + + DeclareUniform(UniformName::uDataIndex, "uDataIndex", UniformType::Int, UniformFamily::PushConstant); + DeclareUniform(UniformName::uPadding1, "uPadding1", UniformType::Int, UniformFamily::PushConstant); + DeclareUniform(UniformName::uPadding2, "uPadding2", UniformType::Int, UniformFamily::PushConstant); + DeclareUniform(UniformName::uPadding3, "uPadding3", UniformType::Int, UniformFamily::PushConstant); + } + + void DeclareUniform(UniformName nameIndex, const char* glslname, UniformType type, UniformFamily family = UniformFamily::Normal) + { + size_t index = (size_t)nameIndex; + if (mUniformInfo.size() <= index) + mUniformInfo.resize(index + 1); + + auto& data = mUniformData[(int)family]; + + UniformInfo& info = mUniformInfo[index]; + info.Name = glslname; + info.Type = type; + info.Family = family; + info.Offset = (int)data.size(); + + static const int bytesize[] = { 4, 4, 4, 8, 12, 16, 8, 12, 16, 8, 12, 16, 16 }; + data.resize(data.size() + bytesize[(int)type]); + } + + void SetUniform(UniformName nameIndex, const PalEntry& value) + { + SetUniform(nameIndex, FVector4(value.r * (1.0f / 255.0f), value.g * (1.0f / 255.0f), value.b * (1.0f / 255.0f), value.a * (1.0f / 255.0f))); + } + + void SetUniform(UniformName nameIndex, double value) + { + SetUniform(nameIndex, (float)value); + } + + void SetUniform(UniformName nameIndex, const DVector2& value) + { + SetUniform(nameIndex, FVector2((float)value.X, (float)value.Y)); + } + + void SetUniform(UniformName nameIndex, const DVector3& value) + { + SetUniform(nameIndex, FVector3((float)value.X, (float)value.Y, (float)value.Z)); + } + + void SetUniform(UniformName nameIndex, const DVector4& value) + { + SetUniform(nameIndex, FVector4((float)value.X, (float)value.Y, (float)value.Z, (float)value.W)); + } + + template + void SetUniform(UniformName nameIndex, const T& value) + { + T* dest = (T*)GetUniformData(nameIndex); + if (*dest != value) + { + *dest = value; + mUniformInfo[(int)nameIndex].LastUpdate++; + } + } + + void SetUniformAlpha(UniformName nameIndex, float alpha) + { + float* dest = (float*)GetUniformData(nameIndex); + if (dest[3] != alpha) + { + dest[3] = alpha; + mUniformInfo[(int)nameIndex].LastUpdate++; + } + } + + void SetUniformIntegerAlpha(UniformName nameIndex, const PalEntry& value) + { + SetUniform(nameIndex, FVector4(value.r * (1.0f / 255.0f), value.g * (1.0f / 255.0f), value.b * (1.0f / 255.0f), (float)value.a)); + } + + template + T GetUniform(UniformName nameIndex) + { + return *(T*)GetUniformData(nameIndex); + } + + void* GetUniformData(UniformName nameIndex) + { + const auto& info = mUniformInfo[(int)nameIndex]; + return mUniformData[(int)info.Family].data() + info.Offset; + } + + struct UniformInfo + { + std::string Name; + UniformType Type = {}; + UniformFamily Family = {}; + int Offset = 0; + int LastUpdate = 0; + }; + + std::vector mUniformInfo; + std::vector mUniformData[(int)UniformFamily::NumFamilies]; + uint8_t mFogEnabled; uint8_t mTextureEnabled:1; uint8_t mGlowEnabled : 1; @@ -213,16 +393,10 @@ protected: uint8_t mTextureMatrixEnabled : 1; uint8_t mSplitEnabled : 1; - int mLightIndex; int mSpecialEffect; int mTextureMode; int mSoftLight; - float mLightParms[4]; - float mAlphaThreshold; - float mClipSplit[2]; - - StreamData mStreamData = {}; PalEntry mFogColor; FRenderStyle mRenderStyle; @@ -243,31 +417,36 @@ public: VSMatrix mTextureMatrix; public: + const std::vector& GetUniformInfo() const { return mUniformInfo; } + const void* GetUniformData(UniformFamily family) const { return mUniformData[(int)family].data(); } + uint32_t GetUniformDataSize(UniformFamily family) const { return (uint32_t)mUniformData[(int)family].size(); } void Reset() { mTextureEnabled = true; mGradientEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false; mFogColor = 0xffffffff; - mStreamData.uFogColor = mFogColor; + SetUniform(UniformName::uFogColor, mFogColor); mTextureMode = -1; - mStreamData.uDesaturationFactor = 0.0f; - mAlphaThreshold = 0.5f; + SetUniform(UniformName::uDesaturationFactor, 0.0f); + SetUniform(UniformName::uAlphaThreshold, 0.5f); mModelMatrixEnabled = false; mTextureMatrixEnabled = false; mSplitEnabled = false; - mStreamData.uAddColor = 0; - mStreamData.uObjectColor = 0xffffffff; - mStreamData.uObjectColor2 = 0; - mStreamData.uTextureBlendColor = 0; - mStreamData.uTextureAddColor = 0; - mStreamData.uTextureModulateColor = 0; + SetUniform(UniformName::uAddColor, 0); + SetUniform(UniformName::uObjectColor, 0xffffffff); + SetUniform(UniformName::uObjectColor2, 0); + SetUniform(UniformName::uTextureBlendColor, 0); + SetUniform(UniformName::uTextureAddColor, 0); + SetUniform(UniformName::uTextureModulateColor, 0); mSoftLight = 0; - mLightParms[0] = mLightParms[1] = mLightParms[2] = 0.0f; - mLightParms[3] = -1.f; + SetUniform(UniformName::uLightDist, 0.0f); + SetUniform(UniformName::uLightFactor, 0.0f); + SetUniform(UniformName::uFogDensity, 0.0f); + SetUniform(UniformName::uLightLevel, -1.f); mSpecialEffect = EFF_NONE; - mLightIndex = -1; - mStreamData.uInterpolationFactor = 0; + SetUniform(UniformName::uLightIndex, -1); + SetUniform(UniformName::uInterpolationFactor, 0); mRenderStyle = DefaultRenderStyle(); mMaterial.Reset(); mBias.Reset(); @@ -277,16 +456,16 @@ public: mVertexOffsets[0] = mVertexOffsets[1] = 0; mIndexBuffer = nullptr; - mStreamData.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f }; - mStreamData.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGlowTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGlowBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGradientTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGradientBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + SetUniform(UniformName::uVertexColor, FVector4{ 1.0f, 1.0f, 1.0f, 1.0f }); + SetUniform(UniformName::uGlowTopColor, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uGlowBottomColor, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uGlowTopPlane, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uGlowBottomPlane, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uGradientTopPlane, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uGradientBottomPlane, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uSplitTopPlane, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uSplitBottomPlane, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uDynLightColor, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); mModelMatrix.loadIdentity(); mTextureMatrix.loadIdentity(); @@ -295,38 +474,38 @@ public: void SetNormal(FVector3 norm) { - mStreamData.uVertexNormal = { norm.X, norm.Y, norm.Z, 0.f }; + SetUniform(UniformName::uVertexNormal, FVector4{ norm.X, norm.Y, norm.Z, 0.f }); } void SetNormal(float x, float y, float z) { - mStreamData.uVertexNormal = { x, y, z, 0.f }; + SetUniform(UniformName::uVertexNormal, FVector4{ x, y, z, 0.f }); } void SetColor(float r, float g, float b, float a = 1.f, int desat = 0) { - mStreamData.uVertexColor = { r, g, b, a }; - mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f); + SetUniform(UniformName::uVertexColor, FVector4{ r, g, b, a }); + SetUniform(UniformName::uDesaturationFactor, desat * (1.0f / 255.0f)); } void SetColor(PalEntry pe, int desat = 0) { const float scale = 1.0f / 255.0f; - mStreamData.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, pe.a * scale }; - mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f); + SetUniform(UniformName::uVertexColor, FVector4{ pe.r * scale, pe.g * scale, pe.b * scale, pe.a * scale }); + SetUniform(UniformName::uDesaturationFactor, desat * (1.0f / 255.0f)); } void SetColorAlpha(PalEntry pe, float alpha = 1.f, int desat = 0) { const float scale = 1.0f / 255.0f; - mStreamData.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, alpha }; - mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f); + SetUniform(UniformName::uVertexColor, FVector4{ pe.r * scale, pe.g * scale, pe.b * scale, alpha }); + SetUniform(UniformName::uDesaturationFactor, desat * (1.0f / 255.0f)); } void ResetColor() { - mStreamData.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f }; - mStreamData.uDesaturationFactor = 0.0f; + SetUniform(UniformName::uVertexColor, FVector4{ 1.0f, 1.0f, 1.0f, 1.0f }); + SetUniform(UniformName::uDesaturationFactor, 0.0f); } void SetTextureMode(int mode) @@ -374,8 +553,8 @@ public: { if (mGlowEnabled && !on) { - mStreamData.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f }; + SetUniform(UniformName::uGlowTopColor, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uGlowBottomColor, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); } mGlowEnabled = on; } @@ -394,8 +573,8 @@ public: { if (mSplitEnabled && !on) { - mStreamData.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; - mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; + SetUniform(UniformName::uSplitTopPlane, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); + SetUniform(UniformName::uSplitBottomPlane, FVector4{ 0.0f, 0.0f, 0.0f, 0.0f }); } mSplitEnabled = on; } @@ -412,78 +591,78 @@ public: void SetGlowParams(float *t, float *b) { - mStreamData.uGlowTopColor = { t[0], t[1], t[2], t[3] }; - mStreamData.uGlowBottomColor = { b[0], b[1], b[2], b[3] }; + SetUniform(UniformName::uGlowTopColor, FVector4{ t[0], t[1], t[2], t[3] }); + SetUniform(UniformName::uGlowBottomColor, FVector4{ b[0], b[1], b[2], b[3] }); } void SetSoftLightLevel(int llevel, int blendfactor = 0) { - if (blendfactor == 0) mLightParms[3] = llevel / 255.f; - else mLightParms[3] = -1.f; + if (blendfactor == 0) SetUniform(UniformName::uLightLevel, llevel / 255.f); + else SetUniform(UniformName::uLightLevel, -1.f); } void SetNoSoftLightLevel() { - mLightParms[3] = -1.f; + SetUniform(UniformName::uLightLevel, -1.f); } void SetGlowPlanes(const secplane_t &top, const secplane_t &bottom) { auto &tn = top.Normal(); auto &bn = bottom.Normal(); - mStreamData.uGlowTopPlane = { (float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD() }; - mStreamData.uGlowBottomPlane = { (float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD() }; + SetUniform(UniformName::uGlowTopPlane, FVector4{ (float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD() }); + SetUniform(UniformName::uGlowBottomPlane, FVector4{ (float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD() }); } void SetGradientPlanes(const secplane_t &top, const secplane_t &bottom) { auto &tn = top.Normal(); auto &bn = bottom.Normal(); - mStreamData.uGradientTopPlane = { (float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD() }; - mStreamData.uGradientBottomPlane = { (float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD() }; + SetUniform(UniformName::uGradientTopPlane, FVector4{ (float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD() }); + SetUniform(UniformName::uGradientBottomPlane, FVector4{ (float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD() }); } void SetSplitPlanes(const secplane_t &top, const secplane_t &bottom) { auto &tn = top.Normal(); auto &bn = bottom.Normal(); - mStreamData.uSplitTopPlane = { (float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD() }; - mStreamData.uSplitBottomPlane = { (float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD() }; + SetUniform(UniformName::uSplitTopPlane, FVector4{ (float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD() }); + SetUniform(UniformName::uSplitBottomPlane, FVector4{ (float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD() }); } void SetDynLight(float r, float g, float b) { - mStreamData.uDynLightColor = { r, g, b, 0.0f }; + SetUniform(UniformName::uDynLightColor, FVector4{ r, g, b, 0.0f }); } void SetObjectColor(PalEntry pe) { - mStreamData.uObjectColor = pe; + SetUniform(UniformName::uObjectColor, pe); } void SetObjectColor2(PalEntry pe) { - mStreamData.uObjectColor2 = pe; + SetUniform(UniformName::uObjectColor2, pe); } void SetAddColor(PalEntry pe) { - mStreamData.uAddColor = pe; + SetUniform(UniformName::uAddColor, pe); } void ApplyTextureManipulation(TextureManipulation* texfx) { if (!texfx || texfx->AddColor.a == 0) { - mStreamData.uTextureAddColor.a = 0; // we only need to set the flags to 0 + SetUniformAlpha(UniformName::uTextureAddColor, 0); // we only need to set the flags to 0 } else { // set up the whole thing - mStreamData.uTextureAddColor.SetIA(texfx->AddColor); + SetUniformIntegerAlpha(UniformName::uTextureAddColor, texfx->AddColor); auto pe = texfx->ModulateColor; - mStreamData.uTextureModulateColor.SetFlt(pe.r * pe.a / 255.f, pe.g * pe.a / 255.f, pe.b * pe.a / 255.f, texfx->DesaturationFactor); - mStreamData.uTextureBlendColor = texfx->BlendColor; + SetUniform(UniformName::uTextureModulateColor, FVector4{ pe.r * pe.a / 255.f, pe.g * pe.a / 255.f, pe.b * pe.a / 255.f, texfx->DesaturationFactor }); + SetUniform(UniformName::uTextureBlendColor, texfx->BlendColor); } } @@ -491,14 +670,14 @@ public: { const float LOG2E = 1.442692f; // = 1/log(2) mFogColor = c; - mStreamData.uFogColor = mFogColor; - if (d >= 0.0f) mLightParms[2] = d * (-LOG2E / 64000.f); + SetUniform(UniformName::uFogColor, mFogColor); + if (d >= 0.0f) SetUniform(UniformName::uFogDensity, d * (-LOG2E / 64000.f)); } void SetLightParms(float f, float d) { - mLightParms[1] = f; - mLightParms[0] = d; + SetUniform(UniformName::uLightFactor, f); + SetUniform(UniformName::uLightDist, d); } PalEntry GetFogColor() const @@ -508,8 +687,8 @@ public: void AlphaFunc(int func, float thresh) { - if (func == Alpha_Greater) mAlphaThreshold = thresh; - else mAlphaThreshold = thresh - 0.001f; + if (func == Alpha_Greater) SetUniform(UniformName::uAlphaThreshold, thresh); + else SetUniform(UniformName::uAlphaThreshold, thresh - 0.001f); } void SetPlaneTextureRotation(HWSectorPlane *plane, FMaterial *texture) @@ -522,7 +701,7 @@ public: void SetLightIndex(int index) { - mLightIndex = index; + SetUniform(UniformName::uLightIndex, index); } void SetRenderStyle(FRenderStyle rs) @@ -560,24 +739,22 @@ public: void SetClipSplit(float bottom, float top) { - mClipSplit[0] = bottom; - mClipSplit[1] = top; + SetUniform(UniformName::uClipSplit, FVector2(bottom, top)); } void SetClipSplit(float *vals) { - memcpy(mClipSplit, vals, 2 * sizeof(float)); + SetUniform(UniformName::uClipSplit, FVector2(vals[0], vals[1])); } void GetClipSplit(float *out) { - memcpy(out, mClipSplit, 2 * sizeof(float)); + memcpy(out, GetUniformData(UniformName::uClipSplit), 2 * sizeof(float)); } void ClearClipSplit() { - mClipSplit[0] = -1000000.f; - mClipSplit[1] = 1000000.f; + SetUniform(UniformName::uClipSplit, FVector2(-1000000.f, 1000000.f)); } void SetVertexBuffer(IVertexBuffer *vb, int offset0, int offset1) @@ -602,12 +779,12 @@ public: void SetInterpolationFactor(float fac) { - mStreamData.uInterpolationFactor = fac; + SetUniform(UniformName::uInterpolationFactor, fac); } float GetInterpolationFactor() { - return mStreamData.uInterpolationFactor; + return GetUniform(UniformName::uInterpolationFactor); } void EnableDrawBufferAttachments(bool on) // Used by fog boundary drawer diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index bf64007637..9602d21c8c 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -246,21 +246,33 @@ void PolyRenderState::Apply() else { int effectState = mMaterial.mOverrideShader >= 0 ? mMaterial.mOverrideShader : (mMaterial.mMaterial ? mMaterial.mMaterial->GetShaderIndex() : 0); - mDrawCommands->SetShader(EFF_NONE, mTextureEnabled ? effectState : SHADER_NoTexture, mAlphaThreshold >= 0.f); + mDrawCommands->SetShader(EFF_NONE, mTextureEnabled ? effectState : SHADER_NoTexture, GetUniform(UniformName::uAlphaThreshold) >= 0.f); } - PolyPushConstants constants; - constants.uFogEnabled = fogset; - constants.uTextureMode = mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode; - constants.uLightDist = mLightParms[0]; - constants.uLightFactor = mLightParms[1]; - constants.uFogDensity = mLightParms[2]; - constants.uLightLevel = mLightParms[3]; - constants.uAlphaThreshold = mAlphaThreshold; - constants.uClipSplit = { mClipSplit[0], mClipSplit[1] }; - constants.uLightIndex = mLightIndex; + PolyUniforms uniforms; + uniforms.uFogEnabled = fogset; + uniforms.uTextureMode = mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode; + uniforms.uLightDist = GetUniform(UniformName::uLightDist); + uniforms.uLightFactor = GetUniform(UniformName::uLightFactor); + uniforms.uFogDensity = GetUniform(UniformName::uFogDensity); + uniforms.uLightLevel = GetUniform(UniformName::uLightLevel); + uniforms.uAlphaThreshold = GetUniform(UniformName::uAlphaThreshold); + uniforms.uClipSplit = GetUniform(UniformName::uClipSplit); + uniforms.uLightIndex = GetUniform(UniformName::uLightIndex); + uniforms.uDesaturationFactor = GetUniform(UniformName::uDesaturationFactor); + uniforms.uInterpolationFactor = GetUniform(UniformName::uInterpolationFactor); + uniforms.uObjectColor = GetUniform(UniformName::uObjectColor); + uniforms.uObjectColor2 = GetUniform(UniformName::uObjectColor2); + uniforms.uGradientTopPlane = GetUniform(UniformName::uGradientTopPlane); + uniforms.uGradientBottomPlane = GetUniform(UniformName::uGradientBottomPlane); + uniforms.uSplitTopPlane = GetUniform(UniformName::uSplitTopPlane); + uniforms.uSplitBottomPlane = GetUniform(UniformName::uSplitBottomPlane); + uniforms.uVertexColor = GetUniform(UniformName::uVertexColor); + uniforms.uVertexNormal = GetUniform(UniformName::uVertexNormal); + uniforms.uAddColor = GetUniform(UniformName::uAddColor); + uniforms.uFogColor = GetUniform(UniformName::uFogColor); - mDrawCommands->PushStreamData(mStreamData, constants); + mDrawCommands->PushStreamData(uniforms); ApplyMatrices(); if (mBias.mChanged) diff --git a/src/rendering/polyrenderer/drawers/poly_thread.cpp b/src/rendering/polyrenderer/drawers/poly_thread.cpp index e90c028790..6215c89254 100644 --- a/src/rendering/polyrenderer/drawers/poly_thread.cpp +++ b/src/rendering/polyrenderer/drawers/poly_thread.cpp @@ -112,23 +112,21 @@ void PolyTriangleThreadData::UpdateClip() clip.bottom = MIN(MIN(viewport_y + viewport_height, scissor.bottom), dest_height); } -void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPushConstants &constants) +void PolyTriangleThreadData::PushStreamData(const PolyUniforms &data) { mainVertexShader.Data = data; - mainVertexShader.uClipSplit = constants.uClipSplit; + mainVertexShader.uClipSplit = data.uClipSplit; - PushConstants = &constants; - - AlphaThreshold = clamp((int)(PushConstants->uAlphaThreshold * 255.0f + 0.5f), 0, 255) << 24; + AlphaThreshold = clamp((int)(data.uAlphaThreshold * 255.0f + 0.5f), 0, 255) << 24; numPolyLights = 0; - if (constants.uLightIndex >= 0) + if (data.uLightIndex >= 0) { - const FVector4 &lightRange = lights[constants.uLightIndex]; + const FVector4 &lightRange = lights[data.uLightIndex]; static_assert(sizeof(FVector4) == 16, "sizeof(FVector4) is not 16 bytes"); if (lightRange.Y > lightRange.X) { - int start = constants.uLightIndex + 1; + int start = data.uLightIndex + 1; int modulatedStart = static_cast(lightRange.X) + start; int modulatedEnd = static_cast(lightRange.Y) + start; for (int i = modulatedStart; i < modulatedEnd; i += 4) diff --git a/src/rendering/polyrenderer/drawers/poly_thread.h b/src/rendering/polyrenderer/drawers/poly_thread.h index 326e5790f6..23c1861c73 100644 --- a/src/rendering/polyrenderer/drawers/poly_thread.h +++ b/src/rendering/polyrenderer/drawers/poly_thread.h @@ -64,7 +64,7 @@ public: void UpdateClip(); - void PushStreamData(const StreamData &data, const PolyPushConstants &constants); + void PushStreamData(const PolyUniforms &data); void PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); void DrawIndexed(int index, int count, PolyDrawMode mode); @@ -142,7 +142,6 @@ public: int EffectState = 0; bool AlphaTest = false; uint32_t AlphaThreshold = 0x7f000000; - const PolyPushConstants* PushConstants = nullptr; const void *vertices = nullptr; const unsigned int *elements = nullptr; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index cae71b2af1..9064ee5efd 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -299,12 +299,11 @@ private: class PolyPushStreamDataCommand : public PolyDrawerCommand { public: - PolyPushStreamDataCommand(const StreamData& data, const PolyPushConstants& constants) : data(data), constants(constants) { } - void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->PushStreamData(data, constants); } + PolyPushStreamDataCommand(const PolyUniforms& data) : data(data) { } + void Execute(DrawerThread* thread) override { PolyTriangleThreadData::Get(thread)->PushStreamData(data); } private: - StreamData data; - PolyPushConstants constants; + PolyUniforms data; }; class PolyDrawCommand : public PolyDrawerCommand @@ -434,9 +433,9 @@ void PolyCommandBuffer::SetShader(int specialEffect, int effectState, bool alpha mQueue->Push(specialEffect, effectState, alphaTest); } -void PolyCommandBuffer::PushStreamData(const StreamData &data, const PolyPushConstants &constants) +void PolyCommandBuffer::PushStreamData(const PolyUniforms &data) { - mQueue->Push(data, constants); + mQueue->Push(data); } void PolyCommandBuffer::PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix) diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 80e9427444..696f4f3f00 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -33,7 +33,6 @@ class RenderMemory; class PolyDrawerCommand; class PolyInputAssembly; class PolyDepthStencil; -struct PolyPushConstants; enum class PolyDrawMode { @@ -68,7 +67,7 @@ public: void SetRenderStyle(FRenderStyle style); void SetTexture(int unit, void *pixels, int width, int height, bool bgra); void SetShader(int specialEffect, int effectState, bool alphaTest); - void PushStreamData(const StreamData &data, const PolyPushConstants &constants); + void PushStreamData(const PolyUniforms& data); void PushMatrices(const VSMatrix &modelMatrix, const VSMatrix &normalModelMatrix, const VSMatrix &textureMatrix); void ClearDepth(float value); void ClearStencil(uint8_t value); @@ -97,23 +96,6 @@ private: std::vector stencilbuffer; }; -struct PolyPushConstants -{ - int uTextureMode; - float uAlphaThreshold; - Vec2f uClipSplit; - - // Lighting + Fog - float uLightLevel; - float uFogDensity; - float uLightFactor; - float uLightDist; - int uFogEnabled; - - // dynamic lights - int uLightIndex; -}; - class PolyInputAssembly { public: diff --git a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h index dd37c2cedf..e1fcad48cb 100644 --- a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h +++ b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h @@ -23,6 +23,39 @@ public: Vec4f vWorldNormal; }; +struct Color4f { float r, g, b, a; }; + +class PolyUniforms +{ +public: + int uTextureMode; + float uAlphaThreshold; + Vec2f uClipSplit; + + float uLightLevel; + float uFogDensity; + float uLightFactor; + float uLightDist; + int uFogEnabled; + + int uLightIndex; + + float uDesaturationFactor; + float uInterpolationFactor; + Color4f uObjectColor; + Color4f uObjectColor2; + FVector4 uGradientTopPlane; + FVector4 uGradientBottomPlane; + FVector4 uSplitTopPlane; + FVector4 uSplitBottomPlane; + + FVector4 uVertexColor; + FVector3 uVertexNormal; + + Color4f uFogColor; + Color4f uAddColor; +}; + class PolyMainVertexShader : public ShadedTriVertex { public: @@ -42,7 +75,7 @@ public: VSMatrix ModelMatrix; VSMatrix NormalModelMatrix; VSMatrix TextureMatrix; - StreamData Data; + PolyUniforms Data; Vec2f uClipSplit; const HWViewpointUniforms *Viewpoint = nullptr; diff --git a/src/rendering/polyrenderer/drawers/screen_scanline_setup.cpp b/src/rendering/polyrenderer/drawers/screen_scanline_setup.cpp index e4fa51a6ad..934cc72eac 100644 --- a/src/rendering/polyrenderer/drawers/screen_scanline_setup.cpp +++ b/src/rendering/polyrenderer/drawers/screen_scanline_setup.cpp @@ -219,14 +219,14 @@ static void WriteDynLightArray(int x0, int x1, PolyTriangleThreadData* thread) static void WriteLightArray(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) { - auto constants = thread->PushConstants; + auto uniforms = &thread->mainVertexShader.Data; auto vColorR = thread->scanline.vColorR; auto vColorG = thread->scanline.vColorG; auto vColorB = thread->scanline.vColorB; auto vColorA = thread->scanline.vColorA; - if (thread->PushConstants->uLightLevel >= 0.0f) + if (uniforms->uLightLevel >= 0.0f) { float startX = x0 + (0.5f - args->v1->x); float startY = y + (0.5f - args->v1->y); @@ -235,7 +235,7 @@ static void WriteLightArray(int y, int x0, int x1, const TriDrawTriangleArgs* ar float globVis = thread->mainVertexShader.Viewpoint->mGlobVis; - uint32_t light = (int)(constants->uLightLevel * 255.0f); + uint32_t light = (int)(uniforms->uLightLevel * 255.0f); fixed_t shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT); fixed_t lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT); fixed_t lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT); @@ -278,10 +278,10 @@ static void WriteLightArray(int y, int x0, int x1, const TriDrawTriangleArgs* ar } } } - else if (constants->uFogEnabled > 0) + else if (uniforms->uFogEnabled > 0) { - float uLightDist = constants->uLightDist; - float uLightFactor = constants->uLightFactor; + float uLightDist = uniforms->uLightDist; + float uLightFactor = uniforms->uLightFactor; float* w = thread->scanline.W; uint32_t* lightarray = thread->scanline.lightarray; for (int x = x0; x < x1; x++) @@ -292,7 +292,7 @@ static void WriteLightArray(int y, int x0, int x1, const TriDrawTriangleArgs* ar uint32_t b = thread->scanline.vColorB[x]; float fogdist = MAX(16.0f, w[x]); - float fogfactor = std::exp2(constants->uFogDensity * fogdist); + float fogfactor = std::exp2(uniforms->uFogDensity * fogdist); // brightening around the player for light mode 2: if (fogdist < uLightDist) @@ -459,7 +459,7 @@ void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyT WriteVaryingColor(args->v1->g * args->v1->w + args->gradientX.G * startX + args->gradientY.G * startY, args->gradientX.G, x0, x1, thread->scanline.W, thread->scanline.vColorG); WriteVaryingColor(args->v1->b * args->v1->w + args->gradientX.B * startX + args->gradientY.B * startY, args->gradientX.B, x0, x1, thread->scanline.W, thread->scanline.vColorB); - if (thread->PushConstants->uFogEnabled != -3 && thread->PushConstants->uTextureMode != TM_FOGLAYER) + if (thread->mainVertexShader.Data.uFogEnabled != -3 && thread->mainVertexShader.Data.uTextureMode != TM_FOGLAYER) WriteLightArray(y, x0, x1, args, thread); if (thread->numPolyLights > 0) diff --git a/src/rendering/polyrenderer/drawers/screen_shader.cpp b/src/rendering/polyrenderer/drawers/screen_shader.cpp index da7e738c0c..2535ffcd81 100644 --- a/src/rendering/polyrenderer/drawers/screen_shader.cpp +++ b/src/rendering/polyrenderer/drawers/screen_shader.cpp @@ -46,7 +46,7 @@ static uint32_t SampleTexture(uint32_t u, uint32_t v, const void* texPixels, int static void EffectFogBoundary(int x0, int x1, PolyTriangleThreadData* thread) { - float uFogDensity = thread->PushConstants->uFogDensity; + float uFogDensity = thread->mainVertexShader.Data.uFogDensity; uint32_t fogcolor = MAKEARGB( 0, static_cast(clamp(thread->mainVertexShader.Data.uFogColor.r, 0.0f, 1.0f) * 255.0f), @@ -380,9 +380,9 @@ static void ProcessMaterial(int x0, int x1, PolyTriangleThreadData* thread) } else // func_normal { - auto constants = thread->PushConstants; + auto uniforms = &thread->mainVertexShader.Data; - switch (constants->uTextureMode) + switch (uniforms->uTextureMode) { default: case TM_NORMAL: @@ -395,7 +395,7 @@ static void ProcessMaterial(int x0, int x1, PolyTriangleThreadData* thread) case TM_INVERTOPAQUE: FuncNormal_InvertOpaque(x0, x1, thread); break; } - if (constants->uTextureMode != TM_FOGLAYER) + if (uniforms->uTextureMode != TM_FOGLAYER) { auto& streamdata = thread->mainVertexShader.Data; @@ -429,7 +429,7 @@ static void GetLightColor(int x0, int x1, PolyTriangleThreadData* thread) uint32_t* fragcolor = thread->scanline.FragColor; uint32_t* lightarray = thread->scanline.lightarray; - if (thread->PushConstants->uFogEnabled >= 0) + if (thread->mainVertexShader.Data.uFogEnabled >= 0) { for (int x = x0; x < x1; x++) { @@ -458,7 +458,7 @@ static void GetLightColor(int x0, int x1, PolyTriangleThreadData* thread) uint32_t fogR = (int)((thread->mainVertexShader.Data.uFogColor.r) * 255.0f); uint32_t fogG = (int)((thread->mainVertexShader.Data.uFogColor.g) * 255.0f); uint32_t fogB = (int)((thread->mainVertexShader.Data.uFogColor.b) * 255.0f); - float uFogDensity = thread->PushConstants->uFogDensity; + float uFogDensity = thread->mainVertexShader.Data.uFogDensity; float* w = thread->scanline.W; for (int x = x0; x < x1; x++) @@ -501,10 +501,10 @@ static void MainFP(int x0, int x1, PolyTriangleThreadData* thread) if (thread->AlphaTest) RunAlphaTest(x0, x1, thread); - auto constants = thread->PushConstants; - if (constants->uFogEnabled != -3) + auto uniforms = &thread->mainVertexShader.Data; + if (uniforms->uFogEnabled != -3) { - if (constants->uTextureMode != TM_FOGLAYER) + if (uniforms->uTextureMode != TM_FOGLAYER) { GetLightColor(x0, x1, thread); } @@ -512,10 +512,10 @@ static void MainFP(int x0, int x1, PolyTriangleThreadData* thread) { /*float fogdist = 0.0f; float fogfactor = 0.0f; - if (constants->uFogEnabled != 0) + if (uniforms->uFogEnabled != 0) { fogdist = MAX(16.0f, w[x]); - fogfactor = std::exp2(constants->uFogDensity * fogdist); + fogfactor = std::exp2(uniforms->uFogDensity * fogdist); } frag = vec4(uFogColor.rgb, (1.0 - fogfactor) * frag.a * 0.75 * vColor.a);*/ } @@ -532,7 +532,7 @@ static void MainFP(int x0, int x1, PolyTriangleThreadData* thread) auto vColorA = thread->scanline.vColorA; uint32_t* fragcolor = thread->scanline.FragColor; - if (constants->uTextureMode == TM_FOGLAYER) + if (uniforms->uTextureMode == TM_FOGLAYER) { // float gray = grayscale(frag); // vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2; diff --git a/src/rendering/vulkan/renderer/vk_renderpass.cpp b/src/rendering/vulkan/renderer/vk_renderpass.cpp index bb62a7a406..4d5a4b4a85 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/rendering/vulkan/renderer/vk_renderpass.cpp @@ -142,7 +142,7 @@ VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(int numLayers) builder.addSetLayout(DynamicSetLayout.get()); if (numLayers != 0) builder.addSetLayout(GetTextureSetLayout(numLayers)); - builder.addPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants)); + builder.addPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, GetVulkanFrameBuffer()->GetRenderState()->GetUniformDataSize(UniformFamily::PushConstant)); layout = builder.create(GetVulkanFrameBuffer()->device); layout->SetDebugName("VkRenderPassManager.PipelineLayout"); return layout.get(); @@ -178,8 +178,8 @@ void VkRenderPassManager::UpdateDynamicSet() WriteDescriptors update; update.addBuffer(DynamicSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms)); update.addBuffer(DynamicSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightBufferSSO->mBuffer.get()); - update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO)); - update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO)); + update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatrixBufferWriter->Buffer()->mBuffer.get(), 0, sizeof(MatricesUBO)); + update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamBufferWriter->Buffer()->mBuffer.get(), 0, fb->StreamBufferWriter->BlockSize()); update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->Shadowmap.View.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); update.updateSets(fb->device); } diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index e1104f9ea3..bfdbdfa024 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -166,9 +166,9 @@ void VkRenderState::Apply(int dt) mApplyCount = 0; } + ApplyRenderPass(dt); ApplyStreamData(); ApplyMatrices(); - ApplyRenderPass(dt); ApplyScissor(); ApplyViewport(); ApplyStencilRef(); @@ -219,7 +219,7 @@ void VkRenderState::ApplyRenderPass(int dt) int effectState = mMaterial.mOverrideShader >= 0 ? mMaterial.mOverrideShader : (mMaterial.mMaterial ? mMaterial.mMaterial->GetShaderIndex() : 0); pipelineKey.SpecialEffect = EFF_NONE; pipelineKey.EffectState = mTextureEnabled ? effectState : SHADER_NoTexture; - pipelineKey.AlphaTest = mAlphaThreshold >= 0.f; + pipelineKey.AlphaTest = GetUniform(UniformName::uAlphaThreshold) >= 0.f; } // Is this the one we already have? @@ -313,17 +313,17 @@ void VkRenderState::ApplyStreamData() auto fb = GetVulkanFrameBuffer(); auto passManager = fb->GetRenderPassManager(); - mStreamData.useVertexData = passManager->GetVertexFormat(static_cast(mVertexBuffer)->VertexFormat)->UseVertexData; + SetUniform(UniformName::useVertexData, passManager->GetVertexFormat(static_cast(mVertexBuffer)->VertexFormat)->UseVertexData); if (mMaterial.mMaterial && mMaterial.mMaterial->tex) - mStreamData.timer = static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->tex->shaderspeed / 1000.); + SetUniform(UniformName::timer, static_cast((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->tex->shaderspeed / 1000.)); else - mStreamData.timer = 0.0f; + SetUniform(UniformName::timer, 0.0f); - if (!mStreamBufferWriter.Write(mStreamData)) + if (!mStreamBufferWriter->Write(GetUniformData(UniformFamily::Normal))) { WaitForStreamBuffers(); - mStreamBufferWriter.Write(mStreamData); + mStreamBufferWriter->Write(GetUniformData(UniformFamily::Normal)); } } @@ -350,32 +350,25 @@ void VkRenderState::ApplyPushConstants() if (mMaterial.mMaterial && mMaterial.mMaterial->tex && mMaterial.mMaterial->tex->isHardwareCanvas()) tempTM = TM_OPAQUE; - mPushConstants.uFogEnabled = fogset; - mPushConstants.uTextureMode = mTextureMode == TM_NORMAL && tempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode; - mPushConstants.uLightDist = mLightParms[0]; - mPushConstants.uLightFactor = mLightParms[1]; - mPushConstants.uFogDensity = mLightParms[2]; - mPushConstants.uLightLevel = mLightParms[3]; - mPushConstants.uAlphaThreshold = mAlphaThreshold; - mPushConstants.uClipSplit = { mClipSplit[0], mClipSplit[1] }; + SetUniform(UniformName::uFogEnabled, fogset); + SetUniform(UniformName::uTextureMode, mTextureMode == TM_NORMAL && tempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode); if (mMaterial.mMaterial && mMaterial.mMaterial->tex) - mPushConstants.uSpecularMaterial = { mMaterial.mMaterial->tex->Glossiness, mMaterial.mMaterial->tex->SpecularLevel }; + SetUniform(UniformName::uSpecularMaterial, FVector2{ mMaterial.mMaterial->tex->Glossiness, mMaterial.mMaterial->tex->SpecularLevel }); - mPushConstants.uLightIndex = mLightIndex; - mPushConstants.uDataIndex = mStreamBufferWriter.DataIndex(); + SetUniform(UniformName::uDataIndex, mStreamBufferWriter->DataIndex()); auto fb = GetVulkanFrameBuffer(); auto passManager = fb->GetRenderPassManager(); - mCommandBuffer->pushConstants(passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants); + mCommandBuffer->pushConstants(passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, GetUniformDataSize(UniformFamily::PushConstant), GetUniformData(UniformFamily::PushConstant)); } void VkRenderState::ApplyMatrices() { - if (!mMatrixBufferWriter.Write(mModelMatrix, mModelMatrixEnabled, mTextureMatrix, mTextureMatrixEnabled)) + if (!mMatrixBufferWriter->Write(mModelMatrix, mModelMatrixEnabled, mTextureMatrix, mTextureMatrixEnabled)) { WaitForStreamBuffers(); - mMatrixBufferWriter.Write(mModelMatrix, mModelMatrixEnabled, mTextureMatrix, mTextureMatrixEnabled); + mMatrixBufferWriter->Write(mModelMatrix, mModelMatrixEnabled, mTextureMatrix, mTextureMatrixEnabled); } } @@ -419,8 +412,8 @@ void VkRenderState::ApplyMaterial() void VkRenderState::ApplyDynamicSet() { auto fb = GetVulkanFrameBuffer(); - uint32_t matrixOffset = mMatrixBufferWriter.Offset(); - uint32_t streamDataOffset = mStreamBufferWriter.StreamDataOffset(); + uint32_t matrixOffset = mMatrixBufferWriter->Offset(); + uint32_t streamDataOffset = mStreamBufferWriter->StreamDataOffset(); if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || streamDataOffset != mLastStreamDataOffset) { auto passManager = fb->GetRenderPassManager(); @@ -438,8 +431,8 @@ void VkRenderState::WaitForStreamBuffers() { GetVulkanFrameBuffer()->WaitForCommands(false); mApplyCount = 0; - mStreamBufferWriter.Reset(); - mMatrixBufferWriter.Reset(); + mStreamBufferWriter->Reset(); + mMatrixBufferWriter->Reset(); } void VkRenderState::Bind(int bindingpoint, uint32_t offset) @@ -475,8 +468,8 @@ void VkRenderState::EndRenderPass() void VkRenderState::EndFrame() { - mMatrixBufferWriter.Reset(); - mStreamBufferWriter.Reset(); + mMatrixBufferWriter->Reset(); + mStreamBufferWriter->Reset(); } void VkRenderState::EnableDrawBuffers(int count) @@ -548,6 +541,9 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer) mMaterial.mChanged = true; mClearTargets = 0; + + mStreamBufferWriter = fb->StreamBufferWriter; + mMatrixBufferWriter = fb->MatrixBufferWriter; } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/rendering/vulkan/renderer/vk_renderstate.h b/src/rendering/vulkan/renderer/vk_renderstate.h index 73c777eb08..c876c56ec4 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.h +++ b/src/rendering/vulkan/renderer/vk_renderstate.h @@ -91,15 +91,13 @@ protected: int mColorMask = 15; int mCullMode = 0; - PushConstants mPushConstants = {}; - uint32_t mLastViewpointOffset = 0xffffffff; uint32_t mLastMatricesOffset = 0xffffffff; uint32_t mLastStreamDataOffset = 0xffffffff; uint32_t mViewpointOffset = 0; - VkStreamBufferWriter mStreamBufferWriter; - VkMatrixBufferWriter mMatrixBufferWriter; + VkStreamBufferWriter *mStreamBufferWriter = nullptr; + VkMatrixBufferWriter *mMatrixBufferWriter = nullptr; int mLastVertexOffsets[2] = { 0, 0 }; IVertexBuffer *mLastVertexBuffer = nullptr; diff --git a/src/rendering/vulkan/renderer/vk_streambuffer.cpp b/src/rendering/vulkan/renderer/vk_streambuffer.cpp index 39275fdb1a..6b62be1983 100644 --- a/src/rendering/vulkan/renderer/vk_streambuffer.cpp +++ b/src/rendering/vulkan/renderer/vk_streambuffer.cpp @@ -32,13 +32,22 @@ uint32_t VkStreamBuffer::NextStreamDataBlock() VkStreamBufferWriter::VkStreamBufferWriter() { - mBuffer = GetVulkanFrameBuffer()->StreamBuffer; + mStreamDataSize = GetVulkanFrameBuffer()->GetRenderState()->GetUniformDataSize(UniformFamily::Normal); + mMaxStreamData = 65536 / mStreamDataSize; + mBuffer = new VkStreamBuffer(mStreamDataSize * mMaxStreamData, 300); + mDataIndex = mMaxStreamData - 1; + mStreamDataOffset = 0; } -bool VkStreamBufferWriter::Write(const StreamData& data) +VkStreamBufferWriter::~VkStreamBufferWriter() +{ + delete mBuffer; +} + +bool VkStreamBufferWriter::Write(const void* data) { mDataIndex++; - if (mDataIndex == MAX_STREAM_DATA) + if (mDataIndex == mMaxStreamData) { mDataIndex = 0; mStreamDataOffset = mBuffer->NextStreamDataBlock(); @@ -46,13 +55,13 @@ bool VkStreamBufferWriter::Write(const StreamData& data) return false; } uint8_t* ptr = (uint8_t*)mBuffer->UniformBuffer->Memory(); - memcpy(ptr + mStreamDataOffset + sizeof(StreamData) * mDataIndex, &data, sizeof(StreamData)); + memcpy(ptr + mStreamDataOffset + mStreamDataSize * mDataIndex, data, mStreamDataSize); return true; } void VkStreamBufferWriter::Reset() { - mDataIndex = MAX_STREAM_DATA - 1; + mDataIndex = mMaxStreamData - 1; mStreamDataOffset = 0; mBuffer->Reset(); } @@ -61,10 +70,16 @@ void VkStreamBufferWriter::Reset() VkMatrixBufferWriter::VkMatrixBufferWriter() { - mBuffer = GetVulkanFrameBuffer()->MatrixBuffer; + auto fb = GetVulkanFrameBuffer(); + mBuffer = new VkStreamBuffer(sizeof(MatricesUBO), 50000); mIdentityMatrix.loadIdentity(); } +VkMatrixBufferWriter::~VkMatrixBufferWriter() +{ + delete mBuffer; +} + template static void BufferedSet(bool& modified, T& dst, const T& src) { diff --git a/src/rendering/vulkan/renderer/vk_streambuffer.h b/src/rendering/vulkan/renderer/vk_streambuffer.h index 21c15867a2..36af9819c0 100644 --- a/src/rendering/vulkan/renderer/vk_streambuffer.h +++ b/src/rendering/vulkan/renderer/vk_streambuffer.h @@ -4,42 +4,7 @@ #include "vulkan/system/vk_buffers.h" #include "vulkan/shaders/vk_shader.h" -class VkStreamBuffer; -class VkMatrixBuffer; - -class VkStreamBufferWriter -{ -public: - VkStreamBufferWriter(); - - bool Write(const StreamData& data); - void Reset(); - - uint32_t DataIndex() const { return mDataIndex; } - uint32_t StreamDataOffset() const { return mStreamDataOffset; } - -private: - VkStreamBuffer* mBuffer; - uint32_t mDataIndex = MAX_STREAM_DATA - 1; - uint32_t mStreamDataOffset = 0; -}; - -class VkMatrixBufferWriter -{ -public: - VkMatrixBufferWriter(); - - bool Write(const VSMatrix& modelMatrix, bool modelMatrixEnabled, const VSMatrix& textureMatrix, bool textureMatrixEnabled); - void Reset(); - - uint32_t Offset() const { return mOffset; } - -private: - VkStreamBuffer* mBuffer; - MatricesUBO mMatrices = {}; - VSMatrix mIdentityMatrix; - uint32_t mOffset = 0; -}; +class VKDataBuffer; class VkStreamBuffer { @@ -51,8 +16,50 @@ public: void Reset() { mStreamDataOffset = 0; } VKDataBuffer* UniformBuffer = nullptr; + uint32_t mBlockSize = 0; private: - uint32_t mBlockSize = 0; uint32_t mStreamDataOffset = 0; }; + +class VkStreamBufferWriter +{ +public: + VkStreamBufferWriter(); + ~VkStreamBufferWriter(); + + bool Write(const void* data); + void Reset(); + + uint32_t DataIndex() const { return mDataIndex; } + uint32_t StreamDataOffset() const { return mStreamDataOffset; } + VKDataBuffer* Buffer() const { return mBuffer->UniformBuffer; } + uint32_t BlockSize() const { return mBuffer->mBlockSize; } + uint32_t MaxStreamData() const { return mMaxStreamData; } + +private: + VkStreamBuffer* mBuffer; + uint32_t mStreamDataSize; + uint32_t mMaxStreamData; + uint32_t mDataIndex; + uint32_t mStreamDataOffset; +}; + +class VkMatrixBufferWriter +{ +public: + VkMatrixBufferWriter(); + ~VkMatrixBufferWriter(); + + bool Write(const VSMatrix& modelMatrix, bool modelMatrixEnabled, const VSMatrix& textureMatrix, bool textureMatrixEnabled); + void Reset(); + + uint32_t Offset() const { return mOffset; } + VKDataBuffer* Buffer() const { return mBuffer->UniformBuffer; } + +private: + VkStreamBuffer* mBuffer; + MatricesUBO mMatrices = {}; + VSMatrix mIdentityMatrix; + uint32_t mOffset = 0; +}; diff --git a/src/rendering/vulkan/shaders/vk_shader.cpp b/src/rendering/vulkan/shaders/vk_shader.cpp index 9ab5a91e65..f63d9befd5 100644 --- a/src/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/rendering/vulkan/shaders/vk_shader.cpp @@ -2,6 +2,9 @@ #include "vk_shader.h" #include "vulkan/system/vk_builders.h" #include "hwrenderer/utility/hw_shaderpatcher.h" +#include "rendering/vulkan/system/vk_framebuffer.h" +#include "rendering/vulkan/renderer/vk_streambuffer.h" +#include "rendering/vulkan/renderer/vk_renderstate.h" #include "w_wad.h" #include "doomerrors.h" #include @@ -112,39 +115,6 @@ static const char *shaderBindings = R"( mat4 TextureMatrix; }; - struct StreamData - { - vec4 uObjectColor; - vec4 uObjectColor2; - vec4 uDynLightColor; - vec4 uAddColor; - vec4 uTextureAddColor; - vec4 uTextureModulateColor; - vec4 uTextureBlendColor; - vec4 uFogColor; - float uDesaturationFactor; - float uInterpolationFactor; - float timer; // timer data for material shaders - int useVertexData; - vec4 uVertexColor; - vec4 uVertexNormal; - - vec4 uGlowTopPlane; - vec4 uGlowTopColor; - vec4 uGlowBottomPlane; - vec4 uGlowBottomColor; - - vec4 uGradientTopPlane; - vec4 uGradientBottomPlane; - - vec4 uSplitTopPlane; - vec4 uSplitBottomPlane; - }; - - layout(set = 0, binding = 3, std140) uniform StreamUBO { - StreamData data[MAX_STREAM_DATA]; - }; - layout(set = 0, binding = 4) uniform sampler2D ShadowMap; // textures @@ -155,30 +125,6 @@ static const char *shaderBindings = R"( layout(set = 1, binding = 4) uniform sampler2D texture5; layout(set = 1, binding = 5) uniform sampler2D texture6; - // This must match the PushConstants struct - layout(push_constant) uniform PushConstants - { - int uTextureMode; - float uAlphaThreshold; - vec2 uClipSplit; - - // Lighting + Fog - float uLightLevel; - float uFogDensity; - float uLightFactor; - float uLightDist; - int uFogEnabled; - - // dynamic lights - int uLightIndex; - - // Blinn glossiness and specular level - vec2 uSpecularMaterial; - - int uDataIndex; - int padding1, padding2, padding3; - }; - // material types #if defined(SPECULAR) #define normaltexture texture2 @@ -194,29 +140,6 @@ static const char *shaderBindings = R"( #define brighttexture texture2 #endif - #define uObjectColor data[uDataIndex].uObjectColor - #define uObjectColor2 data[uDataIndex].uObjectColor2 - #define uDynLightColor data[uDataIndex].uDynLightColor - #define uAddColor data[uDataIndex].uAddColor - #define uTextureBlendColor data[uDataIndex].uTextureBlendColor - #define uTextureModulateColor data[uDataIndex].uTextureModulateColor - #define uTextureAddColor data[uDataIndex].uTextureAddColor - #define uFogColor data[uDataIndex].uFogColor - #define uDesaturationFactor data[uDataIndex].uDesaturationFactor - #define uInterpolationFactor data[uDataIndex].uInterpolationFactor - #define timer data[uDataIndex].timer - #define useVertexData data[uDataIndex].useVertexData - #define uVertexColor data[uDataIndex].uVertexColor - #define uVertexNormal data[uDataIndex].uVertexNormal - #define uGlowTopPlane data[uDataIndex].uGlowTopPlane - #define uGlowTopColor data[uDataIndex].uGlowTopColor - #define uGlowBottomPlane data[uDataIndex].uGlowBottomPlane - #define uGlowBottomColor data[uDataIndex].uGlowBottomColor - #define uGradientTopPlane data[uDataIndex].uGradientTopPlane - #define uGradientBottomPlane data[uDataIndex].uGradientBottomPlane - #define uSplitTopPlane data[uDataIndex].uSplitTopPlane - #define uSplitBottomPlane data[uDataIndex].uSplitBottomPlane - #define SUPPORTS_SHADOWMAPS #define VULKAN_COORDINATE_SYSTEM #define HAS_UNIFORM_VERTEX_DATA @@ -233,13 +156,74 @@ static const char *shaderBindings = R"( vec4 noise4(vec4) { return vec4(0); } )"; +static void AppendStructMembers(FString& code, UniformFamily family) +{ + int index = 0; + for (const auto& info : GetVulkanFrameBuffer()->GetRenderState()->GetUniformInfo()) + { + if (info.Name.empty()) + I_FatalError("Missing uniform declaration for index %d", index); + index++; + + if (info.Family == family) + { + static const char* glsltype[] = { "int", "uint", "float", "vec2", "vec3", "vec4", "ivec2", "ivec3", "ivec4", "uvec2", "uvec3", "uvec4", "mat4" }; + code.AppendFormat("\t%s %s;\n", glsltype[(int)info.Type], info.Name.c_str()); + } + } +} + +static void AppendStructDefines(FString& code, UniformFamily family) +{ + // Generate defines so the shader code can still access the uniforms as if they weren't part of the block: + for (const auto& info : GetVulkanFrameBuffer()->GetRenderState()->GetUniformInfo()) + { + if (info.Family == family) + { + code.AppendFormat("#define %s data[uDataIndex].%s\n", info.Name.c_str(), info.Name.c_str()); + } + } +} + +static FString GetUniformBindings() +{ + FString code; + + // Uniform struct: + + code << "struct StreamData\n"; + code << "{\n"; + AppendStructMembers(code, UniformFamily::Normal); + code << "};\n\n"; + + // Generate uniform block that holds multiple uniform structs: + + code << "layout(set = 0, binding = 3, std140) uniform StreamUBO {\n"; + code.AppendFormat("\tStreamData data[%d];\n", GetVulkanFrameBuffer()->StreamBufferWriter->MaxStreamData()); + code << "};\n\n"; + + AppendStructDefines(code, UniformFamily::Normal); + + // Generate push constants struct: + + code << "layout(push_constant) uniform PushConstants\n"; + code << "{\n"; + AppendStructMembers(code, UniformFamily::PushConstant); + code << "};\n\n"; + + return code; +} + std::unique_ptr VkShaderManager::LoadVertShader(FString shadername, const char *vert_lump, const char *defines) { FString code = GetTargetGlslVersion(); + code << defines; - code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n"; - code << shaderBindings; if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n"; + + code << shaderBindings; + code << GetUniformBindings().GetChars(); + code << "#line 1\n"; code << LoadPrivateShaderLump(vert_lump).GetChars() << "\n"; @@ -251,14 +235,15 @@ std::unique_ptr VkShaderManager::LoadVertShader(FString shadername std::unique_ptr VkShaderManager::LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char *light_lump, const char *defines, bool alphatest, bool gbufferpass) { FString code = GetTargetGlslVersion(); - code << defines; - code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n"; - code << shaderBindings; + code << defines; if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n"; if (!alphatest) code << "#define NO_ALPHATEST\n"; if (gbufferpass) code << "#define GBUFFER_PASS\n"; + code << shaderBindings; + code << GetUniformBindings().GetChars(); + code << "\n#line 1\n"; code << LoadPrivateShaderLump(frag_lump).GetChars() << "\n"; diff --git a/src/rendering/vulkan/shaders/vk_shader.h b/src/rendering/vulkan/shaders/vk_shader.h index c170e5a774..59e078b38d 100644 --- a/src/rendering/vulkan/shaders/vk_shader.h +++ b/src/rendering/vulkan/shaders/vk_shader.h @@ -18,36 +18,6 @@ struct MatricesUBO VSMatrix TextureMatrix; }; -#define MAX_STREAM_DATA ((int)(65536 / sizeof(StreamData))) - -struct StreamUBO -{ - StreamData data[MAX_STREAM_DATA]; -}; - -struct PushConstants -{ - int uTextureMode; - float uAlphaThreshold; - FVector2 uClipSplit; - - // Lighting + Fog - float uLightLevel; - float uFogDensity; - float uLightFactor; - float uLightDist; - int uFogEnabled; - - // dynamic lights - int uLightIndex; - - // Blinn glossiness and specular level - FVector2 uSpecularMaterial; - - int uDataIndex; - int padding1, padding2, padding3; -}; - class VkShaderProgram { public: diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 80532538ca..ffa58d7d36 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -109,8 +109,8 @@ VulkanFrameBuffer::~VulkanFrameBuffer() VKBuffer::ResetAll(); PPResource::ResetAll(); - delete MatrixBuffer; - delete StreamBuffer; + delete MatrixBufferWriter; + delete StreamBufferWriter; delete mVertexData; delete mSkyData; delete mViewpoints; @@ -161,19 +161,19 @@ void VulkanFrameBuffer::InitializeState() CreateFanToTrisIndexBuffer(); - // To do: move this to HW renderer interface maybe? - MatrixBuffer = new VkStreamBuffer(sizeof(MatricesUBO), 50000); - StreamBuffer = new VkStreamBuffer(sizeof(StreamUBO), 300); - - mShaderManager.reset(new VkShaderManager(device)); - mSamplerManager.reset(new VkSamplerManager(device)); - mRenderPassManager->Init(); #ifdef __APPLE__ mRenderState.reset(new VkRenderStateMolten()); #else mRenderState.reset(new VkRenderState()); #endif + StreamBufferWriter = new VkStreamBufferWriter(); + MatrixBufferWriter = new VkMatrixBufferWriter(); + + mShaderManager.reset(new VkShaderManager(device)); + mSamplerManager.reset(new VkSamplerManager(device)); + mRenderPassManager->Init(); + if (device->graphicsTimeQueries) { QueryPoolBuilder querybuilder; diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index 64dfa3e7bd..051da5b5dd 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -14,6 +14,8 @@ class VKDataBuffer; class VkHardwareTexture; class VkRenderBuffers; class VkPostprocess; +class VkStreamBufferWriter; +class VkMatrixBufferWriter; class SWSceneDrawer; class VulkanFrameBuffer : public SystemBaseFrameBuffer @@ -42,8 +44,8 @@ public: VKDataBuffer *ViewpointUBO = nullptr; VKDataBuffer *LightBufferSSO = nullptr; - VkStreamBuffer *MatrixBuffer = nullptr; - VkStreamBuffer *StreamBuffer = nullptr; + VkStreamBufferWriter *StreamBufferWriter = nullptr; + VkMatrixBufferWriter *MatrixBufferWriter = nullptr; VKDataBuffer *LightNodes = nullptr; VKDataBuffer *LightLines = nullptr;