From 709e8292b05282f11c2ee2335bb081f780eeff2b Mon Sep 17 00:00:00 2001 From: vladislavbelov Date: Mon, 31 Jan 2022 20:10:06 +0000 Subject: [PATCH] Moves color mask, depth mask and function management from CShaderPass to DeviceCommandContext. Tested By: Langbart Comments By: Stan Differential Revision: https://code.wildfiregames.com/D4465 This was SVN commit r26284. --- .../mods/mod/shaders/effects/canvas2d.xml | 2 + .../mods/public/shaders/effects/bloom.xml | 10 ++-- .../data/mods/public/shaders/effects/cas.xml | 10 ++-- .../public/shaders/effects/debug_overlay.xml | 2 + .../data/mods/public/shaders/effects/fxaa.xml | 10 ++-- .../mods/public/shaders/effects/model.xml | 10 +++- .../shaders/effects/model_transparent.xml | 23 +++++++- .../public/shaders/effects/postproc/DOF.xml | 11 ++-- .../public/shaders/effects/postproc/hdr.xml | 10 ++-- .../public/shaders/effects/sky_simple.xml | 20 ++++--- .../public/shaders/effects/terrain_blend.xml | 10 +++- .../public/shaders/effects/terrain_decal.xml | 10 +++- .../public/shaders/effects/terrain_solid.xml | 2 + .../public/shaders/effects/water_waves.xml | 1 + source/graphics/MiniMapTexture.cpp | 10 ++-- source/graphics/ShaderManager.cpp | 54 ++++++++++--------- source/graphics/ShaderTechnique.cpp | 39 -------------- source/graphics/ShaderTechnique.h | 16 ------ source/renderer/OverlayRenderer.cpp | 20 ++----- source/renderer/PostprocManager.cpp | 11 ++-- source/renderer/PostprocManager.h | 2 +- source/renderer/SceneRenderer.cpp | 18 +++---- source/renderer/ShadowMap.cpp | 13 ----- source/renderer/SilhouetteRenderer.cpp | 4 -- source/renderer/SkyManager.cpp | 4 -- source/renderer/TerrainOverlay.cpp | 2 - source/renderer/TerrainRenderer.cpp | 13 ----- source/renderer/WaterManager.cpp | 3 -- source/renderer/backend/PipelineState.cpp | 22 ++++++++ source/renderer/backend/PipelineState.h | 40 ++++++++++++++ source/renderer/backend/gl/Device.cpp | 1 - .../backend/gl/DeviceCommandContext.cpp | 21 ++++++++ source/renderer/backend/gl/Mapping.cpp | 23 +++++++- source/renderer/backend/gl/Mapping.h | 6 ++- 34 files changed, 256 insertions(+), 197 deletions(-) diff --git a/binaries/data/mods/mod/shaders/effects/canvas2d.xml b/binaries/data/mods/mod/shaders/effects/canvas2d.xml index 21c7014b02..27610eaa1c 100644 --- a/binaries/data/mods/mod/shaders/effects/canvas2d.xml +++ b/binaries/data/mods/mod/shaders/effects/canvas2d.xml @@ -4,6 +4,7 @@ + @@ -11,6 +12,7 @@ + diff --git a/binaries/data/mods/public/shaders/effects/bloom.xml b/binaries/data/mods/public/shaders/effects/bloom.xml index 49107f8af9..831fae1549 100644 --- a/binaries/data/mods/public/shaders/effects/bloom.xml +++ b/binaries/data/mods/public/shaders/effects/bloom.xml @@ -1,9 +1,11 @@ - - - - + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/cas.xml b/binaries/data/mods/public/shaders/effects/cas.xml index 6a250150bf..03bb183674 100644 --- a/binaries/data/mods/public/shaders/effects/cas.xml +++ b/binaries/data/mods/public/shaders/effects/cas.xml @@ -1,7 +1,9 @@ - - - - + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/debug_overlay.xml b/binaries/data/mods/public/shaders/effects/debug_overlay.xml index cc85add6aa..d1f9e1a4c2 100644 --- a/binaries/data/mods/public/shaders/effects/debug_overlay.xml +++ b/binaries/data/mods/public/shaders/effects/debug_overlay.xml @@ -5,6 +5,7 @@ + @@ -13,6 +14,7 @@ + diff --git a/binaries/data/mods/public/shaders/effects/fxaa.xml b/binaries/data/mods/public/shaders/effects/fxaa.xml index ed76b4c8a1..afaceae1c1 100644 --- a/binaries/data/mods/public/shaders/effects/fxaa.xml +++ b/binaries/data/mods/public/shaders/effects/fxaa.xml @@ -1,7 +1,9 @@ - - - - + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/model.xml b/binaries/data/mods/public/shaders/effects/model.xml index 13257aec7d..c7aa2e4623 100644 --- a/binaries/data/mods/public/shaders/effects/model.xml +++ b/binaries/data/mods/public/shaders/effects/model.xml @@ -20,13 +20,17 @@ - + + + - + + + @@ -47,6 +51,7 @@ + @@ -55,6 +60,7 @@ + diff --git a/binaries/data/mods/public/shaders/effects/model_transparent.xml b/binaries/data/mods/public/shaders/effects/model_transparent.xml index 2c9d209aa7..d17656850d 100644 --- a/binaries/data/mods/public/shaders/effects/model_transparent.xml +++ b/binaries/data/mods/public/shaders/effects/model_transparent.xml @@ -8,6 +8,7 @@ + @@ -18,6 +19,7 @@ + @@ -27,13 +29,30 @@ make it obviously buggy if CRenderer is changed to render these models. --> - + + + + + + + + + + + + + + + + + + - + diff --git a/binaries/data/mods/public/shaders/effects/postproc/DOF.xml b/binaries/data/mods/public/shaders/effects/postproc/DOF.xml index 9fecf4bb69..6576493d13 100644 --- a/binaries/data/mods/public/shaders/effects/postproc/DOF.xml +++ b/binaries/data/mods/public/shaders/effects/postproc/DOF.xml @@ -1,10 +1,13 @@ - - + + + - - + + + + diff --git a/binaries/data/mods/public/shaders/effects/postproc/hdr.xml b/binaries/data/mods/public/shaders/effects/postproc/hdr.xml index cb5a31d647..bfc15265b7 100644 --- a/binaries/data/mods/public/shaders/effects/postproc/hdr.xml +++ b/binaries/data/mods/public/shaders/effects/postproc/hdr.xml @@ -1,9 +1,11 @@ - - - - + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/sky_simple.xml b/binaries/data/mods/public/shaders/effects/sky_simple.xml index 4cca7acc92..d02d81f9b1 100644 --- a/binaries/data/mods/public/shaders/effects/sky_simple.xml +++ b/binaries/data/mods/public/shaders/effects/sky_simple.xml @@ -1,14 +1,18 @@ - - - - + + + + + + - - - - + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/terrain_blend.xml b/binaries/data/mods/public/shaders/effects/terrain_blend.xml index bef2b61b06..b582f44dc1 100644 --- a/binaries/data/mods/public/shaders/effects/terrain_blend.xml +++ b/binaries/data/mods/public/shaders/effects/terrain_blend.xml @@ -5,6 +5,7 @@ + @@ -13,18 +14,23 @@ + - + + + - + + + diff --git a/binaries/data/mods/public/shaders/effects/terrain_decal.xml b/binaries/data/mods/public/shaders/effects/terrain_decal.xml index 19c85473fc..ad020a3ed5 100644 --- a/binaries/data/mods/public/shaders/effects/terrain_decal.xml +++ b/binaries/data/mods/public/shaders/effects/terrain_decal.xml @@ -5,6 +5,7 @@ + @@ -13,18 +14,23 @@ + - + + + - + + + diff --git a/binaries/data/mods/public/shaders/effects/terrain_solid.xml b/binaries/data/mods/public/shaders/effects/terrain_solid.xml index 8f46a0692e..7989a65676 100644 --- a/binaries/data/mods/public/shaders/effects/terrain_solid.xml +++ b/binaries/data/mods/public/shaders/effects/terrain_solid.xml @@ -7,6 +7,7 @@ + @@ -19,6 +20,7 @@ terrain (so silhouettes will still display when behind hills). --> + diff --git a/binaries/data/mods/public/shaders/effects/water_waves.xml b/binaries/data/mods/public/shaders/effects/water_waves.xml index 5ae6ebd692..f411885d79 100644 --- a/binaries/data/mods/public/shaders/effects/water_waves.xml +++ b/binaries/data/mods/public/shaders/effects/water_waves.xml @@ -3,6 +3,7 @@ + diff --git a/source/graphics/MiniMapTexture.cpp b/source/graphics/MiniMapTexture.cpp index aeceb70590..49dde63e6e 100644 --- a/source/graphics/MiniMapTexture.cpp +++ b/source/graphics/MiniMapTexture.cpp @@ -387,8 +387,11 @@ void CMiniMapTexture::RenderFinalTexture( Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA; pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp = Renderer::Backend::BlendOp::ADD; + pipelineStateDesc.blendState.colorWriteMask = + Renderer::Backend::ColorWriteMask::RED | + Renderer::Backend::ColorWriteMask::GREEN | + Renderer::Backend::ColorWriteMask::BLUE; deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); - glColorMask(1, 1, 1, 0); // Draw territory boundaries CTerritoryTexture& territoryTexture = g_Game->GetView()->GetTerritoryTexture(); @@ -400,8 +403,9 @@ void CMiniMapTexture::RenderFinalTexture( DrawTexture(shader); pipelineStateDesc.blendState.enabled = false; + pipelineStateDesc.blendState.colorWriteMask = + Renderer::Backend::ColorWriteMask::ALPHA; deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); - glColorMask(0, 0, 0, 1); shader->BindTexture(str_baseTex, losTexture.GetTexture()); shader->Uniform(str_transform, baseTransform); @@ -411,8 +415,6 @@ void CMiniMapTexture::RenderFinalTexture( tech->EndPass(); - glColorMask(1, 1, 1, 1); - CShaderDefines pointDefines; pointDefines.Add(str_MINIMAP_POINT, str_1); tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, pointDefines); diff --git a/source/graphics/ShaderManager.cpp b/source/graphics/ShaderManager.cpp index 466aa2d8d0..fcc3be4014 100644 --- a/source/graphics/ShaderManager.cpp +++ b/source/graphics/ShaderManager.cpp @@ -272,28 +272,6 @@ bool CShaderManager::NewProgram(const char* name, const CShaderDefines& baseDefi return true; } -static GLenum ParseComparisonFunc(const CStr& str) -{ - if (str == "never") - return GL_NEVER; - if (str == "always") - return GL_ALWAYS; - if (str == "less") - return GL_LESS; - if (str == "lequal") - return GL_LEQUAL; - if (str == "equal") - return GL_EQUAL; - if (str == "gequal") - return GL_GEQUAL; - if (str == "greater") - return GL_GREATER; - if (str == "notequal") - return GL_NOTEQUAL; - debug_warn("Invalid comparison func"); - return GL_ALWAYS; -} - size_t CShaderManager::EffectCacheKeyHash::operator()(const EffectCacheKey& key) const { size_t hash = 0; @@ -348,6 +326,7 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin #define EL(x) int el_##x = XeroFile.GetElementID(#x) #define AT(x) int at_##x = XeroFile.GetAttributeID(#x) EL(blend); + EL(color); EL(cull); EL(define); EL(depth); @@ -359,13 +338,17 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin AT(dst); AT(front_face); AT(func); + AT(mask); + AT(mask_red); + AT(mask_green); + AT(mask_blue); + AT(mask_alpha); AT(mode); + AT(name); AT(op); AT(shader); AT(shaders); AT(src); - AT(mask); - AT(name); AT(value); #undef AT #undef EL @@ -483,6 +466,19 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin } } } + else if (Element.GetNodeName() == el_color) + { + passPipelineStateDesc.blendState.colorWriteMask = 0; + #define MASK_CHANNEL(ATTRIBUTE, VALUE) \ + if (Element.GetAttributes().GetNamedItem(ATTRIBUTE) == "TRUE") \ + passPipelineStateDesc.blendState.colorWriteMask |= Renderer::Backend::ColorWriteMask::VALUE + + MASK_CHANNEL(at_mask_red, RED); + MASK_CHANNEL(at_mask_green, GREEN); + MASK_CHANNEL(at_mask_blue, BLUE); + MASK_CHANNEL(at_mask_alpha, ALPHA); + #undef MASK_CHANNEL + } else if (Element.GetNodeName() == el_cull) { if (!Element.GetAttributes().GetNamedItem(at_mode).empty()) @@ -499,10 +495,16 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin else if (Element.GetNodeName() == el_depth) { if (!Element.GetAttributes().GetNamedItem(at_func).empty()) - pass.DepthFunc(ParseComparisonFunc(Element.GetAttributes().GetNamedItem(at_func))); + { + passPipelineStateDesc.depthStencilState.depthCompareOp = + Renderer::Backend::ParseCompareOp(Element.GetAttributes().GetNamedItem(at_func)); + } if (!Element.GetAttributes().GetNamedItem(at_mask).empty()) - pass.DepthMask(Element.GetAttributes().GetNamedItem(at_mask) == "true" ? 1 : 0); + { + passPipelineStateDesc.depthStencilState.depthWriteEnabled = + Element.GetAttributes().GetNamedItem(at_mask) == "true"; + } } } diff --git a/source/graphics/ShaderTechnique.cpp b/source/graphics/ShaderTechnique.cpp index e4987fe2a4..9cfa7a9229 100644 --- a/source/graphics/ShaderTechnique.cpp +++ b/source/graphics/ShaderTechnique.cpp @@ -26,50 +26,11 @@ CShaderPass::CShaderPass() = default; void CShaderPass::Bind() { m_Shader->Bind(); - - if (m_HasColorMask) - glColorMask(m_ColorMaskR, m_ColorMaskG, m_ColorMaskB, m_ColorMaskA); - - if (m_HasDepthMask) - glDepthMask(m_DepthMask); - - if (m_HasDepthFunc) - glDepthFunc(m_DepthFunc); } void CShaderPass::Unbind() { m_Shader->Unbind(); - - if (m_HasColorMask) - glColorMask(1, 1, 1, 1); - - if (m_HasDepthMask) - glDepthMask(1); - - if (m_HasDepthFunc) - glDepthFunc(GL_LEQUAL); -} - -void CShaderPass::ColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) -{ - m_HasColorMask = true; - m_ColorMaskR = r; - m_ColorMaskG = g; - m_ColorMaskB = b; - m_ColorMaskA = a; -} - -void CShaderPass::DepthMask(GLboolean mask) -{ - m_HasDepthMask = true; - m_DepthMask = mask; -} - -void CShaderPass::DepthFunc(GLenum func) -{ - m_HasDepthFunc = true; - m_DepthFunc = func; } void CShaderPass::SetPipelineStateDesc( diff --git a/source/graphics/ShaderTechnique.h b/source/graphics/ShaderTechnique.h index 5b95b63d06..7bffdda2a6 100644 --- a/source/graphics/ShaderTechnique.h +++ b/source/graphics/ShaderTechnique.h @@ -39,10 +39,6 @@ public: */ void SetShader(const CShaderProgramPtr& shader) { m_Shader = shader; } - // Add various bits of GL state to the pass: - void ColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a); - void DepthMask(GLboolean mask); - void DepthFunc(GLenum func); void SetPipelineStateDesc( const Renderer::Backend::GraphicsPipelineStateDesc& pipelineStateDesc); @@ -65,18 +61,6 @@ private: CShaderProgramPtr m_Shader; Renderer::Backend::GraphicsPipelineStateDesc m_PipelineStateDesc{}; - - bool m_HasColorMask = false; - GLboolean m_ColorMaskR; - GLboolean m_ColorMaskG; - GLboolean m_ColorMaskB; - GLboolean m_ColorMaskA; - - bool m_HasDepthMask = false; - GLboolean m_DepthMask; - - bool m_HasDepthFunc = false; - GLenum m_DepthFunc; }; /** diff --git a/source/renderer/OverlayRenderer.cpp b/source/renderer/OverlayRenderer.cpp index 8bbd8c7579..f7d10486f4 100644 --- a/source/renderer/OverlayRenderer.cpp +++ b/source/renderer/OverlayRenderer.cpp @@ -378,10 +378,6 @@ void OverlayRenderer::RenderOverlaysBeforeWater() #if CONFIG2_GLES #warning TODO: implement OverlayRenderer::RenderOverlaysBeforeWater for GLES #else - // Ignore z so that we draw behind terrain (but don't disable GL_DEPTH_TEST - // since we still want to write to the z buffer) - glDepthFunc(GL_ALWAYS); - for (SOverlayLine* line : m->lines) { if (line->m_Coords.empty()) @@ -389,8 +385,6 @@ void OverlayRenderer::RenderOverlaysBeforeWater() g_Renderer.GetDebugRenderer().DrawLine(line->m_Coords, line->m_Color, static_cast(line->m_Thickness)); } - - glDepthFunc(GL_LEQUAL); #endif } @@ -416,7 +410,6 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceC ogl_WarnIfError(); glActiveTextureARB(GL_TEXTURE0); - glDepthMask(0); CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture(); @@ -427,6 +420,7 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceC { Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = shaderTechTexLineNormal->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthWriteEnabled = false; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -457,6 +451,7 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceC { Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = shaderTechTexLineAlwaysVisible->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthWriteEnabled = false; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -488,8 +483,6 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceC g_Renderer.BindTexture(0, 0); CVertexBuffer::Unbind(); - - glDepthMask(1); } void OverlayRenderer::RenderTexturedOverlayLines(const CShaderProgramPtr& shader, bool alwaysVisible) @@ -532,6 +525,7 @@ void OverlayRenderer::RenderQuadOverlays( Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = shaderTech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthWriteEnabled = false; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -550,7 +544,6 @@ void OverlayRenderer::RenderQuadOverlays( #endif glActiveTextureARB(GL_TEXTURE0); - glDepthMask(0); CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture(); @@ -608,8 +601,6 @@ void OverlayRenderer::RenderQuadOverlays( CVertexBuffer::Unbind(); - glDepthMask(1); - #if !CONFIG2_GLES if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -762,14 +753,13 @@ void OverlayRenderer::RenderSphereOverlays( if (m->spheres.empty()) return; - glDepthMask(0); - CShaderProgramPtr shader; CShaderTechniquePtr tech; tech = g_Renderer.GetShaderManager().LoadEffect(str_overlay_solid); Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = tech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthWriteEnabled = false; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -807,7 +797,5 @@ void OverlayRenderer::RenderSphereOverlays( } tech->EndPass(); - - glDepthMask(1); #endif } diff --git a/source/renderer/PostprocManager.cpp b/source/renderer/PostprocManager.cpp index aa83a8668c..af2680a149 100644 --- a/source/renderer/PostprocManager.cpp +++ b/source/renderer/PostprocManager.cpp @@ -392,10 +392,14 @@ void CPostprocManager::CaptureRenderOutput() } -void CPostprocManager::ReleaseRenderOutput() +void CPostprocManager::ReleaseRenderOutput( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) { ENSURE(m_IsInitialized); + const Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = + Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); + deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -424,7 +428,6 @@ void CPostprocManager::ApplyEffect( glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo); glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); shaderTech1->BeginPass(pass); deviceCommandContext->SetGraphicsPipelineState( @@ -484,7 +487,6 @@ void CPostprocManager::ApplyEffect( shaderTech1->EndPass(pass); - glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); m_WhichBuffer = !m_WhichBuffer; @@ -834,7 +836,8 @@ void CPostprocManager::ApplyPostproc( { } -void CPostprocManager::ReleaseRenderOutput() +void CPostprocManager::ReleaseRenderOutput( + Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext)) { } diff --git a/source/renderer/PostprocManager.h b/source/renderer/PostprocManager.h index 62defc30f6..b1dc4d0045 100644 --- a/source/renderer/PostprocManager.h +++ b/source/renderer/PostprocManager.h @@ -75,7 +75,7 @@ public: // Blits the final postprocessed texture to the system framebuffer. The system framebuffer // is selected as the output buffer. Should be called before silhouette rendering. // @note CPostprocManager must be initialized first - void ReleaseRenderOutput(); + void ReleaseRenderOutput(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); // Returns true if we render main scene in the MSAA framebuffer. bool IsMultisampleEnabled() const; diff --git a/source/renderer/SceneRenderer.cpp b/source/renderer/SceneRenderer.cpp index 82a2634e46..e6d79de3e6 100644 --- a/source/renderer/SceneRenderer.cpp +++ b/source/renderer/SceneRenderer.cpp @@ -638,6 +638,9 @@ void CSceneRenderer::RenderReflections( // try binding the framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wm.m_ReflectionFbo); + const Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = + Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); + deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); glClearColor(0.5f, 0.5f, 1.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -718,6 +721,9 @@ void CSceneRenderer::RenderRefractions( // try binding the framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wm.m_RefractionFbo); + const Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = + Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); + deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); glClearColor(1.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -760,8 +766,6 @@ void CSceneRenderer::RenderSilhouettes( glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glColorMask(0, 0, 0, 0); - // Render occluders: { @@ -779,9 +783,6 @@ void CSceneRenderer::RenderSilhouettes( m->CallTranspModelRenderers(deviceCommandContext, contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0); } - glDepthFunc(GL_GEQUAL); - glColorMask(1, 1, 1, 1); - // Since we can't sort, we'll use the stencil buffer to ensure we only draw // a pixel once (using the color of whatever model happens to be drawn first). glEnable(GL_STENCIL_TEST); @@ -799,7 +800,6 @@ void CSceneRenderer::RenderSilhouettes( } // Restore state - glDepthFunc(GL_LEQUAL); glDisable(GL_STENCIL_TEST); } @@ -980,7 +980,7 @@ void CSceneRenderer::RenderSubmissions( g_Renderer.GetPostprocManager().ResolveMultisampleFramebuffer(); postprocManager.ApplyPostproc(deviceCommandContext); - postprocManager.ReleaseRenderOutput(); + postprocManager.ReleaseRenderOutput(deviceCommandContext); } if (g_RenderingOptions.GetSilhouettes()) @@ -1031,15 +1031,11 @@ void CSceneRenderer::DisplayFrustum() #if CONFIG2_GLES #warning TODO: implement CSceneRenderer::DisplayFrustum for GLES #else - glDepthMask(0); - g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 0.25f), 2); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 1.0f), 2); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - glDepthMask(1); #endif ogl_WarnIfError(); diff --git a/source/renderer/ShadowMap.cpp b/source/renderer/ShadowMap.cpp index 4dc2759a10..1489e807cf 100644 --- a/source/renderer/ShadowMap.cpp +++ b/source/renderer/ShadowMap.cpp @@ -626,10 +626,7 @@ void ShadowMap::BeginRender() // color buffer too, else Mali 400 drivers get confused. // Might as well clear stencil too for completeness. if (g_RenderingOptions.GetShadowAlphaFix()) - { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glColorMask(0, 0, 0, 0); - } else glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } @@ -671,9 +668,6 @@ void ShadowMap::EndRender() const SViewPort vp = { 0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight() }; g_Renderer.SetViewport(vp); - - if (g_RenderingOptions.GetShadowAlphaFix()) - glColorMask(1, 1, 1, 1); } void ShadowMap::BindTo(const CShaderProgramPtr& shader) const @@ -726,8 +720,6 @@ void ShadowMap::SetDepthTextureBits(int bits) void ShadowMap::RenderDebugBounds() { - glDepthMask(0); - // Render various shadow bounds: // Yellow = bounds of objects in view frustum that receive shadows // Red = culling frustum used to find potential shadow casters @@ -754,8 +746,6 @@ void ShadowMap::RenderDebugBounds() g_Renderer.GetDebugRenderer().DrawBrushOutline(frustumBrush, CColor(1.0f, 0.0f, 0.0f, 0.5f)); } - glDepthMask(1); - ogl_WarnIfError(); } @@ -765,8 +755,6 @@ void ShadowMap::RenderDebugTexture( if (!m->Texture) return; - glDepthMask(0); - glDisable(GL_DEPTH_TEST); #if !CONFIG2_GLES @@ -812,7 +800,6 @@ void ShadowMap::RenderDebugTexture( #endif glEnable(GL_DEPTH_TEST); - glDepthMask(1); ogl_WarnIfError(); } diff --git a/source/renderer/SilhouetteRenderer.cpp b/source/renderer/SilhouetteRenderer.cpp index 3336948a85..6a0a9ac4e0 100644 --- a/source/renderer/SilhouetteRenderer.cpp +++ b/source/renderer/SilhouetteRenderer.cpp @@ -450,8 +450,6 @@ void SilhouetteRenderer::RenderDebugOverlays( if (m_DebugBounds.empty() && m_DebugRects.empty()) return; - glDepthMask(0); - for (size_t i = 0; i < m_DebugBounds.size(); ++i) g_Renderer.GetDebugRenderer().DrawBoundingBoxOutline(m_DebugBounds[i].bounds, m_DebugBounds[i].color); @@ -492,8 +490,6 @@ void SilhouetteRenderer::RenderDebugOverlays( } shaderTech->EndPass(); - - glDepthMask(1); } void SilhouetteRenderer::EndFrame() diff --git a/source/renderer/SkyManager.cpp b/source/renderer/SkyManager.cpp index 45067d6e27..f38ca8885a 100644 --- a/source/renderer/SkyManager.cpp +++ b/source/renderer/SkyManager.cpp @@ -207,8 +207,6 @@ void SkyManager::RenderSky( if (m_SkySet.empty() || !m_SkyCubeMap) return; - glDepthMask(GL_FALSE); - const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera(); CShaderTechniquePtr skytech = @@ -295,7 +293,5 @@ void SkyManager::RenderSky( skytech->EndPass(); - glDepthMask(GL_TRUE); - #endif } diff --git a/source/renderer/TerrainOverlay.cpp b/source/renderer/TerrainOverlay.cpp index c3fa8f3cc8..f2f9c3803a 100644 --- a/source/renderer/TerrainOverlay.cpp +++ b/source/renderer/TerrainOverlay.cpp @@ -121,7 +121,6 @@ void TerrainOverlay::RenderBeforeWater( UNUSED2(deviceCommandContext); #warning TODO: implement TerrainOverlay::RenderOverlays for GLES #else - glDepthMask(GL_FALSE); // To ensure that outlines are drawn on top of the terrain correctly (and // don't Z-fight and flicker nastily), draw them as QUADS with the LINE // PolygonMode, and use PolygonOffset to pull them towards the camera. @@ -155,7 +154,6 @@ void TerrainOverlay::RenderBeforeWater( //glDisable(GL_POLYGON_OFFSET_LINE); glDisable(GL_POLYGON_OFFSET_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glDepthMask(GL_TRUE); #endif } diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp index dbf34b7f39..553c92c04e 100644 --- a/source/renderer/TerrainRenderer.cpp +++ b/source/renderer/TerrainRenderer.cpp @@ -174,7 +174,6 @@ void TerrainRenderer::RenderTerrainOverlayTexture( std::vector& visiblePatches = m->visiblePatches[cullGroup]; - glDepthMask(0); glDisable(GL_DEPTH_TEST); CShaderTechniquePtr debugOverlayTech = @@ -216,8 +215,6 @@ void TerrainRenderer::RenderTerrainOverlayTexture( } debugOverlayTech->EndPass(); - - glDepthMask(1); #endif } @@ -280,9 +277,6 @@ void TerrainRenderer::RenderTerrainShader( CPatchRData::RenderBases(deviceCommandContext, visiblePatches, context, shadow); - // no need to write to the depth buffer a second time - glDepthMask(0); - // render blend passes for each patch CPatchRData::RenderBlends(deviceCommandContext, visiblePatches, context, shadow); @@ -292,8 +286,6 @@ void TerrainRenderer::RenderTerrainShader( g_Renderer.BindTexture(1, 0); g_Renderer.BindTexture(2, 0); g_Renderer.BindTexture(3, 0); - - glDepthMask(1); } @@ -416,7 +408,6 @@ bool TerrainRenderer::RenderFancyWater( const float repeatPeriod = waterManager.m_RepeatPeriod; glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); #if !CONFIG2_GLES if (g_Renderer.GetSceneRenderer().GetWaterRenderMode() == WIREFRAME) @@ -518,8 +509,6 @@ bool TerrainRenderer::RenderFancyWater( glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif - glDepthFunc(GL_LEQUAL); - return true; } @@ -538,7 +527,6 @@ void TerrainRenderer::RenderSimpleWater( CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture(); glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); if (g_Renderer.GetSceneRenderer().GetWaterRenderMode() == WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -604,7 +592,6 @@ void TerrainRenderer::RenderWaterFoamOccluders( glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, waterManager.m_FancyEffectsFBO); glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); // Overwrite waves that would be behind the ground. CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_solid); diff --git a/source/renderer/WaterManager.cpp b/source/renderer/WaterManager.cpp index 81b3b7241c..818147ea85 100644 --- a/source/renderer/WaterManager.cpp +++ b/source/renderer/WaterManager.cpp @@ -817,7 +817,6 @@ void WaterManager::RenderWaves( glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_water_waves); tech->BeginPass(); @@ -868,8 +867,6 @@ void WaterManager::RenderWaves( } tech->EndPass(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - - glDepthFunc(GL_LEQUAL); #endif } diff --git a/source/renderer/backend/PipelineState.cpp b/source/renderer/backend/PipelineState.cpp index 095b13875f..4d1dd0afb2 100644 --- a/source/renderer/backend/PipelineState.cpp +++ b/source/renderer/backend/PipelineState.cpp @@ -29,6 +29,9 @@ GraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc() { GraphicsPipelineStateDesc desc{}; + desc.depthStencilState.depthCompareOp = CompareOp::LESS_OR_EQUAL; + desc.depthStencilState.depthWriteEnabled = true; + desc.blendState.enabled = false; desc.blendState.srcColorBlendFactor = desc.blendState.srcAlphaBlendFactor = BlendFactor::ONE; @@ -36,12 +39,31 @@ GraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc() BlendFactor::ZERO; desc.blendState.colorBlendOp = desc.blendState.alphaBlendOp = BlendOp::ADD; desc.blendState.constant = CColor(0.0f, 0.0f, 0.0f, 0.0f); + desc.blendState.colorWriteMask = + ColorWriteMask::RED | ColorWriteMask::GREEN | ColorWriteMask::BLUE | ColorWriteMask::ALPHA; desc.rasterizationState.cullMode = CullMode::BACK; desc.rasterizationState.frontFace = FrontFace::COUNTER_CLOCKWISE; return desc; } +CompareOp ParseCompareOp(const CStr& str) +{ + // TODO: it might make sense to use upper case in XML for consistency. +#define CASE(NAME, VALUE) if (str == NAME) return CompareOp::VALUE + CASE("never", NEVER); + CASE("less", LESS); + CASE("equal", EQUAL); + CASE("lequal", LESS_OR_EQUAL); + CASE("greater", GREATER); + CASE("notequal", NOT_EQUAL); + CASE("gequal", GREATER_OR_EQUAL); + CASE("always", ALWAYS); +#undef CASE + debug_warn("Invalid compare op"); + return CompareOp::NEVER; +} + BlendFactor ParseBlendFactor(const CStr& str) { // TODO: it might make sense to use upper case in XML for consistency. diff --git a/source/renderer/backend/PipelineState.h b/source/renderer/backend/PipelineState.h index cf377ed8bd..c6cc6841dd 100644 --- a/source/renderer/backend/PipelineState.h +++ b/source/renderer/backend/PipelineState.h @@ -28,6 +28,32 @@ namespace Renderer namespace Backend { +enum class CompareOp +{ + // Never passes the comparison. + NEVER, + // Passes if the source value is less than the destination value. + LESS, + // Passes if the source depth value is equal to the destination value. + EQUAL, + // Passes if the source depth value is less than or equal to the destination value. + LESS_OR_EQUAL, + // Passes if the source depth value is greater than the destination value. + GREATER, + // Passes if the source depth value is not equal to the destination value. + NOT_EQUAL, + // Passes if the source depth value is greater than or equal to the destination value. + GREATER_OR_EQUAL, + // Always passes the comparison. + ALWAYS +}; + +struct DepthStencilStateDesc +{ + CompareOp depthCompareOp; + bool depthWriteEnabled; +}; + // TODO: add per constant description. enum class BlendFactor @@ -62,6 +88,16 @@ enum class BlendOp MAX }; +// Using a namespace instead of a enum allows using the same syntax while +// avoiding adding operator overrides and additional checks on casts. +namespace ColorWriteMask +{ +constexpr uint8_t RED = 0x01; +constexpr uint8_t GREEN = 0x02; +constexpr uint8_t BLUE = 0x04; +constexpr uint8_t ALPHA = 0x08; +} // namespace ColorWriteMask + struct BlendStateDesc { bool enabled; @@ -72,6 +108,7 @@ struct BlendStateDesc BlendFactor dstAlphaBlendFactor; BlendOp alphaBlendOp; CColor constant; + uint8_t colorWriteMask; }; enum class CullMode @@ -96,6 +133,7 @@ struct RasterizationStateDesc // TODO: Add a shader program to the graphics pipeline state. struct GraphicsPipelineStateDesc { + DepthStencilStateDesc depthStencilState; BlendStateDesc blendState; RasterizationStateDesc rasterizationState; }; @@ -104,6 +142,8 @@ struct GraphicsPipelineStateDesc // should be described with a related shader and should be switched together. GraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc(); +CompareOp ParseCompareOp(const CStr& str); + BlendFactor ParseBlendFactor(const CStr& str); BlendOp ParseBlendOp(const CStr& str); diff --git a/source/renderer/backend/gl/Device.cpp b/source/renderer/backend/gl/Device.cpp index 6640a4ac0b..c4809169cf 100644 --- a/source/renderer/backend/gl/Device.cpp +++ b/source/renderer/backend/gl/Device.cpp @@ -197,7 +197,6 @@ std::unique_ptr CDevice::Create(SDL_Window* window, const bool arb) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Setup default state. - glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); return device; diff --git a/source/renderer/backend/gl/DeviceCommandContext.cpp b/source/renderer/backend/gl/DeviceCommandContext.cpp index df2a9dcac8..f1d7728502 100644 --- a/source/renderer/backend/gl/DeviceCommandContext.cpp +++ b/source/renderer/backend/gl/DeviceCommandContext.cpp @@ -136,6 +136,17 @@ void CDeviceCommandContext::ResetStates() void CDeviceCommandContext::SetGraphicsPipelineStateImpl( const GraphicsPipelineStateDesc& pipelineStateDesc, const bool force) { + const DepthStencilStateDesc& currentDepthStencilStateDesc = m_GraphicsPipelineStateDesc.depthStencilState; + const DepthStencilStateDesc& nextDepthStencilStateDesc = pipelineStateDesc.depthStencilState; + if (force || currentDepthStencilStateDesc.depthCompareOp != nextDepthStencilStateDesc.depthCompareOp) + { + glDepthFunc(Mapping::DepthFuncFromCompareOp(nextDepthStencilStateDesc.depthCompareOp)); + } + if (force || currentDepthStencilStateDesc.depthWriteEnabled != nextDepthStencilStateDesc.depthWriteEnabled) + { + glDepthMask(nextDepthStencilStateDesc.depthWriteEnabled ? GL_TRUE : GL_FALSE); + } + const BlendStateDesc& currentBlendStateDesc = m_GraphicsPipelineStateDesc.blendState; const BlendStateDesc& nextBlendStateDesc = pipelineStateDesc.blendState; if (force || currentBlendStateDesc.enabled != nextBlendStateDesc.enabled) @@ -194,6 +205,16 @@ void CDeviceCommandContext::SetGraphicsPipelineStateImpl( nextBlendStateDesc.constant.a); } + if (force || + currentBlendStateDesc.colorWriteMask != nextBlendStateDesc.colorWriteMask) + { + glColorMask( + (nextBlendStateDesc.colorWriteMask & ColorWriteMask::RED) != 0 ? GL_TRUE : GL_FALSE, + (nextBlendStateDesc.colorWriteMask & ColorWriteMask::GREEN) != 0 ? GL_TRUE : GL_FALSE, + (nextBlendStateDesc.colorWriteMask & ColorWriteMask::BLUE) != 0 ? GL_TRUE : GL_FALSE, + (nextBlendStateDesc.colorWriteMask & ColorWriteMask::ALPHA) != 0 ? GL_TRUE : GL_FALSE); + } + const RasterizationStateDesc& currentRasterizationStateDesc = m_GraphicsPipelineStateDesc.rasterizationState; const RasterizationStateDesc& nextRasterizationStateDesc = pipelineStateDesc.rasterizationState; if (force || diff --git a/source/renderer/backend/gl/Mapping.cpp b/source/renderer/backend/gl/Mapping.cpp index 4a8d74c7fb..1fc777d9fe 100644 --- a/source/renderer/backend/gl/Mapping.cpp +++ b/source/renderer/backend/gl/Mapping.cpp @@ -34,7 +34,26 @@ namespace GL namespace Mapping { -GLenum FromBlendFactor(BlendFactor blendFactor) +GLenum DepthFuncFromCompareOp(const CompareOp compareOp) +{ + GLenum detphFunc = GL_NEVER; + switch (compareOp) + { +#define CASE(NAME, GL_NAME) case CompareOp::NAME: detphFunc = GL_NAME; break + CASE(NEVER, GL_NEVER); + CASE(LESS, GL_LESS); + CASE(EQUAL, GL_EQUAL); + CASE(LESS_OR_EQUAL, GL_LEQUAL); + CASE(GREATER, GL_GREATER); + CASE(NOT_EQUAL, GL_NOTEQUAL); + CASE(GREATER_OR_EQUAL, GL_GEQUAL); + CASE(ALWAYS, GL_ALWAYS); +#undef CASE + } + return detphFunc; +} + +GLenum FromBlendFactor(const BlendFactor blendFactor) { GLenum factor = GL_ZERO; switch (blendFactor) @@ -67,7 +86,7 @@ GLenum FromBlendFactor(BlendFactor blendFactor) return factor; } -GLenum FromBlendOp(BlendOp blendOp) +GLenum FromBlendOp(const BlendOp blendOp) { GLenum mode = GL_FUNC_ADD; switch (blendOp) diff --git a/source/renderer/backend/gl/Mapping.h b/source/renderer/backend/gl/Mapping.h index bc2b510d80..56a6a07f80 100644 --- a/source/renderer/backend/gl/Mapping.h +++ b/source/renderer/backend/gl/Mapping.h @@ -33,9 +33,11 @@ namespace GL namespace Mapping { -GLenum FromBlendFactor(BlendFactor blendFactor); +GLenum DepthFuncFromCompareOp(const CompareOp compareOp); -GLenum FromBlendOp(BlendOp blendOp); +GLenum FromBlendFactor(const BlendFactor blendFactor); + +GLenum FromBlendOp(const BlendOp blendOp); } // namespace Mapping