зеркало из https://github.com/AvaloniaUI/angle.git
D3D11: fix for atomic assigned to an SSBO.
When assigning the previous value of an atomic op to an SSBO, we do not want to use the "direct assignment" path, since we can't pass the SSBO expression as an argument to Interlocked*(). Instead, we change the RewriteAtomicFunctionExpressions transform not to defer assignments until HLSL output if the LHS is an SSBO expression, and to do its usual creation of a temporary for the previous value of the atomic op. In OutputHLSL, we skip the direct assignment path if the LHS is an SSBO expression. Bug: angleproject:8182 Change-Id: I0707f4f69757119fe5c8f8e7a12bd26025ec74e6 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4573827 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Родитель
721c15efaa
Коммит
e60f64ddb9
|
@ -150,7 +150,8 @@ bool IsAtomicFunctionForSharedVariableDirectAssign(const TIntermBinary &node)
|
|||
|
||||
if (node.getOp() == EOpAssign && BuiltInGroup::IsAtomicMemory(aggregateNode->getOp()))
|
||||
{
|
||||
return !IsInShaderStorageBlock((*aggregateNode->getSequence())[0]->getAsTyped());
|
||||
return !IsInShaderStorageBlock((*aggregateNode->getSequence())[0]->getAsTyped()) &&
|
||||
!IsInShaderStorageBlock(node.getLeft());
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -133,7 +133,8 @@ bool RewriteAtomicFunctionExpressionsTraverser::IsAtomicFunctionInsideExpression
|
|||
|
||||
auto *parentAsBinary = parentNode->getAsBinaryNode();
|
||||
// Assignments are handled in OutputHLSL
|
||||
return !parentAsBinary || parentAsBinary->getOp() != EOpAssign;
|
||||
return !parentAsBinary || (parentAsBinary->getOp() != EOpAssign ||
|
||||
IsInShaderStorageBlock(parentAsBinary->getLeft()));
|
||||
}
|
||||
|
||||
bool RewriteAtomicFunctionExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
|
|
|
@ -5335,6 +5335,61 @@ TEST_P(ComputeShaderTest, SSBOAliasOverWrite)
|
|||
EXPECT_EQ(false, error);
|
||||
}
|
||||
|
||||
// Performs an atomic operation and assigns the previous value to an SSBO.
|
||||
TEST_P(ComputeShaderTest, AtomicOpPreviousValueAssignedToSSBO)
|
||||
{
|
||||
|
||||
constexpr char kCSSource[] = R"(#version 310 es
|
||||
shared int wg;
|
||||
layout(binding = 0, std430) buffer Storage0 {
|
||||
int inner[16];
|
||||
} buf;
|
||||
|
||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
void main() {
|
||||
wg = 0;
|
||||
atomicExchange(wg, 0);
|
||||
barrier();
|
||||
buf.inner[gl_WorkGroupID.x] = atomicOr(wg, 1);
|
||||
})";
|
||||
|
||||
const int dispatchSize = 16;
|
||||
|
||||
// define compute shader output buffer
|
||||
const int outputBufferSizeInBytes = dispatchSize * sizeof(int32_t);
|
||||
const int outputBufferElementsCount = dispatchSize;
|
||||
std::vector<int32_t> minusOnes(outputBufferElementsCount, -1);
|
||||
GLBuffer resultBuffer;
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, outputBufferSizeInBytes, &minusOnes[0], GL_STATIC_DRAW);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
|
||||
glUseProgram(csProgram);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Bind storage buffer to compute shader binding locations
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, resultBuffer);
|
||||
|
||||
glDispatchCompute(dispatchSize, 1, 1);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// verify the result
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
|
||||
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
|
||||
void *mappedResults =
|
||||
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outputBufferSizeInBytes, GL_MAP_READ_BIT);
|
||||
std::vector<int32_t> results(outputBufferElementsCount);
|
||||
memcpy(results.data(), mappedResults, outputBufferSizeInBytes);
|
||||
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
for (int index = 0; index < static_cast<int>(results.size()); ++index)
|
||||
{
|
||||
EXPECT_EQ(results[index], 0);
|
||||
}
|
||||
}
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTest);
|
||||
ANGLE_INSTANTIATE_TEST_ES31(ComputeShaderTest);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче