Commit 77637f2d by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Generate xfb support code in SPIR-V for emulation path

This change moves the code generation at link time from source code to SPIR-V. As a result, transform feedback extension and emulation paths are more similarly handled before SPIR-V transformation (they both store information identically in the ShaderInterfaceVariableInfoMap). This change gets rid of the @@ XFB-OUT @@ marker. With no source code generation at link time, shader compilation can be moved to glCompileShader time. Bug: angleproject:4888 Change-Id: I8cdb89c22b57ce48cf5d226b8e41622d9d550d46 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2713269 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 b3fb450c
...@@ -892,6 +892,7 @@ extern const char kLineRasterEmulationPosition[]; ...@@ -892,6 +892,7 @@ extern const char kLineRasterEmulationPosition[];
// Transform feedback emulation support // Transform feedback emulation support
extern const char kXfbEmulationGetOffsetsFunctionName[]; extern const char kXfbEmulationGetOffsetsFunctionName[];
extern const char kXfbEmulationCaptureFunctionName[];
extern const char kXfbEmulationBufferBlockName[]; extern const char kXfbEmulationBufferBlockName[];
extern const char kXfbEmulationBufferName[]; extern const char kXfbEmulationBufferName[];
extern const char kXfbEmulationBufferFieldName[]; extern const char kXfbEmulationBufferFieldName[];
......
{ {
"src/common/gen_uniform_type_table.py": "src/common/gen_uniform_type_table.py":
"f1f6e52f3897773667c714c8da626122", "714cdb13f7c30af4890922a856456ddb",
"src/common/uniform_type_info_autogen.cpp": "src/common/uniform_type_info_autogen.cpp":
"4903e2a4c6c34e65b0f0c0d6eb2b470d" "85b351f2d5525d1af422a880e361a2bd"
} }
\ No newline at end of file
...@@ -101,7 +101,7 @@ const UniformTypeInfo &GetUniformTypeInfo(GLenum uniformType) ...@@ -101,7 +101,7 @@ const UniformTypeInfo &GetUniformTypeInfo(GLenum uniformType)
}} // namespace gl }} // namespace gl
""" """
type_info_data_template = """{{{type}, {component_type}, {texture_type}, {transposed_type}, {bool_type}, {sampler_format}, {rows}, {columns}, {components}, {component_size}, {internal_size}, {external_size}, {is_sampler}, {is_matrix}, {is_image}, {glsl_asfloat} }}""" type_info_data_template = """{{{type}, {component_type}, {texture_type}, {transposed_type}, {bool_type}, {sampler_format}, {rows}, {columns}, {components}, {component_size}, {internal_size}, {external_size}, {is_sampler}, {is_matrix}, {is_image} }}"""
type_index_case_template = """case {enum_value}: return {index_value};""" type_index_case_template = """case {enum_value}: return {index_value};"""
...@@ -224,22 +224,6 @@ def get_is_image(uniform_type): ...@@ -224,22 +224,6 @@ def get_is_image(uniform_type):
return cpp_bool("_VIDEO_" not in uniform_type and "_IMAGE_" in uniform_type) return cpp_bool("_VIDEO_" not in uniform_type and "_IMAGE_" in uniform_type)
def get_glsl_asfloat(uniform_type):
component_type = get_component_type(uniform_type)
if component_type == "GL_BOOL":
return '""'
elif component_type == "GL_FLOAT":
return '""'
elif component_type == "GL_INT":
return '"intBitsToFloat"'
elif component_type == "GL_UNSIGNED_INT":
return '"uintBitsToFloat"'
elif component_type == "GL_NONE":
return '""'
else:
raise "Invalid component type: " + component_type
def gen_type_info(uniform_type): def gen_type_info(uniform_type):
return type_info_data_template.format( return type_info_data_template.format(
type=uniform_type, type=uniform_type,
...@@ -256,8 +240,7 @@ def gen_type_info(uniform_type): ...@@ -256,8 +240,7 @@ def gen_type_info(uniform_type):
external_size=get_external_size(uniform_type), external_size=get_external_size(uniform_type),
is_sampler=get_is_sampler(uniform_type), is_sampler=get_is_sampler(uniform_type),
is_matrix=get_is_matrix(uniform_type), is_matrix=get_is_matrix(uniform_type),
is_image=get_is_image(uniform_type), is_image=get_is_image(uniform_type))
glsl_asfloat=get_glsl_asfloat(uniform_type))
def gen_type_index_case(index, uniform_type): def gen_type_index_case(index, uniform_type):
......
...@@ -148,8 +148,7 @@ struct UniformTypeInfo final : angle::NonCopyable ...@@ -148,8 +148,7 @@ struct UniformTypeInfo final : angle::NonCopyable
size_t externalSize, size_t externalSize,
bool isSampler, bool isSampler,
bool isMatrixType, bool isMatrixType,
bool isImageType, bool isImageType);
const char *glslAsFloat);
GLenum type; GLenum type;
GLenum componentType; GLenum componentType;
...@@ -166,7 +165,6 @@ struct UniformTypeInfo final : angle::NonCopyable ...@@ -166,7 +165,6 @@ struct UniformTypeInfo final : angle::NonCopyable
bool isSampler; bool isSampler;
bool isMatrixType; bool isMatrixType;
bool isImageType; bool isImageType;
const char *glslAsFloat;
}; };
inline constexpr UniformTypeInfo::UniformTypeInfo(GLenum type, inline constexpr UniformTypeInfo::UniformTypeInfo(GLenum type,
...@@ -183,8 +181,7 @@ inline constexpr UniformTypeInfo::UniformTypeInfo(GLenum type, ...@@ -183,8 +181,7 @@ inline constexpr UniformTypeInfo::UniformTypeInfo(GLenum type,
size_t externalSize, size_t externalSize,
bool isSampler, bool isSampler,
bool isMatrixType, bool isMatrixType,
bool isImageType, bool isImageType)
const char *glslAsFloat)
: type(type), : type(type),
componentType(componentType), componentType(componentType),
textureType(textureType), textureType(textureType),
...@@ -199,8 +196,7 @@ inline constexpr UniformTypeInfo::UniformTypeInfo(GLenum type, ...@@ -199,8 +196,7 @@ inline constexpr UniformTypeInfo::UniformTypeInfo(GLenum type,
externalSize(externalSize), externalSize(externalSize),
isSampler(isSampler), isSampler(isSampler),
isMatrixType(isMatrixType), isMatrixType(isMatrixType),
isImageType(isImageType), isImageType(isImageType)
glslAsFloat(glslAsFloat)
{} {}
const UniformTypeInfo &GetUniformTypeInfo(GLenum uniformType); const UniformTypeInfo &GetUniformTypeInfo(GLenum uniformType);
......
...@@ -927,6 +927,7 @@ const char kAtomicCountersBlockName[] = "ANGLEAtomicCounters"; ...@@ -927,6 +927,7 @@ const char kAtomicCountersBlockName[] = "ANGLEAtomicCounters";
const char kLineRasterEmulationPosition[] = "ANGLEPosition"; const char kLineRasterEmulationPosition[] = "ANGLEPosition";
const char kXfbEmulationGetOffsetsFunctionName[] = "ANGLEGetXfbOffsets"; const char kXfbEmulationGetOffsetsFunctionName[] = "ANGLEGetXfbOffsets";
const char kXfbEmulationCaptureFunctionName[] = "ANGLECaptureXfb";
const char kXfbEmulationBufferBlockName[] = "ANGLEXfbBuffer"; const char kXfbEmulationBufferBlockName[] = "ANGLEXfbBuffer";
const char kXfbEmulationBufferName[] = "ANGLEXfb"; const char kXfbEmulationBufferName[] = "ANGLEXfb";
const char kXfbEmulationBufferFieldName[] = "xfbOut"; const char kXfbEmulationBufferFieldName[] = "xfbOut";
......
...@@ -271,17 +271,6 @@ ANGLE_NO_DISCARD bool ReplaceGLDepthRangeWithDriverUniform(TCompiler *compiler, ...@@ -271,17 +271,6 @@ ANGLE_NO_DISCARD bool ReplaceGLDepthRangeWithDriverUniform(TCompiler *compiler,
return ReplaceVariableWithTyped(compiler, root, depthRangeVar, angleEmulatedDepthRangeRef); return ReplaceVariableWithTyped(compiler, root, depthRangeVar, angleEmulatedDepthRangeRef);
} }
ANGLE_NO_DISCARD bool AppendTransformFeedbackOutputToMain(TCompiler *compiler,
TIntermBlock *root,
TSymbolTable *symbolTable)
{
TVariable *xfbPlaceholder = new TVariable(symbolTable, ImmutableString("@@ XFB-OUT @@"),
new TType(), SymbolType::AngleInternal);
// Append the assignment as a statement at the end of the shader.
return RunAtTheEndOfShader(compiler, root, new TIntermSymbol(xfbPlaceholder), symbolTable);
}
TVariable *AddANGLEPositionVaryingDeclaration(TIntermBlock *root, TVariable *AddANGLEPositionVaryingDeclaration(TIntermBlock *root,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
TQualifier qualifier) TQualifier qualifier)
...@@ -442,6 +431,67 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler, ...@@ -442,6 +431,67 @@ ANGLE_NO_DISCARD bool AddXfbEmulationSupport(TCompiler *compiler,
const size_t mainIndex = FindMainIndex(root); const size_t mainIndex = FindMainIndex(root);
root->insertChildNodes(mainIndex, {functionDef}); root->insertChildNodes(mainIndex, {functionDef});
// Generate the following function and place it before main(). This function will be filled
// with transform feedback capture code at link time.
//
// void ANGLECaptureXfb()
// {
// }
const TType *voidType = StaticType::GetBasic<EbtVoid>();
// Create the function body, which is empty.
body = new TIntermBlock;
// Declare the function
TFunction *xfbCaptureFunction =
new TFunction(symbolTable, ImmutableString(vk::kXfbEmulationCaptureFunctionName),
SymbolType::AngleInternal, voidType, false);
// Insert the function declaration before main().
root->insertChildNodes(mainIndex,
{CreateInternalFunctionDefinitionNode(*xfbCaptureFunction, body)});
// Create the following logic and add it at the end of main():
//
// if (ANGLEUniforms.xfbActiveUnpaused)
// {
// ANGLECaptureXfb();
// }
//
// Create a reference ANGLEUniforms.xfbActiveUnpaused
TIntermBinary *xfbActiveUnpaused = driverUniforms->getXfbActiveUnpaused();
// ANGLEUniforms.xfbActiveUnpaused != 0
TIntermBinary *isXfbActiveUnpaused =
new TIntermBinary(EOpNotEqual, xfbActiveUnpaused, CreateUIntNode(0));
// Create the function call
TIntermAggregate *captureXfbCall =
TIntermAggregate::CreateFunctionCall(*xfbCaptureFunction, {});
TIntermBlock *captureXfbBlock = new TIntermBlock;
captureXfbBlock->appendStatement(captureXfbCall);
// Create a call to ANGLEGetXfbOffsets too, for the sole purpose of preventing it from being
// culled as unused by glslang.
TIntermSequence zero;
zero.push_back(CreateIndexNode(0));
TIntermSequence ivec4Zero;
ivec4Zero.push_back(TIntermAggregate::CreateConstructor(*ivec4Type, &zero));
TIntermAggregate *getOffsetsCall =
TIntermAggregate::CreateFunctionCall(*getOffsetsFunction, &ivec4Zero);
captureXfbBlock->appendStatement(getOffsetsCall);
// Create the if
TIntermIfElse *captureXfb = new TIntermIfElse(isXfbActiveUnpaused, captureXfbBlock, nullptr);
// Run it at the end of the shader.
if (!RunAtTheEndOfShader(compiler, root, captureXfb, symbolTable))
{
return false;
}
// Additionally, generate the following storage buffer declarations used to capture transform // Additionally, generate the following storage buffer declarations used to capture transform
// feedback output. Again, there's a maximum of four buffers. // feedback output. Again, there's a maximum of four buffers.
// //
...@@ -951,15 +1001,6 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -951,15 +1001,6 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
return false; return false;
} }
} }
// Append a macro for transform feedback substitution prior to modifying depth.
if ((compileOptions & SH_ADD_VULKAN_XFB_EMULATION_SUPPORT_CODE) != 0)
{
if (!AppendTransformFeedbackOutputToMain(this, root, &getSymbolTable()))
{
return false;
}
}
} }
switch (packedShaderType) switch (packedShaderType)
......
...@@ -178,6 +178,11 @@ TIntermBinary *DriverUniform::getAbcBufferOffsets() const ...@@ -178,6 +178,11 @@ TIntermBinary *DriverUniform::getAbcBufferOffsets() const
return createDriverUniformRef(kAcbBufferOffsets); return createDriverUniformRef(kAcbBufferOffsets);
} }
TIntermBinary *DriverUniform::getXfbActiveUnpaused() const
{
return createDriverUniformRef(kXfbActiveUnpaused);
}
TIntermBinary *DriverUniform::getXfbVerticesPerInstance() const TIntermBinary *DriverUniform::getXfbVerticesPerInstance() const
{ {
return createDriverUniformRef(kXfbVerticesPerInstance); return createDriverUniformRef(kXfbVerticesPerInstance);
......
...@@ -34,6 +34,7 @@ class DriverUniform ...@@ -34,6 +34,7 @@ class DriverUniform
TIntermBinary *getViewportRef() const; TIntermBinary *getViewportRef() const;
TIntermBinary *getAbcBufferOffsets() const; TIntermBinary *getAbcBufferOffsets() const;
TIntermBinary *getXfbActiveUnpaused() const;
TIntermBinary *getXfbVerticesPerInstance() const; TIntermBinary *getXfbVerticesPerInstance() const;
TIntermBinary *getXfbBufferOffsets() const; TIntermBinary *getXfbBufferOffsets() const;
TIntermBinary *getClipDistancesEnabled() const; TIntermBinary *getClipDistancesEnabled() const;
......
...@@ -65,6 +65,7 @@ struct GlslangSpirvOptions ...@@ -65,6 +65,7 @@ struct GlslangSpirvOptions
bool removeEarlyFragmentTestsOptimization = false; bool removeEarlyFragmentTestsOptimization = false;
bool removeDebugInfo = false; bool removeDebugInfo = false;
bool isTransformFeedbackStage = false; bool isTransformFeedbackStage = false;
bool isTransformFeedbackEmulated = false;
}; };
using SpirvBlob = std::vector<uint32_t>; using SpirvBlob = std::vector<uint32_t>;
...@@ -75,9 +76,19 @@ struct ShaderInterfaceVariableXfbInfo ...@@ -75,9 +76,19 @@ struct ShaderInterfaceVariableXfbInfo
{ {
static constexpr uint32_t kInvalid = std::numeric_limits<uint32_t>::max(); static constexpr uint32_t kInvalid = std::numeric_limits<uint32_t>::max();
// Used by both extension and emulation
uint32_t buffer = kInvalid; uint32_t buffer = kInvalid;
uint32_t offset = kInvalid; uint32_t offset = kInvalid;
uint32_t stride = kInvalid; uint32_t stride = kInvalid;
// Used only by emulation (array index support is missing from VK_EXT_transform_feedback)
uint32_t arraySize = kInvalid;
uint32_t columnCount = kInvalid;
uint32_t rowCount = kInvalid;
uint32_t arrayIndex = kInvalid;
GLenum componentType = GL_FLOAT;
// If empty, the whole array is captured. Otherwise only the specified members are captured.
std::vector<ShaderInterfaceVariableXfbInfo> arrayElements;
}; };
// Information for each shader interface variable. Not all fields are relevant to each shader // Information for each shader interface variable. Not all fields are relevant to each shader
...@@ -169,14 +180,6 @@ bool GetImageNameWithoutIndices(std::string *name); ...@@ -169,14 +180,6 @@ bool GetImageNameWithoutIndices(std::string *name);
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);
// NOTE: options.emulateTransformFeedback is ignored in this case. It is assumed to be always true.
void GlslangGenTransformFeedbackEmulationOutputs(
const GlslangSourceOptions &options,
const gl::ProgramState &programState,
GlslangProgramInterfaceInfo *programInterfaceInfo,
std::string *vertexShader,
ShaderInterfaceVariableInfoMap *variableInfoMapOut);
void GlslangAssignLocations(const GlslangSourceOptions &options, void GlslangAssignLocations(const GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramState &programState,
const gl::ProgramVaryingPacking &varyingPacking, const gl::ProgramVaryingPacking &varyingPacking,
......
...@@ -317,11 +317,9 @@ angle::Result ProgramMtl::linkImpl(const gl::Context *glContext, ...@@ -317,11 +317,9 @@ angle::Result ProgramMtl::linkImpl(const gl::Context *glContext,
// Gather variable info and transform sources. // Gather variable info and transform sources.
gl::ShaderMap<std::string> shaderSources; gl::ShaderMap<std::string> shaderSources;
gl::ShaderMap<std::string> xfbOnlyShaderSources;
ShaderInterfaceVariableInfoMap variableInfoMap; ShaderInterfaceVariableInfoMap variableInfoMap;
ShaderInterfaceVariableInfoMap xfbOnlyVariableInfoMap; ShaderInterfaceVariableInfoMap xfbOnlyVariableInfoMap;
mtl::GlslangGetShaderSource(mState, resources, &shaderSources, mtl::GlslangGetShaderSource(mState, resources, &shaderSources, &variableInfoMap,
&xfbOnlyShaderSources[gl::ShaderType::Vertex], &variableInfoMap,
&xfbOnlyVariableInfoMap); &xfbOnlyVariableInfoMap);
// Convert GLSL to spirv code // Convert GLSL to spirv code
...@@ -329,14 +327,14 @@ angle::Result ProgramMtl::linkImpl(const gl::Context *glContext, ...@@ -329,14 +327,14 @@ angle::Result ProgramMtl::linkImpl(const gl::Context *glContext,
gl::ShaderMap<std::vector<uint32_t>> xfbOnlyShaderCodes; // only vertex shader is needed. gl::ShaderMap<std::vector<uint32_t>> xfbOnlyShaderCodes; // only vertex shader is needed.
ANGLE_TRY(mtl::GlslangGetShaderSpirvCode( ANGLE_TRY(mtl::GlslangGetShaderSpirvCode(
contextMtl, mState.getExecutable().getLinkedShaderStages(), contextMtl->getCaps(), contextMtl, mState.getExecutable().getLinkedShaderStages(), contextMtl->getCaps(),
shaderSources, variableInfoMap, &shaderCodes)); shaderSources, false, variableInfoMap, &shaderCodes));
if (!mState.getLinkedTransformFeedbackVaryings().empty()) if (!mState.getLinkedTransformFeedbackVaryings().empty())
{ {
gl::ShaderBitSet onlyVS; gl::ShaderBitSet onlyVS;
onlyVS.set(gl::ShaderType::Vertex); onlyVS.set(gl::ShaderType::Vertex);
ANGLE_TRY(mtl::GlslangGetShaderSpirvCode(contextMtl, onlyVS, contextMtl->getCaps(), ANGLE_TRY(mtl::GlslangGetShaderSpirvCode(contextMtl, onlyVS, contextMtl->getCaps(),
xfbOnlyShaderSources, xfbOnlyVariableInfoMap, shaderSources, true, xfbOnlyVariableInfoMap,
&xfbOnlyShaderCodes)); &xfbOnlyShaderCodes));
} }
......
...@@ -41,12 +41,10 @@ struct TranslatedShaderInfo ...@@ -41,12 +41,10 @@ struct TranslatedShaderInfo
bool hasUBOArgumentBuffer; bool hasUBOArgumentBuffer;
}; };
// - shaderSourcesOut is result GLSL code per shader stage when XFB emulation is turned off. // shaderSourcesOut is result GLSL code per shader stage.
// - xfbOnlyShaderSourceOut will contain vertex shader's GLSL code when XFB emulation is turned on.
void GlslangGetShaderSource(const gl::ProgramState &programState, void GlslangGetShaderSource(const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources, const gl::ProgramLinkedResources &resources,
gl::ShaderMap<std::string> *shaderSourcesOut, gl::ShaderMap<std::string> *shaderSourcesOut,
std::string *xfbOnlyShaderSourceOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut, ShaderInterfaceVariableInfoMap *variableInfoMapOut,
ShaderInterfaceVariableInfoMap *xfbOnlyVSVariableInfoMapOut); ShaderInterfaceVariableInfoMap *xfbOnlyVSVariableInfoMapOut);
...@@ -54,6 +52,7 @@ angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context, ...@@ -54,6 +52,7 @@ angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
const gl::ShaderBitSet &linkedShaderStages, const gl::ShaderBitSet &linkedShaderStages,
const gl::Caps &glCaps, const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources, const gl::ShaderMap<std::string> &shaderSources,
bool isTransformFeedbackEnabled,
const ShaderInterfaceVariableInfoMap &variableInfoMap, const ShaderInterfaceVariableInfoMap &variableInfoMap,
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut); gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut);
......
...@@ -406,7 +406,6 @@ void TranslatedShaderInfo::reset() ...@@ -406,7 +406,6 @@ void TranslatedShaderInfo::reset()
void GlslangGetShaderSource(const gl::ProgramState &programState, void GlslangGetShaderSource(const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources, const gl::ProgramLinkedResources &resources,
gl::ShaderMap<std::string> *shaderSourcesOut, gl::ShaderMap<std::string> *shaderSourcesOut,
std::string *xfbOnlyShaderSourceOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut, ShaderInterfaceVariableInfoMap *variableInfoMapOut,
ShaderInterfaceVariableInfoMap *xfbOnlyVSVariableInfoMapOut) ShaderInterfaceVariableInfoMap *xfbOnlyVSVariableInfoMapOut)
{ {
...@@ -416,32 +415,21 @@ void GlslangGetShaderSource(const gl::ProgramState &programState, ...@@ -416,32 +415,21 @@ void GlslangGetShaderSource(const gl::ProgramState &programState,
options.supportsTransformFeedbackEmulation = true; options.supportsTransformFeedbackEmulation = true;
// This will generate shader source WITHOUT XFB emulated outputs. // Get shader sources and fill variable info map with transform feedback disabled.
rx::GlslangGetShaderSource(options, programState, resources, &programInterfaceInfo, rx::GlslangGetShaderSource(options, programState, resources, &programInterfaceInfo,
shaderSourcesOut, variableInfoMapOut); shaderSourcesOut, variableInfoMapOut);
// This will generate vertex shader source WITH XFB emulated outputs. // Fill variable info map with transform feedback enabled.
if (xfbOnlyShaderSourceOut && !programState.getLinkedTransformFeedbackVaryings().empty()) if (!programState.getLinkedTransformFeedbackVaryings().empty())
{ {
gl::Shader *glShader = programState.getAttachedShader(gl::ShaderType::Vertex);
*xfbOnlyShaderSourceOut = glShader ? glShader->getTranslatedSource() : "";
GlslangProgramInterfaceInfo xfbOnlyInterfaceInfo; GlslangProgramInterfaceInfo xfbOnlyInterfaceInfo;
ResetGlslangProgramInterfaceInfo(&xfbOnlyInterfaceInfo); ResetGlslangProgramInterfaceInfo(&xfbOnlyInterfaceInfo);
options.enableTransformFeedbackEmulation = true; options.enableTransformFeedbackEmulation = true;
rx::GlslangGenTransformFeedbackEmulationOutputs(
options, programState, &xfbOnlyInterfaceInfo, xfbOnlyShaderSourceOut,
xfbOnlyVSVariableInfoMapOut);
const bool isTransformFeedbackStage =
!programState.getLinkedTransformFeedbackVaryings().empty();
GlslangAssignLocations(options, programState, resources.varyingPacking, GlslangAssignLocations(options, programState, resources.varyingPacking,
gl::ShaderType::Vertex, gl::ShaderType::InvalidEnum, gl::ShaderType::Vertex, gl::ShaderType::InvalidEnum, true,
isTransformFeedbackStage, &xfbOnlyInterfaceInfo, &xfbOnlyInterfaceInfo, xfbOnlyVSVariableInfoMapOut);
xfbOnlyVSVariableInfoMapOut);
} }
} }
...@@ -449,6 +437,7 @@ angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context, ...@@ -449,6 +437,7 @@ angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
const gl::ShaderBitSet &linkedShaderStages, const gl::ShaderBitSet &linkedShaderStages,
const gl::Caps &glCaps, const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources, const gl::ShaderMap<std::string> &shaderSources,
bool isTransformFeedbackEnabled,
const ShaderInterfaceVariableInfoMap &variableInfoMap, const ShaderInterfaceVariableInfoMap &variableInfoMap,
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut) gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
{ {
...@@ -463,7 +452,9 @@ angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context, ...@@ -463,7 +452,9 @@ angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
GlslangSpirvOptions options; GlslangSpirvOptions options;
options.shaderType = shaderType; options.shaderType = shaderType;
options.transformPositionToVulkanClipSpace = true; options.transformPositionToVulkanClipSpace = true;
options.isTransformFeedbackStage = shaderType == gl::ShaderType::Vertex; options.isTransformFeedbackStage =
shaderType == gl::ShaderType::Vertex && isTransformFeedbackEnabled;
options.isTransformFeedbackEmulated = true;
angle::Result status = GlslangTransformSpirvCode( angle::Result status = GlslangTransformSpirvCode(
[context](GlslangError error) { return HandleError(context, error); }, options, [context](GlslangError error) { return HandleError(context, error); }, options,
......
...@@ -24,6 +24,42 @@ namespace rx ...@@ -24,6 +24,42 @@ namespace rx
{ {
namespace namespace
{ {
void LoadShaderInterfaceVariableXfbInfo(gl::BinaryInputStream *stream,
ShaderInterfaceVariableXfbInfo *xfb)
{
xfb->buffer = stream->readInt<uint32_t>();
xfb->offset = stream->readInt<uint32_t>();
xfb->stride = stream->readInt<uint32_t>();
xfb->arraySize = stream->readInt<uint32_t>();
xfb->columnCount = stream->readInt<uint32_t>();
xfb->rowCount = stream->readInt<uint32_t>();
xfb->arrayIndex = stream->readInt<uint32_t>();
xfb->componentType = stream->readInt<uint32_t>();
xfb->arrayElements.resize(stream->readInt<size_t>());
for (ShaderInterfaceVariableXfbInfo &arrayElement : xfb->arrayElements)
{
LoadShaderInterfaceVariableXfbInfo(stream, &arrayElement);
}
}
void SaveShaderInterfaceVariableXfbInfo(const ShaderInterfaceVariableXfbInfo &xfb,
gl::BinaryOutputStream *stream)
{
stream->writeInt(xfb.buffer);
stream->writeInt(xfb.offset);
stream->writeInt(xfb.stride);
stream->writeInt(xfb.arraySize);
stream->writeInt(xfb.columnCount);
stream->writeInt(xfb.rowCount);
stream->writeInt(xfb.arrayIndex);
stream->writeInt(xfb.componentType);
stream->writeInt(xfb.arrayElements.size());
for (const ShaderInterfaceVariableXfbInfo &arrayElement : xfb.arrayElements)
{
SaveShaderInterfaceVariableXfbInfo(arrayElement, stream);
}
}
bool ValidateTransformedSpirV(ContextVk *contextVk, bool ValidateTransformedSpirV(ContextVk *contextVk,
const gl::ShaderBitSet &linkedShaderStages, const gl::ShaderBitSet &linkedShaderStages,
const ShaderInterfaceVariableInfoMap &variableInfoMap, const ShaderInterfaceVariableInfoMap &variableInfoMap,
...@@ -125,6 +161,7 @@ ProgramInfo::~ProgramInfo() = default; ...@@ -125,6 +161,7 @@ ProgramInfo::~ProgramInfo() = default;
angle::Result ProgramInfo::initProgram(ContextVk *contextVk, angle::Result ProgramInfo::initProgram(ContextVk *contextVk,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
bool isLastPreFragmentStage, bool isLastPreFragmentStage,
bool isTransformFeedbackProgram,
const ShaderInfo &shaderInfo, const ShaderInfo &shaderInfo,
ProgramTransformOptions optionBits, ProgramTransformOptions optionBits,
const ShaderInterfaceVariableInfoMap &variableInfoMap) const ShaderInterfaceVariableInfoMap &variableInfoMap)
...@@ -138,9 +175,10 @@ angle::Result ProgramInfo::initProgram(ContextVk *contextVk, ...@@ -138,9 +175,10 @@ angle::Result ProgramInfo::initProgram(ContextVk *contextVk,
options.shaderType = shaderType; options.shaderType = shaderType;
options.removeEarlyFragmentTestsOptimization = options.removeEarlyFragmentTestsOptimization =
shaderType == gl::ShaderType::Fragment && optionBits.removeEarlyFragmentTestsOptimization; shaderType == gl::ShaderType::Fragment && optionBits.removeEarlyFragmentTestsOptimization;
options.removeDebugInfo = !contextVk->getRenderer()->getEnableValidationLayers(); options.removeDebugInfo = !contextVk->getRenderer()->getEnableValidationLayers();
options.isTransformFeedbackStage = isLastPreFragmentStage; options.isTransformFeedbackStage = isLastPreFragmentStage && isTransformFeedbackProgram;
options.negativeViewportSupported = contextVk->getFeatures().supportsNegativeViewport.enabled; options.isTransformFeedbackEmulated = contextVk->getFeatures().emulateTransformFeedback.enabled;
options.negativeViewportSupported = contextVk->getFeatures().supportsNegativeViewport.enabled;
if (isLastPreFragmentStage) if (isLastPreFragmentStage)
{ {
...@@ -245,15 +283,11 @@ std::unique_ptr<rx::LinkEvent> ProgramExecutableVk::load(gl::BinaryInputStream * ...@@ -245,15 +283,11 @@ std::unique_ptr<rx::LinkEvent> ProgramExecutableVk::load(gl::BinaryInputStream *
info.component = stream->readInt<uint32_t>(); info.component = stream->readInt<uint32_t>();
// PackedEnumBitSet uses uint8_t // PackedEnumBitSet uses uint8_t
info.activeStages = gl::ShaderBitSet(stream->readInt<uint8_t>()); info.activeStages = gl::ShaderBitSet(stream->readInt<uint8_t>());
info.xfb.buffer = stream->readInt<uint32_t>(); LoadShaderInterfaceVariableXfbInfo(stream, &info.xfb);
info.xfb.offset = stream->readInt<uint32_t>();
info.xfb.stride = stream->readInt<uint32_t>();
info.fieldXfb.resize(stream->readInt<size_t>()); info.fieldXfb.resize(stream->readInt<size_t>());
for (ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb) for (ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
{ {
xfb.buffer = stream->readInt<uint32_t>(); LoadShaderInterfaceVariableXfbInfo(stream, &xfb);
xfb.offset = stream->readInt<uint32_t>();
xfb.stride = stream->readInt<uint32_t>();
} }
info.useRelaxedPrecision = stream->readBool(); info.useRelaxedPrecision = stream->readBool();
info.varyingIsInput = stream->readBool(); info.varyingIsInput = stream->readBool();
...@@ -283,15 +317,11 @@ void ProgramExecutableVk::save(gl::BinaryOutputStream *stream) ...@@ -283,15 +317,11 @@ void ProgramExecutableVk::save(gl::BinaryOutputStream *stream)
stream->writeInt(info.component); stream->writeInt(info.component);
// PackedEnumBitSet uses uint8_t // PackedEnumBitSet uses uint8_t
stream->writeInt(info.activeStages.bits()); stream->writeInt(info.activeStages.bits());
stream->writeInt(info.xfb.buffer); SaveShaderInterfaceVariableXfbInfo(info.xfb, stream);
stream->writeInt(info.xfb.offset);
stream->writeInt(info.xfb.stride);
stream->writeInt(info.fieldXfb.size()); stream->writeInt(info.fieldXfb.size());
for (const ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb) for (const ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
{ {
stream->writeInt(xfb.buffer); SaveShaderInterfaceVariableXfbInfo(xfb, stream);
stream->writeInt(xfb.offset);
stream->writeInt(xfb.stride);
} }
stream->writeBool(info.useRelaxedPrecision); stream->writeBool(info.useRelaxedPrecision);
stream->writeBool(info.varyingIsInput); stream->writeBool(info.varyingIsInput);
......
...@@ -69,6 +69,7 @@ class ProgramInfo final : angle::NonCopyable ...@@ -69,6 +69,7 @@ class ProgramInfo final : angle::NonCopyable
angle::Result initProgram(ContextVk *contextVk, angle::Result initProgram(ContextVk *contextVk,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
bool isLastPreFragmentStage, bool isLastPreFragmentStage,
bool isTransformFeedbackProgram,
const ShaderInfo &shaderInfo, const ShaderInfo &shaderInfo,
ProgramTransformOptions optionBits, ProgramTransformOptions optionBits,
const ShaderInterfaceVariableInfoMap &variableInfoMap); const ShaderInterfaceVariableInfoMap &variableInfoMap);
......
...@@ -269,7 +269,7 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context, ...@@ -269,7 +269,7 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context,
// Gather variable info and transform sources. // Gather variable info and transform sources.
gl::ShaderMap<std::string> shaderSources; gl::ShaderMap<std::string> shaderSources;
GlslangWrapperVk::GetShaderSource(contextVk->getRenderer()->getFeatures(), mState, resources, GlslangWrapperVk::GetShaderSource(contextVk->getFeatures(), mState, resources,
&mGlslangProgramInterfaceInfo, &shaderSources, &mGlslangProgramInterfaceInfo, &shaderSources,
&mExecutable.mVariableInfoMap); &mExecutable.mVariableInfoMap);
......
...@@ -208,8 +208,11 @@ class ProgramVk : public ProgramImpl ...@@ -208,8 +208,11 @@ class ProgramVk : public ProgramImpl
// specialization constants. // specialization constants.
if (!programInfo->valid(shaderType)) if (!programInfo->valid(shaderType))
{ {
const bool isTransformFeedbackProgram =
!mState.getLinkedTransformFeedbackVaryings().empty();
ANGLE_TRY(programInfo->initProgram(contextVk, shaderType, isLastPreFragmentStage, ANGLE_TRY(programInfo->initProgram(contextVk, shaderType, isLastPreFragmentStage,
mOriginalShaderInfo, optionBits, variableInfoMap)); isTransformFeedbackProgram, mOriginalShaderInfo,
optionBits, variableInfoMap));
} }
ASSERT(programInfo->valid(shaderType)); ASSERT(programInfo->valid(shaderType));
......
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