Commit 29fba5e0 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Prepare for variable-stage pipelines

Compute (single-stage pipeline) is upcoming, but this change prepares GlslangWrapper to handle any number of stages (mostly). Additionally, this change binds each resource to each stage based on whether it's active, so that we don't hit the per-stage limit of resources by binding every resource to every stage. Bug: angleproject:3633 Bug: angleproject:3562 Change-Id: Ifebf691482846e0371c6e314f514226a4cfee258 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1689330Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent a1754dc8
......@@ -722,6 +722,18 @@ void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
LoadShaderVariableBuffer(stream, block);
}
size_t CountUniqueBlocks(const std::vector<InterfaceBlock> &blocks)
{
size_t count = 0;
for (const InterfaceBlock &block : blocks)
{
if (!block.isArray || block.arrayElement == 0)
{
++count;
}
}
return count;
}
} // anonymous namespace
// Saves the linking context for later use in resolveLink().
......@@ -955,7 +967,7 @@ ImageBinding::~ImageBinding() = default;
// ProgramState implementation.
ProgramState::ProgramState()
: mLabel(),
mAttachedShaders({}),
mAttachedShaders{},
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
mMaxActiveAttribLocation(0),
mSamplerUniformRange(0, 0),
......@@ -991,6 +1003,16 @@ Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
return mAttachedShaders[shaderType];
}
size_t ProgramState::getUniqueUniformBlockCount() const
{
return CountUniqueBlocks(mUniformBlocks);
}
size_t ProgramState::getUniqueStorageBlockCount() const
{
return CountUniqueBlocks(mShaderStorageBlocks);
}
GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
{
return GetResourceIndexFromName(mUniforms, name);
......@@ -1029,6 +1051,12 @@ GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
return uniformIndex - mSamplerUniformRange.low();
}
GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
{
ASSERT(samplerIndex < mSamplerUniformRange.length());
return samplerIndex + mSamplerUniformRange.low();
}
bool ProgramState::isImageUniformIndex(GLuint index) const
{
return mImageUniformRange.contains(index);
......@@ -1040,6 +1068,12 @@ GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
return uniformIndex - mImageUniformRange.low();
}
GLuint ProgramState::getUniformIndexFromImageIndex(GLuint imageIndex) const
{
ASSERT(imageIndex < mImageUniformRange.length());
return imageIndex + mImageUniformRange.low();
}
GLuint ProgramState::getAttributeLocation(const std::string &name) const
{
for (const sh::Attribute &attribute : mAttributes)
......@@ -1433,6 +1467,8 @@ angle::Result Program::link(const Context *context)
mState.updateTransformFeedbackStrides();
}
updateLinkedShaderStages();
mLinkingState.reset(new LinkingState());
mLinkingState->context = context;
mLinkingState->linkingFromBinary = false;
......@@ -1474,7 +1510,6 @@ void Program::resolveLinkImpl(const Context *context)
// According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
// Only successfully linked program can replace the executables.
ASSERT(mLinked);
updateLinkedShaderStages();
// Mark implementation-specific unreferenced uniforms as ignored.
mProgram->markUnusedUniformLocations(&mState.mUniformLocations, &mState.mSamplerBindings,
......
......@@ -359,13 +359,19 @@ class ProgramState final : angle::NonCopyable
return mAtomicCounterBuffers;
}
// Count the number of uniform and storage buffer declarations, counting arrays as one.
size_t getUniqueUniformBlockCount() const;
size_t getUniqueStorageBlockCount() const;
GLuint getUniformIndexFromName(const std::string &name) const;
GLuint getUniformIndexFromLocation(GLint location) const;
Optional<GLuint> getSamplerIndex(GLint location) const;
bool isSamplerUniformIndex(GLuint index) const;
GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const;
bool isImageUniformIndex(GLuint index) const;
GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const;
GLuint getUniformIndexFromImageIndex(GLuint imageIndex) const;
GLuint getAttributeLocation(const std::string &name) const;
GLuint getBufferVariableIndexFromName(const std::string &name) const;
......@@ -374,6 +380,11 @@ class ProgramState final : angle::NonCopyable
bool usesMultiview() const { return mNumViews != -1; }
const ShaderBitSet &getLinkedShaderStages() const { return mLinkedShaderStages; }
bool hasLinkedShaderStage(ShaderType shaderType) const
{
return mLinkedShaderStages.test(shaderType);
}
size_t getLinkedShaderStageCount() const { return mLinkedShaderStages.count(); }
bool hasAttachedShader() const;
......
......@@ -410,7 +410,7 @@ class FlattenUniformVisitor : public sh::VariableNameVisitor
bool isSampler = IsSamplerType(variable.type);
bool isImage = IsImageType(variable.type);
bool isAtomicCounter = IsAtomicCounterType(variable.type);
std::vector<gl::LinkedUniform> *uniformList = mUniforms;
std::vector<LinkedUniform> *uniformList = mUniforms;
if (isSampler)
{
uniformList = mSamplerUniforms;
......@@ -618,7 +618,7 @@ bool InterfaceBlockInfo::getBlockSize(const std::string &name,
size_t *sizeOut)
{
size_t nameLengthWithoutArrayIndex;
gl::ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
auto sizeIter = mBlockSizes.find(baseName);
if (sizeIter == mBlockSizes.end())
......@@ -699,7 +699,7 @@ bool UniformLinker::validateGraphicsUniforms(InfoLog &infoLog) const
// Check that uniforms defined in the graphics shaders are identical
std::map<std::string, ShaderUniform> linkedUniforms;
for (ShaderType shaderType : kAllGraphicsShaderTypes)
for (const ShaderType shaderType : kAllGraphicsShaderTypes)
{
Shader *currentShader = mState.getAttachedShader(shaderType);
if (currentShader)
......@@ -988,7 +988,7 @@ bool UniformLinker::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoL
std::vector<LinkedUniform> atomicCounterUniforms;
std::vector<UnusedUniform> unusedUniforms;
for (ShaderType shaderType : AllShaderTypes())
for (const ShaderType shaderType : AllShaderTypes())
{
Shader *shader = mState.getAttachedShader(shaderType);
if (!shader)
......@@ -1050,7 +1050,7 @@ void InterfaceBlockLinker::linkBlocks(const GetBlockSizeFunc &getBlockSize,
std::set<std::string> visitedList;
for (ShaderType shaderType : AllShaderTypes())
for (const ShaderType shaderType : AllShaderTypes())
{
if (!mShaderBlocks[shaderType])
{
......@@ -1242,14 +1242,14 @@ ProgramLinkedResources::ProgramLinkedResources(
ProgramLinkedResources::~ProgramLinkedResources() = default;
void ProgramLinkedResourcesLinker::linkResources(const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources) const
void ProgramLinkedResourcesLinker::linkResources(const ProgramState &programState,
const ProgramLinkedResources &resources) const
{
// Gather uniform interface block info.
InterfaceBlockInfo uniformBlockInfo(mCustomEncoderFactory);
for (gl::ShaderType shaderType : gl::AllShaderTypes())
for (const ShaderType shaderType : AllShaderTypes())
{
gl::Shader *shader = programState.getAttachedShader(shaderType);
Shader *shader = programState.getAttachedShader(shaderType);
if (shader)
{
uniformBlockInfo.getShaderBlockInfo(shader->getUniformBlocks());
......@@ -1272,9 +1272,9 @@ void ProgramLinkedResourcesLinker::linkResources(const gl::ProgramState &program
// Gather storage bufer interface block info.
InterfaceBlockInfo shaderStorageBlockInfo(mCustomEncoderFactory);
for (gl::ShaderType shaderType : gl::AllShaderTypes())
for (const ShaderType shaderType : AllShaderTypes())
{
gl::Shader *shader = programState.getAttachedShader(shaderType);
Shader *shader = programState.getAttachedShader(shaderType);
if (shader)
{
shaderStorageBlockInfo.getShaderBlockInfo(shader->getShaderStorageBlocks());
......@@ -1303,12 +1303,12 @@ void ProgramLinkedResourcesLinker::linkResources(const gl::ProgramState &program
}
void ProgramLinkedResourcesLinker::getAtomicCounterBufferSizeMap(
const gl::ProgramState &programState,
const ProgramState &programState,
std::map<int, unsigned int> &sizeMapOut) const
{
for (unsigned int index : programState.getAtomicCounterUniformRange())
{
const gl::LinkedUniform &glUniform = programState.getUniforms()[index];
const LinkedUniform &glUniform = programState.getUniforms()[index];
auto &bufferDataSize = sizeMapOut[glUniform.binding];
......
......@@ -232,11 +232,11 @@ class ProgramLinkedResourcesLinker final : angle::NonCopyable
: mCustomEncoderFactory(customEncoderFactory)
{}
void linkResources(const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources) const;
void linkResources(const ProgramState &programState,
const ProgramLinkedResources &resources) const;
private:
void getAtomicCounterBufferSizeMap(const gl::ProgramState &programState,
void getAtomicCounterBufferSizeMap(const ProgramState &programState,
std::map<int, unsigned int> &sizeMapOut) const;
CustomBlockLayoutEncoderFactory *mCustomEncoderFactory;
......
......@@ -26,12 +26,6 @@ void ActiveVariable::setActive(ShaderType shaderType, bool used)
mActiveUseBits.set(shaderType, used);
}
bool ActiveVariable::isActive(ShaderType shaderType) const
{
ASSERT(shaderType != ShaderType::InvalidEnum);
return mActiveUseBits[shaderType];
}
void ActiveVariable::unionReferencesWith(const ActiveVariable &other)
{
mActiveUseBits |= other.mActiveUseBits;
......
......@@ -31,7 +31,12 @@ struct ActiveVariable
ShaderType getFirstShaderTypeWhereActive() const;
void setActive(ShaderType shaderType, bool used);
void unionReferencesWith(const ActiveVariable &other);
bool isActive(ShaderType shaderType) const;
bool isActive(ShaderType shaderType) const
{
ASSERT(shaderType != ShaderType::InvalidEnum);
return mActiveUseBits[shaderType];
}
ShaderBitSet activeShaders() const { return mActiveUseBits; }
GLuint activeShaderCount() const;
private:
......
......@@ -444,6 +444,11 @@ constexpr size_t kCubeFaceCount = 6;
using TextureMap = angle::PackedEnumMap<TextureType, BindingPointer<Texture>>;
// ShaderVector can contain one item per shader. It differs from ShaderMap in that the values are
// not indexed by ShaderType.
template <typename T>
using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
template <typename T>
using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
......
......@@ -182,11 +182,9 @@ class ProgramVk : public ProgramImpl
angle::Result linkImpl(const gl::Context *glContext, gl::InfoLog &infoLog);
void linkResources(const gl::ProgramLinkedResources &resources);
uint32_t getUniformBuffersBindingStart() const { return 0; }
uint32_t getStorageBuffersBindingStart() const
{
return static_cast<uint32_t>(mState.getUniformBlocks().size());
}
void updateBindingOffsets();
uint32_t getUniformBlockBindingsOffset() const { return 0; }
uint32_t getStorageBlockBindingsOffset() const { return mStorageBlockBindingsOffset; }
ANGLE_INLINE angle::Result initShaders(ContextVk *contextVk,
gl::PrimitiveMode mode,
......@@ -233,10 +231,7 @@ class ProgramVk : public ProgramImpl
gl::ShaderMap<DefaultUniformBlock> mDefaultUniformBlocks;
gl::ShaderBitSet mDefaultUniformBlocksDirty;
static constexpr uint32_t kShaderTypeMin = static_cast<uint32_t>(gl::kGLES2ShaderTypeMin);
static constexpr uint32_t kShaderTypeMax = static_cast<uint32_t>(gl::kGLES2ShaderTypeMax);
static constexpr uint32_t kShaderTypeCount = kShaderTypeMax - kShaderTypeMin + 1;
std::array<uint32_t, kShaderTypeCount> mDynamicBufferOffsets;
gl::ShaderVector<uint32_t> mDynamicBufferOffsets;
// This is a special "empty" placeholder buffer for when a shader has no uniforms.
// It is necessary because we want to keep a compatible pipeline layout in all cases,
......@@ -285,6 +280,10 @@ class ProgramVk : public ProgramImpl
// We keep the translated linked shader sources to use with shader draw call patching.
gl::ShaderMap<std::string> mShaderSource;
// Storage buffers are placed after uniform buffers in their descriptor set. This cached value
// contains the offset where storage buffer bindings start.
uint32_t mStorageBlockBindingsOffset;
// Store descriptor pools here. We store the descriptors in the Program to facilitate descriptor
// cache management. It can also allow fewer descriptors for shaders which use fewer
// textures/buffers.
......
......@@ -47,9 +47,6 @@ namespace rx
namespace
{
// We currently only allocate 2 uniform buffer per descriptor set, one for the fragment shader and
// one for the vertex shader.
constexpr size_t kUniformBufferDescriptorsPerDescriptorSet = 2;
// Update the pipeline cache every this many swaps (if 60fps, this means every 10 minutes)
constexpr uint32_t kPipelineCacheVkUpdatePeriod = 10 * 60 * 60;
// Wait a maximum of 10s. If that times out, we declare it a failure.
......@@ -1322,25 +1319,6 @@ const gl::Limitations &RendererVk::getNativeLimitations() const
return mNativeLimitations;
}
uint32_t RendererVk::getMaxUniformBlocks() const
{
return std::min<uint32_t>(mPhysicalDeviceProperties.limits.maxDescriptorSetUniformBuffers,
gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS);
}
uint32_t RendererVk::getMaxStorageBlocks() const
{
return std::min<uint32_t>(mPhysicalDeviceProperties.limits.maxDescriptorSetStorageBuffers,
gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
}
uint32_t RendererVk::getMaxActiveTextures() const
{
// TODO(lucferron): expose this limitation to GL in Context Caps
return std::min<uint32_t>(mPhysicalDeviceProperties.limits.maxDescriptorSetSamplers,
gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES);
}
angle::Result RendererVk::getDescriptorSetLayout(
vk::Context *context,
const vk::DescriptorSetLayoutDesc &desc,
......@@ -1575,9 +1553,4 @@ angle::Result RendererVk::cleanupGarbage(vk::Context *context, bool block)
return angle::Result::Continue;
}
uint32_t GetUniformBufferDescriptorCount()
{
return kUniformBufferDescriptorsPerDescriptorSet;
}
} // namespace rx
......@@ -85,9 +85,6 @@ class RendererVk : angle::NonCopyable
const gl::TextureCapsMap &getNativeTextureCaps() const;
const gl::Extensions &getNativeExtensions() const;
const gl::Limitations &getNativeLimitations() const;
uint32_t getMaxUniformBlocks() const;
uint32_t getMaxStorageBlocks() const;
uint32_t getMaxActiveTextures() const;
uint32_t getQueueFamilyIndex() const { return mCurrentQueueFamilyIndex; }
......@@ -233,8 +230,6 @@ class RendererVk : angle::NonCopyable
DescriptorSetLayoutCache mDescriptorSetLayoutCache;
};
uint32_t GetUniformBufferDescriptorCount();
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
......@@ -135,8 +135,7 @@ void TransformFeedbackVk::addFramebufferDependency(ContextVk *contextVk,
void TransformFeedbackVk::updateDescriptorSet(ContextVk *contextVk,
const gl::ProgramState &programState,
VkDescriptorSet descSet,
uint32_t bindingOffset) const
VkDescriptorSet descSet) const
{
const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
mState.getIndexedBuffers();
......@@ -171,7 +170,7 @@ void TransformFeedbackVk::updateDescriptorSet(ContextVk *contextVk,
VkWriteDescriptorSet writeDescriptorInfo = {};
writeDescriptorInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeDescriptorInfo.dstSet = descSet;
writeDescriptorInfo.dstBinding = bindingOffset;
writeDescriptorInfo.dstBinding = kXfbBindingIndexStart;
writeDescriptorInfo.dstArrayElement = 0;
writeDescriptorInfo.descriptorCount = xfbBufferCount;
writeDescriptorInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
......
......@@ -47,8 +47,7 @@ class TransformFeedbackVk : public TransformFeedbackImpl
vk::FramebufferHelper *framebuffer) const;
void updateDescriptorSet(ContextVk *contextVk,
const gl::ProgramState &programState,
VkDescriptorSet descSet,
uint32_t bindingOffset) const;
VkDescriptorSet descSet) const;
void getBufferOffsets(ContextVk *contextVk,
const gl::ProgramState &programState,
GLint drawCallFirstVertex,
......
......@@ -1429,7 +1429,7 @@ void PipelineLayoutDesc::updatePushConstantRange(gl::ShaderType shaderType,
{
ASSERT(shaderType == gl::ShaderType::Vertex || shaderType == gl::ShaderType::Fragment ||
shaderType == gl::ShaderType::Compute);
PackedPushConstantRange &packed = mPushConstantRanges[static_cast<size_t>(shaderType)];
PackedPushConstantRange &packed = mPushConstantRanges[shaderType];
packed.offset = offset;
packed.size = size;
}
......@@ -1770,30 +1770,22 @@ angle::Result PipelineLayoutCache::getPipelineLayout(
}
}
angle::FixedVector<VkPushConstantRange, vk::kMaxPushConstantRanges> pushConstantRanges;
const vk::PushConstantRangeArray<vk::PackedPushConstantRange> &descPushConstantRanges =
desc.getPushConstantRanges();
for (size_t shaderIndex = 0; shaderIndex < descPushConstantRanges.size(); ++shaderIndex)
gl::ShaderVector<VkPushConstantRange> pushConstantRanges;
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
{
const vk::PackedPushConstantRange &pushConstantDesc = descPushConstantRanges[shaderIndex];
const vk::PackedPushConstantRange &pushConstantDesc = descPushConstantRanges[shaderType];
if (pushConstantDesc.size > 0)
{
static constexpr VkShaderStageFlagBits kShaderStages[vk::kMaxPushConstantRanges] = {
VK_SHADER_STAGE_VERTEX_BIT,
VK_SHADER_STAGE_FRAGMENT_BIT,
VK_SHADER_STAGE_GEOMETRY_BIT,
VK_SHADER_STAGE_COMPUTE_BIT,
};
static_assert(static_cast<uint32_t>(gl::ShaderType::Vertex) == 0, "Fix this table");
static_assert(static_cast<uint32_t>(gl::ShaderType::Fragment) == 1, "Fix this table");
static_assert(static_cast<uint32_t>(gl::ShaderType::Geometry) == 2, "Fix this table");
static_assert(static_cast<uint32_t>(gl::ShaderType::Compute) == 3, "Fix this table");
VkPushConstantRange pushConstantRange = {};
pushConstantRange.stageFlags = kShaderStages[shaderIndex];
pushConstantRange.offset = pushConstantDesc.offset;
pushConstantRange.size = pushConstantDesc.size;
pushConstantRanges.push_back(pushConstantRange);
VkPushConstantRange range;
range.stageFlags = gl_vk::kShaderStageMap[shaderType];
range.offset = pushConstantDesc.offset;
range.size = pushConstantDesc.size;
pushConstantRanges.push_back(range);
}
}
......@@ -1803,7 +1795,7 @@ angle::Result PipelineLayoutCache::getPipelineLayout(
createInfo.flags = 0;
createInfo.setLayoutCount = static_cast<uint32_t>(setLayoutHandles.size());
createInfo.pSetLayouts = setLayoutHandles.data();
createInfo.pushConstantRangeCount = static_cast<uint32_t>(pushConstantRanges.size());
createInfo.pushConstantRangeCount = pushConstantRanges.size();
createInfo.pPushConstantRanges = pushConstantRanges.data();
vk::PipelineLayout newLayout;
......
......@@ -532,10 +532,9 @@ class DescriptorSetLayoutDesc final
mPackedDescriptorSetLayout;
};
// The following are for caching descriptor set layouts. Limited to max four descriptor set layouts
// and one push constant per shader stage. This can be extended in the future.
// The following are for caching descriptor set layouts. Limited to max four descriptor set layouts.
// This can be extended in the future.
constexpr size_t kMaxDescriptorSetLayouts = 4;
constexpr size_t kMaxPushConstantRanges = angle::EnumSize<gl::ShaderType>();
struct PackedPushConstantRange
{
......@@ -548,7 +547,7 @@ using DescriptorSetLayoutArray = std::array<T, kMaxDescriptorSetLayouts>;
using DescriptorSetLayoutPointerArray =
DescriptorSetLayoutArray<BindingPointer<DescriptorSetLayout>>;
template <typename T>
using PushConstantRangeArray = std::array<T, kMaxPushConstantRanges>;
using PushConstantRangeArray = gl::ShaderMap<T>;
class PipelineLayoutDesc final
{
......@@ -575,14 +574,14 @@ class PipelineLayoutDesc final
(sizeof(DescriptorSetLayoutDesc) * kMaxDescriptorSetLayouts),
"Unexpected size");
static_assert(sizeof(decltype(mPushConstantRanges)) ==
(sizeof(PackedPushConstantRange) * kMaxPushConstantRanges),
(sizeof(PackedPushConstantRange) * angle::EnumSize<gl::ShaderType>()),
"Unexpected size");
};
// Verify the structure is properly packed.
static_assert(sizeof(PipelineLayoutDesc) ==
(sizeof(DescriptorSetLayoutArray<DescriptorSetLayoutDesc>) +
sizeof(std::array<PackedPushConstantRange, kMaxPushConstantRanges>)),
sizeof(gl::ShaderMap<PackedPushConstantRange>)),
"Unexpected Size");
// Disable warnings about struct padding.
......@@ -911,12 +910,12 @@ constexpr uint32_t kDriverUniformsDescriptorSetIndex = 3;
// Only 1 driver uniform binding is used.
constexpr uint32_t kReservedDriverUniformBindingCount = 1;
// Binding index for default uniforms in the vertex shader:
constexpr uint32_t kVertexUniformsBindingIndex = 0;
// Binding index for default uniforms in the fragment shader:
constexpr uint32_t kFragmentUniformsBindingIndex = 1;
// There is 1 default uniform binding used per stage. Currently, a maxium of two stages are
// supported.
constexpr uint32_t kReservedPerStageDefaultUniformBindingCount = 1;
constexpr uint32_t kReservedDefaultUniformBindingCount = 2;
// Binding index start for transform feedback buffers:
constexpr uint32_t kXfbBindingIndexStart = 2;
constexpr uint32_t kXfbBindingIndexStart = kReservedDefaultUniformBindingCount;
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_
......@@ -176,12 +176,13 @@ void RendererVk::ensureCapsInitialized() const
// we'll defer the implementation until we tackle the next version.
// mNativeCaps.maxServerWaitTimeout
GLuint maxUniformVectors = mPhysicalDeviceProperties.limits.maxUniformBufferRange /
(sizeof(GLfloat) * kComponentsPerVector);
GLuint maxUniformBlockSize = mPhysicalDeviceProperties.limits.maxUniformBufferRange;
// Clamp the maxUniformVectors to 1024u, on AMD the maxUniformBufferRange is way too high.
maxUniformVectors = std::min(1024u, maxUniformVectors);
// Clamp the maxUniformBlockSize to 64KB (majority of devices support up to this size
// currently), on AMD the maxUniformBufferRange is near uint32_t max.
maxUniformBlockSize = std::min(0x10000u, maxUniformBlockSize);
const GLuint maxUniformVectors = maxUniformBlockSize / (sizeof(GLfloat) * kComponentsPerVector);
const GLuint maxUniformComponents = maxUniformVectors * kComponentsPerVector;
// Uniforms are implemented using a uniform buffer, so the max number of uniforms we can
......@@ -191,30 +192,49 @@ void RendererVk::ensureCapsInitialized() const
mNativeCaps.maxFragmentUniformVectors = maxUniformVectors;
mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Fragment] = maxUniformComponents;
// We use the same bindings on each stage, so the texture, UBO and SSBO limitations are the same
// as the per-stage limits.
// Every stage has 1 reserved uniform buffer for the default uniforms, and 1 for the driver
// uniforms.
constexpr uint32_t kTotalReservedPerStageUniformBuffers =
kReservedDriverUniformBindingCount + kReservedPerStageDefaultUniformBindingCount;
constexpr uint32_t kTotalReservedUniformBuffers =
kReservedDriverUniformBindingCount + kReservedDefaultUniformBindingCount;
const uint32_t maxPerStageUniformBuffers =
mPhysicalDeviceProperties.limits.maxPerStageDescriptorUniformBuffers;
mPhysicalDeviceProperties.limits.maxPerStageDescriptorUniformBuffers -
kTotalReservedPerStageUniformBuffers;
const uint32_t maxCombinedUniformBuffers =
mPhysicalDeviceProperties.limits.maxDescriptorSetUniformBuffers -
kTotalReservedUniformBuffers;
mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Vertex] = maxPerStageUniformBuffers;
mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Fragment] = maxPerStageUniformBuffers;
mNativeCaps.maxCombinedUniformBlocks = maxPerStageUniformBuffers;
mNativeCaps.maxCombinedUniformBlocks = maxCombinedUniformBuffers;
mNativeCaps.maxUniformBufferBindings = maxCombinedUniformBuffers;
mNativeCaps.maxUniformBlockSize = maxUniformBlockSize;
mNativeCaps.uniformBufferOffsetAlignment =
static_cast<GLuint>(mPhysicalDeviceProperties.limits.minUniformBufferOffsetAlignment);
// Note that Vulkan currently implements textures as combined image+samplers, so the limit is
// the minimum of supported samplers and sampled images.
const uint32_t maxPerStageTextures =
std::min(mPhysicalDeviceProperties.limits.maxPerStageDescriptorSamplers,
mPhysicalDeviceProperties.limits.maxPerStageDescriptorSampledImages);
mNativeCaps.maxCombinedTextureImageUnits = maxPerStageTextures;
mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment] = maxPerStageTextures;
const uint32_t maxCombinedTextures =
std::min(mPhysicalDeviceProperties.limits.maxDescriptorSetSamplers,
mPhysicalDeviceProperties.limits.maxDescriptorSetSampledImages);
mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex] = maxPerStageTextures;
mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment] = maxPerStageTextures;
mNativeCaps.maxCombinedTextureImageUnits = maxCombinedTextures;
const uint32_t maxPerStageStorageBuffers =
mPhysicalDeviceProperties.limits.maxPerStageDescriptorStorageBuffers;
const uint32_t maxCombinedStorageBuffers =
mPhysicalDeviceProperties.limits.maxDescriptorSetStorageBuffers;
mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Vertex] =
mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics ? maxPerStageStorageBuffers : 0;
mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Fragment] =
mPhysicalDeviceFeatures.fragmentStoresAndAtomics ? maxPerStageStorageBuffers : 0;
mNativeCaps.maxCombinedShaderStorageBlocks = maxPerStageStorageBuffers;
mNativeCaps.maxCombinedShaderStorageBlocks = maxCombinedStorageBuffers;
// A number of storage buffer slots are used in the vertex shader to emulate transform feedback.
// Note that Vulkan requires maxPerStageDescriptorStorageBuffers to be at least 4 (i.e. the same
......@@ -231,22 +251,21 @@ void RendererVk::ensureCapsInitialized() const
ASSERT(maxPerStageStorageBuffers >= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Vertex] -=
gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS;
mNativeCaps.maxCombinedShaderStorageBlocks -=
gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS;
}
// Fill in additional limits for UBOs and SSBOs.
mNativeCaps.maxUniformBufferBindings = maxPerStageUniformBuffers;
mNativeCaps.maxUniformBlockSize = mPhysicalDeviceProperties.limits.maxUniformBufferRange;
mNativeCaps.uniformBufferOffsetAlignment =
static_cast<GLuint>(mPhysicalDeviceProperties.limits.minUniformBufferOffsetAlignment);
mNativeCaps.maxShaderStorageBufferBindings = maxPerStageStorageBuffers;
mNativeCaps.maxShaderStorageBufferBindings = maxCombinedStorageBuffers;
mNativeCaps.maxShaderStorageBlockSize = mPhysicalDeviceProperties.limits.maxStorageBufferRange;
mNativeCaps.shaderStorageBufferOffsetAlignment =
static_cast<GLuint>(mPhysicalDeviceProperties.limits.minStorageBufferOffsetAlignment);
// There is no additional limit to the combined number of components. We can have up to a
// maximum number of uniform buffers, each having the maximum number of components.
const uint32_t maxCombinedUniformComponents = maxPerStageUniformBuffers * maxUniformComponents;
// maximum number of uniform buffers, each having the maximum number of components. Note that
// this limit includes both components in and out of uniform buffers.
const uint32_t maxCombinedUniformComponents =
(maxPerStageUniformBuffers + kReservedPerStageDefaultUniformBindingCount) *
maxUniformComponents;
for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
{
mNativeCaps.maxCombinedShaderUniformComponents[shaderType] = maxCombinedUniformComponents;
......
......@@ -864,6 +864,16 @@ VkColorComponentFlags GetColorComponentFlags(bool red, bool green, bool blue, bo
(blue ? VK_COLOR_COMPONENT_B_BIT : 0) | (alpha ? VK_COLOR_COMPONENT_A_BIT : 0);
}
VkShaderStageFlags GetShaderStageFlags(gl::ShaderBitSet activeShaders)
{
VkShaderStageFlags flags = 0;
for (const gl::ShaderType shaderType : activeShaders)
{
flags |= kShaderStageMap[shaderType];
}
return flags;
}
void GetViewport(const gl::Rectangle &viewport,
float nearPlane,
float farPlane,
......
......@@ -587,11 +587,19 @@ constexpr angle::PackedEnumMap<gl::DrawElementsType, VkIndexType> kIndexTypeMap
{gl::DrawElementsType::UnsignedInt, VK_INDEX_TYPE_UINT32},
};
constexpr gl::ShaderMap<VkShaderStageFlagBits> kShaderStageMap = {
{gl::ShaderType::Vertex, VK_SHADER_STAGE_VERTEX_BIT},
{gl::ShaderType::Fragment, VK_SHADER_STAGE_FRAGMENT_BIT},
{gl::ShaderType::Geometry, VK_SHADER_STAGE_GEOMETRY_BIT},
{gl::ShaderType::Compute, VK_SHADER_STAGE_COMPUTE_BIT},
};
void GetOffset(const gl::Offset &glOffset, VkOffset3D *vkOffset);
void GetExtent(const gl::Extents &glExtent, VkExtent3D *vkExtent);
VkImageType GetImageType(gl::TextureType textureType);
VkImageViewType GetImageViewType(gl::TextureType textureType);
VkColorComponentFlags GetColorComponentFlags(bool red, bool green, bool blue, bool alpha);
VkShaderStageFlags GetShaderStageFlags(gl::ShaderBitSet activeShaders);
void GetViewport(const gl::Rectangle &viewport,
float nearPlane,
......
......@@ -714,14 +714,20 @@
3520 VULKAN : dEQP-GLES31.functional.state_query.texture_level.texture_2d.compressed_integer = SKIP
3520 VULKAN : dEQP-GLES31.functional.state_query.texture_level.texture_2d.compressed_float = SKIP
// Vulkan limits lower than GLES minimum:
3633 VULKAN : dEQP-GLES31.functional.state_query.integer.max_uniform_buffer_bindings_get* = FAIL
3633 VULKAN : dEQP-GLES31.functional.state_query.integer.max_combined_uniform_blocks_get* = FAIL
3633 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.20 = FAIL
3633 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.31 = FAIL
// column/row_major specified on struct member:
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.2 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.9 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.12 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.16 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.23 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.25 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.29 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_per_block_buffers.33 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_shared_buffer.3 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_shared_buffer.11 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_shared_buffer.25 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_shared_buffer.39 = FAIL
3443 VULKAN : dEQP-GLES31.functional.ubo.random.all_shared_buffer.45 = FAIL
// Validation errors:
// Optimal tiling not supported for format:
......
......@@ -536,23 +536,8 @@
3676 VULKAN : dEQP-GLES3.functional.implementation_limits.max_fragment_input_components = FAIL
3676 VULKAN : dEQP-GLES3.functional.implementation_limits.max_program_texel_offset = FAIL
3676 VULKAN : dEQP-GLES3.functional.implementation_limits.min_program_texel_offset = FAIL
// Vulkan limits lower than GLES minimum:
3633 VULKAN : dEQP-GLES3.functional.implementation_limits.max_uniform_buffer_bindings = FAIL
3633 VULKAN : dEQP-GLES3.functional.implementation_limits.max_combined_uniform_blocks = FAIL
3633 VULKAN : dEQP-GLES3.functional.state_query.integers.max_uniform_buffer_bindings_getinteger64 = FAIL
3633 VULKAN : dEQP-GLES3.functional.state_query.integers.max_uniform_buffer_bindings_getfloat = FAIL
3633 VULKAN : dEQP-GLES3.functional.state_query.integers.max_combined_uniform_blocks_getinteger64 = FAIL
3633 VULKAN : dEQP-GLES3.functional.state_query.integers.max_combined_uniform_blocks_getfloat = FAIL
3633 VULKAN : dEQP-GLES3.functional.state_query.integers.max_fragment_input_components_get* = FAIL
3633 VULKAN : dEQP-GLES3.functional.state_query.integers64.max_combined_vertex_uniform_components_getinteger = FAIL
3633 VULKAN : dEQP-GLES3.functional.state_query.integers64.max_combined_vertex_uniform_components_getfloat = FAIL
3633 VULKAN : dEQP-GLES3.functional.state_query.integers64.max_combined_fragment_uniform_components_getinteger = FAIL
3633 VULKAN : dEQP-GLES3.functional.state_query.integers64.max_combined_fragment_uniform_components_getfloat = FAIL
3633 VULKAN : dEQP-GLES3.functional.ubo.random.all_shared_buffer.7 = FAIL
3633 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs_arrays_instance_arrays.18 = FAIL
3633 ANDROID VULKAN : dEQP-GLES3.functional.implementation_limits.max_combined_texture_image_units = FAIL
3633 ANDROID VULKAN : dEQP-GLES3.functional.state_query.integers.max_combined_texture_image_units_get* = FAIL
// MAX_FRAGMENT_INPUT_COMPONENTS is 0
3676 VULKAN : dEQP-GLES3.functional.state_query.integers.max_fragment_input_components_get* = FAIL
// 3D texture:
3188 VULKAN : dEQP-GLES3.functional.fbo.completeness.layer.3d* = SKIP
......@@ -667,7 +652,29 @@
// Shader support:
3219 VULKAN : dEQP-GLES3.functional.negative_api.shader.link_program = FAIL
3219 VULKAN : dEQP-GLES3.functional.negative_api.shader.use_program = FAIL
// column/row_major specified on struct member:
3443 VULKAN : dEQP-GLES3.functional.ubo.random.basic_arrays.10 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.all_per_block_buffers.8 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.all_per_block_buffers.17 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.all_per_block_buffers.25 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.all_per_block_buffers.49 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.all_shared_buffer.11 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.all_shared_buffer.48 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.basic_arrays.18 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.basic_arrays.20 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.basic_arrays.23 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.basic_arrays.8 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.basic_instance_arrays.13 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs.12 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs.17 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs.5 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs_arrays.2 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs_arrays.3 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs_arrays.4 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs_instance_arrays.12 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs_instance_arrays.18 = FAIL
3443 VULKAN : dEQP-GLES3.functional.ubo.random.nested_structs_instance_arrays.24 = FAIL
// New vertex attribute formats:
3193 VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.*.int2_10_10_10.* = SKIP
......
......@@ -39,9 +39,6 @@
// GL_MIN/MAX_PROGRAM_TEXTURE_GATHER_OFFSET not set.
3605 VULKAN : KHR-GLES31.core.texture_gather* = FAIL
// Vulkan limits lower than GLES minimum:
3633 VULKAN : KHR-GLES31.core.layout_binding.block_layout_binding_block_FragmentShader = FAIL
// Compute shaders
3562 VULKAN : KHR-GLES31.core.constant_expressions.* = SKIP
3520 VULKAN : KHR-GLES31.core.compute_shader* = SKIP
......
......@@ -31,9 +31,6 @@
// For now we only log Vulkan test expectations. More back-ends can follow as we need them.
// Vulkan limits lower than GLES minimum:
3633 VULKAN : KHR-GLES3.shaders.uniform_block.random.all_shared_buffer.1 = FAIL
// Crashes trying to load non-existent texture load function.
3455 VULKAN : KHR-GLES3.copy_tex_image_conversions.forbidden.* = SKIP
3455 VULKAN : KHR-GLES3.copy_tex_image_conversions.required.renderbuffer_* = SKIP
......@@ -50,5 +47,17 @@
// CopyTexImage conversion missing 2D Array and 3D texture support.
3458 VULKAN : KHR-GLES3.copy_tex_image_conversions.required.* = SKIP
// column/row_major specified on struct member:
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.all_per_block_buffers.16 = FAIL
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.all_per_block_buffers.3 = FAIL
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.all_per_block_buffers.5 = FAIL
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.all_per_block_buffers.7 = FAIL
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.all_shared_buffer.0 = FAIL
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.basic_instance_arrays.0 = FAIL
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.basic_instance_arrays.4 = FAIL
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.basic_instance_arrays.5 = FAIL
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.nested_structs_arrays.7 = FAIL
3443 VULKAN : KHR-GLES3.shaders.uniform_block.random.nested_structs_arrays_instance_arrays.3 = FAIL
// Require 3D textures.
3188 VULKAN : KHR-GLES3.packed_pixels.varied_rectangle.* = SKIP
......@@ -66,14 +66,20 @@ class VulkanUniformUpdatesTest : public ANGLETest
programVk->getDynamicDescriptorPool(rx::kUniformsAndXfbDescriptorSetIndex);
uniformPool->setMaxSetsPerPoolForTesting(kMaxSetsForTesting);
VkDescriptorPoolSize uniformSetSize = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
rx::GetUniformBufferDescriptorCount()};
rx::kReservedDefaultUniformBindingCount};
(void)uniformPool->init(contextVk, &uniformSetSize, 1);
uint32_t textureCount =
static_cast<uint32_t>(programVk->getState().getSamplerBindings().size());
// To support the bindEmptyForUnusedDescriptorSets workaround.
textureCount = std::max(textureCount, 1u);
rx::vk::DynamicDescriptorPool *texturePool =
programVk->getDynamicDescriptorPool(rx::kTextureDescriptorSetIndex);
texturePool->setMaxSetsPerPoolForTesting(kMaxSetsForTesting);
VkDescriptorPoolSize textureSetSize = {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
contextVk->getRenderer()->getMaxActiveTextures()};
textureCount};
(void)texturePool->init(contextVk, &textureSetSize, 1);
}
......
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