Commit abaa3573 by Tim Van Patten Committed by Commit Bot

Vulkan: Only calculate variable locations once

Variable locations and descriptor set/binding values are calculated multiple times: - Compiling GLSL->SPIR-V - Creating the Vulkan pipeline layout - Updating descriptor sets These values should instead be calculated once and reused throughout since they won't change without recompiling the shader program. Bug: angleproject:3570 Change-Id: I5d8767b3b2e2f741aade7fec9991eea53ee2eb98 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2067101 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 10ade024
...@@ -55,13 +55,6 @@ constexpr char kXfbDeclMarker[] = "@@ XFB-DECL @@"; ...@@ -55,13 +55,6 @@ constexpr char kXfbDeclMarker[] = "@@ XFB-DECL @@";
constexpr char kXfbOutMarker[] = "@@ XFB-OUT @@;"; constexpr char kXfbOutMarker[] = "@@ XFB-OUT @@;";
constexpr char kXfbBuiltInPrefix[] = "xfbANGLE"; constexpr char kXfbBuiltInPrefix[] = "xfbANGLE";
constexpr gl::ShaderMap<const char *> kDefaultUniformNames = {
{gl::ShaderType::Vertex, sh::vk::kDefaultUniformsNameVS},
{gl::ShaderType::Geometry, sh::vk::kDefaultUniformsNameGS},
{gl::ShaderType::Fragment, sh::vk::kDefaultUniformsNameFS},
{gl::ShaderType::Compute, sh::vk::kDefaultUniformsNameCS},
};
template <size_t N> template <size_t N>
constexpr size_t ConstStrLen(const char (&)[N]) constexpr size_t ConstStrLen(const char (&)[N])
{ {
...@@ -146,49 +139,11 @@ bool UniformNameIsIndexZero(const std::string &name, bool excludeCheckForOwningS ...@@ -146,49 +139,11 @@ bool UniformNameIsIndexZero(const std::string &name, bool excludeCheckForOwningS
return true; return true;
} }
// Strip indices from the name. If there are non-zero indices, return false to indicate that this
// image uniform doesn't require set/binding. That is done on index 0.
bool GetImageNameWithoutIndices(std::string *name)
{
if (name->back() != ']')
{
return true;
}
if (!UniformNameIsIndexZero(*name, false))
{
return false;
}
// Strip all indices
*name = name->substr(0, name->find('['));
return true;
}
bool MappedSamplerNameNeedsUserDefinedPrefix(const std::string &originalName) bool MappedSamplerNameNeedsUserDefinedPrefix(const std::string &originalName)
{ {
return originalName.find('.') == std::string::npos; return originalName.find('.') == std::string::npos;
} }
std::string GetMappedSamplerNameOld(const std::string &originalName)
{
std::string samplerName = gl::ParseResourceName(originalName, nullptr);
// Samplers in structs are extracted.
std::replace(samplerName.begin(), samplerName.end(), '.', '_');
// Samplers in arrays of structs are also extracted.
std::replace(samplerName.begin(), samplerName.end(), '[', '_');
samplerName.erase(std::remove(samplerName.begin(), samplerName.end(), ']'), samplerName.end());
if (MappedSamplerNameNeedsUserDefinedPrefix(originalName))
{
samplerName = sh::kUserDefinedNamePrefix + samplerName;
}
return samplerName;
}
template <typename OutputIter, typename ImplicitIter> template <typename OutputIter, typename ImplicitIter>
uint32_t CountExplicitOutputs(OutputIter outputsBegin, uint32_t CountExplicitOutputs(OutputIter outputsBegin,
OutputIter outputsEnd, OutputIter outputsEnd,
...@@ -217,10 +172,10 @@ ShaderInterfaceVariableInfo *GetShaderInterfaceVariable(ShaderInterfaceVariableI ...@@ -217,10 +172,10 @@ ShaderInterfaceVariableInfo *GetShaderInterfaceVariable(ShaderInterfaceVariableI
return &(*infoMap)[varName]; return &(*infoMap)[varName];
} }
ShaderInterfaceVariableInfo *AddResourceInfo(ShaderInterfaceVariableInfoMap *infoMap, ShaderInterfaceVariableInfo *AddResourceInfoToAllStages(ShaderInterfaceVariableInfoMap *infoMap,
const std::string &varName, const std::string &varName,
uint32_t descriptorSet, uint32_t descriptorSet,
uint32_t binding) uint32_t binding)
{ {
gl::ShaderBitSet allStages; gl::ShaderBitSet allStages;
allStages.set(); allStages.set();
...@@ -232,6 +187,22 @@ ShaderInterfaceVariableInfo *AddResourceInfo(ShaderInterfaceVariableInfoMap *inf ...@@ -232,6 +187,22 @@ ShaderInterfaceVariableInfo *AddResourceInfo(ShaderInterfaceVariableInfoMap *inf
return info; return info;
} }
ShaderInterfaceVariableInfo *AddResourceInfo(ShaderInterfaceVariableInfoMap *infoMap,
const std::string &varName,
uint32_t descriptorSet,
uint32_t binding,
const gl::ShaderType shaderType)
{
gl::ShaderBitSet stages;
stages.set(shaderType);
ShaderInterfaceVariableInfo *info = AddShaderInterfaceVariable(infoMap, varName);
info->descriptorSet = descriptorSet;
info->binding = binding;
info->activeStages = stages;
return info;
}
// Add location information for an in/out variable. // Add location information for an in/out variable.
ShaderInterfaceVariableInfo *AddLocationInfo(ShaderInterfaceVariableInfoMap *infoMap, ShaderInterfaceVariableInfo *AddLocationInfo(ShaderInterfaceVariableInfoMap *infoMap,
const std::string &varName, const std::string &varName,
...@@ -356,7 +327,7 @@ std::string GenerateTransformFeedbackVaryingOutput(const gl::TransformFeedbackVa ...@@ -356,7 +327,7 @@ std::string GenerateTransformFeedbackVaryingOutput(const gl::TransformFeedbackVa
return result.str(); return result.str();
} }
void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &options, void GenerateTransformFeedbackEmulationOutputs(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramState &programState,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
std::string *vertexShader, std::string *vertexShader,
...@@ -376,20 +347,20 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio ...@@ -376,20 +347,20 @@ void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &optio
for (uint32_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex) for (uint32_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
{ {
const std::string xfbBinding = const std::string xfbBinding = Str(programInterfaceInfo->currentUniformBindingIndex);
Str(programInterfaceInfo->xfbBindingIndexStart + bufferIndex); xfbIndices[bufferIndex] = Str(bufferIndex);
xfbIndices[bufferIndex] = Str(bufferIndex);
std::string bufferName = "xfbBuffer" + xfbIndices[bufferIndex]; std::string bufferName = GetXfbBufferName(bufferIndex);
xfbDecl += "layout(set = " + xfbSet + ", binding = " + xfbBinding + ") buffer " + xfbDecl += "layout(set = " + xfbSet + ", binding = " + xfbBinding + ") buffer " +
bufferName + " { float xfbOut" + xfbIndices[bufferIndex] + "[]; };\n"; bufferName + " { float xfbOut" + Str(bufferIndex) + "[]; };\n";
// Add this entry to the info map, so we can easily assert that every resource has an entry // Add this entry to the info map, so we can easily assert that every resource has an entry
// in this map. // in this map.
AddResourceInfo(variableInfoMapOut, bufferName, AddResourceInfo(variableInfoMapOut, bufferName,
programInterfaceInfo->uniformsAndXfbDescriptorSetIndex, programInterfaceInfo->uniformsAndXfbDescriptorSetIndex,
programInterfaceInfo->xfbBindingIndexStart + bufferIndex); programInterfaceInfo->currentUniformBindingIndex, gl::ShaderType::Vertex);
++programInterfaceInfo->currentUniformBindingIndex;
} }
std::string xfbOut = std::string xfbOut =
...@@ -733,74 +704,77 @@ void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramState &programS ...@@ -733,74 +704,77 @@ void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramState &programS
} }
} }
void AssignUniformBindings(const GlslangSourceOptions &options, void AssignUniformBindings(GlslangSourceOptions &options,
gl::ShaderMap<std::string> *shaderSources, const gl::ProgramState &programState,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
// Assign binding to the default uniforms block of each shader stage.
uint32_t bindingIndex = 0;
for (const gl::ShaderType shaderType : gl::AllShaderTypes()) for (const gl::ShaderType shaderType : gl::AllShaderTypes())
{ {
const std::string &shaderSource = (*shaderSources)[shaderType]; if (programState.getAttachedShader(shaderType) ||
if (!shaderSource.empty()) programState.getProgramExecutable().hasLinkedShaderStage(shaderType))
{ {
AddResourceInfo(variableInfoMapOut, kDefaultUniformNames[shaderType], AddResourceInfo(variableInfoMapOut, kDefaultUniformNames[shaderType],
programInterfaceInfo->uniformsAndXfbDescriptorSetIndex, bindingIndex); programInterfaceInfo->uniformsAndXfbDescriptorSetIndex,
++bindingIndex; programInterfaceInfo->currentUniformBindingIndex, shaderType);
++programInterfaceInfo->currentUniformBindingIndex;
} }
} }
// Assign binding to the driver uniforms block // Assign binding to the driver uniforms block
AddResourceInfo(variableInfoMapOut, sh::vk::kDriverUniformsBlockName, AddResourceInfoToAllStages(variableInfoMapOut, sh::vk::kDriverUniformsBlockName,
programInterfaceInfo->driverUniformsDescriptorSetIndex, 0); programInterfaceInfo->driverUniformsDescriptorSetIndex, 0);
} }
uint32_t AssignInterfaceBlockBindings(const GlslangSourceOptions &options, // TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
const std::vector<gl::InterfaceBlock> &blocks, // shader stages.
uint32_t bindingStart, void AssignInterfaceBlockBindings(GlslangSourceOptions &options,
GlslangProgramInterfaceInfo *programInterfaceInfo, const std::vector<gl::InterfaceBlock> &blocks,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
uint32_t bindingIndex = bindingStart;
for (const gl::InterfaceBlock &block : blocks) for (const gl::InterfaceBlock &block : blocks)
{ {
if (!block.isArray || block.arrayElement == 0) if (!block.isArray || block.arrayElement == 0)
{ {
AddResourceInfo(variableInfoMapOut, block.mappedName, // TODO: http://anglebug.com/4523: All blocks should be active
programInterfaceInfo->shaderResourceDescriptorSetIndex, bindingIndex); if (block.activeShaders().any())
++bindingIndex; {
AddResourceInfoToAllStages(variableInfoMapOut, block.mappedName,
programInterfaceInfo->shaderResourceDescriptorSetIndex,
programInterfaceInfo->currentShaderResourceBindingIndex);
++programInterfaceInfo->currentShaderResourceBindingIndex;
}
} }
} }
return bindingIndex;
} }
uint32_t AssignAtomicCounterBufferBindings(const GlslangSourceOptions &options, // TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
const std::vector<gl::AtomicCounterBuffer> &buffers, // shader stages.
uint32_t bindingStart, void AssignAtomicCounterBufferBindings(GlslangSourceOptions &options,
GlslangProgramInterfaceInfo *programInterfaceInfo, const std::vector<gl::AtomicCounterBuffer> &buffers,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
if (buffers.size() == 0) if (buffers.size() == 0)
{ {
return bindingStart; return;
} }
AddResourceInfo(variableInfoMapOut, sh::vk::kAtomicCountersBlockName, AddResourceInfoToAllStages(variableInfoMapOut, sh::vk::kAtomicCountersBlockName,
programInterfaceInfo->shaderResourceDescriptorSetIndex, bindingStart); programInterfaceInfo->shaderResourceDescriptorSetIndex,
programInterfaceInfo->currentShaderResourceBindingIndex);
return bindingStart + 1; ++programInterfaceInfo->currentShaderResourceBindingIndex;
} }
uint32_t AssignImageBindings(const GlslangSourceOptions &options, // TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
const std::vector<gl::LinkedUniform> &uniforms, // shader stages.
const gl::RangeUI &imageUniformRange, void AssignImageBindings(GlslangSourceOptions &options,
uint32_t bindingStart, const std::vector<gl::LinkedUniform> &uniforms,
GlslangProgramInterfaceInfo *programInterfaceInfo, const gl::RangeUI &imageUniformRange,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
uint32_t bindingIndex = bindingStart;
for (unsigned int uniformIndex : imageUniformRange) for (unsigned int uniformIndex : imageUniformRange)
{ {
const gl::LinkedUniform &imageUniform = uniforms[uniformIndex]; const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
...@@ -808,48 +782,44 @@ uint32_t AssignImageBindings(const GlslangSourceOptions &options, ...@@ -808,48 +782,44 @@ uint32_t AssignImageBindings(const GlslangSourceOptions &options,
std::string name = imageUniform.mappedName; std::string name = imageUniform.mappedName;
if (GetImageNameWithoutIndices(&name)) if (GetImageNameWithoutIndices(&name))
{ {
AddResourceInfo(variableInfoMapOut, name, AddResourceInfoToAllStages(variableInfoMapOut, name,
programInterfaceInfo->shaderResourceDescriptorSetIndex, bindingIndex); programInterfaceInfo->shaderResourceDescriptorSetIndex,
programInterfaceInfo->currentShaderResourceBindingIndex);
++programInterfaceInfo->currentShaderResourceBindingIndex;
} }
++bindingIndex;
} }
return bindingIndex;
} }
void AssignNonTextureBindings(const GlslangSourceOptions &options, void AssignNonTextureBindings(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramState &programState,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
uint32_t bindingStart = 0;
const std::vector<gl::InterfaceBlock> &uniformBlocks = programState.getUniformBlocks(); const std::vector<gl::InterfaceBlock> &uniformBlocks = programState.getUniformBlocks();
bindingStart = AssignInterfaceBlockBindings(options, uniformBlocks, bindingStart, AssignInterfaceBlockBindings(options, uniformBlocks, programInterfaceInfo, variableInfoMapOut);
programInterfaceInfo, variableInfoMapOut);
const std::vector<gl::InterfaceBlock> &storageBlocks = programState.getShaderStorageBlocks(); const std::vector<gl::InterfaceBlock> &storageBlocks = programState.getShaderStorageBlocks();
bindingStart = AssignInterfaceBlockBindings(options, storageBlocks, bindingStart, AssignInterfaceBlockBindings(options, storageBlocks, programInterfaceInfo, variableInfoMapOut);
programInterfaceInfo, variableInfoMapOut);
const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers = const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
programState.getAtomicCounterBuffers(); programState.getAtomicCounterBuffers();
bindingStart = AssignAtomicCounterBufferBindings(options, atomicCounterBuffers, bindingStart, AssignAtomicCounterBufferBindings(options, atomicCounterBuffers, programInterfaceInfo,
programInterfaceInfo, variableInfoMapOut); variableInfoMapOut);
const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms(); const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms();
const gl::RangeUI &imageUniformRange = programState.getImageUniformRange(); const gl::RangeUI &imageUniformRange = programState.getImageUniformRange();
bindingStart = AssignImageBindings(options, uniforms, imageUniformRange, bindingStart, AssignImageBindings(options, uniforms, imageUniformRange, programInterfaceInfo,
programInterfaceInfo, variableInfoMapOut); variableInfoMapOut);
} }
void AssignTextureBindings(const GlslangSourceOptions &options, // TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
// shader stages.
void AssignTextureBindings(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramState &programState,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
// Assign textures to a descriptor set and binding. // Assign textures to a descriptor set and binding.
uint32_t bindingIndex = 0;
const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms(); const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms();
for (unsigned int uniformIndex : programState.getSamplerUniformRange()) for (unsigned int uniformIndex : programState.getSamplerUniformRange())
...@@ -869,11 +839,15 @@ void AssignTextureBindings(const GlslangSourceOptions &options, ...@@ -869,11 +839,15 @@ void AssignTextureBindings(const GlslangSourceOptions &options,
? GetMappedSamplerNameOld(samplerUniform.name) ? GetMappedSamplerNameOld(samplerUniform.name)
: GlslangGetMappedSamplerName(samplerUniform.name); : GlslangGetMappedSamplerName(samplerUniform.name);
AddResourceInfo(variableInfoMapOut, samplerName, // TODO: http://anglebug.com/4523: All uniforms should be active
programInterfaceInfo->textureDescriptorSetIndex, bindingIndex); if (samplerUniform.activeShaders().any())
{
AddResourceInfoToAllStages(variableInfoMapOut, samplerName,
programInterfaceInfo->textureDescriptorSetIndex,
programInterfaceInfo->currentTextureBindingIndex);
++programInterfaceInfo->currentTextureBindingIndex;
}
} }
++bindingIndex;
} }
} }
...@@ -1755,6 +1729,44 @@ void GlslangRelease() ...@@ -1755,6 +1729,44 @@ void GlslangRelease()
ASSERT(result != 0); ASSERT(result != 0);
} }
// Strip indices from the name. If there are non-zero indices, return false to indicate that this
// image uniform doesn't require set/binding. That is done on index 0.
bool GetImageNameWithoutIndices(std::string *name)
{
if (name->back() != ']')
{
return true;
}
if (!UniformNameIsIndexZero(*name, false))
{
return false;
}
// Strip all indices
*name = name->substr(0, name->find('['));
return true;
}
std::string GetMappedSamplerNameOld(const std::string &originalName)
{
std::string samplerName = gl::ParseResourceName(originalName, nullptr);
// Samplers in structs are extracted.
std::replace(samplerName.begin(), samplerName.end(), '.', '_');
// Samplers in arrays of structs are also extracted.
std::replace(samplerName.begin(), samplerName.end(), '[', '_');
samplerName.erase(std::remove(samplerName.begin(), samplerName.end(), ']'), samplerName.end());
if (MappedSamplerNameNeedsUserDefinedPrefix(originalName))
{
samplerName = sh::kUserDefinedNamePrefix + samplerName;
}
return samplerName;
}
std::string GlslangGetMappedSamplerName(const std::string &originalName) std::string GlslangGetMappedSamplerName(const std::string &originalName)
{ {
std::string samplerName = originalName; std::string samplerName = originalName;
...@@ -1790,24 +1802,25 @@ std::string GlslangGetMappedSamplerName(const std::string &originalName) ...@@ -1790,24 +1802,25 @@ std::string GlslangGetMappedSamplerName(const std::string &originalName)
return samplerName; return samplerName;
} }
void GlslangGetShaderSource(const GlslangSourceOptions &options, std::string GetXfbBufferName(const uint32_t bufferIndex)
{
return "xfbBuffer" + Str(bufferIndex);
}
void GlslangGetShaderSource(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources, const gl::ProgramLinkedResources &resources,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
gl::ShaderMap<std::string> *shaderSourcesOut, gl::ShaderMap<std::string> *shaderSourcesOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
variableInfoMapOut->clear();
for (const gl::ShaderType shaderType : gl::AllShaderTypes()) for (const gl::ShaderType shaderType : gl::AllShaderTypes())
{ {
gl::Shader *glShader = programState.getAttachedShader(shaderType); gl::Shader *glShader = programState.getAttachedShader(shaderType);
(*shaderSourcesOut)[shaderType] = glShader ? glShader->getTranslatedSource() : ""; (*shaderSourcesOut)[shaderType] = glShader ? glShader->getTranslatedSource() : "";
} }
std::string *vertexSource = &(*shaderSourcesOut)[gl::ShaderType::Vertex]; std::string *vertexSource = &(*shaderSourcesOut)[gl::ShaderType::Vertex];
const std::string &fragmentSource = (*shaderSourcesOut)[gl::ShaderType::Fragment];
const std::string &computeSource = (*shaderSourcesOut)[gl::ShaderType::Compute];
// Write transform feedback output code. // Write transform feedback output code.
if (!vertexSource->empty()) if (!vertexSource->empty())
...@@ -1832,19 +1845,24 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options, ...@@ -1832,19 +1845,24 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
} }
} }
const gl::ProgramExecutable &executable = programState.getProgramExecutable();
// Assign outputs to the fragment shader, if any. // Assign outputs to the fragment shader, if any.
if (!fragmentSource.empty()) if (programState.getAttachedShader(gl::ShaderType::Fragment) ||
executable.hasLinkedShaderStage(gl::ShaderType::Fragment))
{ {
AssignOutputLocations(programState, variableInfoMapOut); AssignOutputLocations(programState, variableInfoMapOut);
} }
// Assign attributes to the vertex shader, if any. // Assign attributes to the vertex shader, if any.
if (!vertexSource->empty()) if (programState.getAttachedShader(gl::ShaderType::Vertex) ||
executable.hasLinkedShaderStage(gl::ShaderType::Vertex))
{ {
AssignAttributeLocations(programState, variableInfoMapOut); AssignAttributeLocations(programState, variableInfoMapOut);
} }
if (computeSource.empty()) if (!programState.getAttachedShader(gl::ShaderType::Compute) &&
!executable.hasLinkedShaderStage(gl::ShaderType::Compute))
{ {
// Assign varying locations. // Assign varying locations.
AssignVaryingLocations(options, programState, resources, programInterfaceInfo, AssignVaryingLocations(options, programState, resources, programInterfaceInfo,
...@@ -1859,18 +1877,18 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options, ...@@ -1859,18 +1877,18 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
} }
} }
AssignUniformBindings(options, shaderSourcesOut, programInterfaceInfo, variableInfoMapOut); AssignUniformBindings(options, programState, programInterfaceInfo, variableInfoMapOut);
AssignTextureBindings(options, programState, programInterfaceInfo, variableInfoMapOut); AssignTextureBindings(options, programState, programInterfaceInfo, variableInfoMapOut);
AssignNonTextureBindings(options, programState, programInterfaceInfo, variableInfoMapOut); AssignNonTextureBindings(options, programState, programInterfaceInfo, variableInfoMapOut);
} }
angle::Result GlslangGetShaderSpirvCode(GlslangErrorCallback callback, angle::Result GlslangGetShaderSpirvCode(const GlslangErrorCallback &callback,
const gl::Caps &glCaps, const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources, const gl::ShaderMap<std::string> &shaderSources,
const ShaderInterfaceVariableInfoMap &variableInfoMap, const ShaderInterfaceVariableInfoMap &variableInfoMap,
gl::ShaderMap<SpirvBlob> *spirvBlobsOut) gl::ShaderMap<SpirvBlob> *spirvBlobsOut)
{ {
gl::ShaderMap<std::vector<uint32_t>> initialSpirvBlobs; gl::ShaderMap<SpirvBlob> initialSpirvBlobs;
ANGLE_TRY(GetShaderSpirvCode(callback, glCaps, shaderSources, &initialSpirvBlobs)); ANGLE_TRY(GetShaderSpirvCode(callback, glCaps, shaderSources, &initialSpirvBlobs));
// Transform the SPIR-V code by assigning location/set/binding values. // Transform the SPIR-V code by assigning location/set/binding values.
......
...@@ -21,20 +21,27 @@ enum class GlslangError ...@@ -21,20 +21,27 @@ enum class GlslangError
InvalidSpirv, InvalidSpirv,
}; };
constexpr gl::ShaderMap<const char *> kDefaultUniformNames = {
{gl::ShaderType::Vertex, sh::vk::kDefaultUniformsNameVS},
{gl::ShaderType::Geometry, sh::vk::kDefaultUniformsNameGS},
{gl::ShaderType::Fragment, sh::vk::kDefaultUniformsNameFS},
{gl::ShaderType::Compute, sh::vk::kDefaultUniformsNameCS},
};
struct GlslangProgramInterfaceInfo struct GlslangProgramInterfaceInfo
{ {
// Uniforms set index: // Uniforms set index:
uint32_t uniformsAndXfbDescriptorSetIndex; uint32_t uniformsAndXfbDescriptorSetIndex;
uint32_t currentUniformBindingIndex;
// Textures set index: // Textures set index:
uint32_t textureDescriptorSetIndex; uint32_t textureDescriptorSetIndex;
uint32_t currentTextureBindingIndex;
// Other shader resources set index: // Other shader resources set index:
uint32_t shaderResourceDescriptorSetIndex; uint32_t shaderResourceDescriptorSetIndex;
uint32_t currentShaderResourceBindingIndex;
// ANGLE driver uniforms set index: // ANGLE driver uniforms set index:
uint32_t driverUniformsDescriptorSetIndex; uint32_t driverUniformsDescriptorSetIndex;
// Binding index start for transform feedback buffers:
uint32_t xfbBindingIndexStart;
uint32_t locationsUsedForXfbExtension; uint32_t locationsUsedForXfbExtension;
}; };
...@@ -76,26 +83,32 @@ struct ShaderInterfaceVariableInfo ...@@ -76,26 +83,32 @@ struct ShaderInterfaceVariableInfo
uint32_t xfbStride = kInvalid; uint32_t xfbStride = kInvalid;
}; };
// TODO: http://anglebug.com/4524: Need a different hash key than a string, since
// that's slow to calculate.
using ShaderInterfaceVariableInfoMap = std::unordered_map<std::string, ShaderInterfaceVariableInfo>; using ShaderInterfaceVariableInfoMap = std::unordered_map<std::string, ShaderInterfaceVariableInfo>;
void GlslangInitialize(); void GlslangInitialize();
void GlslangRelease(); void GlslangRelease();
bool GetImageNameWithoutIndices(std::string *name);
// Get the mapped sampler name after the soure is transformed by GlslangGetShaderSource() // Get the mapped sampler name after the soure is transformed by GlslangGetShaderSource()
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);
// Transform the source to include actual binding points for various shader resources (textures, // Transform the source to include actual binding points for various shader resources (textures,
// buffers, xfb, etc). For some variables, these values are instead output to the variableInfoMap // buffers, xfb, etc). For some variables, these values are instead output to the variableInfoMap
// to be set during a SPIR-V transformation. This is a transitory step towards moving all variables // to be set during a SPIR-V transformation. This is a transitory step towards moving all variables
// to this map, at which point GlslangGetShaderSpirvCode will also be called by this function. // to this map, at which point GlslangGetShaderSpirvCode will also be called by this function.
void GlslangGetShaderSource(const GlslangSourceOptions &options, void GlslangGetShaderSource(GlslangSourceOptions &options,
const gl::ProgramState &programState, const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources, const gl::ProgramLinkedResources &resources,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
gl::ShaderMap<std::string> *shaderSourcesOut, gl::ShaderMap<std::string> *shaderSourcesOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut); ShaderInterfaceVariableInfoMap *variableInfoMapOut);
angle::Result GlslangGetShaderSpirvCode(GlslangErrorCallback callback, angle::Result GlslangGetShaderSpirvCode(const GlslangErrorCallback &callback,
const gl::Caps &glCaps, const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources, const gl::ShaderMap<std::string> &shaderSources,
const ShaderInterfaceVariableInfoMap &variableInfoMap, const ShaderInterfaceVariableInfoMap &variableInfoMap,
......
...@@ -27,12 +27,14 @@ void ResetGlslangProgramInterfaceInfo(GlslangProgramInterfaceInfo *programInterf ...@@ -27,12 +27,14 @@ void ResetGlslangProgramInterfaceInfo(GlslangProgramInterfaceInfo *programInterf
// We don't actually use descriptor set for now, the actual binding will be done inside // We don't actually use descriptor set for now, the actual binding will be done inside
// ProgramMtl using spirv-cross. // ProgramMtl using spirv-cross.
programInterfaceInfo->uniformsAndXfbDescriptorSetIndex = kDefaultUniformsBindingIndex; programInterfaceInfo->uniformsAndXfbDescriptorSetIndex = kDefaultUniformsBindingIndex;
programInterfaceInfo->currentUniformBindingIndex = 0;
programInterfaceInfo->textureDescriptorSetIndex = 0; programInterfaceInfo->textureDescriptorSetIndex = 0;
programInterfaceInfo->currentTextureBindingIndex = 0;
programInterfaceInfo->driverUniformsDescriptorSetIndex = kDriverUniformsBindingIndex; programInterfaceInfo->driverUniformsDescriptorSetIndex = kDriverUniformsBindingIndex;
// NOTE(hqle): Unused for now, until we support ES 3.0 // NOTE(hqle): Unused for now, until we support ES 3.0
programInterfaceInfo->shaderResourceDescriptorSetIndex = -1; programInterfaceInfo->shaderResourceDescriptorSetIndex = -1;
programInterfaceInfo->xfbBindingIndexStart = -1; programInterfaceInfo->currentShaderResourceBindingIndex = 0;
programInterfaceInfo->locationsUsedForXfbExtension = 0; programInterfaceInfo->locationsUsedForXfbExtension = 0;
static_assert(kDefaultUniformsBindingIndex != 0, "kDefaultUniformsBindingIndex must not be 0"); static_assert(kDefaultUniformsBindingIndex != 0, "kDefaultUniformsBindingIndex must not be 0");
static_assert(kDriverUniformsBindingIndex != 0, "kDriverUniformsBindingIndex must not be 0"); static_assert(kDriverUniformsBindingIndex != 0, "kDriverUniformsBindingIndex must not be 0");
...@@ -50,11 +52,12 @@ void GlslangGetShaderSource(const gl::ProgramState &programState, ...@@ -50,11 +52,12 @@ void GlslangGetShaderSource(const gl::ProgramState &programState,
gl::ShaderMap<std::string> *shaderSourcesOut, gl::ShaderMap<std::string> *shaderSourcesOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
GlslangSourceOptions options = CreateSourceOptions();
GlslangProgramInterfaceInfo programInterfaceInfo; GlslangProgramInterfaceInfo programInterfaceInfo;
ResetGlslangProgramInterfaceInfo(&programInterfaceInfo); ResetGlslangProgramInterfaceInfo(&programInterfaceInfo);
rx::GlslangGetShaderSource(CreateSourceOptions(), programState, resources, rx::GlslangGetShaderSource(options, programState, resources, &programInterfaceInfo,
&programInterfaceInfo, shaderSourcesOut, variableInfoMapOut); shaderSourcesOut, variableInfoMapOut);
} }
angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context, angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
......
...@@ -598,6 +598,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -598,6 +598,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mVertexArray(nullptr), mVertexArray(nullptr),
mDrawFramebuffer(nullptr), mDrawFramebuffer(nullptr),
mProgram(nullptr), mProgram(nullptr),
mExecutable(nullptr),
mLastIndexBufferOffset(0), mLastIndexBufferOffset(0),
mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum), mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum),
mXfbBaseVertex(0), mXfbBaseVertex(0),
...@@ -2792,7 +2793,8 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2792,7 +2793,8 @@ angle::Result ContextVk::syncState(const gl::Context *context,
case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING: case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
break; break;
case gl::State::DIRTY_BIT_PROGRAM_BINDING: case gl::State::DIRTY_BIT_PROGRAM_BINDING:
mProgram = vk::GetImpl(glState.getProgram()); mProgram = vk::GetImpl(glState.getProgram());
mExecutable = &mProgram->getExecutable();
break; break;
case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE: case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
{ {
......
...@@ -26,6 +26,7 @@ struct FeaturesVk; ...@@ -26,6 +26,7 @@ struct FeaturesVk;
namespace rx namespace rx
{ {
class ProgramExecutableVk;
class RendererVk; class RendererVk;
class WindowSurfaceVk; class WindowSurfaceVk;
...@@ -657,6 +658,11 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -657,6 +658,11 @@ class ContextVk : public ContextImpl, public vk::Context
size_t getVkIndexTypeSize(gl::DrawElementsType glIndexType) const; size_t getVkIndexTypeSize(gl::DrawElementsType glIndexType) const;
bool shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const; bool shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const;
const ProgramExecutableVk *getExecutable() const { return mExecutable; }
ProgramExecutableVk *getExecutable() { return mExecutable; }
ProgramVk *getShaderProgram(const gl::State &glState, gl::ShaderType shaderType) const;
private: private:
// Dirty bits. // Dirty bits.
enum DirtyBitType : size_t enum DirtyBitType : size_t
...@@ -950,6 +956,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -950,6 +956,7 @@ class ContextVk : public ContextImpl, public vk::Context
VertexArrayVk *mVertexArray; VertexArrayVk *mVertexArray;
FramebufferVk *mDrawFramebuffer; FramebufferVk *mDrawFramebuffer;
ProgramVk *mProgram; ProgramVk *mProgram;
ProgramExecutableVk *mExecutable;
// Graph resource used to record dispatch commands and hold resource dependencies. // Graph resource used to record dispatch commands and hold resource dependencies.
vk::DispatchHelper mDispatcher; vk::DispatchHelper mDispatcher;
......
...@@ -21,7 +21,10 @@ angle::Result ErrorHandler(vk::Context *context, GlslangError) ...@@ -21,7 +21,10 @@ angle::Result ErrorHandler(vk::Context *context, GlslangError)
return angle::Result::Stop; return angle::Result::Stop;
} }
GlslangSourceOptions CreateSourceOptions(const angle::FeaturesVk &features) } // namespace
// static
GlslangSourceOptions GlslangWrapperVk::CreateSourceOptions(const angle::FeaturesVk &features)
{ {
GlslangSourceOptions options; GlslangSourceOptions options;
...@@ -33,7 +36,6 @@ GlslangSourceOptions CreateSourceOptions(const angle::FeaturesVk &features) ...@@ -33,7 +36,6 @@ GlslangSourceOptions CreateSourceOptions(const angle::FeaturesVk &features)
return options; return options;
} }
} // namespace
// static // static
void GlslangWrapperVk::ResetGlslangProgramInterfaceInfo( void GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(
...@@ -41,12 +43,14 @@ void GlslangWrapperVk::ResetGlslangProgramInterfaceInfo( ...@@ -41,12 +43,14 @@ void GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(
{ {
glslangProgramInterfaceInfo->uniformsAndXfbDescriptorSetIndex = glslangProgramInterfaceInfo->uniformsAndXfbDescriptorSetIndex =
kUniformsAndXfbDescriptorSetIndex; kUniformsAndXfbDescriptorSetIndex;
glslangProgramInterfaceInfo->textureDescriptorSetIndex = kTextureDescriptorSetIndex; glslangProgramInterfaceInfo->currentUniformBindingIndex = 0;
glslangProgramInterfaceInfo->textureDescriptorSetIndex = kTextureDescriptorSetIndex;
glslangProgramInterfaceInfo->currentTextureBindingIndex = 0;
glslangProgramInterfaceInfo->shaderResourceDescriptorSetIndex = glslangProgramInterfaceInfo->shaderResourceDescriptorSetIndex =
kShaderResourceDescriptorSetIndex; kShaderResourceDescriptorSetIndex;
glslangProgramInterfaceInfo->currentShaderResourceBindingIndex = 0;
glslangProgramInterfaceInfo->driverUniformsDescriptorSetIndex = glslangProgramInterfaceInfo->driverUniformsDescriptorSetIndex =
kDriverUniformsDescriptorSetIndex; kDriverUniformsDescriptorSetIndex;
glslangProgramInterfaceInfo->xfbBindingIndexStart = kXfbBindingIndexStart;
glslangProgramInterfaceInfo->locationsUsedForXfbExtension = 0; glslangProgramInterfaceInfo->locationsUsedForXfbExtension = 0;
} }
...@@ -59,8 +63,9 @@ void GlslangWrapperVk::GetShaderSource(const angle::FeaturesVk &features, ...@@ -59,8 +63,9 @@ void GlslangWrapperVk::GetShaderSource(const angle::FeaturesVk &features,
gl::ShaderMap<std::string> *shaderSourcesOut, gl::ShaderMap<std::string> *shaderSourcesOut,
ShaderInterfaceVariableInfoMap *variableInfoMapOut) ShaderInterfaceVariableInfoMap *variableInfoMapOut)
{ {
GlslangGetShaderSource(CreateSourceOptions(features), programState, resources, GlslangSourceOptions options = CreateSourceOptions(features);
programInterfaceInfo, shaderSourcesOut, variableInfoMapOut); GlslangGetShaderSource(options, programState, resources, programInterfaceInfo, shaderSourcesOut,
variableInfoMapOut);
} }
// static // static
......
...@@ -25,6 +25,8 @@ namespace rx ...@@ -25,6 +25,8 @@ namespace rx
class GlslangWrapperVk class GlslangWrapperVk
{ {
public: public:
static GlslangSourceOptions CreateSourceOptions(const angle::FeaturesVk &features);
static void ResetGlslangProgramInterfaceInfo( static void ResetGlslangProgramInterfaceInfo(
GlslangProgramInterfaceInfo *glslangProgramInterfaceInfo); GlslangProgramInterfaceInfo *glslangProgramInterfaceInfo);
......
...@@ -8,10 +8,13 @@ ...@@ -8,10 +8,13 @@
#include "libANGLE/renderer/vulkan/ProgramExecutableVk.h" #include "libANGLE/renderer/vulkan/ProgramExecutableVk.h"
#include "libANGLE/renderer/glslang_wrapper_utils.h"
#include "libANGLE/renderer/vulkan/BufferVk.h" #include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/GlslangWrapperVk.h"
#include "libANGLE/renderer/vulkan/TextureVk.h" #include "libANGLE/renderer/vulkan/TextureVk.h"
#include "libANGLE/renderer/vulkan/TransformFeedbackVk.h" #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx namespace rx
{ {
...@@ -21,11 +24,7 @@ DefaultUniformBlock::DefaultUniformBlock() = default; ...@@ -21,11 +24,7 @@ DefaultUniformBlock::DefaultUniformBlock() = default;
DefaultUniformBlock::~DefaultUniformBlock() = default; DefaultUniformBlock::~DefaultUniformBlock() = default;
ProgramExecutableVk::ProgramExecutableVk() ProgramExecutableVk::ProgramExecutableVk()
: mStorageBlockBindingsOffset(0), : mEmptyDescriptorSets{}, mNumDefaultUniformDescriptors(0), mDynamicBufferOffsets{}
mAtomicCounterBufferBindingsOffset(0),
mImageBindingsOffset(0),
mEmptyDescriptorSets{},
mDynamicBufferOffsets{}
{} {}
ProgramExecutableVk::~ProgramExecutableVk() = default; ProgramExecutableVk::~ProgramExecutableVk() = default;
...@@ -34,8 +33,6 @@ void ProgramExecutableVk::reset(ContextVk *contextVk) ...@@ -34,8 +33,6 @@ void ProgramExecutableVk::reset(ContextVk *contextVk)
{ {
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
clearVariableInfoMap();
for (auto &descriptorSetLayout : mDescriptorSetLayouts) for (auto &descriptorSetLayout : mDescriptorSetLayouts)
{ {
descriptorSetLayout.reset(); descriptorSetLayout.reset();
...@@ -46,6 +43,7 @@ void ProgramExecutableVk::reset(ContextVk *contextVk) ...@@ -46,6 +43,7 @@ void ProgramExecutableVk::reset(ContextVk *contextVk)
mDescriptorSets.clear(); mDescriptorSets.clear();
mEmptyDescriptorSets.fill(VK_NULL_HANDLE); mEmptyDescriptorSets.fill(VK_NULL_HANDLE);
mNumDefaultUniformDescriptors = 0;
for (vk::RefCountedDescriptorPoolBinding &binding : mDescriptorPoolBindings) for (vk::RefCountedDescriptorPoolBinding &binding : mDescriptorPoolBindings)
{ {
...@@ -61,20 +59,62 @@ void ProgramExecutableVk::reset(ContextVk *contextVk) ...@@ -61,20 +59,62 @@ void ProgramExecutableVk::reset(ContextVk *contextVk)
mDescriptorBuffersCache.clear(); mDescriptorBuffersCache.clear();
} }
void ProgramExecutableVk::clearVariableInfoMap() std::unique_ptr<rx::LinkEvent> ProgramExecutableVk::load(gl::BinaryInputStream *stream)
{ {
mVariableInfoMap.clear(); clearVariableInfoMap();
size_t variableInfoMapSize = stream->readInt<size_t>();
for (size_t i = 0; i < variableInfoMapSize; ++i)
{
const std::string variableName = stream->readString();
ShaderInterfaceVariableInfo *info = &mVariableInfoMap[variableName];
info->descriptorSet = stream->readInt<uint32_t>();
info->binding = stream->readInt<uint32_t>();
for (gl::ShaderType shaderType : gl::AllShaderTypes())
{
info->location[shaderType] = stream->readInt<uint32_t>();
info->component[shaderType] = stream->readInt<uint32_t>();
}
// PackedEnumBitSet uses uint8_t
info->activeStages = gl::ShaderBitSet(stream->readInt<uint8_t>());
info->xfbBuffer = stream->readInt<uint32_t>();
info->xfbOffset = stream->readInt<uint32_t>();
info->xfbStride = stream->readInt<uint32_t>();
}
return std::make_unique<LinkEventDone>(angle::Result::Continue);
} }
void ProgramExecutableVk::updateBindingOffsets(const gl::ProgramState &programState) void ProgramExecutableVk::save(gl::BinaryOutputStream *stream)
{ {
mStorageBlockBindingsOffset = static_cast<uint32_t>(programState.getUniqueUniformBlockCount()); stream->writeInt<size_t>(mVariableInfoMap.size());
for (const auto &it : mVariableInfoMap)
{
stream->writeString(it.first);
stream->writeInt<uint32_t>(it.second.descriptorSet);
stream->writeInt<uint32_t>(it.second.binding);
mAtomicCounterBufferBindingsOffset = static_cast<uint32_t>( for (gl::ShaderType shaderType : gl::AllShaderTypes())
mStorageBlockBindingsOffset + programState.getUniqueStorageBlockCount()); {
stream->writeInt<uint32_t>(it.second.location[shaderType]);
stream->writeInt<uint32_t>(it.second.component[shaderType]);
}
uint32_t atomicCounterBindingCount = programState.getAtomicCounterBuffers().empty() ? 0 : 1; // PackedEnumBitSet uses uint8_t
mImageBindingsOffset = mAtomicCounterBufferBindingsOffset + atomicCounterBindingCount; stream->writeInt<uint8_t>(it.second.activeStages.bits());
stream->writeInt<uint32_t>(it.second.xfbBuffer);
stream->writeInt<uint32_t>(it.second.xfbOffset);
stream->writeInt<uint32_t>(it.second.xfbStride);
}
}
void ProgramExecutableVk::clearVariableInfoMap()
{
mVariableInfoMap.clear();
} }
uint32_t GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> &blocks, uint32_t GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> &blocks,
...@@ -138,28 +178,32 @@ angle::Result ProgramExecutableVk::allocateDescriptorSetAndGetInfo(ContextVk *co ...@@ -138,28 +178,32 @@ angle::Result ProgramExecutableVk::allocateDescriptorSetAndGetInfo(ContextVk *co
return angle::Result::Continue; return angle::Result::Continue;
} }
void AddInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> &blocks, void ProgramExecutableVk::addInterfaceBlockDescriptorSetDesc(
uint32_t bindingStart, const std::vector<gl::InterfaceBlock> &blocks,
VkDescriptorType descType, VkDescriptorType descType,
vk::DescriptorSetLayoutDesc *descOut) vk::DescriptorSetLayoutDesc *descOut)
{ {
uint32_t bindingIndex = 0;
for (uint32_t bufferIndex = 0; bufferIndex < blocks.size();) for (uint32_t bufferIndex = 0; bufferIndex < blocks.size();)
{ {
gl::InterfaceBlock block = blocks[bufferIndex];
const uint32_t arraySize = GetInterfaceBlockArraySize(blocks, bufferIndex); const uint32_t arraySize = GetInterfaceBlockArraySize(blocks, bufferIndex);
VkShaderStageFlags activeStages = bufferIndex += arraySize;
gl_vk::GetShaderStageFlags(blocks[bufferIndex].activeShaders());
descOut->update(bindingStart + bindingIndex, descType, arraySize, activeStages); if (!block.activeShaders().any())
{
continue;
}
bufferIndex += arraySize; const std::string blockName = block.mappedName;
++bindingIndex; const ShaderInterfaceVariableInfo &info = mVariableInfoMap[blockName];
const VkShaderStageFlags &activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
descOut->update(info.binding, descType, arraySize, activeStages);
} }
} }
void AddAtomicCounterBufferDescriptorSetDesc( void ProgramExecutableVk::addAtomicCounterBufferDescriptorSetDesc(
const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers, const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
uint32_t bindingStart,
vk::DescriptorSetLayoutDesc *descOut) vk::DescriptorSetLayoutDesc *descOut)
{ {
if (atomicCounterBuffers.empty()) if (atomicCounterBuffers.empty())
...@@ -167,20 +211,17 @@ void AddAtomicCounterBufferDescriptorSetDesc( ...@@ -167,20 +211,17 @@ void AddAtomicCounterBufferDescriptorSetDesc(
return; return;
} }
VkShaderStageFlags activeStages = 0; std::string blockName(sh::vk::kAtomicCountersBlockName);
for (const gl::AtomicCounterBuffer &buffer : atomicCounterBuffers) const ShaderInterfaceVariableInfo &info = mVariableInfoMap[blockName];
{ VkShaderStageFlags activeStages = rx::gl_vk::GetShaderStageFlags(info.activeStages);
activeStages |= gl_vk::GetShaderStageFlags(buffer.activeShaders());
}
// A single storage buffer array is used for all stages for simplicity. // A single storage buffer array is used for all stages for simplicity.
descOut->update(bindingStart, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descOut->update(info.binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS, activeStages); gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS, activeStages);
} }
void AddImageDescriptorSetDesc(const gl::ProgramState &programState, void ProgramExecutableVk::addImageDescriptorSetDesc(const gl::ProgramState &programState,
uint32_t bindingStart, vk::DescriptorSetLayoutDesc *descOut)
vk::DescriptorSetLayoutDesc *descOut)
{ {
const std::vector<gl::ImageBinding> &imageBindings = programState.getImageBindings(); const std::vector<gl::ImageBinding> &imageBindings = programState.getImageBindings();
const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms(); const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms();
...@@ -191,21 +232,22 @@ void AddImageDescriptorSetDesc(const gl::ProgramState &programState, ...@@ -191,21 +232,22 @@ void AddImageDescriptorSetDesc(const gl::ProgramState &programState,
uint32_t uniformIndex = programState.getUniformIndexFromImageIndex(imageIndex); uint32_t uniformIndex = programState.getUniformIndexFromImageIndex(imageIndex);
const gl::LinkedUniform &imageUniform = uniforms[uniformIndex]; const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
std::string name = imageUniform.mappedName;
GetImageNameWithoutIndices(&name);
ShaderInterfaceVariableInfo &info = mVariableInfoMap[name];
// The front-end always binds array image units sequentially. // The front-end always binds array image units sequentially.
uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size()); uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(imageUniform.activeShaders()); VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
uint32_t bindingIndex = bindingStart + imageIndex; descOut->update(info.binding, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, arraySize, activeStages);
descOut->update(bindingIndex, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, arraySize, activeStages);
} }
} }
void AddTextureDescriptorSetDesc(const gl::ProgramState &programState, void ProgramExecutableVk::addTextureDescriptorSetDesc(const gl::ProgramState &programState,
bool useOldRewriteStructSamplers, bool useOldRewriteStructSamplers,
vk::DescriptorSetLayoutDesc *descOut) vk::DescriptorSetLayoutDesc *descOut)
{ {
uint32_t bindingIndex = 0;
const std::vector<gl::SamplerBinding> &samplerBindings = programState.getSamplerBindings(); const std::vector<gl::SamplerBinding> &samplerBindings = programState.getSamplerBindings();
const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms(); const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms();
...@@ -216,10 +258,14 @@ void AddTextureDescriptorSetDesc(const gl::ProgramState &programState, ...@@ -216,10 +258,14 @@ void AddTextureDescriptorSetDesc(const gl::ProgramState &programState,
uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(textureIndex); uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(textureIndex);
const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex]; const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
const std::string samplerName = useOldRewriteStructSamplers
? GetMappedSamplerNameOld(samplerUniform.name)
: GlslangGetMappedSamplerName(samplerUniform.name);
ShaderInterfaceVariableInfo &info = mVariableInfoMap[samplerName];
// The front-end always binds array sampler units sequentially. // The front-end always binds array sampler units sequentially.
uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size()); uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
VkShaderStageFlags activeStages = VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
gl_vk::GetShaderStageFlags(samplerUniform.activeShaders());
if (!useOldRewriteStructSamplers) if (!useOldRewriteStructSamplers)
{ {
...@@ -237,7 +283,7 @@ void AddTextureDescriptorSetDesc(const gl::ProgramState &programState, ...@@ -237,7 +283,7 @@ void AddTextureDescriptorSetDesc(const gl::ProgramState &programState,
} }
} }
descOut->update(bindingIndex++, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize, descOut->update(info.binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize,
activeStages); activeStages);
} }
} }
...@@ -316,19 +362,24 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon ...@@ -316,19 +362,24 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon
const gl::ShaderBitSet &linkedShaderStages = glExecutable.getLinkedShaderStages(); const gl::ShaderBitSet &linkedShaderStages = glExecutable.getLinkedShaderStages();
reset(contextVk); reset(contextVk);
updateBindingOffsets(programState);
// Store a reference to the pipeline and descriptor set layouts. This will create them if they // Store a reference to the pipeline and descriptor set layouts. This will create them if they
// don't already exist in the cache. // don't already exist in the cache.
// Default uniforms and transform feedback: // Default uniforms and transform feedback:
vk::DescriptorSetLayoutDesc uniformsAndXfbSetDesc; vk::DescriptorSetLayoutDesc uniformsAndXfbSetDesc;
uint32_t uniformBindingIndex = 0;
for (const gl::ShaderType shaderType : linkedShaderStages) for (const gl::ShaderType shaderType : linkedShaderStages)
{ {
uniformsAndXfbSetDesc.update(uniformBindingIndex++, const std::string uniformBlockName = kDefaultUniformNames[shaderType];
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, ShaderInterfaceVariableInfo &info = mVariableInfoMap[uniformBlockName];
if (!info.activeStages[shaderType])
{
continue;
}
uniformsAndXfbSetDesc.update(info.binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
gl_vk::kShaderStageMap[shaderType]); gl_vk::kShaderStageMap[shaderType]);
mNumDefaultUniformDescriptors++;
} }
bool hasVertexShader = glExecutable.hasLinkedShaderStage(gl::ShaderType::Vertex); bool hasVertexShader = glExecutable.hasLinkedShaderStage(gl::ShaderType::Vertex);
bool hasXfbVaryings = !programState.getLinkedTransformFeedbackVaryings().empty(); bool hasXfbVaryings = !programState.getLinkedTransformFeedbackVaryings().empty();
...@@ -336,7 +387,7 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon ...@@ -336,7 +387,7 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon
{ {
size_t xfbBufferCount = programState.getTransformFeedbackBufferCount(); size_t xfbBufferCount = programState.getTransformFeedbackBufferCount();
TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback); TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
transformFeedbackVk->updateDescriptorSetLayout(contextVk, xfbBufferCount, transformFeedbackVk->updateDescriptorSetLayout(contextVk, mVariableInfoMap, xfbBufferCount,
&uniformsAndXfbSetDesc); &uniformsAndXfbSetDesc);
} }
...@@ -347,16 +398,13 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon ...@@ -347,16 +398,13 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon
// Uniform and storage buffers, atomic counter buffers and images: // Uniform and storage buffers, atomic counter buffers and images:
vk::DescriptorSetLayoutDesc resourcesSetDesc; vk::DescriptorSetLayoutDesc resourcesSetDesc;
AddInterfaceBlockDescriptorSetDesc(programState.getUniformBlocks(), addInterfaceBlockDescriptorSetDesc(programState.getUniformBlocks(),
getUniformBlockBindingsOffset(),
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &resourcesSetDesc); VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &resourcesSetDesc);
AddInterfaceBlockDescriptorSetDesc(programState.getShaderStorageBlocks(), addInterfaceBlockDescriptorSetDesc(programState.getShaderStorageBlocks(),
getStorageBlockBindingsOffset(),
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resourcesSetDesc); VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resourcesSetDesc);
AddAtomicCounterBufferDescriptorSetDesc(programState.getAtomicCounterBuffers(), addAtomicCounterBufferDescriptorSetDesc(programState.getAtomicCounterBuffers(),
getAtomicCounterBufferBindingsOffset(),
&resourcesSetDesc); &resourcesSetDesc);
AddImageDescriptorSetDesc(programState, getImageBindingsOffset(), &resourcesSetDesc); addImageDescriptorSetDesc(programState, &resourcesSetDesc);
ANGLE_TRY(renderer->getDescriptorSetLayout( ANGLE_TRY(renderer->getDescriptorSetLayout(
contextVk, resourcesSetDesc, &mDescriptorSetLayouts[kShaderResourceDescriptorSetIndex])); contextVk, resourcesSetDesc, &mDescriptorSetLayouts[kShaderResourceDescriptorSetIndex]));
...@@ -364,16 +412,15 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon ...@@ -364,16 +412,15 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon
// Textures: // Textures:
vk::DescriptorSetLayoutDesc texturesSetDesc; vk::DescriptorSetLayoutDesc texturesSetDesc;
AddTextureDescriptorSetDesc(programState, contextVk->useOldRewriteStructSamplers(), addTextureDescriptorSetDesc(programState, contextVk->useOldRewriteStructSamplers(),
&texturesSetDesc); &texturesSetDesc);
ANGLE_TRY(renderer->getDescriptorSetLayout(contextVk, texturesSetDesc, ANGLE_TRY(renderer->getDescriptorSetLayout(contextVk, texturesSetDesc,
&mDescriptorSetLayouts[kTextureDescriptorSetIndex])); &mDescriptorSetLayouts[kTextureDescriptorSetIndex]));
// Driver uniforms: // Driver uniforms:
VkShaderStageFlags driverUniformsStages = programState.getProgramExecutable().isCompute() VkShaderStageFlags driverUniformsStages =
? VK_SHADER_STAGE_COMPUTE_BIT glExecutable.isCompute() ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS;
: VK_SHADER_STAGE_ALL_GRAPHICS;
vk::DescriptorSetLayoutDesc driverUniformsSetDesc = vk::DescriptorSetLayoutDesc driverUniformsSetDesc =
contextVk->getDriverUniformsDescriptorSetDesc(driverUniformsStages); contextVk->getDriverUniformsDescriptorSetDesc(driverUniformsStages);
ANGLE_TRY(renderer->getDescriptorSetLayout( ANGLE_TRY(renderer->getDescriptorSetLayout(
...@@ -396,7 +443,7 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon ...@@ -396,7 +443,7 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon
// Initialize descriptor pools. // Initialize descriptor pools.
std::array<VkDescriptorPoolSize, 2> uniformAndXfbSetSize = { std::array<VkDescriptorPoolSize, 2> uniformAndXfbSetSize = {
{{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, {{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
static_cast<uint32_t>(programState.getProgramExecutable().getLinkedShaderStageCount())}, static_cast<uint32_t>(mNumDefaultUniformDescriptors)},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS}}}; {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS}}};
uint32_t uniformBlockCount = static_cast<uint32_t>(programState.getUniformBlocks().size()); uint32_t uniformBlockCount = static_cast<uint32_t>(programState.getUniformBlocks().size());
...@@ -451,7 +498,7 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon ...@@ -451,7 +498,7 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon
&textureSetSize, 1)); &textureSetSize, 1));
} }
mDynamicBufferOffsets.resize(programState.getProgramExecutable().getLinkedShaderStageCount()); mDynamicBufferOffsets.resize(glExecutable.getLinkedShaderStageCount());
// Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms, // Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms,
// or atomic counter buffer array indices that are unused. // or atomic counter buffer array indices that are unused.
...@@ -482,17 +529,23 @@ void ProgramExecutableVk::updateDefaultUniformsDescriptorSet( ...@@ -482,17 +529,23 @@ void ProgramExecutableVk::updateDefaultUniformsDescriptorSet(
gl::ShaderVector<VkDescriptorBufferInfo> descriptorBufferInfo(shaderStageCount); gl::ShaderVector<VkDescriptorBufferInfo> descriptorBufferInfo(shaderStageCount);
gl::ShaderVector<VkWriteDescriptorSet> writeDescriptorInfo(shaderStageCount); gl::ShaderVector<VkWriteDescriptorSet> writeDescriptorInfo(shaderStageCount);
uint32_t bindingIndex = 0;
mDescriptorBuffersCache.clear(); mDescriptorBuffersCache.clear();
// Write default uniforms for each shader type. // Write default uniforms for each shader type.
uint32_t writeInfoCount = 0;
for (const gl::ShaderType shaderType : for (const gl::ShaderType shaderType :
programState.getProgramExecutable().getLinkedShaderStages()) programState.getProgramExecutable().getLinkedShaderStages())
{ {
const std::string uniformBlockName = kDefaultUniformNames[shaderType];
ShaderInterfaceVariableInfo &info = mVariableInfoMap[uniformBlockName];
if (!info.activeStages[shaderType])
{
return;
}
DefaultUniformBlock &uniformBlock = defaultUniformBlocks[shaderType]; DefaultUniformBlock &uniformBlock = defaultUniformBlocks[shaderType];
VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[bindingIndex]; VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[writeInfoCount];
VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[bindingIndex]; VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[writeInfoCount];
if (!uniformBlock.uniformData.empty()) if (!uniformBlock.uniformData.empty())
{ {
...@@ -513,7 +566,7 @@ void ProgramExecutableVk::updateDefaultUniformsDescriptorSet( ...@@ -513,7 +566,7 @@ void ProgramExecutableVk::updateDefaultUniformsDescriptorSet(
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.pNext = nullptr; writeInfo.pNext = nullptr;
writeInfo.dstSet = mDescriptorSets[kUniformsAndXfbDescriptorSetIndex]; writeInfo.dstSet = mDescriptorSets[kUniformsAndXfbDescriptorSetIndex];
writeInfo.dstBinding = bindingIndex; writeInfo.dstBinding = info.binding;
writeInfo.dstArrayElement = 0; writeInfo.dstArrayElement = 0;
writeInfo.descriptorCount = 1; writeInfo.descriptorCount = 1;
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
...@@ -521,15 +574,14 @@ void ProgramExecutableVk::updateDefaultUniformsDescriptorSet( ...@@ -521,15 +574,14 @@ void ProgramExecutableVk::updateDefaultUniformsDescriptorSet(
writeInfo.pBufferInfo = &bufferInfo; writeInfo.pBufferInfo = &bufferInfo;
writeInfo.pTexelBufferView = nullptr; writeInfo.pTexelBufferView = nullptr;
++bindingIndex; ++writeInfoCount;
} }
VkDevice device = contextVk->getDevice(); VkDevice device = contextVk->getDevice();
ASSERT(bindingIndex == shaderStageCount); ASSERT(writeInfoCount <= kReservedDefaultUniformBindingCount);
ASSERT(shaderStageCount <= kReservedDefaultUniformBindingCount);
vkUpdateDescriptorSets(device, shaderStageCount, writeDescriptorInfo.data(), 0, nullptr); vkUpdateDescriptorSets(device, writeInfoCount, writeDescriptorInfo.data(), 0, nullptr);
} }
void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk, void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk,
...@@ -548,8 +600,6 @@ void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk, ...@@ -548,8 +600,6 @@ void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk,
ASSERT(descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || ASSERT(descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
const bool isStorageBuffer = descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; const bool isStorageBuffer = descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
const uint32_t bindingStart =
isStorageBuffer ? getStorageBlockBindingsOffset() : getUniformBlockBindingsOffset();
static_assert( static_assert(
gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS >= gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS >=
...@@ -559,9 +609,6 @@ void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk, ...@@ -559,9 +609,6 @@ void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk,
gl::StorageBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo; gl::StorageBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
gl::StorageBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo; gl::StorageBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo;
uint32_t writeCount = 0; uint32_t writeCount = 0;
// The binding is incremented every time arrayElement 0 is encountered, which means there will
// be an increment right at the start. Start from -1 to get 0 as the first binding.
int32_t currentBinding = -1;
// Write uniform or storage buffers. // Write uniform or storage buffers.
const gl::State &glState = contextVk->getState(); const gl::State &glState = contextVk->getState();
...@@ -572,11 +619,9 @@ void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk, ...@@ -572,11 +619,9 @@ void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk,
isStorageBuffer ? glState.getIndexedShaderStorageBuffer(block.binding) isStorageBuffer ? glState.getIndexedShaderStorageBuffer(block.binding)
: glState.getIndexedUniformBuffer(block.binding); : glState.getIndexedUniformBuffer(block.binding);
if (!block.isArray || block.arrayElement == 0) if (!block.activeShaders().any())
{ {
// Array indices of the same buffer binding are placed sequentially in `blocks`. continue;
// Thus, the block binding is updated only when array index 0 is encountered.
++currentBinding;
} }
if (bufferBinding.get() == nullptr) if (bufferBinding.get() == nullptr)
...@@ -584,9 +629,10 @@ void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk, ...@@ -584,9 +629,10 @@ void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk,
continue; continue;
} }
uint32_t binding = bindingStart + currentBinding; ShaderInterfaceVariableInfo info = mVariableInfoMap[block.mappedName];
uint32_t arrayElement = block.isArray ? block.arrayElement : 0; uint32_t binding = info.binding;
VkDeviceSize maxBlockSize = isStorageBuffer ? 0 : block.dataSize; uint32_t arrayElement = block.isArray ? block.arrayElement : 0;
VkDeviceSize maxBlockSize = isStorageBuffer ? 0 : block.dataSize;
VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[writeCount]; VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[writeCount];
VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[writeCount]; VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[writeCount];
...@@ -634,7 +680,8 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet( ...@@ -634,7 +680,8 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet(
VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex]; VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
const uint32_t bindingStart = getAtomicCounterBufferBindingsOffset(); std::string blockName(sh::vk::kAtomicCountersBlockName);
const ShaderInterfaceVariableInfo &info = mVariableInfoMap[blockName];
gl::AtomicCounterBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo; gl::AtomicCounterBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
gl::AtomicCounterBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo; gl::AtomicCounterBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo;
...@@ -661,7 +708,7 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet( ...@@ -661,7 +708,7 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet(
VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[binding]; VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[binding];
WriteBufferDescriptorSetBinding(bufferBinding, 0, descriptorSet, WriteBufferDescriptorSetBinding(bufferBinding, 0, descriptorSet,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, bindingStart, binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, info.binding, binding,
requiredOffsetAlignment, &bufferInfo, &writeInfo); requiredOffsetAlignment, &bufferInfo, &writeInfo);
BufferVk *bufferVk = vk::GetImpl(bufferBinding.get()); BufferVk *bufferVk = vk::GetImpl(bufferBinding.get());
...@@ -688,7 +735,7 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet( ...@@ -688,7 +735,7 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet(
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.pNext = nullptr; writeInfo.pNext = nullptr;
writeInfo.dstSet = descriptorSet; writeInfo.dstSet = descriptorSet;
writeInfo.dstBinding = bindingStart; writeInfo.dstBinding = info.binding;
writeInfo.dstArrayElement = static_cast<uint32_t>(binding); writeInfo.dstArrayElement = static_cast<uint32_t>(binding);
writeInfo.descriptorCount = 1; writeInfo.descriptorCount = 1;
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
...@@ -708,6 +755,7 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt ...@@ -708,6 +755,7 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt
{ {
const gl::State &glState = contextVk->getState(); const gl::State &glState = contextVk->getState();
const std::vector<gl::ImageBinding> &imageBindings = programState.getImageBindings(); const std::vector<gl::ImageBinding> &imageBindings = programState.getImageBindings();
const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms();
if (imageBindings.empty()) if (imageBindings.empty())
{ {
...@@ -718,8 +766,6 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt ...@@ -718,8 +766,6 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt
const gl::ActiveTextureArray<TextureVk *> &activeImages = contextVk->getActiveImages(); const gl::ActiveTextureArray<TextureVk *> &activeImages = contextVk->getActiveImages();
const uint32_t bindingStart = getImageBindingsOffset();
gl::ImagesArray<VkDescriptorImageInfo> descriptorImageInfo; gl::ImagesArray<VkDescriptorImageInfo> descriptorImageInfo;
gl::ImagesArray<VkWriteDescriptorSet> writeDescriptorInfo; gl::ImagesArray<VkWriteDescriptorSet> writeDescriptorInfo;
uint32_t writeCount = 0; uint32_t writeCount = 0;
...@@ -728,6 +774,11 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt ...@@ -728,6 +774,11 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt
for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex) for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
{ {
const gl::ImageBinding &imageBinding = imageBindings[imageIndex]; const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
uint32_t uniformIndex = programState.getUniformIndexFromImageIndex(imageIndex);
const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
std::string name = imageUniform.mappedName;
GetImageNameWithoutIndices(&name);
ShaderInterfaceVariableInfo &info = mVariableInfoMap[name];
ASSERT(!imageBinding.unreferenced); ASSERT(!imageBinding.unreferenced);
...@@ -759,7 +810,7 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt ...@@ -759,7 +810,7 @@ angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramSt
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.pNext = nullptr; writeInfo.pNext = nullptr;
writeInfo.dstSet = descriptorSet; writeInfo.dstSet = descriptorSet;
writeInfo.dstBinding = bindingStart + imageIndex; writeInfo.dstBinding = info.binding;
writeInfo.dstArrayElement = arrayElement; writeInfo.dstArrayElement = arrayElement;
writeInfo.descriptorCount = 1; writeInfo.descriptorCount = 1;
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
...@@ -882,85 +933,89 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(const gl::Program ...@@ -882,85 +933,89 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(const gl::Program
bool emulateSeamfulCubeMapSampling = contextVk->emulateSeamfulCubeMapSampling(); bool emulateSeamfulCubeMapSampling = contextVk->emulateSeamfulCubeMapSampling();
bool useOldRewriteStructSamplers = contextVk->useOldRewriteStructSamplers(); bool useOldRewriteStructSamplers = contextVk->useOldRewriteStructSamplers();
std::unordered_map<std::string, uint32_t> mappedSamplerNameToBindingIndex; for (const gl::ShaderType shaderType : executable.getLinkedShaderStages())
std::unordered_map<std::string, uint32_t> mappedSamplerNameToArrayOffset;
uint32_t currentBindingIndex = 0;
for (uint32_t textureIndex = 0; textureIndex < programState.getSamplerBindings().size();
++textureIndex)
{ {
const gl::SamplerBinding &samplerBinding = programState.getSamplerBindings()[textureIndex]; std::unordered_map<std::string, uint32_t> mappedSamplerNameToArrayOffset;
for (uint32_t textureIndex = 0; textureIndex < programState.getSamplerBindings().size();
ASSERT(!samplerBinding.unreferenced); ++textureIndex)
uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(textureIndex);
const gl::LinkedUniform &samplerUniform = programState.getUniforms()[uniformIndex];
std::string mappedSamplerName = GlslangGetMappedSamplerName(samplerUniform.name);
if (useOldRewriteStructSamplers ||
mappedSamplerNameToBindingIndex.emplace(mappedSamplerName, currentBindingIndex).second)
{
currentBindingIndex++;
}
uint32_t bindingIndex = textureIndex;
uint32_t arrayOffset = 0;
uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
if (!useOldRewriteStructSamplers)
{ {
bindingIndex = mappedSamplerNameToBindingIndex[mappedSamplerName]; const gl::SamplerBinding &samplerBinding =
arrayOffset = mappedSamplerNameToArrayOffset[mappedSamplerName]; programState.getSamplerBindings()[textureIndex];
// Front-end generates array elements in order, so we can just increment
// the offset each time we process a nested array.
mappedSamplerNameToArrayOffset[mappedSamplerName] += arraySize;
}
for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement) ASSERT(!samplerBinding.unreferenced);
{
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
TextureVk *textureVk = activeTextures[textureUnit].texture;
SamplerVk *samplerVk = activeTextures[textureUnit].sampler;
vk::ImageHelper &image = textureVk->getImage(); uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(textureIndex);
const gl::LinkedUniform &samplerUniform = programState.getUniforms()[uniformIndex];
std::string mappedSamplerName = GlslangGetMappedSamplerName(samplerUniform.name);
VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount]; if (!samplerUniform.isActive(shaderType))
{
// Use bound sampler object if one present, otherwise use texture's sampler continue;
const vk::Sampler &sampler = }
(samplerVk != nullptr) ? samplerVk->getSampler() : textureVk->getSampler();
imageInfo.sampler = sampler.getHandle(); uint32_t arrayOffset = 0;
imageInfo.imageLayout = image.getCurrentLayout(); uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
if (emulateSeamfulCubeMapSampling) if (!useOldRewriteStructSamplers)
{ {
// If emulating seamful cubemapping, use the fetch image view. This is basically arrayOffset = mappedSamplerNameToArrayOffset[mappedSamplerName];
// the same image view as read, except it's a 2DArray view for cube maps. // Front-end generates array elements in order, so we can just increment
imageInfo.imageView = // the offset each time we process a nested array.
textureVk->getFetchImageViewAndRecordUse(contextVk).getHandle(); mappedSamplerNameToArrayOffset[mappedSamplerName] += arraySize;
} }
else
for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
{ {
imageInfo.imageView = GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
textureVk->getReadImageViewAndRecordUse(contextVk).getHandle(); TextureVk *textureVk = activeTextures[textureUnit].texture;
SamplerVk *samplerVk = activeTextures[textureUnit].sampler;
vk::ImageHelper &image = textureVk->getImage();
VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
// Use bound sampler object if one present, otherwise use texture's sampler
const vk::Sampler &sampler =
(samplerVk != nullptr) ? samplerVk->getSampler() : textureVk->getSampler();
imageInfo.sampler = sampler.getHandle();
imageInfo.imageLayout = image.getCurrentLayout();
if (emulateSeamfulCubeMapSampling)
{
// If emulating seamful cubemapping, use the fetch image view. This is
// basically the same image view as read, except it's a 2DArray view for
// cube maps.
imageInfo.imageView =
textureVk->getFetchImageViewAndRecordUse(contextVk).getHandle();
}
else
{
imageInfo.imageView =
textureVk->getReadImageViewAndRecordUse(contextVk).getHandle();
}
const std::string samplerName =
contextVk->getRenderer()->getFeatures().forceOldRewriteStructSamplers.enabled
? GetMappedSamplerNameOld(samplerUniform.name)
: GlslangGetMappedSamplerName(samplerUniform.name);
ShaderInterfaceVariableInfo &info = mVariableInfoMap[samplerName];
VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[writeCount];
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.pNext = nullptr;
writeInfo.dstSet = descriptorSet;
writeInfo.dstBinding = info.binding;
writeInfo.dstArrayElement = arrayOffset + arrayElement;
writeInfo.descriptorCount = 1;
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
writeInfo.pImageInfo = &imageInfo;
writeInfo.pBufferInfo = nullptr;
writeInfo.pTexelBufferView = nullptr;
++writeCount;
} }
VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[writeCount];
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.pNext = nullptr;
writeInfo.dstSet = descriptorSet;
writeInfo.dstBinding = bindingIndex;
writeInfo.dstArrayElement = arrayOffset + arrayElement;
writeInfo.descriptorCount = 1;
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
writeInfo.pImageInfo = &imageInfo;
writeInfo.pBufferInfo = nullptr;
writeInfo.pTexelBufferView = nullptr;
++writeCount;
} }
} }
...@@ -1033,10 +1088,10 @@ angle::Result ProgramExecutableVk::updateDescriptorSets(ContextVk *contextVk, ...@@ -1033,10 +1088,10 @@ angle::Result ProgramExecutableVk::updateDescriptorSets(ContextVk *contextVk,
// requires a dynamic offset. // requires a dynamic offset.
const uint32_t uniformBlockOffsetCount = const uint32_t uniformBlockOffsetCount =
descriptorSetIndex == kUniformsAndXfbDescriptorSetIndex descriptorSetIndex == kUniformsAndXfbDescriptorSetIndex
? static_cast<uint32_t>(mDynamicBufferOffsets.size()) ? static_cast<uint32_t>(mNumDefaultUniformDescriptors)
: 0; : 0;
commandBuffer->bindDescriptorSets(mPipelineLayout.get(), pipelineBindPoint, commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint,
descriptorSetIndex, 1, &descSet, uniformBlockOffsetCount, descriptorSetIndex, 1, &descSet, uniformBlockOffsetCount,
mDynamicBufferOffsets.data()); mDynamicBufferOffsets.data());
} }
......
...@@ -44,9 +44,13 @@ class ProgramExecutableVk ...@@ -44,9 +44,13 @@ class ProgramExecutableVk
void reset(ContextVk *contextVk); void reset(ContextVk *contextVk);
void save(gl::BinaryOutputStream *stream);
std::unique_ptr<rx::LinkEvent> load(gl::BinaryInputStream *stream);
void clearVariableInfoMap(); void clearVariableInfoMap();
ShaderInterfaceVariableInfoMap &getShaderInterfaceVariableInfoMap() { return mVariableInfoMap; } ShaderInterfaceVariableInfoMap &getShaderInterfaceVariableInfoMap() { return mVariableInfoMap; }
const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); }
angle::Result createPipelineLayout(const gl::Context *glContext, angle::Result createPipelineLayout(const gl::Context *glContext,
const gl::ProgramExecutable &glExecutable, const gl::ProgramExecutable &glExecutable,
const gl::ProgramState &programState); const gl::ProgramState &programState);
...@@ -68,19 +72,21 @@ class ProgramExecutableVk ...@@ -68,19 +72,21 @@ class ProgramExecutableVk
friend class ProgramVk; friend class ProgramVk;
friend class ProgramPipelineVk; friend class ProgramPipelineVk;
void updateBindingOffsets(const gl::ProgramState &programState);
uint32_t getUniformBlockBindingsOffset() const { return 0; }
uint32_t getStorageBlockBindingsOffset() const { return mStorageBlockBindingsOffset; }
uint32_t getAtomicCounterBufferBindingsOffset() const
{
return mAtomicCounterBufferBindingsOffset;
}
uint32_t getImageBindingsOffset() const { return mImageBindingsOffset; }
angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex); angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
angle::Result allocateDescriptorSetAndGetInfo(ContextVk *contextVk, angle::Result allocateDescriptorSetAndGetInfo(ContextVk *contextVk,
uint32_t descriptorSetIndex, uint32_t descriptorSetIndex,
bool *newPoolAllocatedOut); bool *newPoolAllocatedOut);
void addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> &blocks,
VkDescriptorType descType,
vk::DescriptorSetLayoutDesc *descOut);
void addAtomicCounterBufferDescriptorSetDesc(
const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
vk::DescriptorSetLayoutDesc *descOut);
void addImageDescriptorSetDesc(const gl::ProgramState &programState,
vk::DescriptorSetLayoutDesc *descOut);
void addTextureDescriptorSetDesc(const gl::ProgramState &programState,
bool useOldRewriteStructSamplers,
vk::DescriptorSetLayoutDesc *descOut);
void updateDefaultUniformsDescriptorSet( void updateDefaultUniformsDescriptorSet(
const gl::ProgramState &programState, const gl::ProgramState &programState,
...@@ -100,13 +106,6 @@ class ProgramExecutableVk ...@@ -100,13 +106,6 @@ class ProgramExecutableVk
angle::Result updateImagesDescriptorSet(const gl::ProgramState &programState, angle::Result updateImagesDescriptorSet(const gl::ProgramState &programState,
ContextVk *contextVk); ContextVk *contextVk);
// In their descriptor set, uniform buffers are placed first, then storage buffers, then atomic
// counter buffers and then images. These cached values contain the offsets where storage
// buffer, atomic counter buffer and image bindings start.
uint32_t mStorageBlockBindingsOffset;
uint32_t mAtomicCounterBufferBindingsOffset;
uint32_t mImageBindingsOffset;
// This is a special "empty" placeholder buffer for when a shader has no uniforms or doesn't // This is a special "empty" placeholder buffer for when a shader has no uniforms or doesn't
// use all slots in the atomic counter buffer array. // use all slots in the atomic counter buffer array.
// //
...@@ -118,6 +117,7 @@ class ProgramExecutableVk ...@@ -118,6 +117,7 @@ class ProgramExecutableVk
std::vector<VkDescriptorSet> mDescriptorSets; std::vector<VkDescriptorSet> mDescriptorSets;
vk::DescriptorSetLayoutArray<VkDescriptorSet> mEmptyDescriptorSets; vk::DescriptorSetLayoutArray<VkDescriptorSet> mEmptyDescriptorSets;
std::vector<vk::BufferHelper *> mDescriptorBuffersCache; std::vector<vk::BufferHelper *> mDescriptorBuffersCache;
size_t mNumDefaultUniformDescriptors;
std::unordered_map<vk::TextureDescriptorDesc, VkDescriptorSet> mTextureDescriptorsCache; std::unordered_map<vk::TextureDescriptorDesc, VkDescriptorSet> mTextureDescriptorsCache;
...@@ -137,6 +137,8 @@ class ProgramExecutableVk ...@@ -137,6 +137,8 @@ class ProgramExecutableVk
gl::ShaderVector<uint32_t> mDynamicBufferOffsets; gl::ShaderVector<uint32_t> mDynamicBufferOffsets;
// TODO: http://anglebug.com/4524: Need a different hash key than a string,
// since that's slow to calculate.
ShaderInterfaceVariableInfoMap mVariableInfoMap; ShaderInterfaceVariableInfoMap mVariableInfoMap;
}; };
......
...@@ -303,6 +303,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context, ...@@ -303,6 +303,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
reset(contextVk); reset(contextVk);
mShaderInfo.load(stream); mShaderInfo.load(stream);
mExecutable.load(stream);
// Deserializes the uniformLayout data of mDefaultUniformBlocks // Deserializes the uniformLayout data of mDefaultUniformBlocks
for (gl::ShaderType shaderType : gl::AllShaderTypes()) for (gl::ShaderType shaderType : gl::AllShaderTypes())
...@@ -337,6 +338,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context, ...@@ -337,6 +338,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream) void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
{ {
mShaderInfo.save(stream); mShaderInfo.save(stream);
mExecutable.save(stream);
// Serializes the uniformLayout data of mDefaultUniformBlocks // Serializes the uniformLayout data of mDefaultUniformBlocks
for (gl::ShaderType shaderType : gl::AllShaderTypes()) for (gl::ShaderType shaderType : gl::AllShaderTypes())
...@@ -378,6 +380,7 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context, ...@@ -378,6 +380,7 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context,
linkResources(resources); linkResources(resources);
reset(contextVk); reset(contextVk);
mExecutable.clearVariableInfoMap();
// Gather variable info and transform sources. // Gather variable info and transform sources.
gl::ShaderMap<std::string> shaderSources; gl::ShaderMap<std::string> shaderSources;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Query.h" #include "libANGLE/Query.h"
#include "libANGLE/renderer/glslang_wrapper_utils.h"
#include "libANGLE/renderer/vulkan/BufferVk.h" #include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h" #include "libANGLE/renderer/vulkan/FramebufferVk.h"
...@@ -161,6 +162,7 @@ angle::Result TransformFeedbackVk::bindIndexedBuffer( ...@@ -161,6 +162,7 @@ angle::Result TransformFeedbackVk::bindIndexedBuffer(
void TransformFeedbackVk::updateDescriptorSetLayout( void TransformFeedbackVk::updateDescriptorSetLayout(
ContextVk *contextVk, ContextVk *contextVk,
ShaderInterfaceVariableInfoMap &vsVariableInfoMap,
size_t xfbBufferCount, size_t xfbBufferCount,
vk::DescriptorSetLayoutDesc *descSetLayoutOut) const vk::DescriptorSetLayoutDesc *descSetLayoutOut) const
{ {
...@@ -169,8 +171,11 @@ void TransformFeedbackVk::updateDescriptorSetLayout( ...@@ -169,8 +171,11 @@ void TransformFeedbackVk::updateDescriptorSetLayout(
for (uint32_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex) for (uint32_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
{ {
descSetLayoutOut->update(kXfbBindingIndexStart + bufferIndex, const std::string bufferName = GetXfbBufferName(bufferIndex);
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT); const ShaderInterfaceVariableInfo &info = vsVariableInfoMap[bufferName];
descSetLayoutOut->update(info.binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
VK_SHADER_STAGE_VERTEX_BIT);
} }
} }
...@@ -296,12 +301,17 @@ void TransformFeedbackVk::writeDescriptorSet(ContextVk *contextVk, ...@@ -296,12 +301,17 @@ void TransformFeedbackVk::writeDescriptorSet(ContextVk *contextVk,
VkDescriptorBufferInfo *pBufferInfo, VkDescriptorBufferInfo *pBufferInfo,
VkDescriptorSet descSet) const VkDescriptorSet descSet) const
{ {
VkDevice device = contextVk->getDevice(); VkDevice device = contextVk->getDevice();
ProgramExecutableVk *executableVk = contextVk->getExecutable();
ShaderInterfaceVariableInfoMap variableInfoMap =
executableVk->getShaderInterfaceVariableInfoMap();
const std::string bufferName = GetXfbBufferName(0);
ShaderInterfaceVariableInfo &info = variableInfoMap[bufferName];
VkWriteDescriptorSet writeDescriptorInfo = {}; VkWriteDescriptorSet writeDescriptorInfo = {};
writeDescriptorInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeDescriptorInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeDescriptorInfo.dstSet = descSet; writeDescriptorInfo.dstSet = descSet;
writeDescriptorInfo.dstBinding = kXfbBindingIndexStart; writeDescriptorInfo.dstBinding = info.binding;
writeDescriptorInfo.dstArrayElement = 0; writeDescriptorInfo.dstArrayElement = 0;
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;
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#define LIBANGLE_RENDERER_VULKAN_TRANSFORMFEEDBACKVK_H_ #define LIBANGLE_RENDERER_VULKAN_TRANSFORMFEEDBACKVK_H_
#include "libANGLE/renderer/TransformFeedbackImpl.h" #include "libANGLE/renderer/TransformFeedbackImpl.h"
#include "libANGLE/renderer/glslang_wrapper_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace gl namespace gl
...@@ -54,6 +56,7 @@ class TransformFeedbackVk : public TransformFeedbackImpl ...@@ -54,6 +56,7 @@ class TransformFeedbackVk : public TransformFeedbackImpl
const gl::OffsetBindingPointer<gl::Buffer> &binding) override; const gl::OffsetBindingPointer<gl::Buffer> &binding) override;
void updateDescriptorSetLayout(ContextVk *contextVk, void updateDescriptorSetLayout(ContextVk *contextVk,
ShaderInterfaceVariableInfoMap &vsVariableInfoMap,
size_t xfbBufferCount, size_t xfbBufferCount,
vk::DescriptorSetLayoutDesc *descSetLayoutOut) const; vk::DescriptorSetLayoutDesc *descSetLayoutOut) const;
void initDescriptorSet(ContextVk *contextVk, void initDescriptorSet(ContextVk *contextVk,
......
...@@ -977,8 +977,6 @@ constexpr uint32_t kReservedDriverUniformBindingCount = 1; ...@@ -977,8 +977,6 @@ constexpr uint32_t kReservedDriverUniformBindingCount = 1;
// supported. // supported.
constexpr uint32_t kReservedPerStageDefaultUniformBindingCount = 1; constexpr uint32_t kReservedPerStageDefaultUniformBindingCount = 1;
constexpr uint32_t kReservedDefaultUniformBindingCount = 3; constexpr uint32_t kReservedDefaultUniformBindingCount = 3;
// Binding index start for transform feedback buffers:
constexpr uint32_t kXfbBindingIndexStart = kReservedDefaultUniformBindingCount;
} // namespace rx } // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_ #endif // LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_
...@@ -3998,6 +3998,12 @@ TEST_P(TextureLimitsTest, MaxFragmentTextures) ...@@ -3998,6 +3998,12 @@ TEST_P(TextureLimitsTest, MaxFragmentTextures)
// Test rendering with maximum combined texture units. // Test rendering with maximum combined texture units.
TEST_P(TextureLimitsTest, MaxCombinedTextures) TEST_P(TextureLimitsTest, MaxCombinedTextures)
{ {
// TODO(timvp): http://anglebug.com/3570
// Currently only fails on SwiftShader but we don't have an IsSwiftShader().
// max per-stage sampled image bindings count (32) exceeds device
// maxPerStageDescriptorSampledImages limit (16)
ANGLE_SKIP_TEST_IF(IsVulkan());
GLint vertexTextures = mMaxVertexTextures; GLint vertexTextures = mMaxVertexTextures;
if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures) if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
......
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