Commit c07ef602 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Move xfb buffer decl to translator in emulation path

This makes @@ XFB-DECL @@ empty on this path. Ultimately, this is working towards removing both @@ XFB-DECL @@ and @@ XFB-OUT @@ macros for both the emulation and extension paths, allowing the shaders to be compiled at compile time rather than link time. Bug: angleproject:3606 Change-Id: If16e9d92c419a04ecd3094481ed546d0708cdb43 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2611305 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent a1b4a1f3
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 248 #define ANGLE_SH_VERSION 249
enum ShShaderSpec enum ShShaderSpec
{ {
...@@ -875,6 +875,9 @@ extern const char kLineRasterEmulationPosition[]; ...@@ -875,6 +875,9 @@ extern const char kLineRasterEmulationPosition[];
// Transform feedback emulation helper function // Transform feedback emulation helper function
extern const char kXfbEmulationGetOffsetsFunctionName[]; extern const char kXfbEmulationGetOffsetsFunctionName[];
extern const char kXfbEmulationBufferBlockName[];
extern const char kXfbEmulationBufferName[];
extern const char kXfbEmulationBufferFieldName[];
} // namespace vk } // namespace vk
......
...@@ -140,6 +140,7 @@ class BitSetT final ...@@ -140,6 +140,7 @@ class BitSetT final
constexpr static BitSetT Zero() { return BitSetT(); } constexpr static BitSetT Zero() { return BitSetT(); }
ParamT first() const; ParamT first() const;
ParamT last() const;
private: private:
// Produces a mask of ones up to the "x"th bit. // Produces a mask of ones up to the "x"th bit.
...@@ -460,6 +461,13 @@ ParamT BitSetT<N, BitsT, ParamT>::first() const ...@@ -460,6 +461,13 @@ ParamT BitSetT<N, BitsT, ParamT>::first() const
} }
template <size_t N, typename BitsT, typename ParamT> template <size_t N, typename BitsT, typename ParamT>
ParamT BitSetT<N, BitsT, ParamT>::last() const
{
ASSERT(!none());
return static_cast<ParamT>(gl::ScanReverse(mBits));
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(bits), mCurrentBit(0) BitSetT<N, BitsT, ParamT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(bits), mCurrentBit(0)
{ {
if (bits.any()) if (bits.any())
......
...@@ -1163,6 +1163,13 @@ bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType) ...@@ -1163,6 +1163,13 @@ bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType)
return false; return false;
} }
} }
ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes)
{
shaderTypes.reset(ShaderType::Fragment);
shaderTypes.reset(ShaderType::Compute);
return shaderTypes.any() ? shaderTypes.last() : ShaderType::InvalidEnum;
}
} // namespace gl } // namespace gl
namespace egl namespace egl
......
...@@ -247,6 +247,9 @@ enum class SrgbOverride ...@@ -247,6 +247,9 @@ enum class SrgbOverride
ShaderType GetShaderTypeFromBitfield(size_t singleShaderType); ShaderType GetShaderTypeFromBitfield(size_t singleShaderType);
bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType); bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType);
// Given a set of shader stages, returns the last vertex processing stage. This is the stage that
// interfaces the fragment shader.
ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes);
} // namespace gl } // namespace gl
......
...@@ -793,6 +793,9 @@ const char kAtomicCountersBlockName[] = "ANGLEAtomicCounters"; ...@@ -793,6 +793,9 @@ const char kAtomicCountersBlockName[] = "ANGLEAtomicCounters";
const char kLineRasterEmulationPosition[] = "ANGLEPosition"; const char kLineRasterEmulationPosition[] = "ANGLEPosition";
const char kXfbEmulationGetOffsetsFunctionName[] = "ANGLEGetXfbOffsets"; const char kXfbEmulationGetOffsetsFunctionName[] = "ANGLEGetXfbOffsets";
const char kXfbEmulationBufferBlockName[] = "ANGLEXfbBuffer";
const char kXfbEmulationBufferName[] = "ANGLEXfb";
const char kXfbEmulationBufferFieldName[] = "xfbOut";
} // namespace vk } // namespace vk
......
...@@ -463,7 +463,9 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler, ...@@ -463,7 +463,9 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler,
// return ANGLEUniforms.xfbBufferOffsets + xfbIndex * strides; // return ANGLEUniforms.xfbBufferOffsets + xfbIndex * strides;
// } // }
const TType *ivec4Type = StaticType::GetBasic<EbtInt, 4>(); constexpr uint32_t kMaxXfbBuffers = 4;
const TType *ivec4Type = StaticType::GetBasic<EbtInt, kMaxXfbBuffers>();
// Create the parameter variable. // Create the parameter variable.
TVariable *stridesVar = new TVariable(symbolTable, ImmutableString("strides"), ivec4Type, TVariable *stridesVar = new TVariable(symbolTable, ImmutableString("strides"), ivec4Type,
...@@ -506,9 +508,49 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler, ...@@ -506,9 +508,49 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler,
CreateInternalFunctionDefinitionNode(*getOffsetsFunction, body); CreateInternalFunctionDefinitionNode(*getOffsetsFunction, body);
// Insert the function declaration before main(). // Insert the function declaration before main().
size_t mainIndex = FindMainIndex(root); const size_t mainIndex = FindMainIndex(root);
root->insertChildNodes(mainIndex, {functionDef}); root->insertChildNodes(mainIndex, {functionDef});
// Additionally, generate the following storage buffer declarations used to capture transform
// feedback output. Again, there's a maximum of four buffers.
//
// buffer ANGLEXfbBuffer0
// {
// float xfbOut[];
// } ANGLEXfb0;
// buffer ANGLEXfbBuffer1
// {
// float xfbOut[];
// } ANGLEXfb1;
// ...
for (uint32_t bufferIndex = 0; bufferIndex < kMaxXfbBuffers; ++bufferIndex)
{
TFieldList *fieldList = new TFieldList;
TType *xfbOutType = new TType(EbtFloat);
xfbOutType->makeArray(0);
TField *field = new TField(xfbOutType, ImmutableString(vk::kXfbEmulationBufferFieldName),
TSourceLoc(), SymbolType::AngleInternal);
fieldList->push_back(field);
static_assert(
kMaxXfbBuffers < 10,
"ImmutableStringBuilder memory size below needs to accomodate the number of buffers");
ImmutableStringBuilder blockName(strlen(vk::kXfbEmulationBufferBlockName) + 2);
blockName << vk::kXfbEmulationBufferBlockName;
blockName.appendDecimal(bufferIndex);
ImmutableStringBuilder varName(strlen(vk::kXfbEmulationBufferName) + 2);
varName << vk::kXfbEmulationBufferName;
varName.appendDecimal(bufferIndex);
DeclareInterfaceBlock(root, symbolTable, fieldList, EvqBuffer, TMemoryQualifier::Create(),
0, blockName, varName);
}
return compiler->validateAST(root); return compiler->validateAST(root);
} }
......
...@@ -1250,32 +1250,24 @@ bool ProgramState::hasAttachedShader() const ...@@ -1250,32 +1250,24 @@ bool ProgramState::hasAttachedShader() const
ShaderType ProgramState::getFirstAttachedShaderStageType() const ShaderType ProgramState::getFirstAttachedShaderStageType() const
{ {
if (mExecutable->getLinkedShaderStages().none()) const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
if (linkedStages.none())
{ {
return ShaderType::InvalidEnum; return ShaderType::InvalidEnum;
} }
return *mExecutable->getLinkedShaderStages().begin(); return linkedStages.first();
} }
ShaderType ProgramState::getLastAttachedShaderStageType() const ShaderType ProgramState::getLastAttachedShaderStageType() const
{ {
for (int i = gl::kAllGraphicsShaderTypes.size() - 1; i >= 0; --i) const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
if (linkedStages.none())
{ {
const gl::ShaderType shaderType = gl::kAllGraphicsShaderTypes[i]; return ShaderType::InvalidEnum;
if (mExecutable->hasLinkedShaderStage(shaderType))
{
return shaderType;
}
}
if (mExecutable->hasLinkedShaderStage(ShaderType::Compute))
{
return ShaderType::Compute;
} }
return ShaderType::InvalidEnum; return linkedStages.last();
} }
ShaderType ProgramState::getAttachedTransformFeedbackStage() const ShaderType ProgramState::getAttachedTransformFeedbackStage() const
......
...@@ -489,15 +489,7 @@ bool ProgramExecutable::isYUVOutput() const ...@@ -489,15 +489,7 @@ bool ProgramExecutable::isYUVOutput() const
ShaderType ProgramExecutable::getLinkedTransformFeedbackStage() const ShaderType ProgramExecutable::getLinkedTransformFeedbackStage() const
{ {
if (mLinkedGraphicsShaderStages[ShaderType::Geometry]) return GetLastPreFragmentStage(mLinkedGraphicsShaderStages);
{
return ShaderType::Geometry;
}
if (mLinkedGraphicsShaderStages[ShaderType::TessEvaluation])
{
return ShaderType::TessEvaluation;
}
return ShaderType::Vertex;
} }
bool ProgramExecutable::linkMergedVaryings( bool ProgramExecutable::linkMergedVaryings(
......
...@@ -338,8 +338,10 @@ void GenerateTransformFeedbackVaryingOutput(const gl::TransformFeedbackVarying & ...@@ -338,8 +338,10 @@ void GenerateTransformFeedbackVaryingOutput(const gl::TransformFeedbackVarying &
{ {
for (int row = 0; row < info.rowCount; ++row) for (int row = 0; row < info.rowCount; ++row)
{ {
*xfbOut << "xfbOut" << bufferIndex << "[xfbOffsets[" << bufferIndex << "] + " *xfbOut << sh::vk::kXfbEmulationBufferName << bufferIndex << "."
<< offset << "] = " << info.glslAsFloat << "(" << varying.mappedName; << sh::vk::kXfbEmulationBufferFieldName << "[xfbOffsets[" << bufferIndex
<< "] + " << offset << "] = " << info.glslAsFloat << "("
<< varying.mappedName;
if (varying.isArray()) if (varying.isArray())
{ {
...@@ -363,6 +365,39 @@ void GenerateTransformFeedbackVaryingOutput(const gl::TransformFeedbackVarying & ...@@ -363,6 +365,39 @@ void GenerateTransformFeedbackVaryingOutput(const gl::TransformFeedbackVarying &
} }
} }
void AssignTransformFeedbackEmulationBindings(gl::ShaderType shaderType,
const gl::ProgramState &programState,
bool isTransformFeedbackStage,
GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{
size_t bufferCount = 0;
if (isTransformFeedbackStage)
{
ASSERT(!programState.getLinkedTransformFeedbackVaryings().empty());
const bool isInterleaved =
programState.getTransformFeedbackBufferMode() == GL_INTERLEAVED_ATTRIBS;
bufferCount = isInterleaved ? 1 : programState.getLinkedTransformFeedbackVaryings().size();
}
// Add entries for the transform feedback buffers to the info map, so they can have correct
// set/binding.
for (uint32_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
{
AddResourceInfo(variableInfoMapOut, shaderType, GetXfbBufferName(bufferIndex),
programInterfaceInfo->uniformsAndXfbDescriptorSetIndex,
programInterfaceInfo->currentUniformBindingIndex);
++programInterfaceInfo->currentUniformBindingIndex;
}
// Remove inactive transform feedback buffers.
for (uint32_t bufferIndex = bufferCount;
bufferIndex < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; ++bufferIndex)
{
variableInfoMapOut->add(shaderType, GetXfbBufferName(bufferIndex));
}
}
void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &options, void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &options,
gl::ShaderType shaderType, gl::ShaderType shaderType,
const gl::ProgramState &programState, const gl::ProgramState &programState,
...@@ -379,27 +414,6 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio ...@@ -379,27 +414,6 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio
ASSERT(bufferCount > 0); ASSERT(bufferCount > 0);
const std::string xfbSet = Str(programInterfaceInfo->uniformsAndXfbDescriptorSetIndex); const std::string xfbSet = Str(programInterfaceInfo->uniformsAndXfbDescriptorSetIndex);
std::vector<std::string> xfbIndices(bufferCount);
std::string xfbDecl;
for (uint32_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
{
const std::string xfbBinding = Str(programInterfaceInfo->currentUniformBindingIndex);
xfbIndices[bufferIndex] = Str(bufferIndex);
std::string bufferName = GetXfbBufferName(bufferIndex);
xfbDecl += "layout(set = " + xfbSet + ", binding = " + xfbBinding + ") buffer " +
bufferName + " { float xfbOut" + Str(bufferIndex) + "[]; };\n";
// Add this entry to the info map, so we can easily assert that every resource has an entry
// in this map.
AddResourceInfo(variableInfoMapOut, shaderType, bufferName,
programInterfaceInfo->uniformsAndXfbDescriptorSetIndex,
programInterfaceInfo->currentUniformBindingIndex);
++programInterfaceInfo->currentUniformBindingIndex;
}
const std::string driverUniforms = std::string(sh::vk::kDriverUniformsVarName); const std::string driverUniforms = std::string(sh::vk::kDriverUniformsVarName);
std::ostringstream xfbOut; std::ostringstream xfbOut;
...@@ -430,7 +444,7 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio ...@@ -430,7 +444,7 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio
// For every varying, output to the respective buffer packed. If interleaved, the output is // For every varying, output to the respective buffer packed. If interleaved, the output is
// always to the same buffer, but at different offsets. // always to the same buffer, but at different offsets.
const gl::UniformTypeInfo &info = gl::GetUniformTypeInfo(varying.type); const gl::UniformTypeInfo &info = gl::GetUniformTypeInfo(varying.type);
GenerateTransformFeedbackVaryingOutput(varying, info, outputOffset, xfbIndices[bufferIndex], GenerateTransformFeedbackVaryingOutput(varying, info, outputOffset, Str(bufferIndex),
&xfbOut); &xfbOut);
if (isInterleaved) if (isInterleaved)
...@@ -440,7 +454,7 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio ...@@ -440,7 +454,7 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio
} }
xfbOut << "}\n"; xfbOut << "}\n";
*vertexShader = SubstituteTransformFeedbackMarkers(*vertexShader, xfbDecl, xfbOut.str()); *vertexShader = SubstituteTransformFeedbackMarkers(*vertexShader, "", xfbOut.str());
} }
bool IsFirstRegisterOfVarying(const gl::PackedVaryingRegister &varyingReg, bool allowFields) bool IsFirstRegisterOfVarying(const gl::PackedVaryingRegister &varyingReg, bool allowFields)
...@@ -2305,6 +2319,19 @@ bool SpirvTransformer::transformDebugInfo(const uint32_t *instruction, size_t wo ...@@ -2305,6 +2319,19 @@ bool SpirvTransformer::transformDebugInfo(const uint32_t *instruction, size_t wo
(id == mInputPerVertex.typeId && member > mInputPerVertex.maxActiveMember); (id == mInputPerVertex.typeId && member > mInputPerVertex.maxActiveMember);
} }
// In the case of ANGLEXfbN, unconditionally remove the variable names. If transform
// feedback is not active, the corresponding variables will be removed.
if (GetSpirvInstructionOp(instruction) == spv::OpName)
{
// SPIR-V 1.0 Section 3.32 Instructions, OpName
constexpr size_t kNameIndex = 2;
const char *name = reinterpret_cast<const char *>(&instruction[kNameIndex]);
if (angle::BeginsWith(name, sh::vk::kXfbEmulationBufferName))
{
return true;
}
}
return false; return false;
} }
...@@ -2540,6 +2567,20 @@ bool SpirvTransformer::transformVariable(const uint32_t *instruction, size_t wor ...@@ -2540,6 +2567,20 @@ bool SpirvTransformer::transformVariable(const uint32_t *instruction, size_t wor
return false; return false;
} }
if (mOptions.isTransformFeedbackStage && storageClass == spv::StorageClassUniform)
{
// Exceptionally, the ANGLEXfbN variables are unconditionally generated and may be inactive.
// Remove these variables in that case.
ASSERT(mOptions.shaderType == gl::ShaderType::Vertex);
ASSERT(info == &mVariableInfoMap.get(mOptions.shaderType, GetXfbBufferName(0)) ||
info == &mVariableInfoMap.get(mOptions.shaderType, GetXfbBufferName(1)) ||
info == &mVariableInfoMap.get(mOptions.shaderType, GetXfbBufferName(2)) ||
info == &mVariableInfoMap.get(mOptions.shaderType, GetXfbBufferName(3)));
// Drop the declaration.
return true;
}
// Copy the declaration even though the variable is inactive for the separately compiled shader. // Copy the declaration even though the variable is inactive for the separately compiled shader.
ASSERT(storageClass == spv::StorageClassOutput || storageClass == spv::StorageClassInput); ASSERT(storageClass == spv::StorageClassOutput || storageClass == spv::StorageClassInput);
...@@ -3797,7 +3838,7 @@ std::string GlslangGetMappedSamplerName(const std::string &originalName) ...@@ -3797,7 +3838,7 @@ std::string GlslangGetMappedSamplerName(const std::string &originalName)
std::string GetXfbBufferName(const uint32_t bufferIndex) std::string GetXfbBufferName(const uint32_t bufferIndex)
{ {
return "xfbBuffer" + Str(bufferIndex); return sh::vk::kXfbEmulationBufferBlockName + Str(bufferIndex);
} }
void GlslangGenTransformFeedbackEmulationOutputs(const GlslangSourceOptions &options, void GlslangGenTransformFeedbackEmulationOutputs(const GlslangSourceOptions &options,
...@@ -3812,13 +3853,16 @@ void GlslangGenTransformFeedbackEmulationOutputs(const GlslangSourceOptions &opt ...@@ -3812,13 +3853,16 @@ void GlslangGenTransformFeedbackEmulationOutputs(const GlslangSourceOptions &opt
} }
void GlslangAssignLocations(const GlslangSourceOptions &options, void GlslangAssignLocations(const GlslangSourceOptions &options,
const gl::ProgramExecutable &programExecutable, const gl::ProgramState &programState,
const gl::ProgramVaryingPacking &varyingPacking, const gl::ProgramVaryingPacking &varyingPacking,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
const gl::ShaderType frontShaderType, const gl::ShaderType frontShaderType,
bool isTransformFeedbackStage,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
const gl::ProgramExecutable &programExecutable = programState.getExecutable();
// Assign outputs to the fragment shader, if any. // Assign outputs to the fragment shader, if any.
if ((shaderType == gl::ShaderType::Fragment) && if ((shaderType == gl::ShaderType::Fragment) &&
programExecutable.hasLinkedShaderStage(gl::ShaderType::Fragment)) programExecutable.hasLinkedShaderStage(gl::ShaderType::Fragment))
...@@ -3866,6 +3910,12 @@ void GlslangAssignLocations(const GlslangSourceOptions &options, ...@@ -3866,6 +3910,12 @@ void GlslangAssignLocations(const GlslangSourceOptions &options,
variableInfoMapOut); variableInfoMapOut);
AssignNonTextureBindings(options, programExecutable, shaderType, programInterfaceInfo, AssignNonTextureBindings(options, programExecutable, shaderType, programInterfaceInfo,
variableInfoMapOut); variableInfoMapOut);
if (options.emulateTransformFeedback && gl::ShaderTypeSupportsTransformFeedback(shaderType))
{
AssignTransformFeedbackEmulationBindings(shaderType, programState, isTransformFeedbackStage,
programInterfaceInfo, variableInfoMapOut);
}
} }
void GlslangGetShaderSource(const GlslangSourceOptions &options, void GlslangGetShaderSource(const GlslangSourceOptions &options,
...@@ -3929,8 +3979,10 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options, ...@@ -3929,8 +3979,10 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
for (const gl::ShaderType shaderType : programState.getExecutable().getLinkedShaderStages()) for (const gl::ShaderType shaderType : programState.getExecutable().getLinkedShaderStages())
{ {
GlslangAssignLocations(options, programState.getExecutable(), resources.varyingPacking, const bool isXfbStage =
shaderType, frontShaderType, programInterfaceInfo, shaderType == xfbStage && !programState.getLinkedTransformFeedbackVaryings().empty();
GlslangAssignLocations(options, programState, resources.varyingPacking, shaderType,
frontShaderType, isXfbStage, programInterfaceInfo,
variableInfoMapOut); variableInfoMapOut);
frontShaderType = shaderType; frontShaderType = shaderType;
......
...@@ -158,7 +158,7 @@ void GlslangRelease(); ...@@ -158,7 +158,7 @@ void GlslangRelease();
bool GetImageNameWithoutIndices(std::string *name); bool GetImageNameWithoutIndices(std::string *name);
// Get the mapped sampler name after the soure is transformed by GlslangGetShaderSource() // Get the mapped sampler name after the source is transformed by GlslangGetShaderSource()
std::string GetMappedSamplerNameOld(const std::string &originalName); std::string GetMappedSamplerNameOld(const std::string &originalName);
std::string GlslangGetMappedSamplerName(const std::string &originalName); std::string GlslangGetMappedSamplerName(const std::string &originalName);
std::string GetXfbBufferName(const uint32_t bufferIndex); std::string GetXfbBufferName(const uint32_t bufferIndex);
...@@ -172,10 +172,11 @@ void GlslangGenTransformFeedbackEmulationOutputs( ...@@ -172,10 +172,11 @@ void GlslangGenTransformFeedbackEmulationOutputs(
ShaderInterfaceVariableInfoMap *variableInfoMapOut); ShaderInterfaceVariableInfoMap *variableInfoMapOut);
void GlslangAssignLocations(const GlslangSourceOptions &options, void GlslangAssignLocations(const GlslangSourceOptions &options,
const gl::ProgramExecutable &programExecutable, const gl::ProgramState &programState,
const gl::ProgramVaryingPacking &varyingPacking, const gl::ProgramVaryingPacking &varyingPacking,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
const gl::ShaderType frontShaderType, const gl::ShaderType frontShaderType,
bool isTransformFeedbackStage,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut); ShaderInterfaceVariableInfoMap *variableInfoMapOut);
......
...@@ -414,6 +414,8 @@ void GlslangGetShaderSource(const gl::ProgramState &programState, ...@@ -414,6 +414,8 @@ void GlslangGetShaderSource(const gl::ProgramState &programState,
GlslangProgramInterfaceInfo programInterfaceInfo; GlslangProgramInterfaceInfo programInterfaceInfo;
ResetGlslangProgramInterfaceInfo(&programInterfaceInfo); ResetGlslangProgramInterfaceInfo(&programInterfaceInfo);
options.emulateTransformFeedback = true;
rx::GlslangGetShaderSource(options, programState, resources, &programInterfaceInfo, rx::GlslangGetShaderSource(options, programState, resources, &programInterfaceInfo,
shaderSourcesOut, variableInfoMapOut); shaderSourcesOut, variableInfoMapOut);
...@@ -426,15 +428,17 @@ void GlslangGetShaderSource(const gl::ProgramState &programState, ...@@ -426,15 +428,17 @@ void GlslangGetShaderSource(const gl::ProgramState &programState,
GlslangProgramInterfaceInfo xfbOnlyInterfaceInfo; GlslangProgramInterfaceInfo xfbOnlyInterfaceInfo;
ResetGlslangProgramInterfaceInfo(&xfbOnlyInterfaceInfo); ResetGlslangProgramInterfaceInfo(&xfbOnlyInterfaceInfo);
options.emulateTransformFeedback = true;
rx::GlslangGenTransformFeedbackEmulationOutputs( rx::GlslangGenTransformFeedbackEmulationOutputs(
options, programState, &xfbOnlyInterfaceInfo, xfbOnlyShaderSourceOut, options, programState, &xfbOnlyInterfaceInfo, xfbOnlyShaderSourceOut,
xfbOnlyVSVariableInfoMapOut); xfbOnlyVSVariableInfoMapOut);
GlslangAssignLocations(options, programState.getExecutable(), resources.varyingPacking, const bool isTransformFeedbackStage =
!programState.getLinkedTransformFeedbackVaryings().empty();
GlslangAssignLocations(options, programState, resources.varyingPacking,
gl::ShaderType::Vertex, gl::ShaderType::InvalidEnum, gl::ShaderType::Vertex, gl::ShaderType::InvalidEnum,
&xfbOnlyInterfaceInfo, xfbOnlyVSVariableInfoMapOut); isTransformFeedbackStage, &xfbOnlyInterfaceInfo,
xfbOnlyVSVariableInfoMapOut);
} }
} }
...@@ -454,7 +458,8 @@ angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context, ...@@ -454,7 +458,8 @@ angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
for (const gl::ShaderType shaderType : linkedShaderStages) for (const gl::ShaderType shaderType : linkedShaderStages)
{ {
GlslangSpirvOptions options; GlslangSpirvOptions options;
options.shaderType = shaderType; options.shaderType = shaderType;
options.isTransformFeedbackStage = shaderType == gl::ShaderType::Vertex;
angle::Result status = GlslangTransformSpirvCode( angle::Result status = GlslangTransformSpirvCode(
[context](GlslangError error) { return HandleError(context, error); }, options, [context](GlslangError error) { return HandleError(context, error); }, options,
......
...@@ -818,14 +818,15 @@ angle::Result ProgramExecutableVk::createPipelineLayout( ...@@ -818,14 +818,15 @@ angle::Result ProgramExecutableVk::createPipelineLayout(
gl_vk::kShaderStageMap[shaderType], nullptr); gl_vk::kShaderStageMap[shaderType], nullptr);
mNumDefaultUniformDescriptors++; mNumDefaultUniformDescriptors++;
} }
bool hasVertexShader = glExecutable.hasLinkedShaderStage(gl::ShaderType::Vertex);
gl::ShaderType linkedTransformFeedbackStage = glExecutable.getLinkedTransformFeedbackStage();
bool hasXfbVaryings = bool hasXfbVaryings =
(programStates[gl::ShaderType::Vertex] && linkedTransformFeedbackStage != gl::ShaderType::InvalidEnum &&
!programStates[gl::ShaderType::Vertex]->getLinkedTransformFeedbackVaryings().empty()); !programStates[linkedTransformFeedbackStage]->getLinkedTransformFeedbackVaryings().empty();
if (hasVertexShader && transformFeedback && hasXfbVaryings) if (transformFeedback && hasXfbVaryings)
{ {
const gl::ProgramExecutable &executable = const gl::ProgramExecutable &executable =
programStates[gl::ShaderType::Vertex]->getExecutable(); programStates[linkedTransformFeedbackStage]->getExecutable();
size_t xfbBufferCount = executable.getTransformFeedbackBufferCount(); size_t xfbBufferCount = executable.getTransformFeedbackBufferCount();
TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback); TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
transformFeedbackVk->updateDescriptorSetLayout(contextVk, mVariableInfoMap, xfbBufferCount, transformFeedbackVk->updateDescriptorSetLayout(contextVk, mVariableInfoMap, xfbBufferCount,
......
...@@ -56,9 +56,10 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext, ...@@ -56,9 +56,10 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext,
const gl::ProgramMergedVaryings &mergedVaryings, const gl::ProgramMergedVaryings &mergedVaryings,
const gl::ProgramVaryingPacking &varyingPacking) const gl::ProgramVaryingPacking &varyingPacking)
{ {
ContextVk *contextVk = vk::GetImpl(glContext); ContextVk *contextVk = vk::GetImpl(glContext);
const gl::State &glState = glContext->getState(); const gl::State &glState = glContext->getState();
const gl::ProgramPipeline *glPipeline = glState.getProgramPipeline(); const gl::ProgramPipeline *glPipeline = glState.getProgramPipeline();
const gl::ProgramExecutable &glExecutable = glPipeline->getExecutable();
GlslangSourceOptions options = GlslangSourceOptions options =
GlslangWrapperVk::CreateSourceOptions(contextVk->getRenderer()->getFeatures()); GlslangWrapperVk::CreateSourceOptions(contextVk->getRenderer()->getFeatures());
GlslangProgramInterfaceInfo glslangProgramInterfaceInfo; GlslangProgramInterfaceInfo glslangProgramInterfaceInfo;
...@@ -68,8 +69,10 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext, ...@@ -68,8 +69,10 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext,
// Now that the program pipeline has all of the programs attached, the various descriptor // Now that the program pipeline has all of the programs attached, the various descriptor
// set/binding locations need to be re-assigned to their correct values. // set/binding locations need to be re-assigned to their correct values.
const gl::ShaderType linkedTransformFeedbackStage =
glExecutable.getLinkedTransformFeedbackStage();
gl::ShaderType frontShaderType = gl::ShaderType::InvalidEnum; gl::ShaderType frontShaderType = gl::ShaderType::InvalidEnum;
for (const gl::ShaderType shaderType : glPipeline->getExecutable().getLinkedShaderStages()) for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
{ {
gl::Program *glProgram = gl::Program *glProgram =
const_cast<gl::Program *>(glPipeline->getShaderProgram(shaderType)); const_cast<gl::Program *>(glPipeline->getShaderProgram(shaderType));
...@@ -83,9 +86,13 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext, ...@@ -83,9 +86,13 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext,
glslangProgramInterfaceInfo.locationsUsedForXfbExtension = glslangProgramInterfaceInfo.locationsUsedForXfbExtension =
programProgramInterfaceInfo.locationsUsedForXfbExtension; programProgramInterfaceInfo.locationsUsedForXfbExtension;
GlslangAssignLocations(options, glProgram->getState().getExecutable(), varyingPacking, const bool isTransformFeedbackStage =
shaderType, frontShaderType, &glslangProgramInterfaceInfo, shaderType == linkedTransformFeedbackStage &&
&mExecutable.mVariableInfoMap); !glProgram->getState().getLinkedTransformFeedbackVaryings().empty();
GlslangAssignLocations(options, glProgram->getState(), varyingPacking, shaderType,
frontShaderType, isTransformFeedbackStage,
&glslangProgramInterfaceInfo, &mExecutable.mVariableInfoMap);
frontShaderType = shaderType; frontShaderType = shaderType;
} }
} }
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
namespace rx namespace rx
{ {
TransformFeedbackVk::TransformFeedbackVk(const gl::TransformFeedbackState &state) TransformFeedbackVk::TransformFeedbackVk(const gl::TransformFeedbackState &state)
: TransformFeedbackImpl(state), : TransformFeedbackImpl(state),
mRebindTransformFeedbackBuffer(false), mRebindTransformFeedbackBuffer(false),
...@@ -208,7 +207,9 @@ void TransformFeedbackVk::updateDescriptorSetLayout( ...@@ -208,7 +207,9 @@ void TransformFeedbackVk::updateDescriptorSetLayout(
vk::DescriptorSetLayoutDesc *descSetLayoutOut) const vk::DescriptorSetLayoutDesc *descSetLayoutOut) const
{ {
if (!contextVk->getFeatures().emulateTransformFeedback.enabled) if (!contextVk->getFeatures().emulateTransformFeedback.enabled)
{
return; return;
}
for (uint32_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex) for (uint32_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
{ {
...@@ -227,7 +228,9 @@ void TransformFeedbackVk::initDescriptorSet(ContextVk *contextVk, ...@@ -227,7 +228,9 @@ void TransformFeedbackVk::initDescriptorSet(ContextVk *contextVk,
VkDescriptorSet descSet) const VkDescriptorSet descSet) const
{ {
if (!contextVk->getFeatures().emulateTransformFeedback.enabled) if (!contextVk->getFeatures().emulateTransformFeedback.enabled)
{
return; return;
}
VkDescriptorBufferInfo *descriptorBufferInfo = VkDescriptorBufferInfo *descriptorBufferInfo =
contextVk->allocDescriptorBufferInfos(xfbBufferCount); contextVk->allocDescriptorBufferInfos(xfbBufferCount);
...@@ -250,7 +253,9 @@ void TransformFeedbackVk::updateDescriptorSet(ContextVk *contextVk, ...@@ -250,7 +253,9 @@ void TransformFeedbackVk::updateDescriptorSet(ContextVk *contextVk,
VkDescriptorSet descSet) const VkDescriptorSet descSet) const
{ {
if (!contextVk->getFeatures().emulateTransformFeedback.enabled) if (!contextVk->getFeatures().emulateTransformFeedback.enabled)
{
return; return;
}
const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable(); const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
ASSERT(executable); ASSERT(executable);
...@@ -284,7 +289,9 @@ void TransformFeedbackVk::getBufferOffsets(ContextVk *contextVk, ...@@ -284,7 +289,9 @@ void TransformFeedbackVk::getBufferOffsets(ContextVk *contextVk,
size_t offsetsSize) const size_t offsetsSize) const
{ {
if (!contextVk->getFeatures().emulateTransformFeedback.enabled) if (!contextVk->getFeatures().emulateTransformFeedback.enabled)
{
return; return;
}
GLsizeiptr verticesDrawn = mState.getVerticesDrawn(); GLsizeiptr verticesDrawn = mState.getVerticesDrawn();
const std::vector<GLsizei> &bufferStrides = const std::vector<GLsizei> &bufferStrides =
...@@ -319,7 +326,7 @@ void TransformFeedbackVk::getBufferOffsets(ContextVk *contextVk, ...@@ -319,7 +326,7 @@ void TransformFeedbackVk::getBufferOffsets(ContextVk *contextVk,
void TransformFeedbackVk::writeDescriptorSet(ContextVk *contextVk, void TransformFeedbackVk::writeDescriptorSet(ContextVk *contextVk,
const ShaderInterfaceVariableInfoMap &variableInfoMap, const ShaderInterfaceVariableInfoMap &variableInfoMap,
size_t xfbBufferCount, size_t xfbBufferCount,
VkDescriptorBufferInfo *pBufferInfo, VkDescriptorBufferInfo *bufferInfo,
VkDescriptorSet descSet) const VkDescriptorSet descSet) const
{ {
ASSERT(contextVk->getFeatures().emulateTransformFeedback.enabled); ASSERT(contextVk->getFeatures().emulateTransformFeedback.enabled);
...@@ -336,7 +343,7 @@ void TransformFeedbackVk::writeDescriptorSet(ContextVk *contextVk, ...@@ -336,7 +343,7 @@ void TransformFeedbackVk::writeDescriptorSet(ContextVk *contextVk,
writeDescriptorInfo.descriptorCount = static_cast<uint32_t>(xfbBufferCount); writeDescriptorInfo.descriptorCount = static_cast<uint32_t>(xfbBufferCount);
writeDescriptorInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; writeDescriptorInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
writeDescriptorInfo.pImageInfo = nullptr; writeDescriptorInfo.pImageInfo = nullptr;
writeDescriptorInfo.pBufferInfo = pBufferInfo; writeDescriptorInfo.pBufferInfo = bufferInfo;
writeDescriptorInfo.pTexelBufferView = nullptr; writeDescriptorInfo.pTexelBufferView = nullptr;
} }
......
...@@ -98,7 +98,7 @@ class TransformFeedbackVk : public TransformFeedbackImpl ...@@ -98,7 +98,7 @@ class TransformFeedbackVk : public TransformFeedbackImpl
void writeDescriptorSet(ContextVk *contextVk, void writeDescriptorSet(ContextVk *contextVk,
const ShaderInterfaceVariableInfoMap &variableInfoMap, const ShaderInterfaceVariableInfoMap &variableInfoMap,
size_t xfbBufferCount, size_t xfbBufferCount,
VkDescriptorBufferInfo *pBufferInfo, VkDescriptorBufferInfo *bufferInfo,
VkDescriptorSet descSet) const; VkDescriptorSet descSet) const;
void initializeXFBBuffersDesc(ContextVk *contextVk, size_t xfbBufferCount); void initializeXFBBuffersDesc(ContextVk *contextVk, size_t xfbBufferCount);
......
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