Commit bef8ca7d by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Set vertex attribute locations in SPIR-V

The shader translator outputs arbitrary location indices for vertex attributes. Once compiled by glslang, the SPIR-V transformer modifies these decorations. Bug: angleproject:3394 Change-Id: I88453b44e3a8770f51e79228148233ff308f1885 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2011212 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 71e6afb1
...@@ -93,6 +93,8 @@ class TOutputGLSLBase : public TIntermTraverser ...@@ -93,6 +93,8 @@ class TOutputGLSLBase : public TIntermTraverser
const char *mapQualifierToString(TQualifier qualifier); const char *mapQualifierToString(TQualifier qualifier);
sh::GLenum getShaderType() { return mShaderType; }
private: private:
void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock); void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock);
void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock); void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "compiler/translator/BaseTypes.h" #include "compiler/translator/BaseTypes.h"
#include "compiler/translator/Symbol.h" #include "compiler/translator/Symbol.h"
#include "compiler/translator/ValidateVaryingLocations.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
namespace sh namespace sh
...@@ -36,20 +37,22 @@ TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink, ...@@ -36,20 +37,22 @@ TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink,
shaderVersion, shaderVersion,
output, output,
compileOptions), compileOptions),
mNextUnusedBinding(0) mNextUnusedBinding(0),
mNextUnusedInputLocation(0)
{} {}
void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
{ {
const TType &type = variable->getType(); const TType &type = variable->getType();
bool needsCustomLayout = type.getQualifier() == EvqAttribute || bool needsCustomLayout =
type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqFragmentOut || IsVarying(type.getQualifier());
type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier());
bool needsSetBinding = bool needsSetBinding =
IsSampler(type.getBasicType()) || type.isInterfaceBlock() || IsImage(type.getBasicType()); IsSampler(type.getBasicType()) || type.isInterfaceBlock() || IsImage(type.getBasicType());
bool needsLocation = type.getQualifier() == EvqAttribute || type.getQualifier() == EvqVertexIn;
if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout && !needsSetBinding) if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout && !needsSetBinding &&
!needsLocation)
{ {
return; return;
} }
...@@ -113,6 +116,15 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) ...@@ -113,6 +116,15 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
out << "set=0, binding=" << nextUnusedBinding(); out << "set=0, binding=" << nextUnusedBinding();
separator = ", "; separator = ", ";
} }
if (needsLocation)
{
const unsigned int locationCount =
CalculateVaryingLocationCount(symbol, getShaderType());
out << "location=" << nextUnusedInputLocation(locationCount);
separator = ", ";
}
} }
// Output the list of qualifiers already known at this stage, i.e. everything other than // Output the list of qualifiers already known at this stage, i.e. everything other than
......
...@@ -30,6 +30,12 @@ class TOutputVulkanGLSL : public TOutputGLSL ...@@ -30,6 +30,12 @@ class TOutputVulkanGLSL : public TOutputGLSL
void writeStructType(const TStructure *structure); void writeStructType(const TStructure *structure);
uint32_t nextUnusedBinding() { return mNextUnusedBinding++; } uint32_t nextUnusedBinding() { return mNextUnusedBinding++; }
uint32_t nextUnusedInputLocation(uint32_t consumedCount)
{
uint32_t nextUnused = mNextUnusedInputLocation;
mNextUnusedInputLocation += consumedCount;
return nextUnused;
}
protected: protected:
void writeLayoutQualifier(TIntermTyped *variable) override; void writeLayoutQualifier(TIntermTyped *variable) override;
...@@ -39,9 +45,12 @@ class TOutputVulkanGLSL : public TOutputGLSL ...@@ -39,9 +45,12 @@ class TOutputVulkanGLSL : public TOutputGLSL
bool isFunctionArgument) override; bool isFunctionArgument) override;
// Every resource that requires set & binding layout qualifiers is assigned set 0 and an // Every resource that requires set & binding layout qualifiers is assigned set 0 and an
// arbitrary binding when outputting GLSL. Glslang wrapper modifies set and binding decorations // arbitrary binding when outputting GLSL. Every input/output that requires a location
// in SPIR-V directly. // layout qualifiers is assigned an arbitrary location as well.
//
// Glslang wrapper modifies set, binding and location decorations in SPIR-V directly.
uint32_t mNextUnusedBinding; uint32_t mNextUnusedBinding;
uint32_t mNextUnusedInputLocation;
}; };
} // namespace sh } // namespace sh
...@@ -25,13 +25,13 @@ void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagno ...@@ -25,13 +25,13 @@ void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagno
diagnostics->error(symbol.getLine(), reason, symbol.getName().data()); diagnostics->error(symbol.getLine(), reason, symbol.getName().data());
} }
int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize) unsigned int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize)
{ {
const auto &varyingType = varying->getType(); const auto &varyingType = varying->getType();
if (varyingType.getStruct() != nullptr) if (varyingType.getStruct() != nullptr)
{ {
ASSERT(!varyingType.isArray()); ASSERT(!varyingType.isArray());
int totalLocation = 0; unsigned int totalLocation = 0;
for (const auto *field : varyingType.getStruct()->fields()) for (const auto *field : varyingType.getStruct()->fields())
{ {
const auto *fieldType = field->type(); const auto *fieldType = field->type();
...@@ -56,11 +56,11 @@ int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize) ...@@ -56,11 +56,11 @@ int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize)
} }
else if (varyingType.isMatrix()) else if (varyingType.isMatrix())
{ {
return varyingType.getNominalSize() * static_cast<int>(varyingType.getArraySizeProduct()); return varyingType.getNominalSize() * varyingType.getArraySizeProduct();
} }
else else
{ {
return static_cast<int>(varyingType.getArraySizeProduct()); return varyingType.getArraySizeProduct();
} }
} }
...@@ -172,6 +172,11 @@ void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics) ...@@ -172,6 +172,11 @@ void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics)
} // anonymous namespace } // anonymous namespace
unsigned int CalculateVaryingLocationCount(TIntermSymbol *varying, GLenum shaderType)
{
return GetLocationCount(varying, shaderType == GL_GEOMETRY_SHADER_EXT);
}
bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType) bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType)
{ {
ValidateVaryingLocationsTraverser varyingValidator(shaderType); ValidateVaryingLocationsTraverser varyingValidator(shaderType);
......
...@@ -16,8 +16,10 @@ namespace sh ...@@ -16,8 +16,10 @@ namespace sh
{ {
class TIntermBlock; class TIntermBlock;
class TIntermSymbol;
class TDiagnostics; class TDiagnostics;
unsigned int CalculateVaryingLocationCount(TIntermSymbol *varying, GLenum shaderType);
bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType); bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType);
} // namespace sh } // namespace sh
......
...@@ -517,6 +517,20 @@ ShaderInterfaceVariableInfo *AddResourceInfo(ShaderInterfaceVariableInfoMap *inf ...@@ -517,6 +517,20 @@ ShaderInterfaceVariableInfo *AddResourceInfo(ShaderInterfaceVariableInfoMap *inf
return info; return info;
} }
// Add location information for an in/out variable.
ShaderInterfaceVariableInfo *AddLocationInfo(ShaderInterfaceVariableInfoMap *infoMap,
const std::string &varName,
uint32_t location,
uint32_t component,
gl::ShaderBitSet activeStages)
{
ShaderInterfaceVariableInfo *info = AddShaderInterfaceVariable(infoMap, varName);
info->location = location;
info->component = component;
info->activeStages = activeStages;
return info;
}
std::string GenerateTransformFeedbackVaryingOutput(const gl::TransformFeedbackVarying &varying, std::string GenerateTransformFeedbackVaryingOutput(const gl::TransformFeedbackVarying &varying,
const gl::UniformTypeInfo &info, const gl::UniformTypeInfo &info,
size_t strideBytes, size_t strideBytes,
...@@ -763,18 +777,18 @@ void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programSt ...@@ -763,18 +777,18 @@ void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programSt
} }
void AssignAttributeLocations(const gl::ProgramState &programState, void AssignAttributeLocations(const gl::ProgramState &programState,
IntermediateShaderSource *shaderSource) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
ASSERT(!shaderSource->empty()); gl::ShaderBitSet vertexOnly;
vertexOnly.set(gl::ShaderType::Vertex);
// Parse attribute locations and replace them in the vertex shader. // Assign attribute locations for the vertex shader.
// See corresponding code in OutputVulkanGLSL.cpp.
for (const sh::ShaderVariable &attribute : programState.getProgramInputs()) for (const sh::ShaderVariable &attribute : programState.getProgramInputs())
{ {
ASSERT(attribute.active); ASSERT(attribute.active);
std::string locationString = "location = " + Str(attribute.location); AddLocationInfo(variableInfoMapOut, attribute.mappedName, attribute.location,
shaderSource->insertLayoutSpecifier(attribute.name, locationString); ShaderInterfaceVariableInfo::kInvalid, vertexOnly);
} }
} }
...@@ -1638,7 +1652,7 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options, ...@@ -1638,7 +1652,7 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
// Assign attributes to the vertex shader, if any. // Assign attributes to the vertex shader, if any.
if (!vertexSource->empty()) if (!vertexSource->empty())
{ {
AssignAttributeLocations(programState, vertexSource); AssignAttributeLocations(programState, variableInfoMapOut);
} }
if (computeSource->empty()) if (computeSource->empty())
......
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