Commit c1d4e550 by Martin Radev Committed by Commit Bot

D3D11: Select view in vertex shader

View selection can happen in the vertex shader through the optional feature VPAndRTArrayIndexFromAnyShaderFeedingRasterizer. BUG=angleproject:2062 TEST=angle_end2end_tests Change-Id: Iaf65685e04f828b0936295fea867f6f6cbe69bee Reviewed-on: https://chromium-review.googlesource.com/628419 Commit-Queue: Martin Radev <mradev@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 630d558f
......@@ -107,6 +107,11 @@ struct WorkaroundsD3D
// for buffer data.
// D3D11-only workaround. See http://crbug.com/593024.
bool useSystemMemoryForConstantBuffers = false;
// This workaround is for the ANGLE_multiview extension. If enabled the viewport or render
// target slice will be selected in the geometry shader stage. The workaround flag is added to
// make it possible to select the code path in end2end and performance tests.
bool selectViewInGeometryShader = false;
};
} // namespace angle
......
......@@ -507,7 +507,18 @@ void DynamicHLSL::generateShaderLinkHLSL(const gl::Context *context,
if (vertexBuiltins.glViewIDOVR.enabled)
{
vertexStream << " output.gl_ViewID_OVR = _ViewID_OVR;\n";
vertexStream << " output.gl_ViewID_OVR = _ViewID_OVR;\n";
}
if (programMetadata.hasANGLEMultiviewEnabled() && programMetadata.canSelectViewInVertexShader())
{
ASSERT(vertexBuiltins.glViewportIndex.enabled && vertexBuiltins.glLayer.enabled);
vertexStream << " if (multiviewSelectViewportIndex)\n"
<< " {\n"
<< " output.gl_ViewportIndex = _ViewID_OVR;\n"
<< " } else {\n"
<< " output.gl_ViewportIndex = 0;\n"
<< " output.gl_Layer = _ViewID_OVR;\n"
<< " }\n";
}
// On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
......@@ -906,7 +917,8 @@ std::string DynamicHLSL::generateComputeShaderLinkHLSL(const gl::Context *contex
std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking,
const BuiltinVaryingsD3D &builtinsD3D,
const bool hasANGLEMultiviewEnabled) const
const bool hasANGLEMultiviewEnabled,
const bool selectViewInVS) const
{
ASSERT(mRenderer->getMajorShaderModel() >= 4);
......@@ -932,6 +944,21 @@ std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &va
preambleStream << " output.gl_PointSize = input.gl_PointSize;\n";
}
if (hasANGLEMultiviewEnabled)
{
preambleStream << " output.gl_ViewID_OVR = input.gl_ViewID_OVR;\n";
if (selectViewInVS)
{
ASSERT(builtinsD3D[SHADER_GEOMETRY].glViewportIndex.enabled &&
builtinsD3D[SHADER_GEOMETRY].glLayer.enabled);
// If the view is already selected in the VS, then we just pass the gl_ViewportIndex and
// gl_Layer to the output.
preambleStream << " output.gl_ViewportIndex = input.gl_ViewportIndex;\n"
<< " output.gl_Layer = input.gl_Layer;\n";
}
}
for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList())
{
preambleStream << " output.v" << varyingRegister.semanticIndex << " = ";
......@@ -953,7 +980,7 @@ std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &va
<< "#endif // ANGLE_POINT_SPRITE_SHADER\n"
<< "}\n";
if (hasANGLEMultiviewEnabled)
if (hasANGLEMultiviewEnabled && !selectViewInVS)
{
ASSERT(builtinsD3D[SHADER_GEOMETRY].glViewportIndex.enabled &&
builtinsD3D[SHADER_GEOMETRY].glLayer.enabled);
......@@ -966,7 +993,6 @@ std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &va
preambleStream << "\n"
<< "void selectView(inout GS_OUTPUT output, GS_INPUT input)\n"
<< "{\n"
<< " output.gl_ViewID_OVR = input.gl_ViewID_OVR;\n"
<< " if (multiviewSelectViewportIndex)\n"
<< " {\n"
<< " output.gl_ViewportIndex = input.gl_ViewID_OVR;\n"
......@@ -985,6 +1011,7 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT
const gl::ProgramState &programData,
const bool useViewScale,
const bool hasANGLEMultiviewEnabled,
const bool selectViewInVS,
const bool pointSpriteEmulation,
const std::string &preambleString) const
{
......@@ -1120,7 +1147,7 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT
{
shaderStream << " copyVertex(output, input[" << vertexIndex
<< "], input[lastVertexIndex]);\n";
if (hasANGLEMultiviewEnabled)
if (hasANGLEMultiviewEnabled && !selectViewInVS)
{
shaderStream << " selectView(output, input[" << vertexIndex << "]);\n";
}
......@@ -1345,6 +1372,11 @@ void BuiltinVaryingsD3D::updateBuiltins(ShaderType shaderType,
if (shaderType == SHADER_VERTEX && metadata.hasANGLEMultiviewEnabled())
{
builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++);
if (metadata.canSelectViewInVertexShader())
{
builtins->glViewportIndex.enableSystem("SV_ViewportArrayIndex");
builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex");
}
}
if (shaderType == SHADER_PIXEL && metadata.hasANGLEMultiviewEnabled())
......
......@@ -132,13 +132,15 @@ class DynamicHLSL : angle::NonCopyable
std::string generateGeometryShaderPreamble(const gl::VaryingPacking &varyingPacking,
const BuiltinVaryingsD3D &builtinsD3D,
const bool hasANGLEMultiviewEnabled) const;
const bool hasANGLEMultiviewEnabled,
const bool selectViewInVS) const;
std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
const gl::ContextState &data,
const gl::ProgramState &programData,
const bool useViewScale,
const bool hasANGLEMultiviewEnabled,
const bool selectViewInVS,
const bool pointSpriteEmulation,
const std::string &preambleString) const;
......
......@@ -377,6 +377,7 @@ ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
mUsesViewScale(renderer->presentPathFastEnabled()),
mHasANGLEMultiviewEnabled(vertexShader->hasANGLEMultiviewEnabled()),
mUsesViewID(fragmentShader->usesViewID()),
mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()),
mVertexShader(vertexShader),
mFragmentShader(fragmentShader)
{
......@@ -434,6 +435,11 @@ bool ProgramD3DMetadata::usesViewID() const
return mUsesViewID;
}
bool ProgramD3DMetadata::canSelectViewInVertexShader() const
{
return mCanSelectViewInVertexShader;
}
bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
{
// PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
......@@ -601,7 +607,7 @@ bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
{
if (mHasANGLEMultiviewEnabled)
if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader())
{
return true;
}
......@@ -1322,8 +1328,8 @@ gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::ContextSta
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
geometryShaderType, data, mState, mRenderer->presentPathFastEnabled(),
mHasANGLEMultiviewEnabled, usesGeometryShaderForPointSpriteEmulation(),
mGeometryShaderPreamble);
mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
gl::InfoLog tempInfoLog;
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
......@@ -1623,7 +1629,8 @@ gl::LinkResult ProgramD3D::link(const gl::Context *context,
if (mRenderer->getMajorShaderModel() >= 4)
{
mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
packing, builtins, mHasANGLEMultiviewEnabled);
packing, builtins, mHasANGLEMultiviewEnabled,
metadata.canSelectViewInVertexShader());
}
initAttribLocationsToD3DSemantic(context);
......
......@@ -130,6 +130,7 @@ class ProgramD3DMetadata final : angle::NonCopyable
bool usesViewScale() const;
bool hasANGLEMultiviewEnabled() const;
bool usesViewID() const;
bool canSelectViewInVertexShader() const;
bool addsPointCoordToVertexShader() const;
bool usesTransformFeedbackGLPosition() const;
bool usesSystemValuePointSize() const;
......@@ -144,6 +145,7 @@ class ProgramD3DMetadata final : angle::NonCopyable
const bool mUsesViewScale;
const bool mHasANGLEMultiviewEnabled;
const bool mUsesViewID;
const bool mCanSelectViewInVertexShader;
const ShaderD3D *mVertexShader;
const ShaderD3D *mFragmentShader;
};
......
......@@ -331,6 +331,8 @@ class RendererD3D : public BufferFactoryD3D
Serial generateSerial();
virtual bool canSelectViewInVertexShader() const = 0;
protected:
virtual bool getLUID(LUID *adapterLuid) const = 0;
virtual void generateCaps(gl::Caps *outCaps,
......
......@@ -450,6 +450,7 @@ Renderer11::Renderer11(egl::Display *display)
mRenderer11DeviceCaps.supportsClearView = false;
mRenderer11DeviceCaps.supportsConstantBufferOffsets = false;
mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false;
mRenderer11DeviceCaps.supportsDXGI1_2 = false;
mRenderer11DeviceCaps.B5G6R5support = 0;
mRenderer11DeviceCaps.B4G4R4A4support = 0;
......@@ -921,6 +922,18 @@ void Renderer11::populateRenderer11DeviceCaps()
}
}
if (mDeviceContext3)
{
D3D11_FEATURE_DATA_D3D11_OPTIONS3 d3d11Options3;
HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &d3d11Options3,
sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3));
if (SUCCEEDED(result))
{
mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader =
(d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE);
}
}
if (getWorkarounds().disableB5G6R5Support)
{
mRenderer11DeviceCaps.B5G6R5support = 0;
......@@ -4477,4 +4490,10 @@ gl::Error Renderer11::clearRenderTarget(RenderTargetD3D *renderTarget,
return gl::NoError();
}
bool Renderer11::canSelectViewInVertexShader() const
{
return !getWorkarounds().selectViewInGeometryShader &&
getRenderer11DeviceCaps().supportsVpRtIndexWriteFromVertexShader;
}
} // namespace rx
......@@ -49,6 +49,8 @@ struct Renderer11DeviceCaps
bool supportsDXGI1_2; // Support for DXGI 1.2
bool supportsClearView; // Support for ID3D11DeviceContext1::ClearView
bool supportsConstantBufferOffsets; // Support for Constant buffer offset
bool supportsVpRtIndexWriteFromVertexShader; // VP/RT can be selected in the Vertex Shader
// stage.
UINT B5G6R5support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM
UINT B5G6R5maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B5G6R5_UNORM
UINT B4G4R4A4support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM
......@@ -463,6 +465,8 @@ class Renderer11 : public RendererD3D
const float clearDepthValue,
const unsigned int clearStencilValue) override;
bool canSelectViewInVertexShader() const override;
private:
gl::Error drawArraysImpl(const gl::Context *context,
GLenum mode,
......
......@@ -2084,6 +2084,11 @@ angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps
workarounds.emulateTinyStencilTextures = false;
}
// If the VPAndRTArrayIndexFromAnyShaderFeedingRasterizer feature is not available, we have to
// select the viewport / RT array index in the geometry shader.
workarounds.selectViewInGeometryShader =
(deviceCaps.supportsVpRtIndexWriteFromVertexShader == false);
// Call platform hooks for testing overrides.
auto *platform = ANGLEPlatformCurrent();
platform->overrideWorkaroundsD3D(platform, &workarounds);
......
......@@ -398,6 +398,8 @@ class Renderer9 : public RendererD3D
const float clearDepthValue,
const unsigned int clearStencilValue) override;
bool canSelectViewInVertexShader() const override { return false; }
private:
gl::Error drawArraysImpl(const gl::ContextState &data,
GLenum mode,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment