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
// Write decorations for interface block fields.
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(
&mSpirvDecorations, typeId, spv::DecorationArrayStride,
{spirv::LiteralInteger(sizeInStorageBlock / GetOutermostArraySize(type))});
......
......@@ -4113,15 +4113,9 @@ bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node)
{
// 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());
const spirv::IdRef baseId = mNodeData.back().baseId;
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.
const spirv::IdRef intTypeId = mBuilder.getBasicTypeId(EbtInt, 1);
const spirv::IdRef uintTypeId = mBuilder.getBasicTypeId(EbtUInt, 1);
......@@ -4129,7 +4123,7 @@ bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node)
// Generate the instruction.
const spirv::IdRef resultId = mBuilder.getNewId({});
spirv::WriteArrayLength(mBuilder.getSpirvCurrentFunctionBlock(), uintTypeId, resultId,
typeId, fieldIndex);
baseId, fieldIndex);
// Cast to int.
const spirv::IdRef castResultId = mBuilder.getNewId({});
......@@ -4724,16 +4718,58 @@ bool OutputSPIRVTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
result = createFunctionCall(node, resultTypeId);
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 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:
spirv::WriteMemoryBarrier(
mBuilder.getSpirvCurrentFunctionBlock(), mBuilder.getUintConstant(spv::ScopeDevice),
mBuilder.getUintConstant(spv::MemorySemanticsUniformMemoryMask |
spv::MemorySemanticsAcquireReleaseMask));
break;
case EOpMemoryBarrierImage:
case EOpBarrier:
spirv::WriteMemoryBarrier(
mBuilder.getSpirvCurrentFunctionBlock(), mBuilder.getUintConstant(spv::ScopeDevice),
mBuilder.getUintConstant(spv::MemorySemanticsImageMemoryMask |
spv::MemorySemanticsAcquireReleaseMask));
break;
case EOpMemoryBarrierShared:
case EOpGroupMemoryBarrier:
case EOpBarrierTCS:
// TODO: support barriers. http://anglebug.com/4889
UNIMPLEMENTED();
spirv::WriteMemoryBarrier(
mBuilder.getSpirvCurrentFunctionBlock(), mBuilder.getUintConstant(spv::ScopeDevice),
mBuilder.getUintConstant(spv::MemorySemanticsWorkgroupMemoryMask |
spv::MemorySemanticsAcquireReleaseMask));
break;
case EOpMemoryBarrierAtomicCounter:
// Atomic counters are emulated.
UNREACHABLE();
break;
case EOpEmitVertex:
......
......@@ -1028,11 +1028,11 @@ TEST_P(ComputeShaderTest, TexelFetchFunction)
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF(isSwiftshader());
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;
uniform usampler2D tex;
layout(std140, binding = 0) buffer buf {
uint outData[16][16];
uint outData[12][16];
};
void main()
......@@ -1043,7 +1043,7 @@ void main()
})";
constexpr unsigned int kWidth = 16;
constexpr unsigned int kHeight = 16;
constexpr unsigned int kHeight = 12;
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
......@@ -4580,7 +4580,7 @@ void main()
}
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);
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