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 <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Steven Noonan 2021-10-11 19:26:07 -07:00 коммит произвёл Angle LUCI CQ
Родитель 4b056a17b5
Коммит 01341f9483
6 изменённых файлов: 89 добавлений и 20 удалений

Просмотреть файл

@ -210,3 +210,6 @@ Collabora, Ltd.
LunarG, Inc.
Mark Lobodzinski
Valve Corporation
Steven Noonan

Просмотреть файл

@ -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)

Просмотреть файл

@ -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.

Просмотреть файл

@ -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<float>(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.

Просмотреть файл

@ -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
{

Просмотреть файл

@ -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.