Commit 81ed8d40 by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: SPIR-V Gen: Support barrier* built-ins

This change enables the ComputeShaderTest suite and additionally includes the following fixes: - OpArrayLength was given the array type instead of variable. - Struct arrays inside interface blocks were not decorated with ArrayStride. Bug: angleproject:4889 Change-Id: Ibae95371bcea10e58c86b8fe1d1e172a18d56a09 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3001908 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent dc2d76cd
...@@ -438,9 +438,15 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const TSymbol *bl ...@@ -438,9 +438,15 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const TSymbol *bl
// Write decorations for interface block fields. // Write decorations for interface block fields.
if (type.blockStorage != EbsUnspecified) if (type.blockStorage != EbsUnspecified)
{ {
if (!isOpaqueType && !type.arraySizes.empty() && type.block == nullptr) // Cannot have opaque uniforms inside interface blocks.
ASSERT(!isOpaqueType);
const bool isInterfaceBlock = block != nullptr && block->isInterfaceBlock();
if (!type.arraySizes.empty() && !isInterfaceBlock)
{ {
// Write the ArrayStride decoration for arrays inside interface blocks. // Write the ArrayStride decoration for arrays inside interface blocks. An array of
// interface blocks doesn't need a stride.
spirv::WriteDecorate( spirv::WriteDecorate(
&mSpirvDecorations, typeId, spv::DecorationArrayStride, &mSpirvDecorations, typeId, spv::DecorationArrayStride,
{spirv::LiteralInteger(sizeInStorageBlock / GetOutermostArraySize(type))}); {spirv::LiteralInteger(sizeInStorageBlock / GetOutermostArraySize(type))});
......
...@@ -4113,15 +4113,9 @@ bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node) ...@@ -4113,15 +4113,9 @@ bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node)
{ {
// The access chain must only include the base ssbo + one literal field index. // The access chain must only include the base ssbo + one literal field index.
ASSERT(mNodeData.back().idList.size() == 1 && !mNodeData.back().idList.back().id.valid()); ASSERT(mNodeData.back().idList.size() == 1 && !mNodeData.back().idList.back().id.valid());
const spirv::IdRef baseId = mNodeData.back().baseId;
const spirv::LiteralInteger fieldIndex = mNodeData.back().idList.back().literal; const spirv::LiteralInteger fieldIndex = mNodeData.back().idList.back().literal;
// Get the interface block type from the operand, which is either a symbol or a binary
// operator based on whether the interface block is nameless or not.
TIntermTyped *operand = node->getOperand();
TIntermTyped *ssbo =
operand->getAsBinaryNode() ? operand->getAsBinaryNode()->getLeft() : operand;
const spirv::IdRef typeId = mBuilder.getTypeData(ssbo->getType(), EbsUnspecified).id;
// Get the int and uint type ids. // Get the int and uint type ids.
const spirv::IdRef intTypeId = mBuilder.getBasicTypeId(EbtInt, 1); const spirv::IdRef intTypeId = mBuilder.getBasicTypeId(EbtInt, 1);
const spirv::IdRef uintTypeId = mBuilder.getBasicTypeId(EbtUInt, 1); const spirv::IdRef uintTypeId = mBuilder.getBasicTypeId(EbtUInt, 1);
...@@ -4129,7 +4123,7 @@ bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node) ...@@ -4129,7 +4123,7 @@ bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node)
// Generate the instruction. // Generate the instruction.
const spirv::IdRef resultId = mBuilder.getNewId({}); const spirv::IdRef resultId = mBuilder.getNewId({});
spirv::WriteArrayLength(mBuilder.getSpirvCurrentFunctionBlock(), uintTypeId, resultId, spirv::WriteArrayLength(mBuilder.getSpirvCurrentFunctionBlock(), uintTypeId, resultId,
typeId, fieldIndex); baseId, fieldIndex);
// Cast to int. // Cast to int.
const spirv::IdRef castResultId = mBuilder.getNewId({}); const spirv::IdRef castResultId = mBuilder.getNewId({});
...@@ -4724,16 +4718,58 @@ bool OutputSPIRVTraverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -4724,16 +4718,58 @@ bool OutputSPIRVTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
result = createFunctionCall(node, resultTypeId); result = createFunctionCall(node, resultTypeId);
break; break;
// For barrier functions the scope is device, or with the Vulkan memory model, the queue
// family. We don't use the Vulkan memory model.
case EOpBarrier:
spirv::WriteControlBarrier(
mBuilder.getSpirvCurrentFunctionBlock(),
mBuilder.getUintConstant(spv::ScopeWorkgroup),
mBuilder.getUintConstant(spv::ScopeWorkgroup),
mBuilder.getUintConstant(spv::MemorySemanticsWorkgroupMemoryMask |
spv::MemorySemanticsAcquireReleaseMask));
break;
case EOpBarrierTCS:
// Note: The memory scope and semantics are different with the Vulkan memory model,
// which is not supported.
spirv::WriteControlBarrier(mBuilder.getSpirvCurrentFunctionBlock(),
mBuilder.getUintConstant(spv::ScopeWorkgroup),
mBuilder.getUintConstant(spv::ScopeInvocation),
mBuilder.getUintConstant(spv::MemorySemanticsMaskNone));
break;
case EOpMemoryBarrier: case EOpMemoryBarrier:
case EOpMemoryBarrierAtomicCounter: case EOpGroupMemoryBarrier:
{
const spv::Scope scope =
node->getOp() == EOpMemoryBarrier ? spv::ScopeDevice : spv::ScopeWorkgroup;
spirv::WriteMemoryBarrier(
mBuilder.getSpirvCurrentFunctionBlock(), mBuilder.getUintConstant(scope),
mBuilder.getUintConstant(spv::MemorySemanticsUniformMemoryMask |
spv::MemorySemanticsWorkgroupMemoryMask |
spv::MemorySemanticsImageMemoryMask |
spv::MemorySemanticsAcquireReleaseMask));
break;
}
case EOpMemoryBarrierBuffer: case EOpMemoryBarrierBuffer:
spirv::WriteMemoryBarrier(
mBuilder.getSpirvCurrentFunctionBlock(), mBuilder.getUintConstant(spv::ScopeDevice),
mBuilder.getUintConstant(spv::MemorySemanticsUniformMemoryMask |
spv::MemorySemanticsAcquireReleaseMask));
break;
case EOpMemoryBarrierImage: case EOpMemoryBarrierImage:
case EOpBarrier: spirv::WriteMemoryBarrier(
mBuilder.getSpirvCurrentFunctionBlock(), mBuilder.getUintConstant(spv::ScopeDevice),
mBuilder.getUintConstant(spv::MemorySemanticsImageMemoryMask |
spv::MemorySemanticsAcquireReleaseMask));
break;
case EOpMemoryBarrierShared: case EOpMemoryBarrierShared:
case EOpGroupMemoryBarrier: spirv::WriteMemoryBarrier(
case EOpBarrierTCS: mBuilder.getSpirvCurrentFunctionBlock(), mBuilder.getUintConstant(spv::ScopeDevice),
// TODO: support barriers. http://anglebug.com/4889 mBuilder.getUintConstant(spv::MemorySemanticsWorkgroupMemoryMask |
UNIMPLEMENTED(); spv::MemorySemanticsAcquireReleaseMask));
break;
case EOpMemoryBarrierAtomicCounter:
// Atomic counters are emulated.
UNREACHABLE();
break; break;
case EOpEmitVertex: case EOpEmitVertex:
......
...@@ -1028,11 +1028,11 @@ TEST_P(ComputeShaderTest, TexelFetchFunction) ...@@ -1028,11 +1028,11 @@ TEST_P(ComputeShaderTest, TexelFetchFunction)
// http://anglebug.com/4092 // http://anglebug.com/4092
ANGLE_SKIP_TEST_IF(isSwiftshader()); ANGLE_SKIP_TEST_IF(isSwiftshader());
constexpr char kCS[] = R"(#version 310 es constexpr char kCS[] = R"(#version 310 es
layout(local_size_x=16, local_size_y=16) in; layout(local_size_x=16, local_size_y=12) in;
precision highp usampler2D; precision highp usampler2D;
uniform usampler2D tex; uniform usampler2D tex;
layout(std140, binding = 0) buffer buf { layout(std140, binding = 0) buffer buf {
uint outData[16][16]; uint outData[12][16];
}; };
void main() void main()
...@@ -1043,7 +1043,7 @@ void main() ...@@ -1043,7 +1043,7 @@ void main()
})"; })";
constexpr unsigned int kWidth = 16; constexpr unsigned int kWidth = 16;
constexpr unsigned int kHeight = 16; constexpr unsigned int kHeight = 12;
GLTexture tex; GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex); glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
...@@ -4580,7 +4580,7 @@ void main() ...@@ -4580,7 +4580,7 @@ void main()
} }
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTest);
ANGLE_INSTANTIATE_TEST_ES31(ComputeShaderTest); ANGLE_INSTANTIATE_TEST_ES31_AND(ComputeShaderTest, WithDirectSPIRVGeneration(ES31_VULKAN()));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTestES3); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTestES3);
ANGLE_INSTANTIATE_TEST_ES3(ComputeShaderTestES3); ANGLE_INSTANTIATE_TEST_ES3(ComputeShaderTestES3);
......
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