Commit fcf10b62 by Qin Jiajia Committed by Commit Bot

Fix the regression bug for ComputeBoids

The old implementation missed considering compute program would also enter into applyActiveAttribLocationsMask. However, there was no bindVertexArray before updateAttribEnabled which resulted the previous VAO state was modified in unknown. And that's why ComputeBoids example wouldn't work correctly. This change adds a checking to not enter propagateProgramToVAO if it's a compute program since compute shader doesn't have vertex attributes. And an ASSERT is added to make sure that the right VAO is bound when updateAttribEnabled is called in applyActiveAttribLocationsMask. Bug: angleproject:2810 Change-Id: I6e77853498a527ef3b755bbb1da5826a9134b164 Reviewed-on: https://chromium-review.googlesource.com/c/1226227Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Jiajia Qin <jiajia.qin@intel.com>
parent 6f755b21
...@@ -1991,17 +1991,23 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt ...@@ -1991,17 +1991,23 @@ void StateManagerGL::syncState(const gl::Context *context, const gl::State::Dirt
syncTransformFeedbackState(context); syncTransformFeedbackState(context);
break; break;
case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE: case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
{
mProgramTexturesDirty = true; mProgramTexturesDirty = true;
mProgramImagesDirty = true; mProgramImagesDirty = true;
mProgramStorageBuffersDirty = true; mProgramStorageBuffersDirty = true;
mProgramUniformBuffersDirty = true; mProgramUniformBuffersDirty = true;
mProgramAtomicCounterBuffersDirty = true; mProgramAtomicCounterBuffersDirty = true;
propagateProgramToVAO(state.getProgram(), const gl::Program *program = state.getProgram();
GetImplAs<VertexArrayGL>(state.getVertexArray())); if (!(program && program->hasLinkedShaderStage(gl::ShaderType::Compute)))
updateMultiviewBaseViewLayerIndexUniform( {
state.getProgram(), propagateProgramToVAO(program,
state.getDrawFramebuffer()->getImplementation()->getState()); GetImplAs<VertexArrayGL>(state.getVertexArray()));
updateMultiviewBaseViewLayerIndexUniform(
state.getProgram(),
state.getDrawFramebuffer()->getImplementation()->getState());
}
break; break;
}
case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING: case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
mProgramStorageBuffersDirty = true; mProgramStorageBuffersDirty = true;
break; break;
......
...@@ -180,6 +180,8 @@ class StateManagerGL final : angle::NonCopyable ...@@ -180,6 +180,8 @@ class StateManagerGL final : angle::NonCopyable
const gl::Program *program, const gl::Program *program,
const gl::FramebufferState &drawFramebufferState) const; const gl::FramebufferState &drawFramebufferState) const;
GLuint getVertexArrayID() const { return mVAO; }
private: private:
// Set state that's common among draw commands and compute invocations. // Set state that's common among draw commands and compute invocations.
void setGenericShaderState(const gl::Context *context); void setGenericShaderState(const gl::Context *context);
......
...@@ -730,6 +730,11 @@ void VertexArrayGL::applyNumViewsToDivisor(int numViews) ...@@ -730,6 +730,11 @@ void VertexArrayGL::applyNumViewsToDivisor(int numViews)
void VertexArrayGL::applyActiveAttribLocationsMask(const gl::AttributesMask &activeMask) void VertexArrayGL::applyActiveAttribLocationsMask(const gl::AttributesMask &activeMask)
{ {
gl::AttributesMask updateMask = mProgramActiveAttribLocationsMask ^ activeMask; gl::AttributesMask updateMask = mProgramActiveAttribLocationsMask ^ activeMask;
if (!updateMask.any())
{
return;
}
ASSERT(mVertexArrayID == mStateManager->getVertexArrayID());
mProgramActiveAttribLocationsMask = activeMask; mProgramActiveAttribLocationsMask = activeMask;
for (size_t attribIndex : updateMask) for (size_t attribIndex : updateMask)
......
...@@ -563,8 +563,8 @@ class VertexAttributeTestES3 : public VertexAttributeTest ...@@ -563,8 +563,8 @@ class VertexAttributeTestES3 : public VertexAttributeTest
TEST_P(VertexAttributeTestES3, IntUnnormalized) TEST_P(VertexAttributeTestES3, IntUnnormalized)
{ {
GLint lo = std::numeric_limits<GLint>::min(); GLint lo = std::numeric_limits<GLint>::min();
GLint hi = std::numeric_limits<GLint>::max(); GLint hi = std::numeric_limits<GLint>::max();
std::array<GLint, kVertexCount> inputData = { std::array<GLint, kVertexCount> inputData = {
{0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}}; {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
std::array<GLfloat, kVertexCount> expectedData; std::array<GLfloat, kVertexCount> expectedData;
...@@ -579,8 +579,8 @@ TEST_P(VertexAttributeTestES3, IntUnnormalized) ...@@ -579,8 +579,8 @@ TEST_P(VertexAttributeTestES3, IntUnnormalized)
TEST_P(VertexAttributeTestES3, IntNormalized) TEST_P(VertexAttributeTestES3, IntNormalized)
{ {
GLint lo = std::numeric_limits<GLint>::min(); GLint lo = std::numeric_limits<GLint>::min();
GLint hi = std::numeric_limits<GLint>::max(); GLint hi = std::numeric_limits<GLint>::max();
std::array<GLint, kVertexCount> inputData = { std::array<GLint, kVertexCount> inputData = {
{0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}}; {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
std::array<GLfloat, kVertexCount> expectedData; std::array<GLfloat, kVertexCount> expectedData;
...@@ -595,8 +595,8 @@ TEST_P(VertexAttributeTestES3, IntNormalized) ...@@ -595,8 +595,8 @@ TEST_P(VertexAttributeTestES3, IntNormalized)
TEST_P(VertexAttributeTestES3, UnsignedIntUnnormalized) TEST_P(VertexAttributeTestES3, UnsignedIntUnnormalized)
{ {
GLuint mid = std::numeric_limits<GLuint>::max() >> 1; GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
GLuint hi = std::numeric_limits<GLuint>::max(); GLuint hi = std::numeric_limits<GLuint>::max();
std::array<GLuint, kVertexCount> inputData = { std::array<GLuint, kVertexCount> inputData = {
{0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}}; {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
std::array<GLfloat, kVertexCount> expectedData; std::array<GLfloat, kVertexCount> expectedData;
...@@ -611,8 +611,8 @@ TEST_P(VertexAttributeTestES3, UnsignedIntUnnormalized) ...@@ -611,8 +611,8 @@ TEST_P(VertexAttributeTestES3, UnsignedIntUnnormalized)
TEST_P(VertexAttributeTestES3, UnsignedIntNormalized) TEST_P(VertexAttributeTestES3, UnsignedIntNormalized)
{ {
GLuint mid = std::numeric_limits<GLuint>::max() >> 1; GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
GLuint hi = std::numeric_limits<GLuint>::max(); GLuint hi = std::numeric_limits<GLuint>::max();
std::array<GLuint, kVertexCount> inputData = { std::array<GLuint, kVertexCount> inputData = {
{0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}}; {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
std::array<GLfloat, kVertexCount> expectedData; std::array<GLfloat, kVertexCount> expectedData;
...@@ -1045,7 +1045,7 @@ class VertexAttributeTestES31 : public VertexAttributeTestES3 ...@@ -1045,7 +1045,7 @@ class VertexAttributeTestES31 : public VertexAttributeTestES3
GLint floatStride = std::max(stride / kFloatStride, 1); GLint floatStride = std::max(stride / kFloatStride, 1);
GLuint floatRelativeOffset = relativeOffset / kFloatStride; GLuint floatRelativeOffset = relativeOffset / kFloatStride;
size_t floatCount = static_cast<size_t>(floatRelativeOffset) + kVertexCount * floatStride; size_t floatCount = static_cast<size_t>(floatRelativeOffset) + kVertexCount * floatStride;
GLsizeiptr inputSize = static_cast<GLsizeiptr>(floatCount) * kFloatStride; GLsizeiptr inputSize = static_cast<GLsizeiptr>(floatCount) * kFloatStride;
std::vector<GLfloat> inputData(floatCount); std::vector<GLfloat> inputData(floatCount);
for (size_t count = 0; count < kVertexCount; ++count) for (size_t count = 0; count < kVertexCount; ++count)
...@@ -1165,6 +1165,141 @@ TEST_P(VertexAttributeTestES31, DrawArraysWithLargeRelativeOffset) ...@@ -1165,6 +1165,141 @@ TEST_P(VertexAttributeTestES31, DrawArraysWithLargeRelativeOffset)
drawArraysWithStrideAndRelativeOffset(0, largeRelativeOffset); drawArraysWithStrideAndRelativeOffset(0, largeRelativeOffset);
} }
// Test that vertex array object works correctly when render pipeline and compute pipeline are
// crossly executed.
TEST_P(VertexAttributeTestES31, MixedComputeAndRenderPipelines)
{
constexpr char kComputeShader[] =
R"(#version 310 es
layout(local_size_x=1) in;
void main()
{
})";
ANGLE_GL_COMPUTE_PROGRAM(computePogram, kComputeShader);
glViewport(0, 0, getWindowWidth(), getWindowHeight());
glClearColor(0, 0, 0, 0);
constexpr char kVertexShader[] =
R"(#version 310 es
precision mediump float;
layout(location = 0) in vec4 position;
layout(location = 2) in vec2 aOffset;
layout(location = 3) in vec4 aColor;
out vec4 vColor;
void main() {
vColor = aColor;
gl_Position = position + vec4(aOffset, 0.0, 0.0);
})";
constexpr char kFragmentShader[] =
R"(#version 310 es
precision mediump float;
in vec4 vColor;
out vec4 color;
void main() {
color = vColor;
})";
ANGLE_GL_PROGRAM(renderProgram, kVertexShader, kFragmentShader);
constexpr char kVertexShader1[] =
R"(#version 310 es
precision mediump float;
layout(location = 1) in vec4 position;
layout(location = 2) in vec2 aOffset;
layout(location = 3) in vec4 aColor;
out vec4 vColor;
void main() {
vColor = aColor;
gl_Position = position + vec4(aOffset, 0.0, 0.0);
})";
ANGLE_GL_PROGRAM(renderProgram1, kVertexShader1, kFragmentShader);
std::array<GLfloat, 8> offsets = {
-1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0,
};
GLBuffer offsetBuffer;
glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
glBufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(GLfloat), offsets.data(), GL_STATIC_DRAW);
std::array<GLfloat, 16> colors0 = {
1.0, 0.0, 0.0, 1.0, // Red
0.0, 1.0, 0.0, 1.0, // Green
0.0, 0.0, 1.0, 1.0, // Blue
1.0, 1.0, 0.0, 1.0, // Yellow
};
std::array<GLfloat, 16> colors1 = {
1.0, 1.0, 0.0, 1.0, // Yellow
0.0, 0.0, 1.0, 1.0, // Blue
0.0, 1.0, 0.0, 1.0, // Green
1.0, 0.0, 0.0, 1.0, // Red
};
GLBuffer colorBuffers[2];
glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[0]);
glBufferData(GL_ARRAY_BUFFER, colors0.size() * sizeof(GLfloat), colors0.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[1]);
glBufferData(GL_ARRAY_BUFFER, colors1.size() * sizeof(GLfloat), colors1.data(), GL_STATIC_DRAW);
std::array<GLfloat, 16> positions = {1.0, 1.0, -1.0, 1.0, -1.0, -1.0,
1.0, 1.0, -1.0, -1.0, 1.0, -1.0};
GLBuffer positionBuffer;
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(GLfloat), positions.data(),
GL_STATIC_DRAW);
const int kInstanceCount = 4;
GLVertexArray vao[2];
for (size_t i = 0u; i < 2u; ++i)
{
glBindVertexArray(vao[i]);
glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
glVertexAttribDivisor(2, 1);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, false, 0, 0);
glVertexAttribDivisor(3, 1);
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glEnableVertexAttribArray(i);
glVertexAttribPointer(i, 2, GL_FLOAT, false, 0, 0);
}
glClear(GL_COLOR_BUFFER_BIT);
for (int i = 0; i < 3; i++)
{
glUseProgram(renderProgram.get());
glBindVertexArray(vao[0]);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::yellow);
glBindVertexArray(vao[1]);
glUseProgram(computePogram.get());
glDispatchCompute(1, 1, 1);
glUseProgram(renderProgram1.get());
glBindVertexArray(vao[1]);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::yellow);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
}
}
// 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