ES31: Enable atomic counter for GL backend
This simply translates the offset qualifier and synchronizes
the buffer binding state for GL translator and renderer.
BUG=angleproject:1729
TEST=angle_end2end_tests:AtomicCounterBufferTest31
Change-Id: Ib8424918478ae4c47049d5856ea20ef022f12913
Reviewed-on: https://chromium-review.googlesource.com/575913
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/common/utilities.cpp b/src/common/utilities.cpp
index d0db43e..156bbfb 100644
--- a/src/common/utilities.cpp
+++ b/src/common/utilities.cpp
@@ -711,7 +711,20 @@
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_2D_ARRAY_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
- return 6;
+ case GL_IMAGE_2D:
+ case GL_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE:
+ case GL_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_ATOMIC_COUNTER:
+ return 6;
default:
UNREACHABLE();
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 976ce4c..b7aacee 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -246,6 +246,11 @@
}
}
+ if (IsAtomicCounter(type.getBasicType()))
+ {
+ out << listItemPrefix << "offset = " << layoutQualifier.offset;
+ }
+
out << ") ";
}
diff --git a/src/compiler/translator/Types.cpp b/src/compiler/translator/Types.cpp
index 2dd55ac..122be15 100644
--- a/src/compiler/translator/Types.cpp
+++ b/src/compiler/translator/Types.cpp
@@ -417,6 +417,9 @@
case EbtUImageCube:
mangledName += "uimc";
break;
+ case EbtAtomicCounter:
+ mangledName += "ac";
+ break;
case EbtStruct:
mangledName += structure->mangledName();
break;
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp
index ecb0b0e..dc65646 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -139,6 +139,7 @@
mTextures[GL_TEXTURE_2D_MULTISAMPLE].resize(rendererCaps.maxCombinedTextureImageUnits);
mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks);
+ mIndexedBuffers[GL_ATOMIC_COUNTER_BUFFER].resize(rendererCaps.maxCombinedAtomicCounterBuffers);
for (GLenum queryType : QueryTypes)
{
@@ -900,6 +901,27 @@
}
}
}
+
+ for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
+ {
+ GLuint binding = atomicCounterBuffer.binding;
+ const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
+
+ if (buffer.get() != nullptr)
+ {
+ BufferGL *bufferGL = GetImplAs<BufferGL>(buffer.get());
+
+ if (buffer.getSize() == 0)
+ {
+ bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, binding, bufferGL->getBufferID());
+ }
+ else
+ {
+ bindBufferRange(GL_ATOMIC_COUNTER_BUFFER, binding, bufferGL->getBufferID(),
+ buffer.getOffset(), buffer.getSize());
+ }
+ }
+ }
}
gl::Error StateManagerGL::setGenericDrawState(const gl::Context *context)
diff --git a/src/tests/gl_tests/AtomicCounterBufferTest.cpp b/src/tests/gl_tests/AtomicCounterBufferTest.cpp
index ff485a5..e8c0194 100644
--- a/src/tests/gl_tests/AtomicCounterBufferTest.cpp
+++ b/src/tests/gl_tests/AtomicCounterBufferTest.cpp
@@ -113,6 +113,86 @@
EXPECT_EQ(0u, program);
}
+// Test atomic counter read.
+TEST_P(AtomicCounterBufferTest31, AtomicCounterRead)
+{
+ const std::string &vertShader =
+ "#version 310 es\n"
+ "precision highp float;\n"
+ "in highp vec4 a_position;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = a_position;\n"
+ "}\n";
+
+ const std::string &fragShader =
+ "#version 310 es\n"
+ "precision highp float;\n"
+ "layout(binding = 2, offset = 4) uniform atomic_uint ac;\n"
+ "out highp vec4 my_color;\n"
+ "void main()\n"
+ "{\n"
+ " my_color = vec4(0.0);\n"
+ " uint a1 = atomicCounter(ac);\n"
+ " if (a1 == 3u) my_color = vec4(1.0);\n"
+ "}\n";
+
+ ANGLE_GL_PROGRAM(program, vertShader, fragShader);
+
+ glUseProgram(program.get());
+
+ // The initial value of counter 'ac' is 3u.
+ unsigned int bufferData[3] = {11u, 3u, 1u};
+ GLBuffer atomicCounterBuffer;
+ glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
+ glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
+
+ glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, atomicCounterBuffer);
+
+ drawQuad(program.get(), "a_position", 0.0f);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
+}
+
+// Test atomic counter increment and decrement.
+TEST_P(AtomicCounterBufferTest31, AtomicCounterIncrementAndDecrement)
+{
+ const std::string &csSource =
+ "#version 310 es\n"
+ "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
+ "layout(binding = 2, offset = 4) uniform atomic_uint ac[2];\n"
+ "void main()\n"
+ "{\n"
+ " atomicCounterIncrement(ac[0]);\n"
+ " atomicCounterDecrement(ac[1]);\n"
+ "}\n";
+
+ ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
+
+ glUseProgram(program.get());
+
+ // The initial value of 'ac[0]' is 3u, 'ac[1]' is 1u.
+ unsigned int bufferData[3] = {11u, 3u, 1u};
+ GLBuffer atomicCounterBuffer;
+ glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
+ glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
+
+ glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, atomicCounterBuffer);
+
+ glDispatchCompute(1, 1, 1);
+ EXPECT_GL_NO_ERROR();
+
+ glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
+ void *mappedBuffer =
+ glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
+ memcpy(bufferData, mappedBuffer, sizeof(bufferData));
+ glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
+
+ EXPECT_EQ(11u, bufferData[0]);
+ EXPECT_EQ(4u, bufferData[1]);
+ EXPECT_EQ(0u, bufferData[2]);
+}
+
ANGLE_INSTANTIATE_TEST(AtomicCounterBufferTest,
ES3_OPENGL(),
ES3_OPENGLES(),