Commit f6df8692 by Jamie Madill Committed by Commit Bot

Vulkan: Support XFB in non-Vertex stages.

This updates the code in several places to support Geometry and Tessellation Evaluation shaders to output transform feedback. Does not turn on any new tests but enables support for XFB when we turn on GS/TS. Bug: angleproject:3571 Bug: angleproject:3572 Change-Id: I6dcb768f2df4eeee81a4a500e999fcf16716f58f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2581941Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 8707811d
...@@ -1150,6 +1150,19 @@ ShaderType GetShaderTypeFromBitfield(size_t singleShaderType) ...@@ -1150,6 +1150,19 @@ ShaderType GetShaderTypeFromBitfield(size_t singleShaderType)
return ShaderType::InvalidEnum; return ShaderType::InvalidEnum;
} }
} }
bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType)
{
switch (shaderType)
{
case ShaderType::Vertex:
case ShaderType::Geometry:
case ShaderType::TessEvaluation:
return true;
default:
return false;
}
}
} // namespace gl } // namespace gl
namespace egl namespace egl
......
...@@ -246,6 +246,7 @@ enum class SrgbOverride ...@@ -246,6 +246,7 @@ enum class SrgbOverride
}; };
ShaderType GetShaderTypeFromBitfield(size_t singleShaderType); ShaderType GetShaderTypeFromBitfield(size_t singleShaderType);
bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType);
} // namespace gl } // namespace gl
......
...@@ -341,7 +341,7 @@ ANGLE_NO_DISCARD bool AppendPreRotation(TCompiler *compiler, ...@@ -341,7 +341,7 @@ ANGLE_NO_DISCARD bool AppendPreRotation(TCompiler *compiler,
return RunAtTheEndOfShader(compiler, root, assignment, symbolTable); return RunAtTheEndOfShader(compiler, root, assignment, symbolTable);
} }
ANGLE_NO_DISCARD bool AppendVertexShaderTransformFeedbackOutputToMain(TCompiler *compiler, ANGLE_NO_DISCARD bool AppendTransformFeedbackOutputToMain(TCompiler *compiler,
TIntermBlock *root, TIntermBlock *root,
TSymbolTable *symbolTable) TSymbolTable *symbolTable)
{ {
...@@ -745,11 +745,12 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -745,11 +745,12 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
return false; return false;
} }
gl::ShaderType packedShaderType = gl::FromGLenum<gl::ShaderType>(getShaderType());
if (defaultUniformCount > 0) if (defaultUniformCount > 0)
{ {
gl::ShaderType shaderType = gl::FromGLenum<gl::ShaderType>(getShaderType());
sink << "\nlayout(set=0, binding=" << outputGLSL->nextUnusedBinding() sink << "\nlayout(set=0, binding=" << outputGLSL->nextUnusedBinding()
<< ", std140) uniform " << kDefaultUniformNames[shaderType] << "\n{\n"; << ", std140) uniform " << kDefaultUniformNames[packedShaderType] << "\n{\n";
DeclareDefaultUniformsTraverser defaultTraverser(&sink, getHashFunction(), &getNameMap()); DeclareDefaultUniformsTraverser defaultTraverser(&sink, getHashFunction(), &getNameMap());
root->traverse(&defaultTraverser); root->traverse(&defaultTraverser);
...@@ -797,7 +798,7 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -797,7 +798,7 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
} }
} }
if (getShaderType() != GL_COMPUTE_SHADER) if (packedShaderType != gl::ShaderType::Compute)
{ {
if (!ReplaceGLDepthRangeWithDriverUniform(this, root, driverUniforms, &getSymbolTable())) if (!ReplaceGLDepthRangeWithDriverUniform(this, root, driverUniforms, &getSymbolTable()))
{ {
...@@ -814,9 +815,21 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -814,9 +815,21 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
} }
} }
// Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData if (gl::ShaderTypeSupportsTransformFeedback(packedShaderType))
// if it's core profile shaders and they are used. {
if (getShaderType() == GL_FRAGMENT_SHADER) // Add a macro to declare transform feedback buffers.
sink << "@@ XFB-DECL @@\n\n";
// Append a macro for transform feedback substitution prior to modifying depth.
if (!AppendTransformFeedbackOutputToMain(this, root, &getSymbolTable()))
{
return false;
}
}
switch (packedShaderType)
{
case gl::ShaderType::Fragment:
{ {
bool usesPointCoord = false; bool usesPointCoord = false;
bool usesFragCoord = false; bool usesFragCoord = false;
...@@ -852,7 +865,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -852,7 +865,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
if (compileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION) if (compileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION)
{ {
if (!AddBresenhamEmulationFS(this, compileOptions, sink, root, &getSymbolTable(), if (!AddBresenhamEmulationFS(this, compileOptions, sink, root, &getSymbolTable(),
&surfaceRotationSpecConst, driverUniforms, usesFragCoord)) &surfaceRotationSpecConst, driverUniforms,
usesFragCoord))
{ {
return false; return false;
} }
...@@ -885,6 +899,9 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -885,6 +899,9 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
continue; continue;
} }
} }
// Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
// if it's core profile shaders and they are used.
ASSERT(!(hasGLFragColor && hasGLFragData)); ASSERT(!(hasGLFragColor && hasGLFragData));
if (hasGLFragColor) if (hasGLFragColor)
{ {
...@@ -913,7 +930,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -913,7 +930,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
} }
} }
if (!RotateAndFlipBuiltinVariable(this, root, GetMainSequence(root), flipNegXY, if (!RotateAndFlipBuiltinVariable(this, root, GetMainSequence(root), flipNegXY,
&getSymbolTable(), BuiltInVariable::gl_PointCoord(), &getSymbolTable(),
BuiltInVariable::gl_PointCoord(),
kFlippedPointCoordName, pivot, fragRotation)) kFlippedPointCoordName, pivot, fragRotation))
{ {
return false; return false;
...@@ -958,8 +976,9 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -958,8 +976,9 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
} }
{ {
const TVariable *numSamplesVar = static_cast<const TVariable *>( const TVariable *numSamplesVar =
getSymbolTable().findBuiltIn(ImmutableString("gl_NumSamples"), getShaderVersion())); static_cast<const TVariable *>(getSymbolTable().findBuiltIn(
ImmutableString("gl_NumSamples"), getShaderVersion()));
TIntermBinary *numSamples = driverUniforms->getNumSamplesRef(); TIntermBinary *numSamples = driverUniforms->getNumSamplesRef();
if (!ReplaceVariableWithTyped(this, root, numSamplesVar, numSamples)) if (!ReplaceVariableWithTyped(this, root, numSamplesVar, numSamples))
{ {
...@@ -968,8 +987,10 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -968,8 +987,10 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
} }
EmitEarlyFragmentTestsGLSL(*this, sink); EmitEarlyFragmentTestsGLSL(*this, sink);
break;
} }
else if (getShaderType() == GL_VERTEX_SHADER)
case gl::ShaderType::Vertex:
{ {
if (compileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION) if (compileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION)
{ {
...@@ -980,15 +1001,6 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -980,15 +1001,6 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
mSpecConstUsageBits.set(vk::SpecConstUsage::LineRasterEmulation); mSpecConstUsageBits.set(vk::SpecConstUsage::LineRasterEmulation);
} }
// Add a macro to declare transform feedback buffers.
sink << "@@ XFB-DECL @@\n\n";
// Append a macro for transform feedback substitution prior to modifying depth.
if (!AppendVertexShaderTransformFeedbackOutputToMain(this, root, &getSymbolTable()))
{
return false;
}
// Search for the gl_ClipDistance usage, if its used, we need to do some replacements. // Search for the gl_ClipDistance usage, if its used, we need to do some replacements.
bool useClipDistance = false; bool useClipDistance = false;
for (const ShaderVariable &outputVarying : mOutputVaryings) for (const ShaderVariable &outputVarying : mOutputVaryings)
...@@ -1021,22 +1033,31 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -1021,22 +1033,31 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
{ {
return false; return false;
} }
break;
} }
else if (getShaderType() == GL_GEOMETRY_SHADER)
case gl::ShaderType::Geometry:
{ {
int maxVertices = getGeometryShaderMaxVertices(); int maxVertices = getGeometryShaderMaxVertices();
// max_vertices=0 is not valid in Vulkan // max_vertices=0 is not valid in Vulkan
maxVertices = std::max(1, maxVertices); maxVertices = std::max(1, maxVertices);
WriteGeometryShaderLayoutQualifiers(sink, getGeometryShaderInputPrimitiveType(), WriteGeometryShaderLayoutQualifiers(
getGeometryShaderInvocations(), sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
getGeometryShaderOutputPrimitiveType(), maxVertices); getGeometryShaderOutputPrimitiveType(), maxVertices);
break;
} }
else
case gl::ShaderType::Compute:
{ {
ASSERT(getShaderType() == GL_COMPUTE_SHADER);
EmitWorkGroupSizeGLSL(*this, sink); EmitWorkGroupSizeGLSL(*this, sink);
break;
}
default:
UNREACHABLE();
break;
} }
surfaceRotationSpecConst.outputLayoutString(sink); surfaceRotationSpecConst.outputLayoutString(sink);
......
...@@ -1276,6 +1276,19 @@ ShaderType ProgramState::getLastAttachedShaderStageType() const ...@@ -1276,6 +1276,19 @@ ShaderType ProgramState::getLastAttachedShaderStageType() const
return ShaderType::InvalidEnum; return ShaderType::InvalidEnum;
} }
ShaderType ProgramState::getAttachedTransformFeedbackStage() const
{
if (mAttachedShaders[ShaderType::Geometry])
{
return ShaderType::Geometry;
}
if (mAttachedShaders[ShaderType::TessEvaluation])
{
return ShaderType::TessEvaluation;
}
return ShaderType::Vertex;
}
Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle) Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
: mSerial(factory->generateSerial()), : mSerial(factory->generateSerial()),
mProgram(factory->createProgram(mState)), mProgram(factory->createProgram(mState)),
......
...@@ -372,6 +372,8 @@ class ProgramState final : angle::NonCopyable ...@@ -372,6 +372,8 @@ class ProgramState final : angle::NonCopyable
int getBaseInstanceLocation() const { return mBaseInstanceLocation; } int getBaseInstanceLocation() const { return mBaseInstanceLocation; }
ShaderType getAttachedTransformFeedbackStage() const;
private: private:
friend class MemoryProgramCache; friend class MemoryProgramCache;
friend class Program; friend class Program;
......
...@@ -538,4 +538,17 @@ bool ProgramExecutable::isYUVOutput() const ...@@ -538,4 +538,17 @@ bool ProgramExecutable::isYUVOutput() const
{ {
return !isCompute() && mYUVOutput; return !isCompute() && mYUVOutput;
} }
ShaderType ProgramExecutable::getLinkedTransformFeedbackStage() const
{
if (mLinkedGraphicsShaderStages[ShaderType::Geometry])
{
return ShaderType::Geometry;
}
if (mLinkedGraphicsShaderStages[ShaderType::TessEvaluation])
{
return ShaderType::TessEvaluation;
}
return ShaderType::Vertex;
}
} // namespace gl } // namespace gl
...@@ -152,6 +152,8 @@ class ProgramExecutable final : public angle::Subject ...@@ -152,6 +152,8 @@ class ProgramExecutable final : public angle::Subject
: mLinkedGraphicsShaderStages.count(); : mLinkedGraphicsShaderStages.count();
} }
ShaderType getLinkedTransformFeedbackStage() const;
// A PPO can have both graphics and compute programs attached, so // A PPO can have both graphics and compute programs attached, so
// we don't know if the PPO is a 'graphics' or 'compute' PPO until the // we don't know if the PPO is a 'graphics' or 'compute' PPO until the
// actual draw/dispatch call. // actual draw/dispatch call.
......
...@@ -466,7 +466,7 @@ bool IsFirstRegisterOfVarying(const gl::PackedVaryingRegister &varyingReg) ...@@ -466,7 +466,7 @@ bool IsFirstRegisterOfVarying(const gl::PackedVaryingRegister &varyingReg)
// values for the SPIR-V transformation. // values for the SPIR-V transformation.
void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programState, void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources, const gl::ProgramLinkedResources &resources,
std::string *vertexShader, std::string *xfbShaderSource,
uint32_t *locationsUsedForXfbExtensionOut) uint32_t *locationsUsedForXfbExtensionOut)
{ {
const std::vector<gl::TransformFeedbackVarying> &tfVaryings = const std::vector<gl::TransformFeedbackVarying> &tfVaryings =
...@@ -502,7 +502,7 @@ void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programSt ...@@ -502,7 +502,7 @@ void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programSt
} }
} }
*vertexShader = SubstituteTransformFeedbackMarkers(*vertexShader, xfbDecl, xfbOut); *xfbShaderSource = SubstituteTransformFeedbackMarkers(*xfbShaderSource, xfbDecl, xfbOut);
} }
void AssignAttributeLocations(const gl::ProgramExecutable &programExecutable, void AssignAttributeLocations(const gl::ProgramExecutable &programExecutable,
...@@ -3664,11 +3664,12 @@ void GlslangAssignLocations(const GlslangSourceOptions &options, ...@@ -3664,11 +3664,12 @@ void GlslangAssignLocations(const GlslangSourceOptions &options,
programInterfaceInfo, variableInfoMapOut); programInterfaceInfo, variableInfoMapOut);
if (!programExecutable.getLinkedTransformFeedbackVaryings().empty() && if (!programExecutable.getLinkedTransformFeedbackVaryings().empty() &&
options.supportsTransformFeedbackExtension && (shaderType == gl::ShaderType::Vertex)) options.supportsTransformFeedbackExtension &&
(shaderType == programExecutable.getLinkedTransformFeedbackStage()))
{ {
AssignTransformFeedbackExtensionQualifiers( AssignTransformFeedbackExtensionQualifiers(
programExecutable, programInterfaceInfo->locationsUsedForXfbExtension, programExecutable, programInterfaceInfo->locationsUsedForXfbExtension, shaderType,
gl::ShaderType::Vertex, &(*variableInfoMapOut)[gl::ShaderType::Vertex]); &(*variableInfoMapOut)[shaderType]);
} }
} }
...@@ -3693,34 +3694,48 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options, ...@@ -3693,34 +3694,48 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
(*shaderSourcesOut)[shaderType] = glShader ? glShader->getTranslatedSource() : ""; (*shaderSourcesOut)[shaderType] = glShader ? glShader->getTranslatedSource() : "";
} }
std::string *vertexSource = &(*shaderSourcesOut)[gl::ShaderType::Vertex]; gl::ShaderType xfbStage = programState.getAttachedTransformFeedbackStage();
std::string *xfbSource = &(*shaderSourcesOut)[xfbStage];
// Write transform feedback output code. // Write transform feedback output code.
if (!vertexSource->empty()) if (!xfbSource->empty())
{ {
if (programState.getLinkedTransformFeedbackVaryings().empty()) if (!programState.getLinkedTransformFeedbackVaryings().empty())
{
*vertexSource = SubstituteTransformFeedbackMarkers(*vertexSource, "", "");
}
else
{ {
if (options.supportsTransformFeedbackExtension) if (options.supportsTransformFeedbackExtension)
{ {
GenerateTransformFeedbackExtensionOutputs( GenerateTransformFeedbackExtensionOutputs(
programState, resources, vertexSource, programState, resources, xfbSource,
&programInterfaceInfo->locationsUsedForXfbExtension); &programInterfaceInfo->locationsUsedForXfbExtension);
} }
else if (options.emulateTransformFeedback) else if (options.emulateTransformFeedback)
{ {
GenerateTransformFeedbackEmulationOutputs( ASSERT(xfbStage == gl::ShaderType::Vertex);
options, programState, programInterfaceInfo, vertexSource, GenerateTransformFeedbackEmulationOutputs(options, programState,
&(*variableInfoMapOut)[gl::ShaderType::Vertex]); programInterfaceInfo, xfbSource,
&(*variableInfoMapOut)[xfbStage]);
} }
else else
{ {
*vertexSource = SubstituteTransformFeedbackMarkers(*vertexSource, "", ""); *xfbSource = SubstituteTransformFeedbackMarkers(*xfbSource, "", "");
}
} }
else
{
*xfbSource = SubstituteTransformFeedbackMarkers(*xfbSource, "", "");
}
}
std::string *tessEvalSources = &(*shaderSourcesOut)[gl::ShaderType::TessEvaluation];
if (xfbStage > gl::ShaderType::TessEvaluation && !tessEvalSources->empty())
{
*tessEvalSources = SubstituteTransformFeedbackMarkers(*tessEvalSources, "", "");
} }
std::string *vertexSource = &(*shaderSourcesOut)[gl::ShaderType::Vertex];
if (xfbStage > gl::ShaderType::Vertex && !vertexSource->empty())
{
*vertexSource = SubstituteTransformFeedbackMarkers(*vertexSource, "", "");
} }
gl::ShaderType frontShaderType = gl::ShaderType::InvalidEnum; gl::ShaderType frontShaderType = gl::ShaderType::InvalidEnum;
......
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