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)
angle::Result Buffer11::markTransformFeedbackUsage(const gl::Context *context)
{
BufferStorage *transformFeedbackStorage = nullptr;
ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK,
&transformFeedbackStorage));
if (transformFeedbackStorage)
{
onStorageUpdate(transformFeedbackStorage);
}
invalidateStaticData(context);
ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK));
return angle::Result::Continue;
}
......@@ -628,6 +619,20 @@ void Buffer11::markBufferUsage(BufferUsage usage)
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)
{
if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory())
......@@ -696,6 +701,12 @@ angle::Result Buffer11::getConstantBufferRange(const gl::Context *context,
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,
GLintptr offset,
GLsizeiptr size,
......@@ -704,14 +715,6 @@ angle::Result Buffer11::getRawUAVRange(const gl::Context *context,
NativeStorage *nativeStorage = nullptr;
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),
static_cast<unsigned int>(size), uavOut);
}
......
......@@ -75,6 +75,7 @@ class Buffer11 : public BufferD3D
GLsizeiptr size,
d3d11::UnorderedAccessView **uavOut);
angle::Result markRawBufferUsage(const gl::Context *context);
bool isMapped() const { return mMappedStorage != nullptr; }
angle::Result packPixels(const gl::Context *context,
const gl::FramebufferAttachment &readAttachment,
......@@ -129,6 +130,7 @@ class Buffer11 : public BufferD3D
};
void markBufferUsage(BufferUsage usage);
angle::Result markBufferUsage(const gl::Context *context, BufferUsage usage);
angle::Result garbageCollection(const gl::Context *context, BufferUsage currentUsage);
angle::Result updateBufferStorage(const gl::Context *context,
......
......@@ -3734,6 +3734,14 @@ angle::Result Renderer11::dispatchCompute(const gl::Context *context,
GLuint numGroupsY,
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));
mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
......@@ -3742,6 +3750,13 @@ angle::Result Renderer11::dispatchCompute(const gl::Context *context,
angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
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);
ASSERT(dispatchIndirectBuffer);
......@@ -3925,6 +3940,36 @@ angle::Result Renderer11::mapResource(const gl::Context *context,
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)
{
const gl::State &glState = context->getState();
......
......@@ -549,6 +549,8 @@ class Renderer11 : public RendererD3D
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 drawWithGeometryShaderAndTransformFeedback(Context11 *context11,
gl::PrimitiveMode mode,
......
......@@ -2489,9 +2489,6 @@ void main()
// Test storage buffer bound is unchanged, shader writes it, buffer content should be updated.
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
layout(local_size_x=16, local_size_y=16) in;
precision highp usampler2D;
......
......@@ -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.
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