From d23c7273508956da9bed4b9cd09c3a21551a0cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 7 Jan 2025 16:25:24 -0300 Subject: [PATCH] refactor custom uniforms in preparation for custom material uniforms --- .../postprocessing/hw_postprocess.cpp | 195 +++++++++------- .../postprocessing/hw_postprocess.h | 106 ++------- .../postprocessing/hw_postprocessshader.cpp | 172 +++++++++++--- .../postprocessing/hw_postprocessshader.h | 19 +- .../hw_postprocessshader_ccmds.cpp | 74 ++++-- .../postprocessing/hw_useruniforms.h | 149 ++++++++++++ .../rendering/vulkan/vk_postprocess.cpp | 3 +- .../rendering/vulkan/vk_pprenderstate.cpp | 4 +- src/common/textures/textures.h | 6 + src/r_data/gldefs.cpp | 216 +++++++++++++----- 10 files changed, 657 insertions(+), 287 deletions(-) create mode 100644 src/common/rendering/hwrenderer/postprocessing/hw_useruniforms.h diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp index 691a72ae3..892d308f7 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp @@ -96,13 +96,14 @@ void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneH // Extract blooming pixels from scene texture: renderstate->Clear(); renderstate->Shader = &BloomExtract; - renderstate->Uniforms.Set(extractUniforms); + renderstate->Uniforms.Set(&extractUniforms); renderstate->Viewport = level0.Viewport; renderstate->SetInputCurrent(0, PPFilterMode::Linear); renderstate->SetInputTexture(1, &hw_postprocess.exposure.CameraTexture); renderstate->SetOutputTexture(&level0.VTexture); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); const float blurAmount = gl_bloom_amount; BlurUniforms blurUniforms; @@ -120,7 +121,6 @@ void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneH // Linear downscale: renderstate->Clear(); renderstate->Shader = &BloomCombine; - renderstate->Uniforms.Clear(); renderstate->Viewport = next.Viewport; renderstate->SetInputTexture(0, &blevel.VTexture, PPFilterMode::Linear); renderstate->SetOutputTexture(&next.VTexture); @@ -140,7 +140,6 @@ void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneH // Linear upscale: renderstate->Clear(); renderstate->Shader = &BloomCombine; - renderstate->Uniforms.Clear(); renderstate->Viewport = next.Viewport; renderstate->SetInputTexture(0, &blevel.VTexture, PPFilterMode::Linear); renderstate->SetOutputTexture(&next.VTexture); @@ -154,7 +153,6 @@ void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneH // Add bloom back to scene texture: renderstate->Clear(); renderstate->Shader = &BloomCombine; - renderstate->Uniforms.Clear(); renderstate->Viewport = screen->mSceneViewport; renderstate->SetInputTexture(0, &level0.VTexture, PPFilterMode::Linear); renderstate->SetOutputCurrent(); @@ -265,12 +263,13 @@ void PPBloom::BlurStep(PPRenderState *renderstate, const BlurUniforms &blurUnifo { renderstate->Clear(); renderstate->Shader = vertical ? &BlurVertical : &BlurHorizontal; - renderstate->Uniforms.Set(blurUniforms); + renderstate->Uniforms.Set(&blurUniforms); renderstate->Viewport = viewport; renderstate->SetInputTexture(0, &input); renderstate->SetOutputTexture(&output); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); } float PPBloom::ComputeBlurGaussian(float n, float theta) // theta = Blur Amount @@ -344,12 +343,13 @@ void PPLensDistort::Render(PPRenderState *renderstate) renderstate->Clear(); renderstate->Shader = &Lens; - renderstate->Uniforms.Set(uniforms); + renderstate->Uniforms.Set(&uniforms); renderstate->Viewport = screen->mScreenViewport; renderstate->SetInputCurrent(0, PPFilterMode::Linear); renderstate->SetOutputNext(); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); renderstate->PopGroup(); } @@ -380,9 +380,10 @@ void PPFXAA::Render(PPRenderState *renderstate) renderstate->Draw(); renderstate->Shader = &FXAA; - renderstate->Uniforms.Set(uniforms); + renderstate->Uniforms.Set(&uniforms); renderstate->SetInputCurrent(0, PPFilterMode::Linear); renderstate->Draw(); + renderstate->Uniforms.Clear(); renderstate->PopGroup(); } @@ -457,12 +458,13 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc // Extract light blevel from scene texture: renderstate->Clear(); renderstate->Shader = &ExposureExtract; - renderstate->Uniforms.Set(extractUniforms); + renderstate->Uniforms.Set(&extractUniforms); renderstate->Viewport = level0.Viewport; renderstate->SetInputCurrent(0, PPFilterMode::Linear); renderstate->SetOutputTexture(&level0.Texture); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); // Find the average value: for (size_t i = 0; i + 1 < ExposureLevels.size(); i++) @@ -471,7 +473,6 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc auto &next = ExposureLevels[i + 1]; renderstate->Shader = &ExposureAverage; - renderstate->Uniforms.Clear(); renderstate->Viewport = next.Viewport; renderstate->SetInputTexture(0, &blevel.Texture, PPFilterMode::Linear); renderstate->SetOutputTexture(&next.Texture); @@ -481,7 +482,7 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc // Combine average value with current camera exposure: renderstate->Shader = &ExposureCombine; - renderstate->Uniforms.Set(combineUniforms); + renderstate->Uniforms.Set(&combineUniforms); renderstate->Viewport.left = 0; renderstate->Viewport.top = 0; renderstate->Viewport.width = 1; @@ -493,6 +494,7 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc else renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); renderstate->PopGroup(); @@ -559,12 +561,13 @@ void PPColormap::Render(PPRenderState *renderstate, int fixedcm, float flash) renderstate->Clear(); renderstate->Shader = &Colormap; - renderstate->Uniforms.Set(uniforms); + renderstate->Uniforms.Set(&uniforms); renderstate->Viewport = screen->mScreenViewport; renderstate->SetInputCurrent(0); renderstate->SetOutputNext(); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); renderstate->PopGroup(); } @@ -664,13 +667,14 @@ void PPLinearDepth::Render(PPRenderState* renderstate, int sceneWidth, int scene // Calculate linear depth values renderstate->Clear(); renderstate->Shader = gl_multisample > 1 ? &LinearDepthMS : &LinearDepth; - renderstate->Uniforms.Set(linearUniforms); + renderstate->Uniforms.Set(&linearUniforms); renderstate->Viewport = viewport; renderstate->SetInputSceneDepth(0); renderstate->SetInputSceneColor(1); renderstate->SetOutputSceneLinearDepth(); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); renderstate->PopGroup(); } @@ -818,7 +822,7 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW // Apply ambient occlusion renderstate->Clear(); renderstate->Shader = gl_multisample > 1 ? &AmbientOccludeMS : &AmbientOcclude; - renderstate->Uniforms.Set(ssaoUniforms); + renderstate->Uniforms.Set(&ssaoUniforms); renderstate->Viewport = ambientViewport; renderstate->SetInputSceneLinearDepth(0); renderstate->SetInputSceneNormal(1); @@ -826,33 +830,36 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW renderstate->SetOutputTexture(&Ambient0); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); // Blur SSAO texture if (gl_ssao_debug < 2 && !gl_shownormals) { renderstate->Clear(); renderstate->Shader = &BlurHorizontal; - renderstate->Uniforms.Set(blurUniforms); + renderstate->Uniforms.Set(&blurUniforms); renderstate->Viewport = ambientViewport; renderstate->SetInputTexture(0, &Ambient0); renderstate->SetOutputTexture(&Ambient1); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); renderstate->Clear(); renderstate->Shader = &BlurVertical; - renderstate->Uniforms.Set(blurUniforms); + renderstate->Uniforms.Set(&blurUniforms); renderstate->Viewport = ambientViewport; renderstate->SetInputTexture(0, &Ambient1); renderstate->SetOutputTexture(&Ambient0); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); } // Add SSAO back to scene texture: renderstate->Clear(); renderstate->Shader = gl_multisample > 1 ? &CombineMS : &Combine; - renderstate->Uniforms.Set(combineUniforms); + renderstate->Uniforms.Set(&combineUniforms); renderstate->Viewport = screen->mSceneViewport; renderstate->SetInputTexture(0, &Ambient0, PPFilterMode::Linear); if (gl_ssao_debug < 4 && !gl_shownormals) @@ -865,6 +872,7 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW else renderstate->SetAlphaBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); renderstate->PopGroup(); } @@ -903,12 +911,13 @@ void PPShadowMap::Update(PPRenderState* renderstate) renderstate->Clear(); renderstate->Shader = &ShadowMap; - renderstate->Uniforms.Set(uniforms); + renderstate->Uniforms.Set(&uniforms); renderstate->Viewport = { 0, 0, gl_shadowmap_quality, 1024 }; renderstate->SetShadowMapBuffers(true); renderstate->SetOutputShadowMap(); renderstate->SetNoBlend(); renderstate->Draw(); + renderstate->Uniforms.Clear(); renderstate->PopGroup(); } @@ -948,11 +957,13 @@ void PPCustomShaders::CreateShaders() ///////////////////////////////////////////////////////////////////////////// -PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(desc) +void UserUniforms::LoadUniforms(const TMap &Uniforms) { + assert(UniformStructSize == 0); + // Build an uniform block to be used as input - TMap::Iterator it(Desc->Uniforms); - TMap::Pair *pair; + TMap::ConstIterator it(Uniforms); + TMap::ConstPair *pair; size_t offset = 0; while (it.NextPair(pair)) { @@ -961,16 +972,21 @@ PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(d switch (pair->Value.Type) { - case PostProcessUniformType::Float: AddUniformField(offset, name, UniformType::Float, sizeof(float)); break; - case PostProcessUniformType::Int: AddUniformField(offset, name, UniformType::Int, sizeof(int)); break; - case PostProcessUniformType::Vec2: AddUniformField(offset, name, UniformType::Vec2, sizeof(float) * 2); break; - case PostProcessUniformType::Vec3: AddUniformField(offset, name, UniformType::Vec3, sizeof(float) * 3, sizeof(float) * 4); break; - case PostProcessUniformType::Vec4: AddUniformField(offset, name, UniformType::Vec4, sizeof(float) * 4); break; + case UniformType::Float: AddUniformField(offset, name, UniformType::Float, sizeof(float)); break; + case UniformType::Int: AddUniformField(offset, name, UniformType::Int, sizeof(int)); break; + case UniformType::Vec2: AddUniformField(offset, name, UniformType::Vec2, sizeof(float) * 2); break; + case UniformType::Vec3: AddUniformField(offset, name, UniformType::Vec3, sizeof(float) * 3, sizeof(float) * 4); break; + case UniformType::Vec4: AddUniformField(offset, name, UniformType::Vec4, sizeof(float) * 4); break; default: break; } } - UniformStructSize = ((int)offset + 15) / 16 * 16; + UniformStructSize = ((int)offset + 15) / 16 * 16; + BuildStruct(Uniforms); +} + +PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(desc) +{ // Build the input textures FString uniformTextures; uniformTextures += "layout(binding=0) uniform sampler2D InputTexture;\n"; @@ -1000,7 +1016,7 @@ PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(d prolog += uniformTextures; prolog += pipelineInOut; - Shader = PPShader(Desc->ShaderLumpName, prolog, Fields); + Shader = PPShader(Desc->ShaderLumpName, prolog, Desc->Uniforms.Fields); } void PPCustomShaderInstance::Run(PPRenderState *renderstate) @@ -1070,75 +1086,82 @@ void PPCustomShaderInstance::SetTextures(PPRenderState *renderstate) void PPCustomShaderInstance::SetUniforms(PPRenderState *renderstate) { - TArray uniforms; - uniforms.Resize(UniformStructSize); - - TMap::Iterator it(Desc->Uniforms); - TMap::Pair *pair; - while (it.NextPair(pair)) - { - auto it2 = FieldOffset.find(pair->Key); - if (it2 != FieldOffset.end()) - { - uint8_t *dst = &uniforms[it2->second]; - float fValues[4]; - int iValues[4]; - switch (pair->Value.Type) - { - case PostProcessUniformType::Float: - fValues[0] = (float)pair->Value.Values[0]; - memcpy(dst, fValues, sizeof(float)); - break; - case PostProcessUniformType::Int: - iValues[0] = (int)pair->Value.Values[0]; - memcpy(dst, iValues, sizeof(int)); - break; - case PostProcessUniformType::Vec2: - fValues[0] = (float)pair->Value.Values[0]; - fValues[1] = (float)pair->Value.Values[1]; - memcpy(dst, fValues, sizeof(float) * 2); - break; - case PostProcessUniformType::Vec3: - fValues[0] = (float)pair->Value.Values[0]; - fValues[1] = (float)pair->Value.Values[1]; - fValues[2] = (float)pair->Value.Values[2]; - memcpy(dst, fValues, sizeof(float) * 3); - break; - case PostProcessUniformType::Vec4: - fValues[0] = (float)pair->Value.Values[0]; - fValues[1] = (float)pair->Value.Values[1]; - fValues[2] = (float)pair->Value.Values[2]; - fValues[3] = (float)pair->Value.Values[3]; - memcpy(dst, fValues, sizeof(float) * 4); - break; - default: - break; - } - } - } - - renderstate->Uniforms.Data = uniforms; + Desc->Uniforms.WriteUniforms(renderstate->Uniforms); } -void PPCustomShaderInstance::AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment) +void UserUniforms::BuildStruct(const TMap &Uniforms) +{ + if(UniformStruct) delete[] UniformStruct; + + UniformStruct = new uint8_t[UniformStructSize]; + + for(UniformFieldDesc &field : Fields) + { + uint8_t *dst = &UniformStruct[field.Offset]; + float *fValues = reinterpret_cast(dst); + int *iValues = reinterpret_cast(dst); + + const UserUniformValue &val = Uniforms[field.Name]; + + switch (field.Type) + { + case UniformType::Float: + fValues[0] = (float)val.Values[0]; + break; + case UniformType::Int: + iValues[0] = (int)val.Values[0]; + break; + case UniformType::Vec2: + fValues[0] = (float)val.Values[0]; + fValues[1] = (float)val.Values[1]; + break; + case UniformType::Vec3: + fValues[0] = (float)val.Values[0]; + fValues[1] = (float)val.Values[1]; + fValues[2] = (float)val.Values[2]; + break; + case UniformType::Vec4: + fValues[0] = (float)val.Values[0]; + fValues[1] = (float)val.Values[1]; + fValues[2] = (float)val.Values[2]; + fValues[3] = (float)val.Values[3]; + break; + default: + break; + } + } +} + +UniformField UserUniforms::GetField(const FString &name) +{ + size_t *index = FieldNames.CheckKey(name); + if(!index || !UniformStruct) return {}; + + auto &field = Fields[*index]; + + return {field.Type, UniformStruct + field.Offset}; +} + +void UserUniforms::WriteUniforms(UniformStructHolder &Uniforms) +{ + Uniforms.Clear(); + Uniforms.addr = UniformStruct; + Uniforms.sz = UniformStructSize; +} + +void UserUniforms::AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment) { if (alignment == 0) alignment = fieldsize; offset = (offset + alignment - 1) / alignment * alignment; - FieldOffset[name] = offset; - - auto name2 = std::make_unique(name); - auto chars = name2->GetChars(); - FieldNames.push_back(std::move(name2)); - Fields.push_back({ chars, type, offset }); + FieldNames.Insert(name, Fields.size()); + Fields.push_back({ name, type, offset }); offset += fieldsize; if (fieldsize != alignment) // Workaround for buggy OpenGL drivers that does not do std140 layout correctly for vec3 { - name2 = std::make_unique(name + "_F39350FF12DE_padding"); - chars = name2->GetChars(); - FieldNames.push_back(std::move(name2)); - Fields.push_back({ chars, UniformType::Float, offset }); + FString name2 = name + "_F39350FF12DE_padding"; + Fields.push_back({ name2, UniformType::Float, offset }); offset += alignment - fieldsize; } } diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h index cd08fa45a..191bdc7be 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.h @@ -9,6 +9,8 @@ #include "vectors.h" #include +#include "hw_useruniforms.h" + struct PostProcessShader; typedef FRenderStyle PPBlendMode; @@ -29,34 +31,6 @@ enum class ETonemapMode : uint8_t NumTonemapModes }; -enum class UniformType -{ - Int, - UInt, - Float, - Vec2, - Vec3, - Vec4, - IVec2, - IVec3, - IVec4, - UVec2, - UVec3, - UVec4, - Mat4 -}; - -class UniformFieldDesc -{ -public: - UniformFieldDesc() = default; - UniformFieldDesc(const char* name, UniformType type, std::size_t offset) : Name(name), Type(type), Offset(offset) { } - - const char* Name; - UniformType Type; - std::size_t Offset; -}; - enum class PPFilterMode { Nearest, Linear }; enum class PPWrapMode { Clamp, Repeat }; @@ -78,47 +52,6 @@ public: PPTexture *Texture = nullptr; }; -class PPUniforms -{ -public: - PPUniforms() - { - } - - PPUniforms(const PPUniforms &src) - { - Data = src.Data; - } - - ~PPUniforms() - { - Clear(); - } - - PPUniforms &operator=(const PPUniforms &src) - { - Data = src.Data; - return *this; - } - - void Clear() - { - Data.Clear(); - } - - template - void Set(const T &v) - { - if (Data.Size() != (int)sizeof(T)) - { - Data.Resize(sizeof(T)); - memcpy(Data.Data(), &v, Data.Size()); - } - } - - TArray Data; -}; - class PPRenderState { public: @@ -133,7 +66,7 @@ public: { Shader = nullptr; Textures = TArray(); - Uniforms = PPUniforms(); + Uniforms.Clear(); Viewport = PPViewport(); BlendMode = PPBlendMode(); Output = PPOutput(); @@ -265,7 +198,7 @@ public: PPShader *Shader; TArray Textures; - PPUniforms Uniforms; + UniformStructHolder Uniforms; PPViewport Viewport; PPBlendMode BlendMode; PPOutput Output; @@ -371,7 +304,7 @@ public: ///////////////////////////////////////////////////////////////////////////// -struct ExtractUniforms +struct alignas(32) ExtractUniforms { FVector2 Scale; FVector2 Offset; @@ -386,7 +319,7 @@ struct ExtractUniforms } }; -struct BlurUniforms +struct alignas(32) BlurUniforms { float SampleWeights[8]; @@ -441,7 +374,7 @@ private: ///////////////////////////////////////////////////////////////////////////// -struct LensUniforms +struct alignas(32) LensUniforms { float AspectRatio; float Scale; @@ -474,7 +407,7 @@ private: ///////////////////////////////////////////////////////////////////////////// -struct FXAAUniforms +struct alignas(32) FXAAUniforms { FVector2 ReciprocalResolution; float Padding0, Padding1; @@ -507,7 +440,7 @@ private: ///////////////////////////////////////////////////////////////////////////// -struct ExposureExtractUniforms +struct alignas(32) ExposureExtractUniforms { FVector2 Scale; FVector2 Offset; @@ -522,7 +455,7 @@ struct ExposureExtractUniforms } }; -struct ExposureCombineUniforms +struct alignas(32) ExposureCombineUniforms { float ExposureBase; float ExposureMin; @@ -568,7 +501,7 @@ private: ///////////////////////////////////////////////////////////////////////////// -struct ColormapUniforms +struct alignas(32) ColormapUniforms { FVector4 MapStart; FVector4 MapRange; @@ -616,7 +549,7 @@ private: ///////////////////////////////////////////////////////////////////////////// -struct LinearDepthUniforms +struct alignas(32) LinearDepthUniforms { int SampleIndex; float LinearizeDepthA; @@ -657,7 +590,7 @@ private: ///////////////////////////////////////////////////////////////////////////// -struct SSAOUniforms +struct alignas(32) SSAOUniforms { FVector2 UVToViewA; FVector2 UVToViewB; @@ -693,7 +626,7 @@ struct SSAOUniforms } }; -struct DepthBlurUniforms +struct alignas(32) DepthBlurUniforms { float BlurSharpness; float PowExponent; @@ -711,7 +644,7 @@ struct DepthBlurUniforms } }; -struct AmbientCombineUniforms +struct alignas(32) AmbientCombineUniforms { int SampleCount; int DebugMode, Padding1, Padding2; @@ -772,7 +705,7 @@ private: PPTexture AmbientRandomTexture[NumAmbientRandomTextures]; }; -struct PresentUniforms +struct alignas(32) PresentUniforms { float InvGamma; float Contrast; @@ -816,7 +749,7 @@ public: PPShader Row3D = { "shaders/pp/present_row3d.fp", "", PresentUniforms::Desc() }; }; -struct ShadowMapUniforms +struct alignas(32) ShadowMapUniforms { float ShadowmapQuality; int NodesCount; @@ -844,16 +777,11 @@ public: PostProcessShader *Desc = nullptr; private: - void AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment = 0); void SetTextures(PPRenderState *renderstate); void SetUniforms(PPRenderState *renderstate); PPShader Shader; - int UniformStructSize = 0; - std::vector Fields; - std::vector> FieldNames; std::map> Textures; - std::map FieldOffset; }; class PPCustomShaders diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp index f48d3f7d1..0e2b8d8cf 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp @@ -43,18 +43,42 @@ DEFINE_ACTION_FUNCTION_NATIVE(_PPShader, SetEnabled, ShaderSetEnabled) return 0; } -static void ShaderSetUniform1f(const FString &shaderName, const FString &uniformName, double value) +static void ShaderSetUniform1f(const FString &shaderName, const FString &uniformName, double x) { for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) { PostProcessShader &shader = PostProcessShaders[i]; if (shader.Name == shaderName) { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = value; - vec4[1] = 0.0; - vec4[2] = 0.0; - vec4[3] = 1.0; + auto uniform = shader.Uniforms.GetField(uniformName); + float * f = (float *)uniform.Value; + int * i = (int *)uniform.Value; + switch(uniform.Type) + { + case UniformType::Undefined: + break; + case UniformType::Int: + *i = (int)x; + break; + case UniformType::Float: + *f = (float)x; + break; + case UniformType::Vec2: + f[0] = (float)x; + f[1] = 0.0f; + break; + case UniformType::Vec3: + f[0] = (float)x; + f[1] = 0.0f; + f[2] = 0.0f; + break; + case UniformType::Vec4: + f[0] = (float)x; + f[1] = 0.0f; + f[2] = 0.0f; + f[3] = 1.0f; + break; + } } } } @@ -82,11 +106,35 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform2f) PostProcessShader &shader = PostProcessShaders[i]; if (shader.Name == shaderName) { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = x; - vec4[1] = y; - vec4[2] = 0.0; - vec4[3] = 1.0; + auto uniform = shader.Uniforms.GetField(uniformName); + float * f = (float *)uniform.Value; + int * i = (int *)uniform.Value; + switch(uniform.Type) + { + case UniformType::Undefined: + break; + case UniformType::Int: + *i = (int)x; + break; + case UniformType::Float: + *f = (float)x; + break; + case UniformType::Vec2: + f[0] = (float)x; + f[1] = (float)y; + break; + case UniformType::Vec3: + f[0] = (float)x; + f[1] = (float)y; + f[2] = 0.0f; + break; + case UniformType::Vec4: + f[0] = (float)x; + f[1] = (float)y; + f[2] = 0.0f; + f[3] = 1.0f; + break; + } } } return 0; @@ -106,11 +154,35 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform3f) PostProcessShader &shader = PostProcessShaders[i]; if (shader.Name == shaderName) { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = x; - vec4[1] = y; - vec4[2] = z; - vec4[3] = 1.0; + auto uniform = shader.Uniforms.GetField(uniformName); + float * f = (float *)uniform.Value; + int * i = (int *)uniform.Value; + switch(uniform.Type) + { + case UniformType::Undefined: + break; + case UniformType::Int: + *i = (int)x; + break; + case UniformType::Float: + *f = (float)x; + break; + case UniformType::Vec2: + f[0] = (float)x; + f[1] = (float)y; + break; + case UniformType::Vec3: + f[0] = (float)x; + f[1] = (float)y; + f[2] = (float)z; + break; + case UniformType::Vec4: + f[0] = (float)x; + f[1] = (float)y; + f[2] = (float)z; + f[3] = 1.0f; + break; + } } } return 0; @@ -131,11 +203,35 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform4f) PostProcessShader &shader = PostProcessShaders[i]; if (shader.Name == shaderName) { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = x; - vec4[1] = y; - vec4[2] = z; - vec4[3] = w; + auto uniform = shader.Uniforms.GetField(uniformName); + float * f = (float *)uniform.Value; + int * i = (int *)uniform.Value; + switch(uniform.Type) + { + case UniformType::Undefined: + break; + case UniformType::Int: + *i = (int)x; + break; + case UniformType::Float: + *f = (float)x; + break; + case UniformType::Vec2: + f[0] = (float)x; + f[1] = (float)y; + break; + case UniformType::Vec3: + f[0] = (float)x; + f[1] = (float)y; + f[2] = (float)z; + break; + case UniformType::Vec4: + f[0] = (float)x; + f[1] = (float)y; + f[2] = (float)z; + f[3] = (float)w; + break; + } } } return 0; @@ -153,11 +249,35 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform1i) PostProcessShader &shader = PostProcessShaders[i]; if (shader.Name == shaderName) { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = (double)value; - vec4[1] = 0.0; - vec4[2] = 0.0; - vec4[3] = 1.0; + auto uniform = shader.Uniforms.GetField(uniformName); + float * f = (float *)uniform.Value; + int * i = (int *)uniform.Value; + switch(uniform.Type) + { + case UniformType::Undefined: + break; + case UniformType::Int: + *i = value; + break; + case UniformType::Float: + *f = (float)value; + break; + case UniformType::Vec2: + f[0] = (float)value; + f[1] = 0.0f; + break; + case UniformType::Vec3: + f[0] = (float)value; + f[1] = 0.0f; + f[2] = 0.0f; + break; + case UniformType::Vec4: + f[0] = (float)value; + f[1] = 0.0f; + f[2] = 0.0f; + f[3] = 1.0f; + break; + } } } return 0; diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h index fcb32c5e1..f3ac7869a 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h @@ -3,21 +3,7 @@ #include "zstring.h" #include "tarray.h" -enum class PostProcessUniformType -{ - Undefined, - Int, - Float, - Vec2, - Vec3, - Vec4 -}; - -struct PostProcessUniformValue -{ - PostProcessUniformType Type = PostProcessUniformType::Undefined; - double Values[4] = { 0.0, 0.0, 0.0, 0.0 }; -}; +#include "hw_useruniforms.h" struct PostProcessShader { @@ -28,7 +14,8 @@ struct PostProcessShader FString Name; bool Enabled = false; - TMap Uniforms; + //TMap Uniforms; + UserUniforms Uniforms; TMap Textures; }; diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp index 7ab93b3ec..93706d72e 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader_ccmds.cpp @@ -56,6 +56,33 @@ CCMD (shaderenable) Printf("No shader named '%s' found\n", shaderName); } +static void PrintUniform(const char * shaderName, const char * uniformName, const UniformField &uniform) +{ + float * f = (float *)uniform.Value; + int * i = (int *)uniform.Value; + switch(uniform.Type) + { + case UniformType::Undefined: + Printf("Shader '%s': could not find uniform '%s': %f %f %f\n", shaderName, uniformName); + break; + case UniformType::Int: + Printf("Shader '%s' uniform '%s': %d\n", shaderName, uniformName, *i); + break; + case UniformType::Float: + Printf("Shader '%s' uniform '%s': %f\n", shaderName, uniformName, *f); + break; + case UniformType::Vec2: + Printf("Shader '%s' uniform '%s': %f %f\n", shaderName, uniformName, f[0], f[1]); + break; + case UniformType::Vec3: + Printf("Shader '%s' uniform '%s': %f %f %f\n", shaderName, uniformName, f[0], f[1], f[2]); + break; + case UniformType::Vec4: + Printf("Shader '%s' uniform '%s': %f %f %f %f\n", shaderName, uniformName, f[0], f[1], f[2], f[3]); + break; + } +} + CCMD (shaderuniform) { if (argv.argc() < 3) @@ -74,16 +101,40 @@ CCMD (shaderuniform) { if (argv.argc() > 3) { - double *vec4 = shader.Uniforms[uniformName].Values; - vec4[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0; - vec4[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0; - vec4[2] = argv.argc()>=6 ? atof(argv[5]) : 0.0; - vec4[3] = 1.0; + auto uniform = shader.Uniforms.GetField(uniformName); + float * f = (float *)uniform.Value; + int * i = (int *)uniform.Value; + switch(uniform.Type) + { + case UniformType::Undefined: + Printf("Shader '%s': could not find uniform '%s': %f %f %f\n", shaderName, uniformName); + break; + case UniformType::Int: + *i = atoi(argv[3]); + break; + case UniformType::Float: + *f = atof(argv[3]); + break; + case UniformType::Vec2: + f[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0; + f[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0; + break; + case UniformType::Vec3: + f[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0; + f[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0; + f[2] = argv.argc()>=6 ? atof(argv[5]) : 0.0; + break; + case UniformType::Vec4: + f[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0; + f[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0; + f[2] = argv.argc()>=6 ? atof(argv[5]) : 0.0; + f[3] = argv.argc()>=7 ? atof(argv[6]) : 1.0; + break; + } } else { - double *vec4 = shader.Uniforms[uniformName].Values; - Printf("Shader '%s' uniform '%s': %f %f %f\n", shaderName, uniformName, vec4[0], vec4[1], vec4[2]); + PrintUniform(shaderName, uniformName, shader.Uniforms.GetField(uniformName)); } found = 1; } @@ -120,14 +171,11 @@ CCMD(listuniforms) { Printf("Shader '%s' uniforms:\n", shaderName); - decltype(shader.Uniforms)::Iterator it(shader.Uniforms); - decltype(shader.Uniforms)::Pair* pair; - - while (it.NextPair(pair)) + for(auto &field : shader.Uniforms.Fields) { - double *vec4 = shader.Uniforms[pair->Key].Values; - Printf(" %s : %f %f %f\n", pair->Key.GetChars(), vec4[0], vec4[1], vec4[2]); + PrintUniform(shaderName, field.Name.GetChars(), shader.Uniforms.GetField(field.Name)); } + found = 1; } } diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_useruniforms.h b/src/common/rendering/hwrenderer/postprocessing/hw_useruniforms.h new file mode 100644 index 000000000..66a55a8b4 --- /dev/null +++ b/src/common/rendering/hwrenderer/postprocessing/hw_useruniforms.h @@ -0,0 +1,149 @@ +#pragma once + +#include +#include +#include +#include + +#include "tarray.h" +#include "zstring.h" + +enum class UniformType +{ + Undefined, + Int, + UInt, + Float, + Vec2, + Vec3, + Vec4, + IVec2, + IVec3, + IVec4, + UVec2, + UVec3, + UVec4, + Mat4 +}; + +struct UserUniformValue +{ + UniformType Type = UniformType::Undefined; + double Values[4] = { 0.0, 0.0, 0.0, 0.0 }; +}; + +struct UniformFieldDesc +{ + FString Name; + UniformType Type; + std::size_t Offset; +}; + +struct UniformField +{ + UniformType Type = UniformType::Undefined; + void * Value = nullptr; +}; + +class UniformStructHolder +{ +public: + UniformStructHolder() + { + } + + UniformStructHolder(const UniformStructHolder &src) + { + *this = src; + } + + ~UniformStructHolder() + { + Clear(); + } + + UniformStructHolder &operator=(const UniformStructHolder &src) + { + Clear(); + + if(src.alloc) + { + alloc = true; + sz = src.sz; + addr = new uint8_t[sz]; + memcpy((uint8_t*)addr, src.addr, sz); + } + else + { + sz = src.sz; + addr = src.addr; + } + + return *this; + } + + void Clear() + { + if(alloc) + { + delete[] addr; + } + alloc = false; + addr = nullptr; + sz = 0; + } + + template + void Set(const T *v) + { + Clear(); + + sz = sizeof(T); + addr = reinterpret_cast(v); + } + + template + void Set(const T &v, typename std::enable_if, bool>::type enabled = true) + { + static_assert(std::is_trivially_copyable_v); + + alloc = true; + sz = sizeof(T); + addr = new uint8_t[sizeof(T)]; + memcpy((uint8_t*)addr, &v, sizeof(T)); + } + + bool alloc = false; + size_t sz = 0; + const uint8_t * addr = nullptr; +}; + +class UserUniforms +{ + void AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment = 0); + void BuildStruct(const TMap &Uniforms); +public: + UserUniforms() = default; + UserUniforms(const TMap &Uniforms) + { + LoadUniforms(Uniforms); + } + + ~UserUniforms() + { + if(UniformStruct) delete[] UniformStruct; + } + + //must only be called once + void LoadUniforms(const TMap &Uniforms); + void WriteUniforms(UniformStructHolder &Data); + + + int UniformStructSize = 0; + uint8_t * UniformStruct = nullptr; + + UniformField GetField(const FString &name); + + std::vector Fields; + TMap FieldNames; +}; \ No newline at end of file diff --git a/src/common/rendering/vulkan/vk_postprocess.cpp b/src/common/rendering/vulkan/vk_postprocess.cpp index 199698c7f..162a901fa 100644 --- a/src/common/rendering/vulkan/vk_postprocess.cpp +++ b/src/common/rendering/vulkan/vk_postprocess.cpp @@ -233,7 +233,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool renderstate.Clear(); renderstate.Shader = &hw_postprocess.present.Present; - renderstate.Uniforms.Set(uniforms); + renderstate.Uniforms.Set(&uniforms); renderstate.Viewport = box; renderstate.SetInputCurrent(0, ViewportLinearScale() ? PPFilterMode::Linear : PPFilterMode::Nearest); renderstate.SetInputTexture(1, &hw_postprocess.present.Dither, PPFilterMode::Nearest, PPWrapMode::Repeat); @@ -243,6 +243,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool renderstate.SetOutputSwapChain(); renderstate.SetNoBlend(); renderstate.Draw(); + renderstate.Uniforms.Clear(); } void VkPostprocess::UpdateLinearDepthTexture() diff --git a/src/common/rendering/vulkan/vk_pprenderstate.cpp b/src/common/rendering/vulkan/vk_pprenderstate.cpp index 8b4a9093a..eac3cd6e0 100644 --- a/src/common/rendering/vulkan/vk_pprenderstate.cpp +++ b/src/common/rendering/vulkan/vk_pprenderstate.cpp @@ -58,7 +58,7 @@ void VkPPRenderState::Draw() VkPPRenderPassKey key; key.BlendMode = BlendMode; key.InputTextures = Textures.Size(); - key.Uniforms = Uniforms.Data.Size(); + key.Uniforms = Uniforms.sz; key.Shader = fb->GetShaderManager()->GetVkShader(Shader); key.SwapChain = (Output.Type == PPTextureType::SwapChain); key.ShadowMapBuffers = ShadowMapBuffers; @@ -88,7 +88,7 @@ void VkPPRenderState::Draw() VulkanDescriptorSet *input = fb->GetDescriptorSetManager()->GetInput(passSetup, Textures, ShadowMapBuffers); VulkanFramebuffer *output = fb->GetBuffers()->GetOutput(passSetup, Output, key.StencilTest, framebufferWidth, framebufferHeight); - RenderScreenQuad(passSetup, input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest == WhichDepthStencil::Scene); + RenderScreenQuad(passSetup, input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.addr, Uniforms.sz, key.StencilTest == WhichDepthStencil::Scene); // Advance to next PP texture if our output was sent there if (Output.Type == PPTextureType::NextPipelineTexture) diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h index a146c96d3..d6fdbb726 100644 --- a/src/common/textures/textures.h +++ b/src/common/textures/textures.h @@ -44,6 +44,9 @@ #include "hw_texcontainer.h" #include "floatrect.h" #include "refcounted.h" +#include "tarray.h" + +#include "hwrenderer/postprocessing/hw_useruniforms.h" class FImageSource; class FGameTexture; @@ -110,6 +113,9 @@ struct UserShaderDesc FString defines; bool disablealphatest = false; uint8_t shaderFlags = 0; + + TMap Uniforms; + UserUniforms UniformData; }; extern TArray usershaders; diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index c70b992b8..cd6a7d3a5 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -65,46 +65,121 @@ struct ExtraUniformCVARData { FString Shader; FString Uniform; - double* vec4 = nullptr; + void * data = nullptr; ExtraUniformCVARData* Next = nullptr; void (*OldCallback)(FBaseCVar &); }; -static void do_uniform_set(DVector4 value, ExtraUniformCVARData* data) +void pp_uniform_get_data(ExtraUniformCVARData* data) { - if (!(data->vec4)) + if (!(data->data)) { for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) { PostProcessShader& shader = PostProcessShaders[i]; if (strcmp(shader.Name.GetChars(), data->Shader.GetChars()) == 0) { - data->vec4 = shader.Uniforms[data->Uniform].Values; + data->data = shader.Uniforms.GetField(data->Uniform).Value; } } } - double* vec4 = data->vec4; - if (vec4) +} + +static void do_pp_uniform_set1i(int value, ExtraUniformCVARData* data) +{ + pp_uniform_get_data(data); + + int * i1 = (int *)data->data; + if (i1) { - vec4[0] = value.X; - vec4[1] = value.Y; - vec4[2] = value.Z; - vec4[3] = value.W; + i1[0] = value; } + if (data->Next) - do_uniform_set(value, data->Next); + do_pp_uniform_set1i(value, data->Next); +} + +static void do_pp_uniform_set1f(float value, ExtraUniformCVARData* data) +{ + pp_uniform_get_data(data); + + float * f1 = (float *)data->data; + if (f1) + { + f1[0] = value; + } + + if (data->Next) + do_pp_uniform_set1f(value, data->Next); +} + +static void do_pp_uniform_set2f(float x, float y, ExtraUniformCVARData* data) +{ + pp_uniform_get_data(data); + + float * f2 = (float *)data->data; + if (f2) + { + f2[0] = x; + f2[1] = y; + } + + if (data->Next) + do_pp_uniform_set2f(x, y, data->Next); +} + +static void do_pp_uniform_set3f(float x, float y, float z, ExtraUniformCVARData* data) +{ + pp_uniform_get_data(data); + + float * f3 = (float *)data->data; + if (f3) + { + f3[0] = x; + f3[1] = y; + f3[2] = z; + } + + if (data->Next) + do_pp_uniform_set3f(x, y, z, data->Next); +} + +static void do_pp_uniform_set4f(float x, float y, float z, float w, ExtraUniformCVARData* data) +{ + pp_uniform_get_data(data); + + float * f4 = (float *)data->data; + if (f4) + { + f4[0] = x; + f4[1] = y; + f4[2] = z; + f4[3] = w; + } + + if (data->Next) + do_pp_uniform_set4f(x, y, z, w, data->Next); } template -void uniform_callback1(T &self) +void pp_uniform_callback1i(T &self) { auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2(); if(data->OldCallback) data->OldCallback(self); - do_uniform_set(DVector4(*self, 0.0, 0.0, 1.0), data); + do_pp_uniform_set1i(*self, data); } -void uniform_callback_color(FColorCVar &self) +template +void pp_uniform_callback1f(T &self) +{ + auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2(); + if(data->OldCallback) data->OldCallback(self); + + do_pp_uniform_set1f(*self, data); +} + +void pp_uniform_callback_color3f(FColorCVar &self) { auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2(); if(data->OldCallback) data->OldCallback(self); @@ -112,7 +187,18 @@ void uniform_callback_color(FColorCVar &self) PalEntry col; col.d = *self; - do_uniform_set(DVector4(col.r / 255.0, col.g / 255.0, col.b / 255.0, col.a / 255.0), data); + do_pp_uniform_set3f(col.r / 255.0, col.g / 255.0, col.b / 255.0, data); +} + +void pp_uniform_callback_color4f(FColorCVar &self) +{ + auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2(); + if(data->OldCallback) data->OldCallback(self); + + PalEntry col; + col.d = *self; + + do_pp_uniform_set4f(col.r / 255.0, col.g / 255.0, col.b / 255.0, col.a / 255.0, data); } //----------------------------------------------------------------------------- @@ -1875,6 +1961,7 @@ class GLDefsParser sc.MustGetString(); PostProcessShader shaderdesc; + TMap Uniforms; shaderdesc.Target = sc.String; shaderdesc.Target.ToLower(); @@ -1916,27 +2003,27 @@ class GLDefsParser sc.MustGetString(); FString uniformName = sc.String; - PostProcessUniformType parsedType = PostProcessUniformType::Undefined; + UniformType parsedType = UniformType::Undefined; if (uniformType.Compare("int") == 0) { - parsedType = PostProcessUniformType::Int; + parsedType = UniformType::Int; } else if (uniformType.Compare("float") == 0) { - parsedType = PostProcessUniformType::Float; + parsedType = UniformType::Float; } else if (uniformType.Compare("vec2") == 0) { - parsedType = PostProcessUniformType::Vec2; + parsedType = UniformType::Vec2; } else if (uniformType.Compare("vec3") == 0) { - parsedType = PostProcessUniformType::Vec3; + parsedType = UniformType::Vec3; } else if (uniformType.Compare("vec4") == 0) { - parsedType = PostProcessUniformType::Vec4; + parsedType = UniformType::Vec4; } else { @@ -1954,21 +2041,21 @@ class GLDefsParser } else switch(parsedType) { - case PostProcessUniformType::Int: + case UniformType::Int: sc.MustGetNumber(); Values[0] = sc.BigNumber; break; - case PostProcessUniformType::Float: + case UniformType::Float: sc.MustGetFloat(); Values[0] = sc.Float; break; - case PostProcessUniformType::Vec2: + case UniformType::Vec2: sc.MustGetFloat(); Values[0] = sc.Float; sc.MustGetFloat(); Values[1] = sc.Float; break; - case PostProcessUniformType::Vec3: + case UniformType::Vec3: sc.MustGetFloat(); Values[0] = sc.Float; sc.MustGetFloat(); @@ -1976,7 +2063,7 @@ class GLDefsParser sc.MustGetFloat(); Values[2] = sc.Float; break; - case PostProcessUniformType::Vec4: + case UniformType::Vec4: sc.MustGetFloat(); Values[0] = sc.Float; sc.MustGetFloat(); @@ -1992,11 +2079,11 @@ class GLDefsParser if (ok && !is_cvar) { - shaderdesc.Uniforms[uniformName].Type = parsedType; - shaderdesc.Uniforms[uniformName].Values[0] = Values[0]; - shaderdesc.Uniforms[uniformName].Values[1] = Values[1]; - shaderdesc.Uniforms[uniformName].Values[2] = Values[2]; - shaderdesc.Uniforms[uniformName].Values[3] = Values[3]; + Uniforms[uniformName].Type = parsedType; + Uniforms[uniformName].Values[0] = Values[0]; + Uniforms[uniformName].Values[1] = Values[1]; + Uniforms[uniformName].Values[2] = Values[2]; + Uniforms[uniformName].Values[3] = Values[3]; } if (ok && is_cvar) @@ -2027,38 +2114,53 @@ class GLDefsParser switch (cvar->GetRealType()) { case CVAR_Int: - if(parsedType != PostProcessUniformType::Int && parsedType != PostProcessUniformType::Float) + if(parsedType == UniformType::Int) + { + callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1i); + Values[0] = cvar->GetGenericRep(CVAR_Int).Int; + } + else if(parsedType == UniformType::Float) + { + callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1f); + Values[0] = cvar->GetGenericRep(CVAR_Int).Int; + } + else { sc.ScriptError("CVar '%s' type (int) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars()); ok = false; } - else - { - callback = (void (*)(FBaseCVar&))(&uniform_callback1); - Values[0] = cvar->GetGenericRep(CVAR_Int).Int; - } break; case CVAR_Float: - if(parsedType != PostProcessUniformType::Int && parsedType != PostProcessUniformType::Float) + if(parsedType == UniformType::Int) + { + callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1i); + Values[0] = cvar->GetGenericRep(CVAR_Float).Float; + } + else if(parsedType == UniformType::Float) + { + callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1f); + Values[0] = cvar->GetGenericRep(CVAR_Float).Float; + } + else { sc.ScriptError("CVar '%s' type (float) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars()); ok = false; } - else - { - callback = (void (*)(FBaseCVar&))(&uniform_callback1); - Values[0] = cvar->GetGenericRep(CVAR_Float).Float; - } break; case CVAR_Color: - if(parsedType != PostProcessUniformType::Vec3 && parsedType != PostProcessUniformType::Vec4) + if(parsedType == UniformType::Vec3) { - sc.ScriptError("CVar '%s' type (color) is not convertible to uniform type (%s), must be vec3 or vec4", cvarname.GetChars(), uniformType.GetChars()); - ok = false; + callback = (void (*)(FBaseCVar&))(&pp_uniform_callback_color3f); + + PalEntry col; + col.d = cvar->GetGenericRep(CVAR_Int).Int; + Values[0] = col.r / 255.0; + Values[1] = col.g / 255.0; + Values[2] = col.b / 255.0; } - else + else if(parsedType == UniformType::Vec4) { - callback = (void (*)(FBaseCVar&))uniform_callback_color; + callback = (void (*)(FBaseCVar&))(&pp_uniform_callback_color4f); PalEntry col; col.d = cvar->GetGenericRep(CVAR_Int).Int; @@ -2067,6 +2169,11 @@ class GLDefsParser Values[2] = col.b / 255.0; Values[3] = col.a / 255.0; } + else + { + sc.ScriptError("CVar '%s' type (color) is not convertible to uniform type (%s), must be vec3 or vec4", cvarname.GetChars(), uniformType.GetChars()); + ok = false; + } break; default: sc.ScriptError("CVar '%s' type not supported for uniforms!", cvarname.GetChars()); @@ -2088,11 +2195,11 @@ class GLDefsParser cvar->SetCallback(callback); cvar->SetExtraDataPointer2(extra); - shaderdesc.Uniforms[uniformName].Type = parsedType; - shaderdesc.Uniforms[uniformName].Values[0] = Values[0]; - shaderdesc.Uniforms[uniformName].Values[1] = Values[1]; - shaderdesc.Uniforms[uniformName].Values[2] = Values[2]; - shaderdesc.Uniforms[uniformName].Values[3] = Values[3]; + Uniforms[uniformName].Type = parsedType; + Uniforms[uniformName].Values[0] = Values[0]; + Uniforms[uniformName].Values[1] = Values[1]; + Uniforms[uniformName].Values[2] = Values[2]; + Uniforms[uniformName].Values[3] = Values[3]; } } } @@ -2116,7 +2223,8 @@ class GLDefsParser } } - PostProcessShaders.Push(shaderdesc); + auto index = PostProcessShaders.Push(shaderdesc); + PostProcessShaders[index].Uniforms.LoadUniforms(Uniforms); } else {