From 01341f94838325016519b159b854cd09acd05f82 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Mon, 11 Oct 2021 19:26:07 -0700 Subject: D3D11: implement EXT_clip_control This implements EXT_clip_control for the D3D11 renderer, so that I can use a reversed-Z depth buffer with ANGLE. Tested with angle_deqp_gles2_tests.exe --deqp-egl-display-type=angle-d3d11 --deqp-case=dEQP-GLES2.functional.clip_control.* and angle_end2end_tests.exe --gtest_filter=*D3D11* Bug: angleproject:6554 Change-Id: I1d11cd04a6654c28530b11104470f0cad0009abe Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3218659 Reviewed-by: Jamie Madill Reviewed-by: Geoff Lang Commit-Queue: Jamie Madill --- CONTRIBUTORS | 3 ++ src/compiler/translator/OutputHLSL.cpp | 15 ++++++--- src/libANGLE/renderer/d3d/DynamicHLSL.cpp | 29 ++++++++++++----- src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp | 37 +++++++++++++++++++--- src/libANGLE/renderer/d3d/d3d11/StateManager11.h | 22 +++++++++++-- .../renderer/d3d/d3d11/renderer11_utils.cpp | 3 ++ 6 files changed, 89 insertions(+), 20 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index c1c2e4d1c9..770d7e4284 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -210,3 +210,6 @@ Collabora, Ltd. LunarG, Inc. Mark Lobodzinski + +Valve Corporation + Steven Noonan diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp index 001d9031d7..04ba480399 100644 --- a/src/compiler/translator/OutputHLSL.cpp +++ b/src/compiler/translator/OutputHLSL.cpp @@ -969,14 +969,17 @@ void OutputHLSL::header(TInfoSinkBase &out, out << " float multiviewSelectViewportIndex : packoffset(c3.z);\n"; } + out << " float clipControlOrigin : packoffset(c3.w);\n"; + out << " float clipControlZeroToOne : packoffset(c4);\n"; + if (mOutputType == SH_HLSL_4_1_OUTPUT) { - mResourcesHLSL->samplerMetadataUniforms(out, 4); + mResourcesHLSL->samplerMetadataUniforms(out, 5); } if (mUsesVertexID) { - out << " uint dx_VertexID : packoffset(c3.w);\n"; + out << " uint dx_VertexID : packoffset(c4.y);\n"; } out << "};\n" @@ -990,8 +993,12 @@ void OutputHLSL::header(TInfoSinkBase &out, } out << "uniform float4 dx_ViewAdjust : register(c1);\n"; - out << "uniform float2 dx_ViewCoords : register(c2);\n" - "\n"; + out << "uniform float2 dx_ViewCoords : register(c2);\n"; + + out << "static const float clipControlOrigin = -1.0f;\n"; + out << "static const float clipControlZeroToOne = 0.0f;\n"; + + out << "\n"; } if (mUsesDepthRange) diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp index 6c167f7a9f..950a6ef269 100644 --- a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp +++ b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp @@ -553,12 +553,19 @@ void DynamicHLSL::generateShaderLinkHLSL(const gl::Caps &caps, } else { - vertexGenerateOutput << " output.dx_Position.y = - gl_Position.y;\n"; + vertexGenerateOutput + << " output.dx_Position.y = clipControlOrigin * gl_Position.y;\n"; } vertexGenerateOutput - << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - << " output.dx_Position.w = gl_Position.w;\n"; + << " if (clipControlZeroToOne)\n" + << " {\n" + << " output.dx_Position.z = gl_Position.z;\n" + << " } else {\n" + << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + << " }\n"; + + vertexGenerateOutput << " output.dx_Position.w = gl_Position.w;\n"; } else { @@ -576,14 +583,20 @@ void DynamicHLSL::generateShaderLinkHLSL(const gl::Caps &caps, } else { - vertexGenerateOutput - << " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + " - "dx_ViewAdjust.y * gl_Position.w);\n"; + vertexGenerateOutput << " output.dx_Position.y = clipControlOrigin * (gl_Position.y " + "* dx_ViewAdjust.w + " + "dx_ViewAdjust.y * gl_Position.w);\n"; } vertexGenerateOutput - << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - << " output.dx_Position.w = gl_Position.w;\n"; + << " if (clipControlZeroToOne)\n" + << " {\n" + << " output.dx_Position.z = gl_Position.z;\n" + << " } else {\n" + << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + << " }\n"; + + vertexGenerateOutput << " output.dx_Position.w = gl_Position.w;\n"; } // We don't need to output gl_PointSize if we use are emulating point sprites via instancing. diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp index fd94e2bdee..6b14031c88 100644 --- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp @@ -589,6 +589,13 @@ void ShaderConstants11::onImageChange(gl::ShaderType shaderType, } } +void ShaderConstants11::onClipControlChange(bool lowerLeft, bool zeroToOne) +{ + mVertex.clipControlOrigin = lowerLeft ? -1.0f : 1.0f; + mVertex.clipControlZeroToOne = zeroToOne ? 1.0f : 0.0f; + mShaderConstantsDirty.set(gl::ShaderType::Vertex); +} + angle::Result ShaderConstants11::updateBuffer(const gl::Context *context, Renderer11 *renderer, gl::ShaderType shaderType, @@ -848,12 +855,12 @@ void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized, void StateManager11::checkPresentPath(const gl::Context *context) { - if (!mRenderer->presentPathFastEnabled()) - return; - const auto *framebuffer = context->getState().getDrawFramebuffer(); const auto *firstColorAttachment = framebuffer->getFirstColorAttachment(); - const bool presentPathFastActive = UsePresentPathFast(mRenderer, firstColorAttachment); + const bool clipSpaceOriginUpperLeft = + context->getState().getClipSpaceOrigin() == gl::ClipSpaceOrigin::UpperLeft; + const bool presentPathFastActive = + UsePresentPathFast(mRenderer, firstColorAttachment) || clipSpaceOriginUpperLeft; const int colorBufferHeight = firstColorAttachment ? firstColorAttachment->getSize().height : 0; @@ -1205,6 +1212,22 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt case gl::State::DIRTY_BIT_PROVOKING_VERTEX: invalidateShaders(); break; + case gl::State::DIRTY_BIT_EXTENDED: + { + gl::State::ExtendedDirtyBits extendedDirtyBits = + state.getAndResetExtendedDirtyBits(); + + for (size_t extendedDirtyBit : extendedDirtyBits) + { + switch (extendedDirtyBit) + { + case gl::State::EXTENDED_DIRTY_BIT_CLIP_CONTROL: + checkPresentPath(context); + break; + } + } + break; + } default: break; } @@ -1429,6 +1452,10 @@ void StateManager11::syncViewport(const gl::Context *context) dxMinViewportBoundsY = 0; } + bool clipSpaceOriginLowerLeft = glState.getClipSpaceOrigin() == gl::ClipSpaceOrigin::LowerLeft; + mShaderConstants.onClipControlChange(clipSpaceOriginLowerLeft, + glState.isClipControlDepthZeroToOne()); + const auto &viewport = glState.getViewport(); int dxViewportTopLeftX = 0; @@ -1447,7 +1474,7 @@ void StateManager11::syncViewport(const gl::Context *context) D3D11_VIEWPORT dxViewport; dxViewport.TopLeftX = static_cast(dxViewportTopLeftX); - if (mCurPresentPathFastEnabled) + if (mCurPresentPathFastEnabled && clipSpaceOriginLowerLeft) { // When present path fast is active and we're rendering to framebuffer 0, we must invert // the viewport in Y-axis. diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h index 3155b2bf47..ee2fe887a0 100644 --- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h +++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h @@ -53,6 +53,7 @@ class ShaderConstants11 : angle::NonCopyable void onImageChange(gl::ShaderType shaderType, unsigned int imageIndex, const gl::ImageUnit &imageUnit); + void onClipControlChange(bool lowerLeft, bool zeroToOne); angle::Result updateBuffer(const gl::Context *context, Renderer11 *renderer, @@ -69,7 +70,10 @@ class ShaderConstants11 : angle::NonCopyable viewCoords{.0f}, viewScale{.0f}, multiviewWriteToViewportIndex{.0f}, - firstVertex{0} + clipControlOrigin{-1.0f}, + clipControlZeroToOne{.0f}, + firstVertex{0}, + padding{.0f, .0f} {} float depthRange[4]; @@ -81,8 +85,19 @@ class ShaderConstants11 : angle::NonCopyable // whenever a multi-view draw framebuffer is made active. float multiviewWriteToViewportIndex; + // EXT_clip_control + // Multiplied with Y coordinate: -1.0 for GL_LOWER_LEFT_EXT, 1.0f for GL_UPPER_LEFT_EXT + float clipControlOrigin; + // 0.0 for GL_NEGATIVE_ONE_TO_ONE_EXT, 1.0 for GL_ZERO_TO_ONE_EXT + float clipControlZeroToOne; + uint32_t firstVertex; + + // Added here to manually pad the struct to 16 byte boundary + float padding[2]; }; + static_assert(sizeof(Vertex) % 16u == 0, + "D3D11 constant buffers must be multiples of 16 bytes"); struct Pixel { @@ -91,8 +106,8 @@ class ShaderConstants11 : angle::NonCopyable viewCoords{.0f}, depthFront{.0f}, viewScale{.0f}, - multiviewWriteToViewportIndex(0), - padding(0) + multiviewWriteToViewportIndex{.0f}, + padding{.0f} {} float depthRange[4]; @@ -107,6 +122,7 @@ class ShaderConstants11 : angle::NonCopyable // Added here to manually pad the struct. float padding; }; + static_assert(sizeof(Pixel) % 16u == 0, "D3D11 constant buffers must be multiples of 16 bytes"); struct Compute { diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp index f9f6c18e7a..00b40848ea 100644 --- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp @@ -1666,6 +1666,9 @@ void GenerateCaps(ID3D11Device *device, extensions->readStencilNV = false; extensions->depthBufferFloat2NV = false; + // GL_EXT_clip_control + extensions->clipControlEXT = (renderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_9_3); + // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing. // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't // support gl_FrontFacing. -- cgit v1.2.3