Commit 49c9dfe3 by Qin Jiajia Committed by Commit Bot

Fix the SSBO sync bug in two dispatch calls

We should make sure that the raw buffer is the latest buffer before each dispatch call since the dispatch itself can update the raw buffer content. Bug: angleproject:3037 Change-Id: I75dddfd3e57b3c9cbcc58c02ed057c66cc8e1785 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1392379Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jiajia Qin <jiajia.qin@intel.com>
parent b6a2f6bc
...@@ -557,16 +557,7 @@ angle::Result Buffer11::unmap(const gl::Context *context, GLboolean *result) ...@@ -557,16 +557,7 @@ angle::Result Buffer11::unmap(const gl::Context *context, GLboolean *result)
angle::Result Buffer11::markTransformFeedbackUsage(const gl::Context *context) angle::Result Buffer11::markTransformFeedbackUsage(const gl::Context *context)
{ {
BufferStorage *transformFeedbackStorage = nullptr; ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK));
ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK,
&transformFeedbackStorage));
if (transformFeedbackStorage)
{
onStorageUpdate(transformFeedbackStorage);
}
invalidateStaticData(context);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -628,6 +619,20 @@ void Buffer11::markBufferUsage(BufferUsage usage) ...@@ -628,6 +619,20 @@ void Buffer11::markBufferUsage(BufferUsage usage)
mIdleness[usage] = 0; mIdleness[usage] = 0;
} }
angle::Result Buffer11::markBufferUsage(const gl::Context *context, BufferUsage usage)
{
BufferStorage *bufferStorage = nullptr;
ANGLE_TRY(getBufferStorage(context, usage, &bufferStorage));
if (bufferStorage)
{
onStorageUpdate(bufferStorage);
}
invalidateStaticData(context);
return angle::Result::Continue;
}
angle::Result Buffer11::garbageCollection(const gl::Context *context, BufferUsage currentUsage) angle::Result Buffer11::garbageCollection(const gl::Context *context, BufferUsage currentUsage)
{ {
if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory()) if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory())
...@@ -696,6 +701,12 @@ angle::Result Buffer11::getConstantBufferRange(const gl::Context *context, ...@@ -696,6 +701,12 @@ angle::Result Buffer11::getConstantBufferRange(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result Buffer11::markRawBufferUsage(const gl::Context *context)
{
ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_RAW_UAV));
return angle::Result::Continue;
}
angle::Result Buffer11::getRawUAVRange(const gl::Context *context, angle::Result Buffer11::getRawUAVRange(const gl::Context *context,
GLintptr offset, GLintptr offset,
GLsizeiptr size, GLsizeiptr size,
...@@ -704,14 +715,6 @@ angle::Result Buffer11::getRawUAVRange(const gl::Context *context, ...@@ -704,14 +715,6 @@ angle::Result Buffer11::getRawUAVRange(const gl::Context *context,
NativeStorage *nativeStorage = nullptr; NativeStorage *nativeStorage = nullptr;
ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_RAW_UAV, &nativeStorage)); ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_RAW_UAV, &nativeStorage));
BufferStorage *latestBuffer = nullptr;
ANGLE_TRY(getLatestBufferStorage(context, &latestBuffer));
// As UAVs could have been updated by the shader, they hold the latest version of the data.
if (latestBuffer != nativeStorage)
{
onStorageUpdate(nativeStorage);
}
return nativeStorage->getRawUAV(context, static_cast<unsigned int>(offset), return nativeStorage->getRawUAV(context, static_cast<unsigned int>(offset),
static_cast<unsigned int>(size), uavOut); static_cast<unsigned int>(size), uavOut);
} }
......
...@@ -75,6 +75,7 @@ class Buffer11 : public BufferD3D ...@@ -75,6 +75,7 @@ class Buffer11 : public BufferD3D
GLsizeiptr size, GLsizeiptr size,
d3d11::UnorderedAccessView **uavOut); d3d11::UnorderedAccessView **uavOut);
angle::Result markRawBufferUsage(const gl::Context *context);
bool isMapped() const { return mMappedStorage != nullptr; } bool isMapped() const { return mMappedStorage != nullptr; }
angle::Result packPixels(const gl::Context *context, angle::Result packPixels(const gl::Context *context,
const gl::FramebufferAttachment &readAttachment, const gl::FramebufferAttachment &readAttachment,
...@@ -129,6 +130,7 @@ class Buffer11 : public BufferD3D ...@@ -129,6 +130,7 @@ class Buffer11 : public BufferD3D
}; };
void markBufferUsage(BufferUsage usage); void markBufferUsage(BufferUsage usage);
angle::Result markBufferUsage(const gl::Context *context, BufferUsage usage);
angle::Result garbageCollection(const gl::Context *context, BufferUsage currentUsage); angle::Result garbageCollection(const gl::Context *context, BufferUsage currentUsage);
angle::Result updateBufferStorage(const gl::Context *context, angle::Result updateBufferStorage(const gl::Context *context,
......
...@@ -3734,6 +3734,14 @@ angle::Result Renderer11::dispatchCompute(const gl::Context *context, ...@@ -3734,6 +3734,14 @@ angle::Result Renderer11::dispatchCompute(const gl::Context *context,
GLuint numGroupsY, GLuint numGroupsY,
GLuint numGroupsZ) GLuint numGroupsZ)
{ {
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
if (program->getActiveShaderStorageBlockCount() > 0 ||
program->getActiveAtomicCounterBufferCount() > 0)
{
ANGLE_TRY(markRawBufferUsage(context));
}
ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ)); ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ));
mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ); mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
...@@ -3742,6 +3750,13 @@ angle::Result Renderer11::dispatchCompute(const gl::Context *context, ...@@ -3742,6 +3750,13 @@ angle::Result Renderer11::dispatchCompute(const gl::Context *context,
angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{ {
const auto &glState = context->getState(); const auto &glState = context->getState();
const gl::Program *program = glState.getProgram();
if (program->getActiveShaderStorageBlockCount() > 0 ||
program->getActiveAtomicCounterBufferCount() > 0)
{
ANGLE_TRY(markRawBufferUsage(context));
}
auto *dispatchIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DispatchIndirect); auto *dispatchIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DispatchIndirect);
ASSERT(dispatchIndirectBuffer); ASSERT(dispatchIndirectBuffer);
...@@ -3925,6 +3940,36 @@ angle::Result Renderer11::mapResource(const gl::Context *context, ...@@ -3925,6 +3940,36 @@ angle::Result Renderer11::mapResource(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result Renderer11::markRawBufferUsage(const gl::Context *context)
{
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
blockIndex++)
{
GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
if (shaderStorageBuffer.get() != nullptr)
{
Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
ANGLE_TRY(bufferStorage->markRawBufferUsage(context));
}
}
for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
{
GLuint binding = atomicCounterBuffer.binding;
const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
if (buffer.get() != nullptr)
{
Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get());
ANGLE_TRY(bufferStorage->markRawBufferUsage(context));
}
}
return angle::Result::Continue;
}
angle::Result Renderer11::markTransformFeedbackUsage(const gl::Context *context) angle::Result Renderer11::markTransformFeedbackUsage(const gl::Context *context)
{ {
const gl::State &glState = context->getState(); const gl::State &glState = context->getState();
......
...@@ -549,6 +549,8 @@ class Renderer11 : public RendererD3D ...@@ -549,6 +549,8 @@ class Renderer11 : public RendererD3D
d3d11::ANGLED3D11DeviceType getDeviceType() const; d3d11::ANGLED3D11DeviceType getDeviceType() const;
// Make sure that the raw buffer is the latest buffer.
angle::Result markRawBufferUsage(const gl::Context *context);
angle::Result markTransformFeedbackUsage(const gl::Context *context); angle::Result markTransformFeedbackUsage(const gl::Context *context);
angle::Result drawWithGeometryShaderAndTransformFeedback(Context11 *context11, angle::Result drawWithGeometryShaderAndTransformFeedback(Context11 *context11,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
......
...@@ -2489,9 +2489,6 @@ void main() ...@@ -2489,9 +2489,6 @@ void main()
// Test storage buffer bound is unchanged, shader writes it, buffer content should be updated. // Test storage buffer bound is unchanged, shader writes it, buffer content should be updated.
TEST_P(ComputeShaderTest, StorageBufferBoundUnchanged) TEST_P(ComputeShaderTest, StorageBufferBoundUnchanged)
{ {
// TODO(xinghua.cao@intel.com): Fix this. http://anglebug.com/3037
ANGLE_SKIP_TEST_IF(IsD3D11());
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=16) in;
precision highp usampler2D; precision highp usampler2D;
......
...@@ -1317,6 +1317,66 @@ void main() { ...@@ -1317,6 +1317,66 @@ void main() {
} }
} }
TEST_P(VertexAttributeTestES31, UseComputeShaderToUpdateVertexBuffer)
{
initTest();
constexpr char kComputeShader[] =
R"(#version 310 es
layout(local_size_x=24) in;
layout(std430, binding = 0) buffer buf {
uint outData[24];
};
void main()
{
outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
})";
ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
glUseProgram(mProgram);
GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
GLuint hi = std::numeric_limits<GLuint>::max();
std::array<GLuint, kVertexCount> inputData = {
{0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
std::array<GLfloat, kVertexCount> expectedData;
for (size_t i = 0; i < kVertexCount; i++)
{
expectedData[i] = Normalize(inputData[i]);
}
// Normalized unsigned int attribute will be classified as translated static attribute.
TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
GLint typeSize = 4;
GLsizei dataSize = kVertexCount * TypeStride(data.type);
GLBuffer testBuffer;
glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
reinterpret_cast<void *>(data.bufferOffset));
glEnableVertexAttribArray(mTestAttrib);
glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
// Draw twice to make sure that all static attributes dirty bits are synced.
glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawArrays(GL_TRIANGLES, 0, 6);
checkPixels();
// Modify the testBuffer using a raw buffer
glUseProgram(computeProgram);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
// Draw again to verify that testBuffer has been changed.
glUseProgram(mProgram);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_NO_ERROR();
checkPixelsUnEqual();
}
// Verify that using VertexAttribBinding after VertexAttribPointer won't mess up the draw. // Verify that using VertexAttribBinding after VertexAttribPointer won't mess up the draw.
TEST_P(VertexAttributeTestES31, ChangeAttribBindingAfterVertexAttribPointer) TEST_P(VertexAttributeTestES31, ChangeAttribBindingAfterVertexAttribPointer)
{ {
......
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