mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-06 02:09:55 +03:00
Vulkan: Output SPIR-V ids from compiler
In this change, the shader interface variables are given SPIR-V ids by the compiler before SPIR-V generation. Those ids are made available through the ShaderVariable interface. The transformer does not yet rely on this information. A follow up change will rework the backend's name->info map and the transformer to directly use ids instead of names. Bug: angleproject:7220 Change-Id: Ic0a62681d4bcf3ed171c39c3ecd83e438ea068c8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4600609 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Roman Lavrov <romanl@google.com> Reviewed-by: Yuxin Hu <yuxinhu@google.com>
This commit is contained in:
committed by
Angle LUCI CQ
parent
acdf872299
commit
10380f4ba4
@@ -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 334
|
#define ANGLE_SH_VERSION 335
|
||||||
|
|
||||||
enum ShShaderSpec
|
enum ShShaderSpec
|
||||||
{
|
{
|
||||||
@@ -1027,10 +1027,15 @@ enum ReservedIds
|
|||||||
|
|
||||||
// Pre-rotation and Z-correction support
|
// Pre-rotation and Z-correction support
|
||||||
kIdTransformPositionFunction,
|
kIdTransformPositionFunction,
|
||||||
|
kIdOutputPerVertexVar,
|
||||||
|
|
||||||
// Transform feedback support
|
// Transform feedback support
|
||||||
kIdXfbEmulationGetOffsetsFunction,
|
kIdXfbEmulationGetOffsetsFunction,
|
||||||
kIdXfbEmulationCaptureFunction,
|
kIdXfbEmulationCaptureFunction,
|
||||||
|
kIdXfbEmulationBufferVarZero,
|
||||||
|
kIdXfbEmulationBufferVarOne,
|
||||||
|
kIdXfbEmulationBufferVarTwo,
|
||||||
|
kIdXfbEmulationBufferVarThree,
|
||||||
|
|
||||||
// Multisampling support
|
// Multisampling support
|
||||||
kIdSampleID,
|
kIdSampleID,
|
||||||
@@ -1039,12 +1044,14 @@ enum ReservedIds
|
|||||||
// ANGLE internal shader variables, which are not produced as ShaderVariables.
|
// ANGLE internal shader variables, which are not produced as ShaderVariables.
|
||||||
// kIdShaderVariablesBegin marks the beginning of these ids. variableId -> info maps in the
|
// kIdShaderVariablesBegin marks the beginning of these ids. variableId -> info maps in the
|
||||||
// backend can use |variableId - kIdShaderVariablesBegin| as key into a flat array.
|
// backend can use |variableId - kIdShaderVariablesBegin| as key into a flat array.
|
||||||
|
//
|
||||||
|
// Note that for blocks, only the block id is in this section as that is the id used in the
|
||||||
|
// variableId -> info maps.
|
||||||
kIdShaderVariablesBegin,
|
kIdShaderVariablesBegin,
|
||||||
|
|
||||||
// gl_PerVertex
|
// gl_PerVertex
|
||||||
kIdInputPerVertexBlock = kIdShaderVariablesBegin,
|
kIdInputPerVertexBlock = kIdShaderVariablesBegin,
|
||||||
kIdOutputPerVertexBlock,
|
kIdOutputPerVertexBlock,
|
||||||
kIdOutputPerVertexVar,
|
|
||||||
// The driver and default uniform blocks
|
// The driver and default uniform blocks
|
||||||
kIdDriverUniformsBlock,
|
kIdDriverUniformsBlock,
|
||||||
kIdDefaultUniformsBlock,
|
kIdDefaultUniformsBlock,
|
||||||
@@ -1055,10 +1062,6 @@ enum ReservedIds
|
|||||||
kIdXfbEmulationBufferBlockOne,
|
kIdXfbEmulationBufferBlockOne,
|
||||||
kIdXfbEmulationBufferBlockTwo,
|
kIdXfbEmulationBufferBlockTwo,
|
||||||
kIdXfbEmulationBufferBlockThree,
|
kIdXfbEmulationBufferBlockThree,
|
||||||
kIdXfbEmulationBufferVarZero,
|
|
||||||
kIdXfbEmulationBufferVarOne,
|
|
||||||
kIdXfbEmulationBufferVarTwo,
|
|
||||||
kIdXfbEmulationBufferVarThree,
|
|
||||||
// Additional varying added to hold untransformed gl_Position for transform feedback capture
|
// Additional varying added to hold untransformed gl_Position for transform feedback capture
|
||||||
kIdXfbExtensionPosition,
|
kIdXfbExtensionPosition,
|
||||||
|
|
||||||
|
|||||||
@@ -240,6 +240,11 @@ struct ShaderVariable
|
|||||||
// If the variable is a sampler that has ever been statically used with texelFetch
|
// If the variable is a sampler that has ever been statically used with texelFetch
|
||||||
bool texelFetchStaticUse;
|
bool texelFetchStaticUse;
|
||||||
|
|
||||||
|
// Id of the variable in the shader. Currently used by the SPIR-V output to communicate the
|
||||||
|
// SPIR-V id of the variable. This value is only set for variables that the SPIR-V transformer
|
||||||
|
// needs to know about, i.e. active variables, excluding non-zero array elements etc.
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool isSameVariableAtLinkTime(const ShaderVariable &other,
|
bool isSameVariableAtLinkTime(const ShaderVariable &other,
|
||||||
bool matchPrecision,
|
bool matchPrecision,
|
||||||
@@ -296,6 +301,9 @@ struct InterfaceBlock
|
|||||||
bool isReadOnly;
|
bool isReadOnly;
|
||||||
BlockType blockType;
|
BlockType blockType;
|
||||||
std::vector<ShaderVariable> fields;
|
std::vector<ShaderVariable> fields;
|
||||||
|
|
||||||
|
// Id of the interface block in the shader. Similar to |ShaderVariable::id|.
|
||||||
|
uint32_t id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorkGroupSize
|
struct WorkGroupSize
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ void WriteShaderVar(gl::BinaryOutputStream *stream, const sh::ShaderVariable &va
|
|||||||
stream->writeBool(var.isPatch);
|
stream->writeBool(var.isPatch);
|
||||||
stream->writeBool(var.texelFetchStaticUse);
|
stream->writeBool(var.texelFetchStaticUse);
|
||||||
stream->writeInt(var.getFlattenedOffsetInParentArrays());
|
stream->writeInt(var.getFlattenedOffsetInParentArrays());
|
||||||
|
stream->writeInt(var.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
|
void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
|
||||||
@@ -134,6 +135,7 @@ void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
|
|||||||
var->isPatch = stream->readBool();
|
var->isPatch = stream->readBool();
|
||||||
var->texelFetchStaticUse = stream->readBool();
|
var->texelFetchStaticUse = stream->readBool();
|
||||||
var->setParentArrayIndex(stream->readInt<int>());
|
var->setParentArrayIndex(stream->readInt<int>());
|
||||||
|
var->id = stream->readInt<uint32_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteShInterfaceBlock(gl::BinaryOutputStream *stream, const sh::InterfaceBlock &block)
|
void WriteShInterfaceBlock(gl::BinaryOutputStream *stream, const sh::InterfaceBlock &block)
|
||||||
@@ -148,6 +150,7 @@ void WriteShInterfaceBlock(gl::BinaryOutputStream *stream, const sh::InterfaceBl
|
|||||||
stream->writeBool(block.staticUse);
|
stream->writeBool(block.staticUse);
|
||||||
stream->writeBool(block.active);
|
stream->writeBool(block.active);
|
||||||
stream->writeEnum(block.blockType);
|
stream->writeEnum(block.blockType);
|
||||||
|
stream->writeInt(block.id);
|
||||||
|
|
||||||
stream->writeInt<size_t>(block.fields.size());
|
stream->writeInt<size_t>(block.fields.size());
|
||||||
for (const sh::ShaderVariable &shaderVariable : block.fields)
|
for (const sh::ShaderVariable &shaderVariable : block.fields)
|
||||||
@@ -168,6 +171,7 @@ void LoadShInterfaceBlock(gl::BinaryInputStream *stream, sh::InterfaceBlock *blo
|
|||||||
block->staticUse = stream->readBool();
|
block->staticUse = stream->readBool();
|
||||||
block->active = stream->readBool();
|
block->active = stream->readBool();
|
||||||
block->blockType = stream->readEnum<sh::BlockType>();
|
block->blockType = stream->readEnum<sh::BlockType>();
|
||||||
|
block->id = stream->readInt<uint32_t>();
|
||||||
|
|
||||||
block->fields.resize(stream->readInt<size_t>());
|
block->fields.resize(stream->readInt<size_t>());
|
||||||
for (sh::ShaderVariable &variable : block->fields)
|
for (sh::ShaderVariable &variable : block->fields)
|
||||||
|
|||||||
@@ -508,12 +508,13 @@ SPIRVBuilder::SPIRVBuilder(TCompiler *compiler,
|
|||||||
const ShCompileOptions &compileOptions,
|
const ShCompileOptions &compileOptions,
|
||||||
ShHashFunction64 hashFunction,
|
ShHashFunction64 hashFunction,
|
||||||
NameMap &nameMap,
|
NameMap &nameMap,
|
||||||
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap)
|
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap,
|
||||||
|
uint32_t firstUnusedSpirvId)
|
||||||
: mCompiler(compiler),
|
: mCompiler(compiler),
|
||||||
mCompileOptions(compileOptions),
|
mCompileOptions(compileOptions),
|
||||||
mShaderType(gl::FromGLenum<gl::ShaderType>(compiler->getShaderType())),
|
mShaderType(gl::FromGLenum<gl::ShaderType>(compiler->getShaderType())),
|
||||||
mUniqueToSpirvIdMap(uniqueToSpirvIdMap),
|
mUniqueToSpirvIdMap(uniqueToSpirvIdMap),
|
||||||
mNextAvailableId(vk::spirv::kIdFirstUnreserved),
|
mNextAvailableId(firstUnusedSpirvId),
|
||||||
mHashFunction(hashFunction),
|
mHashFunction(hashFunction),
|
||||||
mNameMap(nameMap),
|
mNameMap(nameMap),
|
||||||
mNextUnusedBinding(0),
|
mNextUnusedBinding(0),
|
||||||
|
|||||||
@@ -309,7 +309,8 @@ class SPIRVBuilder : angle::NonCopyable
|
|||||||
const ShCompileOptions &compileOptions,
|
const ShCompileOptions &compileOptions,
|
||||||
ShHashFunction64 hashFunction,
|
ShHashFunction64 hashFunction,
|
||||||
NameMap &nameMap,
|
NameMap &nameMap,
|
||||||
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap);
|
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap,
|
||||||
|
uint32_t firstUnusedSpirvId);
|
||||||
|
|
||||||
spirv::IdRef getNewId(const SpirvDecorations &decorations);
|
spirv::IdRef getNewId(const SpirvDecorations &decorations);
|
||||||
spirv::IdRef getReservedOrNewId(TSymbolUniqueId uniqueId, const SpirvDecorations &decorations);
|
spirv::IdRef getReservedOrNewId(TSymbolUniqueId uniqueId, const SpirvDecorations &decorations);
|
||||||
|
|||||||
@@ -181,7 +181,8 @@ class OutputSPIRVTraverser : public TIntermTraverser
|
|||||||
public:
|
public:
|
||||||
OutputSPIRVTraverser(TCompiler *compiler,
|
OutputSPIRVTraverser(TCompiler *compiler,
|
||||||
const ShCompileOptions &compileOptions,
|
const ShCompileOptions &compileOptions,
|
||||||
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap);
|
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap,
|
||||||
|
uint32_t firstUnusedSpirvId);
|
||||||
~OutputSPIRVTraverser() override;
|
~OutputSPIRVTraverser() override;
|
||||||
|
|
||||||
spirv::Blob getSpirv();
|
spirv::Blob getSpirv();
|
||||||
@@ -499,7 +500,8 @@ spv::StorageClass GetStorageClass(const TType &type, GLenum shaderType)
|
|||||||
|
|
||||||
OutputSPIRVTraverser::OutputSPIRVTraverser(TCompiler *compiler,
|
OutputSPIRVTraverser::OutputSPIRVTraverser(TCompiler *compiler,
|
||||||
const ShCompileOptions &compileOptions,
|
const ShCompileOptions &compileOptions,
|
||||||
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap)
|
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap,
|
||||||
|
uint32_t firstUnusedSpirvId)
|
||||||
: TIntermTraverser(true, true, true, &compiler->getSymbolTable()),
|
: TIntermTraverser(true, true, true, &compiler->getSymbolTable()),
|
||||||
mCompiler(compiler),
|
mCompiler(compiler),
|
||||||
mCompileOptions(compileOptions),
|
mCompileOptions(compileOptions),
|
||||||
@@ -507,7 +509,8 @@ OutputSPIRVTraverser::OutputSPIRVTraverser(TCompiler *compiler,
|
|||||||
compileOptions,
|
compileOptions,
|
||||||
compiler->getHashFunction(),
|
compiler->getHashFunction(),
|
||||||
compiler->getNameMap(),
|
compiler->getNameMap(),
|
||||||
uniqueToSpirvIdMap)
|
uniqueToSpirvIdMap,
|
||||||
|
firstUnusedSpirvId)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
OutputSPIRVTraverser::~OutputSPIRVTraverser()
|
OutputSPIRVTraverser::~OutputSPIRVTraverser()
|
||||||
@@ -6462,7 +6465,8 @@ spirv::Blob OutputSPIRVTraverser::getSpirv()
|
|||||||
bool OutputSPIRV(TCompiler *compiler,
|
bool OutputSPIRV(TCompiler *compiler,
|
||||||
TIntermBlock *root,
|
TIntermBlock *root,
|
||||||
const ShCompileOptions &compileOptions,
|
const ShCompileOptions &compileOptions,
|
||||||
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap)
|
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap,
|
||||||
|
uint32_t firstUnusedSpirvId)
|
||||||
{
|
{
|
||||||
// Find the list of nodes that require NoContraction (as a result of |precise|).
|
// Find the list of nodes that require NoContraction (as a result of |precise|).
|
||||||
if (compiler->hasAnyPreciseType())
|
if (compiler->hasAnyPreciseType())
|
||||||
@@ -6471,7 +6475,8 @@ bool OutputSPIRV(TCompiler *compiler,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Traverse the tree and generate SPIR-V instructions
|
// Traverse the tree and generate SPIR-V instructions
|
||||||
OutputSPIRVTraverser traverser(compiler, compileOptions, uniqueToSpirvIdMap);
|
OutputSPIRVTraverser traverser(compiler, compileOptions, uniqueToSpirvIdMap,
|
||||||
|
firstUnusedSpirvId);
|
||||||
root->traverse(&traverser);
|
root->traverse(&traverser);
|
||||||
|
|
||||||
// Generate the final SPIR-V and store in the sink
|
// Generate the final SPIR-V and store in the sink
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ namespace sh
|
|||||||
bool OutputSPIRV(TCompiler *compiler,
|
bool OutputSPIRV(TCompiler *compiler,
|
||||||
TIntermBlock *root,
|
TIntermBlock *root,
|
||||||
const ShCompileOptions &compileOptions,
|
const ShCompileOptions &compileOptions,
|
||||||
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap);
|
const angle::HashMap<int, uint32_t> &uniqueToSpirvIdMap,
|
||||||
|
uint32_t firstUnusedSpirvId);
|
||||||
} // namespace sh
|
} // namespace sh
|
||||||
|
|
||||||
#endif // COMPILER_TRANSLATOR_OUTPUTSPIRV_H_
|
#endif // COMPILER_TRANSLATOR_OUTPUTSPIRV_H_
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ ShaderVariable::ShaderVariable(GLenum typeIn)
|
|||||||
isShaderIOBlock(false),
|
isShaderIOBlock(false),
|
||||||
isPatch(false),
|
isPatch(false),
|
||||||
texelFetchStaticUse(false),
|
texelFetchStaticUse(false),
|
||||||
|
id(0),
|
||||||
flattenedOffsetInParentArrays(-1)
|
flattenedOffsetInParentArrays(-1)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -94,6 +95,7 @@ ShaderVariable::ShaderVariable(const ShaderVariable &other)
|
|||||||
isShaderIOBlock(other.isShaderIOBlock),
|
isShaderIOBlock(other.isShaderIOBlock),
|
||||||
isPatch(other.isPatch),
|
isPatch(other.isPatch),
|
||||||
texelFetchStaticUse(other.texelFetchStaticUse),
|
texelFetchStaticUse(other.texelFetchStaticUse),
|
||||||
|
id(other.id),
|
||||||
flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays)
|
flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -127,13 +129,14 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
|
|||||||
isShaderIOBlock = other.isShaderIOBlock;
|
isShaderIOBlock = other.isShaderIOBlock;
|
||||||
isPatch = other.isPatch;
|
isPatch = other.isPatch;
|
||||||
texelFetchStaticUse = other.texelFetchStaticUse;
|
texelFetchStaticUse = other.texelFetchStaticUse;
|
||||||
|
id = other.id;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShaderVariable::operator==(const ShaderVariable &other) const
|
bool ShaderVariable::operator==(const ShaderVariable &other) const
|
||||||
{
|
{
|
||||||
if (type != other.type || precision != other.precision || name != other.name ||
|
if (id != other.id || type != other.type || precision != other.precision ||
|
||||||
mappedName != other.mappedName || arraySizes != other.arraySizes ||
|
name != other.name || mappedName != other.mappedName || arraySizes != other.arraySizes ||
|
||||||
staticUse != other.staticUse || active != other.active ||
|
staticUse != other.staticUse || active != other.active ||
|
||||||
fields.size() != other.fields.size() || structOrBlockName != other.structOrBlockName ||
|
fields.size() != other.fields.size() || structOrBlockName != other.structOrBlockName ||
|
||||||
mappedStructOrBlockName != other.mappedStructOrBlockName ||
|
mappedStructOrBlockName != other.mappedStructOrBlockName ||
|
||||||
@@ -485,7 +488,8 @@ InterfaceBlock::InterfaceBlock()
|
|||||||
staticUse(false),
|
staticUse(false),
|
||||||
active(false),
|
active(false),
|
||||||
isReadOnly(false),
|
isReadOnly(false),
|
||||||
blockType(BlockType::BLOCK_UNIFORM)
|
blockType(BlockType::BLOCK_UNIFORM),
|
||||||
|
id(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
InterfaceBlock::~InterfaceBlock() {}
|
InterfaceBlock::~InterfaceBlock() {}
|
||||||
@@ -502,7 +506,8 @@ InterfaceBlock::InterfaceBlock(const InterfaceBlock &other)
|
|||||||
active(other.active),
|
active(other.active),
|
||||||
isReadOnly(other.isReadOnly),
|
isReadOnly(other.isReadOnly),
|
||||||
blockType(other.blockType),
|
blockType(other.blockType),
|
||||||
fields(other.fields)
|
fields(other.fields),
|
||||||
|
id(other.id)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
|
InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
|
||||||
@@ -518,6 +523,7 @@ InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
|
|||||||
active = other.active;
|
active = other.active;
|
||||||
isReadOnly = other.isReadOnly;
|
isReadOnly = other.isReadOnly;
|
||||||
blockType = other.blockType;
|
blockType = other.blockType;
|
||||||
|
id = other.id;
|
||||||
fields = other.fields;
|
fields = other.fields;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -534,10 +540,10 @@ std::string InterfaceBlock::fieldMappedPrefix() const
|
|||||||
|
|
||||||
bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const
|
bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const
|
||||||
{
|
{
|
||||||
if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize ||
|
if (id != other.id || name != other.name || mappedName != other.mappedName ||
|
||||||
layout != other.layout || isRowMajorLayout != other.isRowMajorLayout ||
|
arraySize != other.arraySize || layout != other.layout ||
|
||||||
binding != other.binding || blockType != other.blockType ||
|
isRowMajorLayout != other.isRowMajorLayout || binding != other.binding ||
|
||||||
fields.size() != other.fields.size())
|
blockType != other.blockType || fields.size() != other.fields.size())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,8 +162,8 @@ bool DeclareDefaultUniforms(TranslatorVulkan *compiler,
|
|||||||
root, symbolTable, uniformList, EvqUniform, layoutQualifier, TMemoryQualifier::Create(), 0,
|
root, symbolTable, uniformList, EvqUniform, layoutQualifier, TMemoryQualifier::Create(), 0,
|
||||||
ImmutableString(kDefaultUniformNames[shaderType]), ImmutableString(""));
|
ImmutableString(kDefaultUniformNames[shaderType]), ImmutableString(""));
|
||||||
|
|
||||||
compiler->assignReservedSpirvId(uniformBlock->getType().getInterfaceBlock()->uniqueId(),
|
compiler->assignSpirvId(uniformBlock->getType().getInterfaceBlock()->uniqueId(),
|
||||||
vk::spirv::kIdDefaultUniformsBlock);
|
vk::spirv::kIdDefaultUniformsBlock);
|
||||||
|
|
||||||
// Create a map from the uniform variables to new variables that reference the fields of the
|
// Create a map from the uniform variables to new variables that reference the fields of the
|
||||||
// block.
|
// block.
|
||||||
@@ -382,8 +382,8 @@ TIntermSequence *GetMainSequence(TIntermBlock *root)
|
|||||||
ivec4Type, true);
|
ivec4Type, true);
|
||||||
getOffsetsFunction->addParameter(stridesVar);
|
getOffsetsFunction->addParameter(stridesVar);
|
||||||
|
|
||||||
compiler->assignReservedSpirvId(getOffsetsFunction->uniqueId(),
|
compiler->assignSpirvId(getOffsetsFunction->uniqueId(),
|
||||||
vk::spirv::kIdXfbEmulationGetOffsetsFunction);
|
vk::spirv::kIdXfbEmulationGetOffsetsFunction);
|
||||||
|
|
||||||
TIntermFunctionDefinition *functionDef =
|
TIntermFunctionDefinition *functionDef =
|
||||||
CreateInternalFunctionDefinitionNode(*getOffsetsFunction, body);
|
CreateInternalFunctionDefinitionNode(*getOffsetsFunction, body);
|
||||||
@@ -407,8 +407,8 @@ TIntermSequence *GetMainSequence(TIntermBlock *root)
|
|||||||
TFunction *xfbCaptureFunction = new TFunction(symbolTable, ImmutableString("ANGLECaptureXfb"),
|
TFunction *xfbCaptureFunction = new TFunction(symbolTable, ImmutableString("ANGLECaptureXfb"),
|
||||||
SymbolType::AngleInternal, voidType, false);
|
SymbolType::AngleInternal, voidType, false);
|
||||||
|
|
||||||
compiler->assignReservedSpirvId(xfbCaptureFunction->uniqueId(),
|
compiler->assignSpirvId(xfbCaptureFunction->uniqueId(),
|
||||||
vk::spirv::kIdXfbEmulationCaptureFunction);
|
vk::spirv::kIdXfbEmulationCaptureFunction);
|
||||||
|
|
||||||
// Insert the function declaration before main().
|
// Insert the function declaration before main().
|
||||||
root->insertChildNodes(mainIndex,
|
root->insertChildNodes(mainIndex,
|
||||||
@@ -489,10 +489,10 @@ TIntermSequence *GetMainSequence(TIntermBlock *root)
|
|||||||
static_assert(vk::spirv::kIdXfbEmulationBufferVarThree ==
|
static_assert(vk::spirv::kIdXfbEmulationBufferVarThree ==
|
||||||
vk::spirv::kIdXfbEmulationBufferVarZero + 3);
|
vk::spirv::kIdXfbEmulationBufferVarZero + 3);
|
||||||
|
|
||||||
compiler->assignReservedSpirvId(xfbBuffer->getType().getInterfaceBlock()->uniqueId(),
|
compiler->assignSpirvId(xfbBuffer->getType().getInterfaceBlock()->uniqueId(),
|
||||||
vk::spirv::kIdXfbEmulationBufferBlockZero + bufferIndex);
|
vk::spirv::kIdXfbEmulationBufferBlockZero + bufferIndex);
|
||||||
compiler->assignReservedSpirvId(xfbBuffer->uniqueId(),
|
compiler->assignSpirvId(xfbBuffer->uniqueId(),
|
||||||
vk::spirv::kIdXfbEmulationBufferVarZero + bufferIndex);
|
vk::spirv::kIdXfbEmulationBufferVarZero + bufferIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return compiler->validateAST(root);
|
return compiler->validateAST(root);
|
||||||
@@ -530,7 +530,7 @@ TIntermSequence *GetMainSequence(TIntermBlock *root)
|
|||||||
new TVariable(symbolTable, ImmutableString(vk::kXfbExtensionPositionOutName), vec4Type,
|
new TVariable(symbolTable, ImmutableString(vk::kXfbExtensionPositionOutName), vec4Type,
|
||||||
SymbolType::AngleInternal);
|
SymbolType::AngleInternal);
|
||||||
|
|
||||||
compiler->assignReservedSpirvId(varyingVar->uniqueId(), vk::spirv::kIdXfbExtensionPosition);
|
compiler->assignSpirvId(varyingVar->uniqueId(), vk::spirv::kIdXfbExtensionPosition);
|
||||||
|
|
||||||
TIntermDeclaration *varyingDecl = new TIntermDeclaration();
|
TIntermDeclaration *varyingDecl = new TIntermDeclaration();
|
||||||
varyingDecl->appendDeclarator(new TIntermSymbol(varyingVar));
|
varyingDecl->appendDeclarator(new TIntermSymbol(varyingVar));
|
||||||
@@ -625,8 +625,8 @@ TIntermSequence *GetMainSequence(TIntermBlock *root)
|
|||||||
SymbolType::AngleInternal, vec4Type, true);
|
SymbolType::AngleInternal, vec4Type, true);
|
||||||
transformPositionFunction->addParameter(positionVar);
|
transformPositionFunction->addParameter(positionVar);
|
||||||
|
|
||||||
compiler->assignReservedSpirvId(transformPositionFunction->uniqueId(),
|
compiler->assignSpirvId(transformPositionFunction->uniqueId(),
|
||||||
vk::spirv::kIdTransformPositionFunction);
|
vk::spirv::kIdTransformPositionFunction);
|
||||||
|
|
||||||
TIntermFunctionDefinition *functionDef =
|
TIntermFunctionDefinition *functionDef =
|
||||||
CreateInternalFunctionDefinitionNode(*transformPositionFunction, body);
|
CreateInternalFunctionDefinitionNode(*transformPositionFunction, body);
|
||||||
@@ -670,10 +670,86 @@ bool HasFramebufferFetch(const TExtensionBehavior &extBehavior,
|
|||||||
(compileOptions.pls.type == ShPixelLocalStorageType::FramebufferFetch &&
|
(compileOptions.pls.type == ShPixelLocalStorageType::FramebufferFetch &&
|
||||||
IsExtensionEnabled(extBehavior, TExtension::ANGLE_shader_pixel_local_storage));
|
IsExtensionEnabled(extBehavior, TExtension::ANGLE_shader_pixel_local_storage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Variable>
|
||||||
|
Variable *FindShaderVariable(std::vector<Variable> *vars, const ImmutableString &name)
|
||||||
|
{
|
||||||
|
for (Variable &var : *vars)
|
||||||
|
{
|
||||||
|
if (name == var.name)
|
||||||
|
{
|
||||||
|
return &var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderVariable *FindIOBlockShaderVariable(std::vector<ShaderVariable> *vars,
|
||||||
|
const ImmutableString &name)
|
||||||
|
{
|
||||||
|
for (ShaderVariable &var : *vars)
|
||||||
|
{
|
||||||
|
if (name == var.structOrBlockName)
|
||||||
|
{
|
||||||
|
return &var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderVariable *FindUniformFieldShaderVariable(std::vector<ShaderVariable> *vars,
|
||||||
|
const ImmutableString &name,
|
||||||
|
const char *prefix)
|
||||||
|
{
|
||||||
|
for (ShaderVariable &var : *vars)
|
||||||
|
{
|
||||||
|
// The name of the sampler is derived from the uniform name + fields
|
||||||
|
// that reach the uniform, concatenated with '_' per RewriteStructSamplers.
|
||||||
|
std::string varName = prefix;
|
||||||
|
varName += '_';
|
||||||
|
varName += var.name;
|
||||||
|
|
||||||
|
if (name == varName)
|
||||||
|
{
|
||||||
|
return &var;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderVariable *field = FindUniformFieldShaderVariable(&var.fields, name, varName.c_str());
|
||||||
|
if (field != nullptr)
|
||||||
|
{
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderVariable *FindUniformShaderVariable(std::vector<ShaderVariable> *vars,
|
||||||
|
const ImmutableString &name)
|
||||||
|
{
|
||||||
|
for (ShaderVariable &var : *vars)
|
||||||
|
{
|
||||||
|
if (name == var.name)
|
||||||
|
{
|
||||||
|
return &var;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: samplers in structs are moved out. Such samplers will be found in the fields of
|
||||||
|
// the struct uniform.
|
||||||
|
ShaderVariable *field = FindUniformFieldShaderVariable(&var.fields, name, var.name.c_str());
|
||||||
|
if (field != nullptr)
|
||||||
|
{
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec)
|
TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec)
|
||||||
: TCompiler(type, spec, SH_SPIRV_VULKAN_OUTPUT)
|
: TCompiler(type, spec, SH_SPIRV_VULKAN_OUTPUT), mFirstUnusedSpirvId(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool TranslatorVulkan::translateImpl(TIntermBlock *root,
|
bool TranslatorVulkan::translateImpl(TIntermBlock *root,
|
||||||
@@ -808,7 +884,7 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
|
|||||||
driverUniforms->addGraphicsDriverUniformsToShader(root, &getSymbolTable());
|
driverUniforms->addGraphicsDriverUniformsToShader(root, &getSymbolTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
assignReservedSpirvId(
|
assignSpirvId(
|
||||||
driverUniforms->getDriverUniformsVariable()->getType().getInterfaceBlock()->uniqueId(),
|
driverUniforms->getDriverUniformsVariable()->getType().getInterfaceBlock()->uniqueId(),
|
||||||
vk::spirv::kIdDriverUniformsBlock);
|
vk::spirv::kIdDriverUniformsBlock);
|
||||||
|
|
||||||
@@ -830,8 +906,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
assignReservedSpirvId(atomicCounters->getType().getInterfaceBlock()->uniqueId(),
|
assignSpirvId(atomicCounters->getType().getInterfaceBlock()->uniqueId(),
|
||||||
vk::spirv::kIdAtomicCounterBlock);
|
vk::spirv::kIdAtomicCounterBlock);
|
||||||
}
|
}
|
||||||
else if (getShaderVersion() >= 310)
|
else if (getShaderVersion() >= 310)
|
||||||
{
|
{
|
||||||
@@ -1182,16 +1258,20 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
|
|||||||
|
|
||||||
if (inputPerVertex)
|
if (inputPerVertex)
|
||||||
{
|
{
|
||||||
assignReservedSpirvId(inputPerVertex->getType().getInterfaceBlock()->uniqueId(),
|
assignSpirvId(inputPerVertex->getType().getInterfaceBlock()->uniqueId(),
|
||||||
vk::spirv::kIdInputPerVertexBlock);
|
vk::spirv::kIdInputPerVertexBlock);
|
||||||
}
|
}
|
||||||
if (outputPerVertex)
|
if (outputPerVertex)
|
||||||
{
|
{
|
||||||
assignReservedSpirvId(outputPerVertex->getType().getInterfaceBlock()->uniqueId(),
|
assignSpirvId(outputPerVertex->getType().getInterfaceBlock()->uniqueId(),
|
||||||
vk::spirv::kIdOutputPerVertexBlock);
|
vk::spirv::kIdOutputPerVertexBlock);
|
||||||
assignReservedSpirvId(outputPerVertex->uniqueId(), vk::spirv::kIdOutputPerVertexVar);
|
assignSpirvId(outputPerVertex->uniqueId(), vk::spirv::kIdOutputPerVertexVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now that all transformations are done, assign SPIR-V ids to whatever shader variable is still
|
||||||
|
// present in the shader in some form. This should be the last thing done in this function.
|
||||||
|
assignSpirvIds(root);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1200,6 +1280,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
|
|||||||
PerformanceDiagnostics *perfDiagnostics)
|
PerformanceDiagnostics *perfDiagnostics)
|
||||||
{
|
{
|
||||||
mUniqueToSpirvIdMap.clear();
|
mUniqueToSpirvIdMap.clear();
|
||||||
|
mFirstUnusedSpirvId = 0;
|
||||||
|
|
||||||
SpecConst specConst(&getSymbolTable(), compileOptions, getShaderType());
|
SpecConst specConst(&getSymbolTable(), compileOptions, getShaderType());
|
||||||
|
|
||||||
@@ -1215,7 +1296,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OutputSPIRV(this, root, compileOptions, mUniqueToSpirvIdMap);
|
return OutputSPIRV(this, root, compileOptions, mUniqueToSpirvIdMap, mFirstUnusedSpirvId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll()
|
bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll()
|
||||||
@@ -1224,9 +1305,109 @@ bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranslatorVulkan::assignReservedSpirvId(TSymbolUniqueId uniqueId, uint32_t spirvId)
|
void TranslatorVulkan::assignSpirvId(TSymbolUniqueId uniqueId, uint32_t spirvId)
|
||||||
{
|
{
|
||||||
ASSERT(mUniqueToSpirvIdMap.find(uniqueId.get()) == mUniqueToSpirvIdMap.end());
|
ASSERT(mUniqueToSpirvIdMap.find(uniqueId.get()) == mUniqueToSpirvIdMap.end());
|
||||||
mUniqueToSpirvIdMap[uniqueId.get()] = spirvId;
|
mUniqueToSpirvIdMap[uniqueId.get()] = spirvId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TranslatorVulkan::assignSpirvIds(TIntermBlock *root)
|
||||||
|
{
|
||||||
|
// Match the declarations with collected variables and assign a new id to each, starting from
|
||||||
|
// the first unreserved id. This makes sure that the reserved ids for internal variables and
|
||||||
|
// ids for shader variables form a minimal contiguous range. The Vulkan backend takes advantage
|
||||||
|
// of this fact for optimal hashing.
|
||||||
|
mFirstUnusedSpirvId = vk::spirv::kIdFirstUnreserved;
|
||||||
|
|
||||||
|
for (TIntermNode *node : *root->getSequence())
|
||||||
|
{
|
||||||
|
TIntermDeclaration *decl = node->getAsDeclarationNode();
|
||||||
|
if (decl == nullptr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TIntermSymbol *symbol = decl->getSequence()->front()->getAsSymbolNode();
|
||||||
|
if (symbol == nullptr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TType &type = symbol->getType();
|
||||||
|
const TQualifier qualifier = type.getQualifier();
|
||||||
|
|
||||||
|
// Skip internal symbols, which already have a reserved id.
|
||||||
|
const TSymbolUniqueId uniqueId =
|
||||||
|
type.isInterfaceBlock() ? type.getInterfaceBlock()->uniqueId() : symbol->uniqueId();
|
||||||
|
if (mUniqueToSpirvIdMap.find(uniqueId.get()) != mUniqueToSpirvIdMap.end())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t *variableId = nullptr;
|
||||||
|
if (type.isInterfaceBlock())
|
||||||
|
{
|
||||||
|
if (IsVaryingIn(qualifier))
|
||||||
|
{
|
||||||
|
ShaderVariable *varying =
|
||||||
|
FindIOBlockShaderVariable(&mInputVaryings, type.getInterfaceBlock()->name());
|
||||||
|
variableId = &varying->id;
|
||||||
|
}
|
||||||
|
else if (IsVaryingOut(qualifier))
|
||||||
|
{
|
||||||
|
ShaderVariable *varying =
|
||||||
|
FindIOBlockShaderVariable(&mOutputVaryings, type.getInterfaceBlock()->name());
|
||||||
|
variableId = &varying->id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InterfaceBlock *block =
|
||||||
|
FindShaderVariable(&mInterfaceBlocks, type.getInterfaceBlock()->name());
|
||||||
|
variableId = &block->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (qualifier == EvqUniform)
|
||||||
|
{
|
||||||
|
ShaderVariable *uniform = FindUniformShaderVariable(&mUniforms, symbol->getName());
|
||||||
|
variableId = &uniform->id;
|
||||||
|
}
|
||||||
|
else if (qualifier == EvqAttribute || qualifier == EvqVertexIn)
|
||||||
|
{
|
||||||
|
ShaderVariable *attribute = FindShaderVariable(&mAttributes, symbol->getName());
|
||||||
|
variableId = &attribute->id;
|
||||||
|
}
|
||||||
|
else if (IsShaderIn(qualifier))
|
||||||
|
{
|
||||||
|
ShaderVariable *varying = FindShaderVariable(&mInputVaryings, symbol->getName());
|
||||||
|
variableId = &varying->id;
|
||||||
|
}
|
||||||
|
else if (qualifier == EvqFragmentOut)
|
||||||
|
{
|
||||||
|
// webgl_FragColor, webgl_FragData, webgl_SecondaryFragColor and webgl_SecondaryFragData
|
||||||
|
// are recorded with their original names (starting with gl_)
|
||||||
|
ImmutableString name(symbol->getName());
|
||||||
|
if (angle::BeginsWith(name.data(), "webgl_"))
|
||||||
|
{
|
||||||
|
name = ImmutableString(name.data() + 3, name.length() - 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderVariable *output = FindShaderVariable(&mOutputVariables, name);
|
||||||
|
variableId = &output->id;
|
||||||
|
}
|
||||||
|
else if (IsShaderOut(qualifier))
|
||||||
|
{
|
||||||
|
ShaderVariable *varying = FindShaderVariable(&mOutputVaryings, symbol->getName());
|
||||||
|
variableId = &varying->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variableId == nullptr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(variableId != nullptr);
|
||||||
|
assignSpirvId(uniqueId, mFirstUnusedSpirvId);
|
||||||
|
*variableId = mFirstUnusedSpirvId++;
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace sh
|
} // namespace sh
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class TranslatorVulkan final : public TCompiler
|
|||||||
public:
|
public:
|
||||||
TranslatorVulkan(sh::GLenum type, ShShaderSpec spec);
|
TranslatorVulkan(sh::GLenum type, ShShaderSpec spec);
|
||||||
|
|
||||||
void assignReservedSpirvId(TSymbolUniqueId uniqueId, uint32_t spirvId);
|
void assignSpirvId(TSymbolUniqueId uniqueId, uint32_t spirvId);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
[[nodiscard]] bool translate(TIntermBlock *root,
|
[[nodiscard]] bool translate(TIntermBlock *root,
|
||||||
@@ -39,10 +39,12 @@ class TranslatorVulkan final : public TCompiler
|
|||||||
PerformanceDiagnostics *perfDiagnostics,
|
PerformanceDiagnostics *perfDiagnostics,
|
||||||
SpecConst *specConst,
|
SpecConst *specConst,
|
||||||
DriverUniform *driverUniforms);
|
DriverUniform *driverUniforms);
|
||||||
|
void assignSpirvIds(TIntermBlock *root);
|
||||||
|
|
||||||
// A map from TSymbolUniqueId::mId to SPIR-V reserved ids. Used by the SPIR-V generator to
|
// A map from TSymbolUniqueId::mId to SPIR-V reserved ids. Used by the SPIR-V generator to
|
||||||
// quickly know when to use a reserved id and not have to resort to name matching.
|
// quickly know when to use a reserved id and not have to resort to name matching.
|
||||||
angle::HashMap<int, uint32_t> mUniqueToSpirvIdMap;
|
angle::HashMap<int, uint32_t> mUniqueToSpirvIdMap;
|
||||||
|
uint32_t mFirstUnusedSpirvId;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sh
|
} // namespace sh
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ class EmulateFragColorDataTraverser : public TIntermTraverser
|
|||||||
name = "webgl_FragData";
|
name = "webgl_FragData";
|
||||||
break;
|
break;
|
||||||
case EvqSecondaryFragColorEXT:
|
case EvqSecondaryFragColorEXT:
|
||||||
name = "webgl_SecondaryFragColor";
|
name = "webgl_SecondaryFragColorEXT";
|
||||||
index = 1;
|
index = 1;
|
||||||
break;
|
break;
|
||||||
case EvqSecondaryFragDataEXT:
|
case EvqSecondaryFragDataEXT:
|
||||||
name = "webgl_SecondaryFragData";
|
name = "webgl_SecondaryFragDataEXT";
|
||||||
index = 1;
|
index = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -452,6 +452,7 @@ class FlattenUniformVisitor : public sh::VariableNameVisitor
|
|||||||
linkedUniform.staticUse = mMarkStaticUse;
|
linkedUniform.staticUse = mMarkStaticUse;
|
||||||
linkedUniform.outerArraySizes = arraySizes;
|
linkedUniform.outerArraySizes = arraySizes;
|
||||||
linkedUniform.texelFetchStaticUse = variable.texelFetchStaticUse;
|
linkedUniform.texelFetchStaticUse = variable.texelFetchStaticUse;
|
||||||
|
linkedUniform.id = variable.id;
|
||||||
linkedUniform.imageUnitFormat = variable.imageUnitFormat;
|
linkedUniform.imageUnitFormat = variable.imageUnitFormat;
|
||||||
linkedUniform.isFragmentInOut = variable.isFragmentInOut;
|
linkedUniform.isFragmentInOut = variable.isFragmentInOut;
|
||||||
if (variable.hasParentArrayIndex())
|
if (variable.hasParentArrayIndex())
|
||||||
@@ -1421,6 +1422,7 @@ void InterfaceBlockLinker::defineInterfaceBlock(const GetBlockSizeFunc &getBlock
|
|||||||
firstFieldArraySize, blockBinding);
|
firstFieldArraySize, blockBinding);
|
||||||
block.memberIndexes = blockIndexes;
|
block.memberIndexes = blockIndexes;
|
||||||
block.setActive(shaderType, interfaceBlock.active);
|
block.setActive(shaderType, interfaceBlock.active);
|
||||||
|
block.id = interfaceBlock.id;
|
||||||
|
|
||||||
// Since all block elements in an array share the same active interface blocks, they
|
// Since all block elements in an array share the same active interface blocks, they
|
||||||
// will all be active once any block member is used. So, since interfaceBlock.name[0]
|
// will all be active once any block member is used. So, since interfaceBlock.name[0]
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ int ShaderVariableBuffer::numActiveVariables() const
|
|||||||
return static_cast<int>(memberIndexes.size());
|
return static_cast<int>(memberIndexes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
InterfaceBlock::InterfaceBlock() : isArray(false), isReadOnly(false), arrayElement(0) {}
|
InterfaceBlock::InterfaceBlock() : isArray(false), isReadOnly(false), arrayElement(0), id(0) {}
|
||||||
|
|
||||||
InterfaceBlock::InterfaceBlock(const std::string &nameIn,
|
InterfaceBlock::InterfaceBlock(const std::string &nameIn,
|
||||||
const std::string &mappedNameIn,
|
const std::string &mappedNameIn,
|
||||||
@@ -140,7 +140,8 @@ InterfaceBlock::InterfaceBlock(const std::string &nameIn,
|
|||||||
isArray(isArrayIn),
|
isArray(isArrayIn),
|
||||||
isReadOnly(isReadOnlyIn),
|
isReadOnly(isReadOnlyIn),
|
||||||
arrayElement(arrayElementIn),
|
arrayElement(arrayElementIn),
|
||||||
firstFieldArraySize(firstFieldArraySizeIn)
|
firstFieldArraySize(firstFieldArraySizeIn),
|
||||||
|
id(0)
|
||||||
{
|
{
|
||||||
binding = bindingIn;
|
binding = bindingIn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ struct InterfaceBlock : public ShaderVariableBuffer
|
|||||||
bool isReadOnly;
|
bool isReadOnly;
|
||||||
unsigned int arrayElement;
|
unsigned int arrayElement;
|
||||||
unsigned int firstFieldArraySize;
|
unsigned int firstFieldArraySize;
|
||||||
|
// The ID of the block, coming from sh::InterfaceBlock::id
|
||||||
|
uint32_t id;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gl
|
} // namespace gl
|
||||||
|
|||||||
@@ -350,14 +350,14 @@ void AssignSecondaryOutputLocations(const gl::ProgramExecutable &programExecutab
|
|||||||
if (outputVar.name == "gl_SecondaryFragColorEXT")
|
if (outputVar.name == "gl_SecondaryFragColorEXT")
|
||||||
{
|
{
|
||||||
AddLocationInfo(variableInfoMapOut, gl::ShaderType::Fragment,
|
AddLocationInfo(variableInfoMapOut, gl::ShaderType::Fragment,
|
||||||
ShaderVariableType::SecondaryOutput, "webgl_SecondaryFragColor", 0,
|
ShaderVariableType::SecondaryOutput, "webgl_SecondaryFragColorEXT",
|
||||||
ShaderInterfaceVariableInfo::kInvalid, 0, 0);
|
0, ShaderInterfaceVariableInfo::kInvalid, 0, 0);
|
||||||
}
|
}
|
||||||
else if (outputVar.name == "gl_SecondaryFragDataEXT")
|
else if (outputVar.name == "gl_SecondaryFragDataEXT")
|
||||||
{
|
{
|
||||||
AddLocationInfo(variableInfoMapOut, gl::ShaderType::Fragment,
|
AddLocationInfo(variableInfoMapOut, gl::ShaderType::Fragment,
|
||||||
ShaderVariableType::SecondaryOutput, "webgl_SecondaryFragData", 0,
|
ShaderVariableType::SecondaryOutput, "webgl_SecondaryFragDataEXT",
|
||||||
ShaderInterfaceVariableInfo::kInvalid, 0, 0);
|
0, ShaderInterfaceVariableInfo::kInvalid, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user