Commit c13ca2af by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Allow more than one atomic counter buffer binding

dEQP assumes there are more than one atomic counter buffers available. This is technically not a requirement by the standard, but nevertheless could be what applications expect as well. This change adds support for multiple atomic counter buffer bindings. This is done by declaring an array of storage buffers for the atomic counter buffers (instead of declaring only one) and passing the (binding, offset) pair around to functions instead of just the offset. The atomic counter is found by indexing `binding` into the storage buffer array first before indexing `offset` into its `uint[]`. ProgramVk's default uniform collection is also fixed not to include atomic counter uniforms. A remaining issue is that atomic counter buffer offsets don't have alignment requirements in GLES, but Vulkan does for storage buffers. Similar to emulated transform feedback buffer offsets, these should be sent to the shader through uniform values. This will be done in a follow up change. Bug: angleproject:3566 Change-Id: I5600225c24c38f1a8ecf5c64388073055733197d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1707931 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 2a53d83a
...@@ -105,6 +105,23 @@ bool TConstantUnion::getBConst() const ...@@ -105,6 +105,23 @@ bool TConstantUnion::getBConst() const
return bConst; return bConst;
} }
bool TConstantUnion::isZero() const
{
switch (type)
{
case EbtInt:
return getIConst() == 0;
case EbtUInt:
return getUConst() == 0;
case EbtFloat:
return getFConst() == 0.0f;
case EbtBool:
return getBConst() == false;
default:
return false;
}
}
TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const
{ {
ASSERT(type == EbtYuvCscStandardEXT); ASSERT(type == EbtYuvCscStandardEXT);
......
...@@ -56,6 +56,7 @@ class TConstantUnion ...@@ -56,6 +56,7 @@ class TConstantUnion
unsigned int getUConst() const; unsigned int getUConst() const;
float getFConst() const; float getFConst() const;
bool getBConst() const; bool getBConst() const;
bool isZero() const;
TYuvCscStandardEXT getYuvCscStandardEXTConst() const; TYuvCscStandardEXT getYuvCscStandardEXTConst() const;
bool operator==(const int i) const; bool operator==(const int i) const;
......
...@@ -333,6 +333,10 @@ class TIntermConstantUnion : public TIntermExpression ...@@ -333,6 +333,10 @@ class TIntermConstantUnion : public TIntermExpression
{ {
return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false; return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
} }
bool isZero(size_t index) const
{
return mUnionArrayPointer ? mUnionArrayPointer[index].isZero() : false;
}
TIntermConstantUnion *getAsConstantUnion() override { return this; } TIntermConstantUnion *getAsConstantUnion() override { return this; }
void traverse(TIntermTraverser *it) final; void traverse(TIntermTraverser *it) final;
......
...@@ -163,6 +163,8 @@ TIntermConstantUnion *CreateFloatConstant(float value) ...@@ -163,6 +163,8 @@ TIntermConstantUnion *CreateFloatConstant(float value)
constexpr ImmutableString kFlippedPointCoordName = ImmutableString("flippedPointCoord"); constexpr ImmutableString kFlippedPointCoordName = ImmutableString("flippedPointCoord");
constexpr ImmutableString kFlippedFragCoordName = ImmutableString("flippedFragCoord"); constexpr ImmutableString kFlippedFragCoordName = ImmutableString("flippedFragCoord");
constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams"); constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams");
constexpr ImmutableString kUniformsBlockName = ImmutableString("ANGLEUniformBlock");
constexpr ImmutableString kUniformsVarName = ImmutableString("ANGLEUniforms");
constexpr const char kViewport[] = "viewport"; constexpr const char kViewport[] = "viewport";
constexpr const char kHalfRenderAreaHeight[] = "halfRenderAreaHeight"; constexpr const char kHalfRenderAreaHeight[] = "halfRenderAreaHeight";
...@@ -375,7 +377,8 @@ const TVariable *AddDriverUniformsToShader(TIntermBlock *root, TSymbolTable *sym ...@@ -375,7 +377,8 @@ const TVariable *AddDriverUniformsToShader(TIntermBlock *root, TSymbolTable *sym
// Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms". // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms".
return DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform, return DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform,
TMemoryQualifier::Create(), "ANGLEUniformBlock", "ANGLEUniforms"); TMemoryQualifier::Create(), 0, kUniformsBlockName,
kUniformsVarName);
} }
TIntermPreprocessorDirective *GenerateLineRasterIfDef() TIntermPreprocessorDirective *GenerateLineRasterIfDef()
......
...@@ -33,7 +33,10 @@ class BlockLayoutMapVisitor : public BlockEncoderVisitor ...@@ -33,7 +33,10 @@ class BlockLayoutMapVisitor : public BlockEncoderVisitor
const std::string &mappedName) override const std::string &mappedName) override
{ {
ASSERT(!gl::IsSamplerType(variable.type)); ASSERT(!gl::IsSamplerType(variable.type));
(*mInfoOut)[name] = variableInfo; if (!gl::IsOpaqueType(variable.type))
{
(*mInfoOut)[name] = variableInfo;
}
} }
private: private:
......
...@@ -213,22 +213,26 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root, ...@@ -213,22 +213,26 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root,
TFieldList *fieldList, TFieldList *fieldList,
TQualifier qualifier, TQualifier qualifier,
const TMemoryQualifier &memoryQualifier, const TMemoryQualifier &memoryQualifier,
const char *blockTypeName, uint32_t arraySize,
const char *blockVariableName) const ImmutableString &blockTypeName,
const ImmutableString &blockVariableName)
{ {
// Define an interface block. // Define an interface block.
TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
TInterfaceBlock *interfaceBlock = TInterfaceBlock *interfaceBlock = new TInterfaceBlock(
new TInterfaceBlock(symbolTable, ImmutableString(blockTypeName), fieldList, layoutQualifier, symbolTable, blockTypeName, fieldList, layoutQualifier, SymbolType::AngleInternal);
SymbolType::AngleInternal);
// Turn the inteface block into a declaration. // Turn the inteface block into a declaration.
TType *interfaceBlockType = new TType(interfaceBlock, qualifier, layoutQualifier); TType *interfaceBlockType = new TType(interfaceBlock, qualifier, layoutQualifier);
interfaceBlockType->setMemoryQualifier(memoryQualifier); interfaceBlockType->setMemoryQualifier(memoryQualifier);
if (arraySize > 0)
{
interfaceBlockType->makeArray(arraySize);
}
TIntermDeclaration *interfaceBlockDecl = new TIntermDeclaration; TIntermDeclaration *interfaceBlockDecl = new TIntermDeclaration;
TVariable *interfaceBlockVar = new TVariable(symbolTable, ImmutableString(blockVariableName), TVariable *interfaceBlockVar = new TVariable(symbolTable, blockVariableName, interfaceBlockType,
interfaceBlockType, SymbolType::AngleInternal); SymbolType::AngleInternal);
TIntermSymbol *interfaceBlockDeclarator = new TIntermSymbol(interfaceBlockVar); TIntermSymbol *interfaceBlockDeclarator = new TIntermSymbol(interfaceBlockVar);
interfaceBlockDecl->appendDeclarator(interfaceBlockDeclarator); interfaceBlockDecl->appendDeclarator(interfaceBlockDeclarator);
......
...@@ -48,8 +48,9 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root, ...@@ -48,8 +48,9 @@ const TVariable *DeclareInterfaceBlock(TIntermBlock *root,
TFieldList *fieldList, TFieldList *fieldList,
TQualifier qualifier, TQualifier qualifier,
const TMemoryQualifier &memoryQualifier, const TMemoryQualifier &memoryQualifier,
const char *blockTypeName, uint32_t arraySize,
const char *blockVariableName); const ImmutableString &blockTypeName,
const ImmutableString &blockVariableName);
// If the input node is nullptr, return nullptr. // If the input node is nullptr, return nullptr.
// If the input node is a block node, return it. // If the input node is a block node, return it.
......
...@@ -489,23 +489,22 @@ bool TIntermTraverser::CompareInsertion(const NodeInsertMultipleEntry &a, ...@@ -489,23 +489,22 @@ bool TIntermTraverser::CompareInsertion(const NodeInsertMultipleEntry &a,
{ {
if (a.parent != b.parent) if (a.parent != b.parent)
{ {
return a.parent > b.parent; return a.parent < b.parent;
} }
return a.position > b.position; return a.position < b.position;
} }
void TIntermTraverser::updateTree() void TIntermTraverser::updateTree()
{ {
// Sort the insertions so that insertion position is decreasing. This way multiple insertions to // Sort the insertions so that insertion position is increasing and same position insertions are
// not reordered. The insertions are processed in reverse order so that multiple insertions to
// the same parent node are handled correctly. // the same parent node are handled correctly.
std::sort(mInsertions.begin(), mInsertions.end(), CompareInsertion); std::stable_sort(mInsertions.begin(), mInsertions.end(), CompareInsertion);
for (size_t ii = 0; ii < mInsertions.size(); ++ii) for (size_t ii = 0; ii < mInsertions.size(); ++ii)
{ {
// We can't know here what the intended ordering of two insertions to the same position is, // If two insertions are to the same position, insert them in the order they were specified.
// so it is not supported. // The std::stable_sort call above will automatically guarantee this.
ASSERT(ii == 0 || mInsertions[ii].position != mInsertions[ii - 1].position || const NodeInsertMultipleEntry &insertion = mInsertions[mInsertions.size() - ii - 1];
mInsertions[ii].parent != mInsertions[ii - 1].parent);
const NodeInsertMultipleEntry &insertion = mInsertions[ii];
ASSERT(insertion.parent); ASSERT(insertion.parent);
if (!insertion.insertionsAfter.empty()) if (!insertion.insertionsAfter.empty())
{ {
......
...@@ -495,6 +495,7 @@ template <typename T> ...@@ -495,6 +495,7 @@ template <typename T>
using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>; using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
template <typename T> template <typename T>
using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>; using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>;
using AtomicCounterBufferMask = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>;
using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>; using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
......
...@@ -740,23 +740,27 @@ uint32_t AssignAtomicCounterBufferBindings(const std::vector<gl::AtomicCounterBu ...@@ -740,23 +740,27 @@ uint32_t AssignAtomicCounterBufferBindings(const std::vector<gl::AtomicCounterBu
uint32_t bindingStart, uint32_t bindingStart,
gl::ShaderMap<IntermediateShaderSource> *shaderSources) gl::ShaderMap<IntermediateShaderSource> *shaderSources)
{ {
const std::string resourcesDescriptorSet = "set = " + Str(kShaderResourceDescriptorSetIndex); if (buffers.size() == 0)
{
return bindingStart;
}
// Currently, we only support a single atomic counter buffer binding. constexpr char kAtomicCounterBlockName[] = "ANGLEAtomicCounters";
ASSERT(buffers.size() <= 1); const std::string bindingString =
"set = " + Str(kShaderResourceDescriptorSetIndex) + ", binding = " + Str(bindingStart);
uint32_t bindingIndex = bindingStart; for (const gl::ShaderType shaderType : gl::AllShaderTypes())
for (const gl::AtomicCounterBuffer &buffer : buffers)
{ {
const std::string bindingString = IntermediateShaderSource &shaderSource = (*shaderSources)[shaderType];
resourcesDescriptorSet + ", binding = " + Str(bindingIndex++); if (!shaderSource.empty())
{
constexpr char kAtomicCounterBlockName[] = "ANGLEAtomicCounters"; // All atomic counter buffers are placed under one binding shared between all stages.
AssignResourceBinding(buffer.activeShaders(), kAtomicCounterBlockName, bindingString, shaderSource.insertLayoutSpecifier(kAtomicCounterBlockName, bindingString);
qualifier, kUnusedBlockSubstitution, shaderSources); shaderSource.insertQualifierSpecifier(kAtomicCounterBlockName, qualifier);
}
} }
return bindingIndex; return bindingStart + 1;
} }
void AssignBufferBindings(const gl::ProgramState &programState, void AssignBufferBindings(const gl::ProgramState &programState,
......
...@@ -266,10 +266,12 @@ class ProgramVk : public ProgramImpl ...@@ -266,10 +266,12 @@ class ProgramVk : public ProgramImpl
gl::ShaderVector<uint32_t> mDynamicBufferOffsets; gl::ShaderVector<uint32_t> mDynamicBufferOffsets;
// This is a special "empty" placeholder buffer for when a shader has no uniforms. // 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.
//
// It is necessary because we want to keep a compatible pipeline layout in all cases, // It is necessary because we want to keep a compatible pipeline layout in all cases,
// and Vulkan does not tolerate having null handles in a descriptor set. // and Vulkan does not tolerate having null handles in a descriptor set.
vk::BufferHelper mEmptyUniformBlockStorage; vk::BufferHelper mEmptyBuffer;
// Descriptor sets for uniform blocks and textures for this program. // Descriptor sets for uniform blocks and textures for this program.
std::vector<VkDescriptorSet> mDescriptorSets; std::vector<VkDescriptorSet> mDescriptorSets;
......
...@@ -1115,10 +1115,13 @@ gl::Version RendererVk::getMaxSupportedESVersion() const ...@@ -1115,10 +1115,13 @@ gl::Version RendererVk::getMaxSupportedESVersion() const
// Limit to ES3.0 if there are any blockers for 3.1. // Limit to ES3.0 if there are any blockers for 3.1.
// ES3.1 requires at least one atomic counter buffer and four storage buffers in compute. // ES3.1 requires at least one atomic counter buffer and four storage buffers in compute.
// Atomic counter buffers are emulated with storage buffers, so if Vulkan doesn't support at // Atomic counter buffers are emulated with storage buffers. For simplicity, we always support
// least 5 storage buffers in compute, we cannot support 3.1. // either none or IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS atomic counter buffers. So if
// Vulkan doesn't support at least that many storage buffers in compute, we don't support 3.1.
const uint32_t kMinimumStorageBuffersForES31 =
gl::limits::kMinimumComputeStorageBuffers + gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS;
if (mPhysicalDeviceProperties.limits.maxPerStageDescriptorStorageBuffers < if (mPhysicalDeviceProperties.limits.maxPerStageDescriptorStorageBuffers <
gl::limits::kMinimumComputeStorageBuffers + 1) kMinimumStorageBuffersForES31)
{ {
maxVersion = std::min(maxVersion, gl::Version(3, 0)); maxVersion = std::min(maxVersion, gl::Version(3, 0));
} }
......
...@@ -894,11 +894,11 @@ class PipelineLayoutCache final : angle::NonCopyable ...@@ -894,11 +894,11 @@ class PipelineLayoutCache final : angle::NonCopyable
// //
// The set/binding assignment is done as following: // The set/binding assignment is done as following:
// //
// - Set 0 contains uniform blocks created to encompass default uniforms. Bindings 0 and 1 // - Set 0 contains uniform blocks created to encompass default uniforms. 1 binding is used per
// correspond to default uniforms in the vertex and fragment shaders respectively. Additionally, // pipeline stage. Additionally, transform feedback buffers are bound from binding 2 and up.
// transform feedback buffers are bound from binding 2 and up.
// - Set 1 contains all textures. // - Set 1 contains all textures.
// - Set 2 contains all other shader resources. // - Set 2 contains all other shader resources, such as uniform and storage blocks, atomic counter
// buffers and images.
// - Set 3 contains the ANGLE driver uniforms at binding 0. Note that driver uniforms are updated // - Set 3 contains the ANGLE driver uniforms at binding 0. Note that driver uniforms are updated
// only under rare circumstances, such as viewport or depth range change. However, there is only // only under rare circumstances, such as viewport or depth range change. However, there is only
// one binding in this set. // one binding in this set.
......
...@@ -264,31 +264,39 @@ void RendererVk::ensureCapsInitialized() const ...@@ -264,31 +264,39 @@ void RendererVk::ensureCapsInitialized() const
maxPerStageStorageBuffers = std::min(maxPerStageStorageBuffers, maxCombinedStorageBuffers); maxPerStageStorageBuffers = std::min(maxPerStageStorageBuffers, maxCombinedStorageBuffers);
} }
// Reserve one storage buffer in the fragment and compute stages for atomic counters. This is // Reserve up to IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS storage buffers in the fragment and
// only possible if the number of per-stage storage buffers is greater than 4, which is the // compute stages for atomic counters. This is only possible if the number of per-stage storage
// required GLES minimum for compute. We use the same value for fragment, to avoid giving one // buffers is greater than 4, which is the required GLES minimum for compute.
// of the precious few storage buffers available to an atomic counter buffer. The spec allows //
// there to be zero of either of these resources in the fragment stage. // For each stage, we'll either not support atomic counter buffers, or support exactly
// IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS. This is due to restrictions in the shader
// translator where we can't know how many atomic counter buffers we would really need after
// linking so we can't create a packed buffer array.
//
// For the vertex stage, we could support atomic counters without storage buffers, but that's
// likely not very useful, so we use the same limit (4 + MAX_ATOMIC_COUNTER_BUFFERS) for the
// vertex stage to determine if we would want to add support for atomic counter buffers.
constexpr uint32_t kMinimumStorageBuffersForAtomicCounterBufferSupport =
gl::limits::kMinimumComputeStorageBuffers + gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS;
uint32_t maxVertexStageAtomicCounterBuffers = 0; uint32_t maxVertexStageAtomicCounterBuffers = 0;
uint32_t maxPerStageAtomicCounterBuffers = 0; uint32_t maxPerStageAtomicCounterBuffers = 0;
uint32_t maxCombinedAtomicCounterBuffers = 0; uint32_t maxCombinedAtomicCounterBuffers = 0;
if (maxPerStageStorageBuffers > gl::limits::kMinimumComputeStorageBuffers) if (maxPerStageStorageBuffers >= kMinimumStorageBuffersForAtomicCounterBufferSupport)
{ {
--maxPerStageStorageBuffers; maxPerStageAtomicCounterBuffers = gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS;
--maxCombinedStorageBuffers; maxCombinedAtomicCounterBuffers = gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS;
maxPerStageAtomicCounterBuffers = 1;
maxCombinedAtomicCounterBuffers = 1;
} }
// For the vertex stage, similarly reserve one storage buffer for atomic counters, if there are if (maxVertexStageStorageBuffers >= kMinimumStorageBuffersForAtomicCounterBufferSupport)
// excess storage buffers.
if (maxVertexStageStorageBuffers > gl::limits::kMinimumComputeStorageBuffers)
{ {
--maxVertexStageStorageBuffers; maxVertexStageAtomicCounterBuffers = gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS;
maxVertexStageAtomicCounterBuffers = 1;
} }
maxVertexStageStorageBuffers -= maxVertexStageAtomicCounterBuffers;
maxPerStageStorageBuffers -= maxPerStageAtomicCounterBuffers;
maxCombinedStorageBuffers -= maxCombinedAtomicCounterBuffers;
mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Vertex] = mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Vertex] =
mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics ? maxVertexStageStorageBuffers : 0; mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics ? maxVertexStageStorageBuffers : 0;
mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Fragment] = mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Fragment] =
......
...@@ -617,6 +617,12 @@ ...@@ -617,6 +617,12 @@
3520 VULKAN ANDROID : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texparameterf = FAIL 3520 VULKAN ANDROID : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texparameterf = FAIL
3520 VULKAN ANDROID : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texparameterfv = FAIL 3520 VULKAN ANDROID : dEQP-GLES31.functional.debug.negative_coverage.get_error.texture.texparameterfv = FAIL
// Passing on recent drivers:
3726 VULKAN ANDROID : dEQP-GLES31.functional.ssbo.layout.* = FAIL
3726 VULKAN ANDROID : dEQP-GLES31.functional.atomic_counter.* = FAIL
3726 VULKAN ANDROID : dEQP-GLES31.functional.synchronization.inter_call.without_memory_barrier.*atomic_counter* = FAIL
3726 VULKAN ANDROID : dEQP-GLES31.functional.compute.basic.atomic_counter* = FAIL
// General Vulkan failures // General Vulkan failures
// Limits: // Limits:
...@@ -650,6 +656,10 @@ ...@@ -650,6 +656,10 @@
// SSBO and Image qualifiers: // SSBO and Image qualifiers:
3602 VULKAN : dEQP-GLES31.functional.synchronization.in_invocation.ssbo_alias_overwrite = FAIL 3602 VULKAN : dEQP-GLES31.functional.synchronization.in_invocation.ssbo_alias_overwrite = FAIL
// Array of array in atomic counters:
3566 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.atomic_counter_buffer_index.default_block.array.var_array_array = SKIP
3566 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.location.default_block.array.array.atomic_uint = SKIP
// Struct referenced by: // Struct referenced by:
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.*.referenced_by*struct* = FAIL 3596 VULKAN : dEQP-GLES31.functional.program_interface_query.*.referenced_by*struct* = FAIL
3596 VULKAN : dEQP-GLES31.functional.program_interface_query.*random* = FAIL 3596 VULKAN : dEQP-GLES31.functional.program_interface_query.*random* = FAIL
...@@ -666,11 +676,6 @@ ...@@ -666,11 +676,6 @@
// Tessellation geometry interaction: // Tessellation geometry interaction:
3572 VULKAN : dEQP-GLES31.functional.tessellation_geometry_interaction.* = FAIL 3572 VULKAN : dEQP-GLES31.functional.tessellation_geometry_interaction.* = FAIL
// dEQP bug where atomic counter bindings > max result in failure instead of not-supported:
// https://github.com/KhronosGroup/VK-GL-CTS/issues/156
3566 VULKAN : dEQP-GLES31.functional.atomic_counter.* = FAIL
3566 VULKAN : dEQP-GLES31.functional.synchronization.inter_call.without_memory_barrier.*atomic_counter* = FAIL
// Storage image: // Storage image:
3563 VULKAN : dEQP-GLES31.functional.state_query.*image* = FAIL 3563 VULKAN : dEQP-GLES31.functional.state_query.*image* = FAIL
3563 VULKAN : dEQP-GLES31.functional.synchronization.*.image* = FAIL 3563 VULKAN : dEQP-GLES31.functional.synchronization.*.image* = FAIL
......
...@@ -105,11 +105,14 @@ ...@@ -105,11 +105,14 @@
// Blend equations: // Blend equations:
3586 VULKAN : KHR-GLES31.core.blend_equation_advanced.* = SKIP 3586 VULKAN : KHR-GLES31.core.blend_equation_advanced.* = SKIP
// Atomic Counter buffers:
3566 VULKAN : KHR-GLES31.core.shader_atomic_counters.advanced-usage-multi-stage = FAIL
// Storage image: // Storage image:
3563 VULKAN : KHR-GLES31.core.layout_binding.sampler2D_layout_binding_texture_ComputeShader = FAIL 3563 VULKAN : KHR-GLES31.core.layout_binding.sampler2D_layout_binding_texture_ComputeShader = FAIL
3563 VULKAN : KHR-GLES31.core.layout_binding.block_layout_binding_block_ComputeShader = FAIL 3563 VULKAN : KHR-GLES31.core.layout_binding.block_layout_binding_block_ComputeShader = FAIL
3563 VULKAN : KHR-GLES31.core.layout_binding.buffer_layout_binding_atomic* = SKIP 3563 VULKAN : KHR-GLES31.core.layout_binding.buffer_layout_binding_atomicAdd_ComputeShader = FAIL
3563 VULKAN : KHR-GLES31.core.layout_binding.atomic_uint_layout_binding_atomic* = FAIL 3563 VULKAN : KHR-GLES31.core.layout_binding.atomic_uint_layout_binding_atomic_ComputeShader = FAIL
3520 VULKAN : KHR-GLES31.core.internalformat.copy_tex_image* = FAIL 3520 VULKAN : KHR-GLES31.core.internalformat.copy_tex_image* = FAIL
3520 VULKAN : KHR-GLES31.core.internalformat.renderbuffer* = FAIL 3520 VULKAN : KHR-GLES31.core.internalformat.renderbuffer* = FAIL
...@@ -118,3 +121,7 @@ ...@@ -118,3 +121,7 @@
// Sampler objects: // Sampler objects:
3208 VULKAN : KHR-GLES31.shaders.layout_location.*sampler* = FAIL 3208 VULKAN : KHR-GLES31.shaders.layout_location.*sampler* = FAIL
// Passing on recent drivers:
3726 VULKAN ANDROID : KHR-GLES31.core.shader_atomic_counters.* = FAIL
3726 VULKAN ANDROID : KHR-GLES31.core.shader_atomic_counters.advanced-usage-* = SKIP
...@@ -130,16 +130,21 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterReadCompute) ...@@ -130,16 +130,21 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterReadCompute)
// Crashes in older drivers. http://anglebug.com/3738 // Crashes in older drivers. http://anglebug.com/3738
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsAMD()); ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsAMD());
// Skipping due to a bug on the Qualcomm Vulkan Android driver.
// http://anglebug.com/3726
ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
// Skipping due to a bug on the Adreno OpenGLES Android driver. // Skipping due to a bug on the Adreno OpenGLES Android driver.
// http://anglebug.com/2925 // http://anglebug.com/2925
ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES()); ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
constexpr char kComputeShaderSource[] = R"(#version 310 es constexpr char kComputeShaderSource[] = R"(#version 310 es
layout(local_size_x=1, local_size_y=1, local_size_z=1) in; layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(binding = 0, offset = 8) uniform atomic_uint ac[3];
void atomicCounterInFunction(in atomic_uint counter[3]); void atomicCounterInFunction(in atomic_uint counter[3]);
layout(binding = 0, offset = 8) uniform atomic_uint ac[3];
void atomicCounterInFunction(in atomic_uint counter[3]) void atomicCounterInFunction(in atomic_uint counter[3])
{ {
atomicCounter(counter[0]); atomicCounter(counter[0]);
...@@ -161,6 +166,10 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterRead) ...@@ -161,6 +166,10 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterRead)
// Crashes in older drivers. http://anglebug.com/3738 // Crashes in older drivers. http://anglebug.com/3738
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsAMD()); ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsAMD());
// Skipping due to a bug on the Qualcomm Vulkan Android driver.
// http://anglebug.com/3726
ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
// Skipping test while we work on enabling atomic counter buffer support in th D3D renderer. // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
// http://anglebug.com/1729 // http://anglebug.com/1729
ANGLE_SKIP_TEST_IF(IsD3D11()); ANGLE_SKIP_TEST_IF(IsD3D11());
...@@ -200,6 +209,10 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterIncrementAndDecrement) ...@@ -200,6 +209,10 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterIncrementAndDecrement)
// Crashes in older drivers. http://anglebug.com/3738 // Crashes in older drivers. http://anglebug.com/3738
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsAMD()); ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsAMD());
// Skipping due to a bug on the Qualcomm Vulkan Android driver.
// http://anglebug.com/3726
ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
constexpr char kCS[] = constexpr char kCS[] =
"#version 310 es\n" "#version 310 es\n"
"layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n" "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
...@@ -244,6 +257,10 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterMultipleBuffers) ...@@ -244,6 +257,10 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterMultipleBuffers)
// Crashes in older drivers. http://anglebug.com/3738 // Crashes in older drivers. http://anglebug.com/3738
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsAMD()); ANGLE_SKIP_TEST_IF(IsOpenGL() && IsWindows() && IsAMD());
// Skipping due to a bug on the Qualcomm Vulkan Android driver.
// http://anglebug.com/3726
ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
GLint maxAtomicCounterBuffers = 0; GLint maxAtomicCounterBuffers = 0;
glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers); glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers);
constexpr unsigned int kBufferCount = 3; constexpr unsigned int kBufferCount = 3;
......
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