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
const char *mapQualifierToString(TQualifier qualifier);
sh::GLenum getShaderType() { return mShaderType; }
private:
void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock);
void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock);
......
......@@ -13,6 +13,7 @@
#include "compiler/translator/BaseTypes.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/ValidateVaryingLocations.h"
#include "compiler/translator/util.h"
namespace sh
......@@ -36,20 +37,22 @@ TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink,
shaderVersion,
output,
compileOptions),
mNextUnusedBinding(0)
mNextUnusedBinding(0),
mNextUnusedInputLocation(0)
{}
void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
{
const TType &type = variable->getType();
bool needsCustomLayout = type.getQualifier() == EvqAttribute ||
type.getQualifier() == EvqFragmentOut ||
type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier());
bool needsCustomLayout =
type.getQualifier() == EvqFragmentOut || IsVarying(type.getQualifier());
bool needsSetBinding =
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;
}
......@@ -113,6 +116,15 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
out << "set=0, binding=" << nextUnusedBinding();
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
......
......@@ -30,6 +30,12 @@ class TOutputVulkanGLSL : public TOutputGLSL
void writeStructType(const TStructure *structure);
uint32_t nextUnusedBinding() { return mNextUnusedBinding++; }
uint32_t nextUnusedInputLocation(uint32_t consumedCount)
{
uint32_t nextUnused = mNextUnusedInputLocation;
mNextUnusedInputLocation += consumedCount;
return nextUnused;
}
protected:
void writeLayoutQualifier(TIntermTyped *variable) override;
......@@ -39,9 +45,12 @@ class TOutputVulkanGLSL : public TOutputGLSL
bool isFunctionArgument) override;
// 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
// in SPIR-V directly.
// arbitrary binding when outputting GLSL. Every input/output that requires a location
// 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 mNextUnusedInputLocation;
};
} // namespace sh
......@@ -25,13 +25,13 @@ void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagno
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();
if (varyingType.getStruct() != nullptr)
{
ASSERT(!varyingType.isArray());
int totalLocation = 0;
unsigned int totalLocation = 0;
for (const auto *field : varyingType.getStruct()->fields())
{
const auto *fieldType = field->type();
......@@ -56,11 +56,11 @@ int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize)
}
else if (varyingType.isMatrix())
{
return varyingType.getNominalSize() * static_cast<int>(varyingType.getArraySizeProduct());
return varyingType.getNominalSize() * varyingType.getArraySizeProduct();
}
else
{
return static_cast<int>(varyingType.getArraySizeProduct());
return varyingType.getArraySizeProduct();
}
}
......@@ -172,6 +172,11 @@ void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics)
} // 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)
{
ValidateVaryingLocationsTraverser varyingValidator(shaderType);
......
......@@ -16,8 +16,10 @@ namespace sh
{
class TIntermBlock;
class TIntermSymbol;
class TDiagnostics;
unsigned int CalculateVaryingLocationCount(TIntermSymbol *varying, GLenum shaderType);
bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType);
} // namespace sh
......
......@@ -517,6 +517,20 @@ ShaderInterfaceVariableInfo *AddResourceInfo(ShaderInterfaceVariableInfoMap *inf
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,
const gl::UniformTypeInfo &info,
size_t strideBytes,
......@@ -763,18 +777,18 @@ void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programSt
}
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.
// See corresponding code in OutputVulkanGLSL.cpp.
// Assign attribute locations for the vertex shader.
for (const sh::ShaderVariable &attribute : programState.getProgramInputs())
{
ASSERT(attribute.active);
std::string locationString = "location = " + Str(attribute.location);
shaderSource->insertLayoutSpecifier(attribute.name, locationString);
AddLocationInfo(variableInfoMapOut, attribute.mappedName, attribute.location,
ShaderInterfaceVariableInfo::kInvalid, vertexOnly);
}
}
......@@ -1638,7 +1652,7 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
// Assign attributes to the vertex shader, if any.
if (!vertexSource->empty())
{
AssignAttributeLocations(programState, vertexSource);
AssignAttributeLocations(programState, variableInfoMapOut);
}
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