| // |
| // Copyright 2021 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // MemoryBarrierTest: |
| // Ensure that implementation of glMemoryBarrier is correct both in terms of memory barriers |
| // issued and potential reordering of commands. |
| // |
| // The barrier bits accepted by glMemoryBarrier are used for synchronization as such: |
| // |
| // VERTEX_ATTRIB_ARRAY_BARRIER_BIT: shader write -> vertex read |
| // ELEMENT_ARRAY_BARRIER_BIT: shader write -> index read |
| // UNIFORM_BARRIER_BIT: shader write -> uniform read |
| // TEXTURE_FETCH_BARRIER_BIT: shader write -> texture sample |
| // SHADER_IMAGE_ACCESS_BARRIER_BIT: shader write -> image access |
| // any access -> image write |
| // COMMAND_BARRIER_BIT: shader write -> indirect buffer read |
| // PIXEL_BUFFER_BARRIER_BIT: shader write -> pbo access |
| // TEXTURE_UPDATE_BARRIER_BIT: shader write -> texture data upload |
| // BUFFER_UPDATE_BARRIER_BIT: shader write -> buffer data upload/map |
| // FRAMEBUFFER_BARRIER_BIT: shader write -> access through framebuffer |
| // TRANSFORM_FEEDBACK_BARRIER_BIT: shader write -> transform feedback write |
| // ATOMIC_COUNTER_BARRIER_BIT: shader write -> atomic counter access |
| // SHADER_STORAGE_BARRIER_BIT: shader write -> buffer access |
| // any access -> buffer write |
| // |
| // In summary, every bit defines a memory barrier for some access after a shader write. |
| // Additionally, SHADER_IMAGE_ACCESS_BARRIER_BIT and SHADER_STORAGE_BARRIER_BIT bits are used to |
| // define a memory barrier for shader writes after other accesses. |
| |
| #include "test_utils/ANGLETest.h" |
| #include "test_utils/gl_raii.h" |
| #include "util/random_utils.h" |
| |
| using namespace angle; |
| |
| namespace |
| { |
| enum class ShaderWritePipeline |
| { |
| Graphics, |
| Compute, |
| }; |
| |
| enum class WriteResource |
| { |
| Image, |
| ImageBuffer, |
| Buffer, |
| }; |
| |
| enum class NoopOp |
| { |
| None, |
| Draw, |
| Dispatch, |
| }; |
| |
| // Variations corresponding to enums above. |
| using MemoryBarrierVariationsTestParams = |
| std::tuple<angle::PlatformParameters, ShaderWritePipeline, WriteResource, NoopOp, NoopOp>; |
| |
| void ParseMemoryBarrierVariationsTestParams(const MemoryBarrierVariationsTestParams ¶ms, |
| ShaderWritePipeline *writePipelineOut, |
| WriteResource *writeResourceOut, |
| NoopOp *preBarrierOpOut, |
| NoopOp *postBarrierOpOut) |
| { |
| *writePipelineOut = std::get<1>(params); |
| *writeResourceOut = std::get<2>(params); |
| *preBarrierOpOut = std::get<3>(params); |
| *postBarrierOpOut = std::get<4>(params); |
| } |
| |
| std::string MemoryBarrierVariationsTestPrint( |
| const ::testing::TestParamInfo<MemoryBarrierVariationsTestParams> ¶msInfo) |
| { |
| const MemoryBarrierVariationsTestParams ¶ms = paramsInfo.param; |
| std::ostringstream out; |
| |
| out << std::get<0>(params); |
| |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| |
| ParseMemoryBarrierVariationsTestParams(params, &writePipeline, &writeResource, &preBarrierOp, |
| &postBarrierOp); |
| |
| out << "_"; |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| out << "_graphics"; |
| } |
| else |
| { |
| out << "_compute"; |
| } |
| |
| switch (writeResource) |
| { |
| case WriteResource::Image: |
| out << "_image"; |
| break; |
| case WriteResource::Buffer: |
| out << "_buffer"; |
| break; |
| case WriteResource::ImageBuffer: |
| out << "_imagebuffer"; |
| break; |
| } |
| |
| if (preBarrierOp == NoopOp::Draw) |
| { |
| out << "_prebarrierNoopDraw"; |
| } |
| else if (preBarrierOp == NoopOp::Dispatch) |
| { |
| out << "_prebarrierNoopDispatch"; |
| } |
| |
| if (postBarrierOp == NoopOp::Draw) |
| { |
| out << "_postbarrierNoopDraw"; |
| } |
| else if (postBarrierOp == NoopOp::Dispatch) |
| { |
| out << "_postbarrierNoopDispatch"; |
| } |
| |
| return out.str(); |
| } |
| |
| class MemoryBarrierTestBase |
| { |
| protected: |
| bool hasExtensions(WriteResource writeResource); |
| |
| // Helper functions |
| void createFramebuffer(GLuint color, GLuint fbo, GLColor initialColor); |
| void createStorageBuffer(WriteResource writeResource, |
| GLuint buffer, |
| GLuint textureBuffer, |
| size_t size, |
| const void *initialData); |
| void createStorageImage(WriteResource writeResource, |
| GLuint bufferStorage, |
| GLuint texture, |
| const std::array<float, 4> &initialData); |
| void createProgram(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| GLProgram *programOut); |
| void createNoopGraphicsProgram(GLProgram *programOut); |
| void createNoopComputeProgram(GLProgram *programOut); |
| void createQuadVertexArray(GLuint positionBuffer); |
| void setupVertexArray(ShaderWritePipeline writePipeline, GLuint program); |
| void setUniformData(GLuint program, const std::array<float, 4> &data); |
| void noopOp(NoopOp op); |
| |
| template <typename T> |
| void verifyBufferContents(const std::array<T, 4> &expected); |
| |
| void verifyImageContents(GLuint texture, const std::array<float, 4> &expected); |
| |
| template <typename T> |
| void verifyFramebufferAndBufferContents(ShaderWritePipeline writePipeline, |
| const std::array<T, 4> &expected); |
| |
| void verifyFramebufferAndImageContents(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| GLuint texture, |
| const std::array<float, 4> &expected); |
| |
| // Barrier bits affecting only buffers and imageBuffers |
| void createVertexVerifyProgram(GLuint vertexBuffer, GLProgram *programOut); |
| void vertexAttribArrayBitBufferWriteThenVertexRead(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void vertexAttribArrayBitVertexReadThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void createIndexVerifyProgram(GLuint indexBuffer, GLProgram *programOut); |
| void elementArrayBitBufferWriteThenIndexRead(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void elementArrayBitIndexReadThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void createUBOVerifyProgram(GLuint buffer, GLProgram *programOut); |
| void uniformBitBufferWriteThenUBORead(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void uniformBitUBOReadThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void createIndirectVerifyProgram(GLuint buffer, GLProgram *programOut); |
| void commandBitBufferWriteThenIndirectRead(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void commandBitIndirectReadThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void pixelBufferBitBufferWriteThenPack(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void pixelBufferBitBufferWriteThenUnpack(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void pixelBufferBitPackThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| void pixelBufferBitUnpackThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void bufferUpdateBitBufferWriteThenCopy(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void bufferUpdateBitCopyThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void createXfbVerifyProgram(GLuint buffer, GLProgram *programOut); |
| void transformFeedbackBitBufferWriteThenCapture(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void transformFeedbackBitCaptureThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void createAtomicCounterVerifyProgram(GLuint buffer, GLProgram *programOut); |
| void atomicCounterBitBufferWriteThenAtomic(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void atomicCounterBitAtomicThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void createSsboVerifyProgram(WriteResource writeResourcee, GLProgram *programOut); |
| void shaderStorageBitBufferWriteThenBufferRead(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void shaderStorageBitBufferReadThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| // Barrier bits affecting only images and imageBuffers |
| void createTextureVerifyProgram(WriteResource writeResource, |
| GLuint texture, |
| GLProgram *programOut); |
| void textureFetchBitImageWriteThenSamplerRead(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void textureFetchBitSamplerReadThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void createImageVerifyProgram(WriteResource writeResource, |
| GLuint texture, |
| GLProgram *programOut); |
| void shaderImageAccessBitImageWriteThenImageRead(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void shaderImageAccessBitImageReadThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| |
| // Barrier bits affecting only images |
| void textureUpdateBitImageWriteThenCopy(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void textureUpdateBitCopyThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| void framebufferBitImageWriteThenDraw(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void framebufferBitImageWriteThenReadPixels(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void framebufferBitImageWriteThenCopy(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void framebufferBitImageWriteThenBlit(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp); |
| void framebufferBitDrawThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| void framebufferBitReadPixelsThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| void framebufferBitCopyThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| void framebufferBitBlitThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit); |
| |
| static constexpr int kTextureSize = 1; |
| static constexpr char kUniformName[] = "uniformData"; |
| }; |
| |
| // Can be removed with C++17 |
| constexpr char MemoryBarrierTestBase::kUniformName[]; |
| |
| bool MemoryBarrierTestBase::hasExtensions(WriteResource writeResource) |
| { |
| return writeResource != WriteResource::ImageBuffer || |
| IsGLExtensionEnabled("GL_OES_texture_buffer"); |
| } |
| |
| void MemoryBarrierTestBase::createFramebuffer(GLuint color, GLuint fbo, GLColor initialColor) |
| { |
| glBindTexture(GL_TEXTURE_2D, color); |
| glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureSize, kTextureSize); |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureSize, kTextureSize, GL_RGBA, GL_UNSIGNED_BYTE, |
| &initialColor); |
| EXPECT_GL_NO_ERROR(); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); |
| EXPECT_GL_NO_ERROR(); |
| |
| // Ensure all staged data is flushed. |
| EXPECT_PIXEL_COLOR_EQ(0, 0, initialColor); |
| } |
| |
| void MemoryBarrierTestBase::createStorageBuffer(WriteResource writeResource, |
| GLuint buffer, |
| GLuint textureBuffer, |
| size_t size, |
| const void *initialData) |
| { |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, size, initialData, GL_STATIC_DRAW); |
| glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer); |
| EXPECT_GL_NO_ERROR(); |
| |
| if (writeResource == WriteResource::ImageBuffer) |
| { |
| glBindTexture(GL_TEXTURE_BUFFER, textureBuffer); |
| glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA32F, buffer); |
| glBindImageTexture(0, textureBuffer, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); |
| EXPECT_GL_NO_ERROR(); |
| } |
| } |
| |
| void MemoryBarrierTestBase::createStorageImage(WriteResource writeResource, |
| GLuint bufferStorage, |
| GLuint texture, |
| const std::array<float, 4> &initialData) |
| { |
| const std::array<uint8_t, 4> initialDataAsUnorm = { |
| static_cast<uint8_t>(initialData[0] * 255), |
| static_cast<uint8_t>(initialData[1] * 255), |
| static_cast<uint8_t>(initialData[2] * 255), |
| static_cast<uint8_t>(initialData[3] * 255), |
| }; |
| |
| if (writeResource == WriteResource::ImageBuffer) |
| { |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferStorage); |
| glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(initialData), initialData.data(), |
| GL_STATIC_DRAW); |
| EXPECT_GL_NO_ERROR(); |
| |
| glBindTexture(GL_TEXTURE_BUFFER, texture); |
| glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA32F, bufferStorage); |
| glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); |
| EXPECT_GL_NO_ERROR(); |
| } |
| else |
| { |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureSize, kTextureSize); |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureSize, kTextureSize, GL_RGBA, |
| GL_UNSIGNED_BYTE, initialDataAsUnorm.data()); |
| glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); |
| } |
| } |
| |
| void MemoryBarrierTestBase::createProgram(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| GLProgram *programOut) |
| { |
| constexpr char kGraphicsImageFS[] = R"(#version 310 es |
| precision mediump float; |
| layout(rgba8, binding = 0) uniform highp writeonly image2D dst; |
| uniform vec4 uniformData; |
| out vec4 colorOut; |
| void main() |
| { |
| colorOut = vec4(0, 0, 1.0, 1.0); |
| imageStore(dst, ivec2(gl_FragCoord.xy), uniformData); |
| })"; |
| |
| constexpr char kGraphicsBufferFS[] = R"(#version 310 es |
| precision mediump float; |
| uniform vec4 uniformData; |
| layout(std430, binding = 0) buffer block { |
| vec4 data; |
| } outBlock; |
| out vec4 colorOut; |
| void main() |
| { |
| colorOut = vec4(0, 0, 1.0, 1.0); |
| outBlock.data = uniformData; |
| } |
| )"; |
| |
| constexpr char kGraphicsImageBufferFS[] = R"(#version 310 es |
| #extension GL_OES_texture_buffer : require |
| precision mediump float; |
| layout(rgba32f, binding = 0) uniform highp writeonly imageBuffer dst; |
| uniform vec4 uniformData; |
| out vec4 colorOut; |
| void main() |
| { |
| colorOut = vec4(0, 0, 1.0, 1.0); |
| imageStore(dst, int(gl_FragCoord.x), uniformData); |
| })"; |
| |
| constexpr char kComputeImage[] = R"(#version 310 es |
| layout(local_size_x=1, local_size_y=1, local_size_z=1) in; |
| layout(rgba8, binding = 0) uniform highp writeonly image2D dst; |
| uniform vec4 uniformData; |
| void main() |
| { |
| imageStore(dst, ivec2(gl_GlobalInvocationID.xy), uniformData); |
| })"; |
| |
| constexpr char kComputeBuffer[] = R"(#version 310 es |
| layout(local_size_x=1, local_size_y=1, local_size_z=1) in; |
| uniform vec4 uniformData; |
| layout(std430, binding = 0) buffer block { |
| vec4 data; |
| } outBlock; |
| void main() |
| { |
| outBlock.data = uniformData; |
| } |
| )"; |
| |
| constexpr char kComputeImageBuffer[] = R"(#version 310 es |
| #extension GL_OES_texture_buffer : require |
| layout(local_size_x=1, local_size_y=1, local_size_z=1) in; |
| layout(rgba32f, binding = 0) uniform highp writeonly imageBuffer dst; |
| uniform vec4 uniformData; |
| void main() |
| { |
| imageStore(dst, int(gl_GlobalInvocationID.x), uniformData); |
| })"; |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| const char *fs = ""; |
| switch (writeResource) |
| { |
| case WriteResource::Image: |
| fs = kGraphicsImageFS; |
| break; |
| case WriteResource::Buffer: |
| fs = kGraphicsBufferFS; |
| break; |
| case WriteResource::ImageBuffer: |
| fs = kGraphicsImageBufferFS; |
| break; |
| } |
| |
| programOut->makeRaster(essl31_shaders::vs::Simple(), fs); |
| } |
| else |
| { |
| const char *cs = ""; |
| switch (writeResource) |
| { |
| case WriteResource::Image: |
| cs = kComputeImage; |
| break; |
| case WriteResource::Buffer: |
| cs = kComputeBuffer; |
| break; |
| case WriteResource::ImageBuffer: |
| cs = kComputeImageBuffer; |
| break; |
| } |
| |
| programOut->makeCompute(cs); |
| } |
| |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| } |
| |
| void MemoryBarrierTestBase::createNoopGraphicsProgram(GLProgram *programOut) |
| { |
| programOut->makeRaster(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); |
| ASSERT_TRUE(programOut->valid()); |
| } |
| |
| void MemoryBarrierTestBase::createNoopComputeProgram(GLProgram *programOut) |
| { |
| constexpr char kCS[] = R"(#version 310 es |
| layout(local_size_x=1, local_size_y=1, local_size_z=1) in; |
| void main() |
| { |
| })"; |
| |
| programOut->makeCompute(kCS); |
| ASSERT_TRUE(programOut->valid()); |
| } |
| |
| void MemoryBarrierTestBase::createQuadVertexArray(GLuint positionBuffer) |
| { |
| const std::array<Vector3, 6> kQuadVertices = {{ |
| Vector3(-1.0f, 1.0f, 0.5f), |
| Vector3(-1.0f, -1.0f, 0.5f), |
| Vector3(1.0f, -1.0f, 0.5f), |
| Vector3(-1.0f, 1.0f, 0.5f), |
| Vector3(1.0f, -1.0f, 0.5f), |
| Vector3(1.0f, 1.0f, 0.5f), |
| }}; |
| |
| const size_t bufferSize = kQuadVertices.size() * sizeof(Vector3); |
| |
| glBindBuffer(GL_ARRAY_BUFFER, positionBuffer); |
| glBufferData(GL_ARRAY_BUFFER, bufferSize, kQuadVertices.data(), GL_STATIC_DRAW); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::setupVertexArray(ShaderWritePipeline writePipeline, GLuint program) |
| { |
| if (writePipeline == ShaderWritePipeline::Compute) |
| { |
| return; |
| } |
| |
| GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib()); |
| ASSERT_NE(-1, positionLoc); |
| |
| glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); |
| glEnableVertexAttribArray(positionLoc); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::setUniformData(GLuint program, const std::array<float, 4> &data) |
| { |
| GLint uniformLocation = glGetUniformLocation(program, kUniformName); |
| ASSERT_NE(uniformLocation, -1); |
| |
| glUniform4f(uniformLocation, data[0], data[1], data[2], data[3]); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::noopOp(NoopOp op) |
| { |
| if (op == NoopOp::None) |
| { |
| return; |
| } |
| |
| GLProgram noopProgram; |
| if (op == NoopOp::Draw) |
| { |
| createNoopGraphicsProgram(&noopProgram); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ZERO, GL_ONE); |
| |
| glUseProgram(noopProgram); |
| glDrawArrays(GL_TRIANGLES, 0, 3); |
| |
| glDisable(GL_BLEND); |
| } |
| else |
| { |
| createNoopComputeProgram(&noopProgram); |
| glUseProgram(noopProgram); |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| template <typename T> |
| void MemoryBarrierTestBase::verifyBufferContents(const std::array<T, 4> &expected) |
| { |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| T *bufferContents = static_cast<T *>( |
| glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(expected), GL_MAP_READ_BIT)); |
| EXPECT_GL_NO_ERROR(); |
| |
| EXPECT_EQ(bufferContents[0], expected[0]); |
| EXPECT_EQ(bufferContents[1], expected[1]); |
| EXPECT_EQ(bufferContents[2], expected[2]); |
| EXPECT_EQ(bufferContents[3], expected[3]); |
| glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); |
| } |
| |
| void MemoryBarrierTestBase::verifyImageContents(GLuint texture, |
| const std::array<float, 4> &expected) |
| { |
| glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); |
| EXPECT_GL_NO_ERROR(); |
| |
| const GLColor kExpected(expected[0] * 255, expected[1] * 255, expected[2] * 255, |
| expected[3] * 255); |
| EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1); |
| } |
| |
| template <typename T> |
| void MemoryBarrierTestBase::verifyFramebufferAndBufferContents(ShaderWritePipeline writePipeline, |
| const std::array<T, 4> &expected) |
| { |
| // Verify the result of the verify shader |
| const GLColor kExpected = |
| writePipeline == ShaderWritePipeline::Graphics ? GLColor::cyan : GLColor::green; |
| EXPECT_PIXEL_COLOR_EQ(0, 0, kExpected); |
| |
| // Verify the contents of the buffer |
| verifyBufferContents(expected); |
| } |
| |
| void MemoryBarrierTestBase::verifyFramebufferAndImageContents(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| GLuint texture, |
| const std::array<float, 4> &expected) |
| { |
| // Verify the result of the verify shader |
| const GLColor kExpected = |
| writePipeline == ShaderWritePipeline::Graphics ? GLColor::cyan : GLColor::green; |
| EXPECT_PIXEL_COLOR_EQ(0, 0, kExpected); |
| |
| if (writeResource == WriteResource::ImageBuffer) |
| { |
| // Verify the contents of the buffer |
| verifyBufferContents(expected); |
| } |
| else |
| { |
| // Verify the contents of the image |
| verifyImageContents(texture, expected); |
| } |
| } |
| |
| void MemoryBarrierTestBase::createVertexVerifyProgram(GLuint vertexBuffer, GLProgram *programOut) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| in float attribIn; |
| out float v; |
| |
| void main() |
| { |
| v = attribIn; |
| // gl_VertexID x y |
| // 0 -1 -1 |
| // 1 1 -1 |
| // 2 -1 1 |
| // 3 1 1 |
| int bit0 = gl_VertexID & 1; |
| int bit1 = gl_VertexID >> 1; |
| gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1); |
| })"; |
| |
| constexpr char kFS[] = R"(#version 310 es |
| precision mediump float; |
| in float v; |
| out vec4 colorOut; |
| void main() |
| { |
| if (v == 2.0) |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| else |
| colorOut = vec4(1.0, 0, 0, 1.0); |
| })"; |
| |
| programOut->makeRaster(kVS, kFS); |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| |
| GLint attribLoc = glGetAttribLocation(*programOut, "attribIn"); |
| ASSERT_NE(-1, attribLoc); |
| |
| glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); |
| glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr); |
| glEnableVertexAttribArray(attribLoc); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::vertexAttribArrayBitBufferWriteThenVertexRead( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer vertexBuffer; |
| GLTexture vertexTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {12.34, 5.6, 78.91, 123.456}; |
| createStorageBuffer(writeResource, vertexBuffer, vertexTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| constexpr std::array<float, 4> kWriteData = {2.0, 2.0, 2.0, 2.0}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createVertexVerifyProgram(vertexBuffer, &readProgram); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| // Verify the vertex data was read correctly |
| const GLColor kExpected = |
| writePipeline == ShaderWritePipeline::Graphics ? GLColor::cyan : GLColor::green; |
| EXPECT_PIXEL_COLOR_EQ(0, 0, kExpected); |
| |
| // Verify the contents of the buffer |
| verifyBufferContents(kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::vertexAttribArrayBitVertexReadThenBufferWrite( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer vertexBuffer; |
| GLTexture vertexTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {2.0, 2.0, 2.0, 2.0}; |
| createStorageBuffer(writeResource, vertexBuffer, vertexTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createVertexVerifyProgram(vertexBuffer, &readProgram); |
| |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| GLint attribLoc = glGetAttribLocation(readProgram, "attribIn"); |
| glDisableVertexAttribArray(attribLoc); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the buffer |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {12.34, 5.6, 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::createIndexVerifyProgram(GLuint indexBuffer, GLProgram *programOut) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| void main() |
| { |
| // gl_VertexID x y |
| // 0 -1 -1 |
| // 1 1 -1 |
| // 2 -1 1 |
| // 3 1 1 |
| int bit0 = gl_VertexID & 1; |
| int bit1 = gl_VertexID >> 1; |
| gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1); |
| })"; |
| |
| constexpr char kFS[] = R"(#version 310 es |
| precision mediump float; |
| out vec4 colorOut; |
| void main() |
| { |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| })"; |
| |
| programOut->makeRaster(kVS, kFS); |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::elementArrayBitBufferWriteThenIndexRead( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer indexBuffer; |
| GLTexture indexTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {12.34, 5.6, 78.91, 123.456}; |
| createStorageBuffer(writeResource, indexBuffer, indexTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| constexpr std::array<uint32_t, 4> kWriteData = {0, 1, 2, 3}; |
| const std::array<float, 4> kWriteDataAsFloat = { |
| *reinterpret_cast<const float *>(&kWriteData[0]), |
| *reinterpret_cast<const float *>(&kWriteData[1]), |
| *reinterpret_cast<const float *>(&kWriteData[2]), |
| *reinterpret_cast<const float *>(&kWriteData[3]), |
| }; |
| setUniformData(writeProgram, kWriteDataAsFloat); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createIndexVerifyProgram(indexBuffer, &readProgram); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); |
| EXPECT_GL_NO_ERROR(); |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::elementArrayBitIndexReadThenBufferWrite( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer indexBuffer; |
| GLTexture indexTextureBuffer; |
| constexpr std::array<uint32_t, 4> kInitData = {0, 1, 2, 3}; |
| createStorageBuffer(writeResource, indexBuffer, indexTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createIndexVerifyProgram(indexBuffer, &readProgram); |
| |
| glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the buffer |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {12.34, 5.6, 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::createUBOVerifyProgram(GLuint buffer, GLProgram *programOut) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| void main() |
| { |
| // gl_VertexID x y |
| // 0 -1 -1 |
| // 1 1 -1 |
| // 2 -1 1 |
| // 3 1 1 |
| int bit0 = gl_VertexID & 1; |
| int bit1 = gl_VertexID >> 1; |
| gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1); |
| })"; |
| |
| constexpr char kFS[] = R"(#version 310 es |
| precision mediump float; |
| layout(binding = 0) uniform block { |
| vec4 data; |
| } ubo; |
| out vec4 colorOut; |
| void main() |
| { |
| if (ubo.data == vec4(1.5, 3.75, 5.0, 12.125)) |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| else |
| colorOut = vec4(1.0, 0, 0, 1.0); |
| })"; |
| |
| programOut->makeRaster(kVS, kFS); |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| |
| glBindBuffer(GL_UNIFORM_BUFFER, buffer); |
| glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::uniformBitBufferWriteThenUBORead(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer uniformBuffer; |
| GLTexture uniformTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {12.34, 5.6, 78.91, 123.456}; |
| createStorageBuffer(writeResource, uniformBuffer, uniformTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| constexpr std::array<float, 4> kWriteData = {1.5, 3.75, 5.0, 12.125}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_UNIFORM_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createUBOVerifyProgram(uniformBuffer, &readProgram); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::uniformBitUBOReadThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer uniformBuffer; |
| GLTexture uniformTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {1.5, 3.75, 5.0, 12.125}; |
| createStorageBuffer(writeResource, uniformBuffer, uniformTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createUBOVerifyProgram(uniformBuffer, &readProgram); |
| |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the buffer |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {12.34, 5.6, 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::createIndirectVerifyProgram(GLuint buffer, GLProgram *programOut) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| void main() |
| { |
| // gl_VertexID x y |
| // 0 -1 -1 |
| // 1 1 -1 |
| // 2 -1 1 |
| // 3 1 1 |
| int bit0 = gl_VertexID & 1; |
| int bit1 = gl_VertexID >> 1; |
| gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1); |
| })"; |
| |
| constexpr char kFS[] = R"(#version 310 es |
| precision mediump float; |
| out vec4 colorOut; |
| void main() |
| { |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| })"; |
| |
| programOut->makeRaster(kVS, kFS); |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| |
| glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::commandBitBufferWriteThenIndirectRead(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer indirectBuffer; |
| GLTexture indirectTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {12.34, 5.6, 78.91, 123.456}; |
| createStorageBuffer(writeResource, indirectBuffer, indirectTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| constexpr std::array<uint32_t, 4> kWriteData = {4, 1, 0, 0}; |
| const std::array<float, 4> kWriteDataAsFloat = { |
| *reinterpret_cast<const float *>(&kWriteData[0]), |
| *reinterpret_cast<const float *>(&kWriteData[1]), |
| *reinterpret_cast<const float *>(&kWriteData[2]), |
| *reinterpret_cast<const float *>(&kWriteData[3]), |
| }; |
| setUniformData(writeProgram, kWriteDataAsFloat); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_COMMAND_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createIndirectVerifyProgram(indirectBuffer, &readProgram); |
| |
| GLVertexArray vao; |
| glBindVertexArray(vao); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArraysIndirect(GL_TRIANGLE_STRIP, nullptr); |
| EXPECT_GL_NO_ERROR(); |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::commandBitIndirectReadThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer indirectBuffer; |
| GLTexture indirectTextureBuffer; |
| constexpr std::array<uint32_t, 4> kInitData = {4, 1, 0, 0}; |
| createStorageBuffer(writeResource, indirectBuffer, indirectTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createIndirectVerifyProgram(indirectBuffer, &readProgram); |
| |
| GLVertexArray vao; |
| glBindVertexArray(vao); |
| |
| glDrawArraysIndirect(GL_TRIANGLE_STRIP, nullptr); |
| EXPECT_GL_NO_ERROR(); |
| |
| glBindVertexArray(0); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the buffer |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {12.34, 5.6, 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::pixelBufferBitBufferWriteThenPack(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer packBuffer; |
| GLTexture packTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {1.5, 3.75, 5.0, 12.125}; |
| createStorageBuffer(writeResource, packBuffer, packTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| constexpr std::array<float, 4> kWriteData = {12.34, 5.6, 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glDisable(GL_BLEND); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the buffer |
| glBindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer); |
| glReadPixels(0, 0, kTextureSize, kTextureSize, GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); |
| |
| const std::array<uint32_t, 4> kExpectedData = { |
| writePipeline == ShaderWritePipeline::Graphics ? 0xFFFFFF00u : 0xFF00FF00u, |
| *reinterpret_cast<const uint32_t *>(&kWriteData[1]), |
| *reinterpret_cast<const uint32_t *>(&kWriteData[2]), |
| *reinterpret_cast<const uint32_t *>(&kWriteData[3]), |
| }; |
| verifyFramebufferAndBufferContents(writePipeline, kExpectedData); |
| } |
| |
| void MemoryBarrierTestBase::pixelBufferBitBufferWriteThenUnpack(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer unpackBuffer; |
| GLTexture unpackTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {1.5, 3.75, 5.0, 12.125}; |
| createStorageBuffer(writeResource, unpackBuffer, unpackTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| const std::array<float, 4> kWriteData = {*reinterpret_cast<const float *>(&GLColor::green), 5.6, |
| 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glDisable(GL_BLEND); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the buffer |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer); |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureSize, kTextureSize, GL_RGBA, GL_UNSIGNED_BYTE, |
| 0); |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); |
| |
| // Verify the result of the unpack operation |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); |
| |
| // Verify the contents of the buffer |
| verifyBufferContents(kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::pixelBufferBitPackThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| |
| GLBuffer packBuffer; |
| GLTexture packTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {1.5, 3.75, 5.0, 12.125}; |
| createStorageBuffer(writeResource, packBuffer, packTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| // Use the buffer |
| glBindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer); |
| glReadPixels(0, 0, kTextureSize, kTextureSize, GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the buffer |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {12.34, 5.6, 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::pixelBufferBitUnpackThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer unpackBuffer; |
| GLTexture unpackTextureBuffer; |
| const std::array<float, 4> kInitData = {*reinterpret_cast<const float *>(&GLColor::green), 3.75, |
| 5.0, 12.125}; |
| createStorageBuffer(writeResource, unpackBuffer, unpackTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| // Use the buffer |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer); |
| glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureSize, kTextureSize, GL_RGBA, GL_UNSIGNED_BYTE, |
| 0); |
| glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the buffer |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {12.34, 5.6, 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::bufferUpdateBitBufferWriteThenCopy(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLBuffer srcBuffer; |
| GLTexture srcTextureBuffer; |
| constexpr std::array<float, 4> kSrcInitData = {9.3, 3.7, 11.34, 0.65}; |
| createStorageBuffer(WriteResource::Buffer, srcBuffer, srcTextureBuffer, sizeof(kSrcInitData), |
| kSrcInitData.data()); |
| |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer writeBuffer; |
| GLTexture writeTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {12.34, 5.6, 78.91, 123.456}; |
| createStorageBuffer(writeResource, writeBuffer, writeTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| constexpr std::array<float, 4> kWriteData = {1.5, 3.75, 5.0, 12.125}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glDisable(GL_BLEND); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Copy from src buffer over the buffer |
| glBindBuffer(GL_UNIFORM_BUFFER, srcBuffer); |
| glCopyBufferSubData(GL_UNIFORM_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(kInitData)); |
| |
| verifyFramebufferAndBufferContents(writePipeline, kSrcInitData); |
| |
| // Verify the src buffer is unaffected |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, srcBuffer); |
| verifyBufferContents(kSrcInitData); |
| } |
| |
| void MemoryBarrierTestBase::bufferUpdateBitCopyThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLBuffer srcBuffer; |
| GLTexture srcTextureBuffer; |
| constexpr std::array<float, 4> kSrcInitData = {9.3, 3.7, 11.34, 0.65}; |
| createStorageBuffer(WriteResource::Buffer, srcBuffer, srcTextureBuffer, sizeof(kSrcInitData), |
| kSrcInitData.data()); |
| |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| |
| GLBuffer writeBuffer; |
| GLTexture writeTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {12.34, 5.6, 78.91, 123.456}; |
| createStorageBuffer(writeResource, writeBuffer, writeTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| // Copy from src buffer over the buffer |
| glBindBuffer(GL_UNIFORM_BUFFER, srcBuffer); |
| glCopyBufferSubData(GL_UNIFORM_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(kInitData)); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the buffer |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {1.5, 3.75, 5.0, 12.125}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| |
| // Verify the src buffer is unaffected |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, srcBuffer); |
| verifyBufferContents(kSrcInitData); |
| } |
| |
| void MemoryBarrierTestBase::createXfbVerifyProgram(GLuint buffer, GLProgram *programOut) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| void main() |
| { |
| // gl_VertexID x y |
| // 0 (000) -1 -1 |
| // 1 (001) 1 -1 |
| // 2 (010) -1 1 |
| // 3 (011) 1 1 |
| // 4 (100) -1 1 |
| // 5 (101) 1 -1 |
| int bit0 = gl_VertexID & 1; |
| int bit1 = gl_VertexID < 4 ? gl_VertexID >> 1 & 1 : ~bit0 & 1; |
| gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1); |
| })"; |
| |
| constexpr char kFS[] = R"(#version 310 es |
| precision mediump float; |
| out vec4 colorOut; |
| void main() |
| { |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| })"; |
| |
| const std::vector<std::string> &tfVaryings = {"gl_Position"}; |
| |
| programOut->makeRasterWithTransformFeedback(kVS, kFS, tfVaryings, GL_INTERLEAVED_ATTRIBS); |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| |
| glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::transformFeedbackBitBufferWriteThenCapture( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer xfbBuffer; |
| GLTexture xfbTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {12.34, 5.6, 78.91, 123.456}; |
| createStorageBuffer(writeResource, xfbBuffer, xfbTextureBuffer, sizeof(kInitData) * 6, |
| kInitData.data()); |
| |
| constexpr std::array<float, 4> kWriteData = {1.5, 3.75, 5.0, 12.125}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the buffer |
| GLProgram xfbProgram; |
| createXfbVerifyProgram(xfbBuffer, &xfbProgram); |
| |
| glBeginTransformFeedback(GL_TRIANGLES); |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glEndTransformFeedback(); |
| EXPECT_GL_NO_ERROR(); |
| |
| const std::array<float, 4> kExpectedData = {-1.0, -1.0, 0.0, 1.0}; |
| verifyFramebufferAndBufferContents(writePipeline, kExpectedData); |
| } |
| |
| void MemoryBarrierTestBase::transformFeedbackBitCaptureThenBufferWrite( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer xfbBuffer; |
| GLTexture xfbTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {12.34, 5.6, 78.91, 123.456}; |
| createStorageBuffer(writeResource, xfbBuffer, xfbTextureBuffer, sizeof(kInitData) * 6, |
| kInitData.data()); |
| |
| // Use the buffer |
| GLProgram xfbProgram; |
| createXfbVerifyProgram(xfbBuffer, &xfbProgram); |
| |
| glBeginTransformFeedback(GL_TRIANGLES); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glEndTransformFeedback(); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the buffer |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {1.5, 3.75, 5.0, 12.125}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::createAtomicCounterVerifyProgram(GLuint buffer, GLProgram *programOut) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| void main() |
| { |
| // gl_VertexID x y |
| // 0 -1 -1 |
| // 1 1 -1 |
| // 2 -1 1 |
| // 3 1 1 |
| int bit0 = gl_VertexID & 1; |
| int bit1 = gl_VertexID >> 1; |
| gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1); |
| })"; |
| |
| constexpr char kFS[] = R"(#version 310 es |
| precision mediump float; |
| layout(binding = 0, offset = 0) uniform atomic_uint ac[4]; |
| out vec4 colorOut; |
| void main() |
| { |
| uvec4 acValue = uvec4(atomicCounterIncrement(ac[0]), |
| atomicCounterIncrement(ac[1]), |
| atomicCounterIncrement(ac[2]), |
| atomicCounterIncrement(ac[3])); |
| |
| if (all(equal(acValue, uvec4(10, 20, 30, 40)))) |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| else |
| colorOut = vec4(1.0, 0, 0, 1.0); |
| })"; |
| |
| programOut->makeRaster(kVS, kFS); |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| |
| glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer); |
| glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, buffer); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::atomicCounterBitBufferWriteThenAtomic(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer atomicCounterBuffer; |
| GLTexture atomicCounterTextureBuffer; |
| constexpr std::array<uint32_t, 4> kInitData = {0x12345678u, 0x9ABCDEF0u, 0x13579BDFu, |
| 0x2468ACE0u}; |
| createStorageBuffer(writeResource, atomicCounterBuffer, atomicCounterTextureBuffer, |
| sizeof(kInitData), kInitData.data()); |
| |
| constexpr std::array<uint32_t, 4> kWriteData = {10, 20, 30, 40}; |
| const std::array<float, 4> kWriteDataAsFloat = { |
| *reinterpret_cast<const float *>(&kWriteData[0]), |
| *reinterpret_cast<const float *>(&kWriteData[1]), |
| *reinterpret_cast<const float *>(&kWriteData[2]), |
| *reinterpret_cast<const float *>(&kWriteData[3]), |
| }; |
| setUniformData(writeProgram, kWriteDataAsFloat); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createAtomicCounterVerifyProgram(atomicCounterBuffer, &readProgram); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| constexpr std::array<uint32_t, 4> kExpectedData = {11, 21, 31, 41}; |
| verifyFramebufferAndBufferContents(writePipeline, kExpectedData); |
| } |
| |
| void MemoryBarrierTestBase::atomicCounterBitAtomicThenBufferWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer atomicCounterBuffer; |
| GLTexture atomicCounterTextureBuffer; |
| constexpr std::array<uint32_t, 4> kInitData = {10, 20, 30, 40}; |
| createStorageBuffer(writeResource, atomicCounterBuffer, atomicCounterTextureBuffer, |
| sizeof(kInitData), kInitData.data()); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createAtomicCounterVerifyProgram(atomicCounterBuffer, &readProgram); |
| |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the buffer |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {12.34, 5.6, 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::createSsboVerifyProgram(WriteResource writeResource, |
| GLProgram *programOut) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| void main() |
| { |
| // gl_VertexID x y |
| // 0 -1 -1 |
| // 1 1 -1 |
| // 2 -1 1 |
| // 3 1 1 |
| int bit0 = gl_VertexID & 1; |
| int bit1 = gl_VertexID >> 1; |
| gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1); |
| })"; |
| |
| constexpr char kFS[] = R"(#version 310 es |
| precision mediump float; |
| layout(std430, binding = 0) buffer block { |
| vec4 data; |
| } inBlock; |
| out vec4 colorOut; |
| void main() |
| { |
| if (all(lessThan(abs(inBlock.data - vec4(1.5, 3.75, 5.0, 12.125)), vec4(0.01)))) |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| else |
| colorOut = vec4(1.0, 0, 0, 1.0); |
| })"; |
| |
| programOut->makeRaster(kVS, kFS); |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| } |
| |
| void MemoryBarrierTestBase::shaderStorageBitBufferWriteThenBufferRead( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer writeBuffer; |
| GLTexture writeTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {12.34, 5.6, 78.91, 123.456}; |
| createStorageBuffer(writeResource, writeBuffer, writeTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| constexpr std::array<float, 4> kWriteData = {1.5, 3.75, 5.0, 12.125}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the buffer |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createSsboVerifyProgram(writeResource, &readProgram); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::shaderStorageBitBufferReadThenBufferWrite( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer writeBuffer; |
| GLTexture writeTextureBuffer; |
| constexpr std::array<float, 4> kInitData = {1.5, 3.75, 5.0, 12.125}; |
| createStorageBuffer(writeResource, writeBuffer, writeTextureBuffer, sizeof(kInitData), |
| kInitData.data()); |
| |
| // Use the buffer |
| GLProgram readProgram; |
| createSsboVerifyProgram(writeResource, &readProgram); |
| |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the image |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {12.34, 5.6, 78.91, 123.456}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndBufferContents(writePipeline, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::createTextureVerifyProgram(WriteResource writeResource, |
| GLuint texture, |
| GLProgram *programOut) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| void main() |
| { |
| // gl_VertexID x y |
| // 0 -1 -1 |
| // 1 1 -1 |
| // 2 -1 1 |
| // 3 1 1 |
| int bit0 = gl_VertexID & 1; |
| int bit1 = gl_VertexID >> 1; |
| gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1); |
| })"; |
| |
| constexpr char kImageFS[] = R"(#version 310 es |
| precision mediump float; |
| uniform sampler2D s; |
| out vec4 colorOut; |
| void main() |
| { |
| if (all(lessThan(abs(texelFetch(s, ivec2(0, 0), 0)- vec4(0.125, 0.25, 0.5, 0.75)), vec4(0.01)))) |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| else |
| colorOut = vec4(1.0, 0, 0, 1.0); |
| })"; |
| |
| constexpr char kImageBufferFS[] = R"(#version 310 es |
| #extension GL_OES_texture_buffer : require |
| precision mediump float; |
| uniform highp samplerBuffer s; |
| out vec4 colorOut; |
| void main() |
| { |
| if (texelFetch(s, 0) == vec4(0.125, 0.25, 0.5, 0.75)) |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| else |
| colorOut = vec4(1.0, 0, 0, 1.0); |
| })"; |
| |
| programOut->makeRaster(kVS, |
| writeResource == WriteResource::ImageBuffer ? kImageBufferFS : kImageFS); |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| |
| glBindTexture(writeResource == WriteResource::ImageBuffer ? GL_TEXTURE_BUFFER : GL_TEXTURE_2D, |
| texture); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::textureFetchBitImageWriteThenSamplerRead( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.65, 0.92, 0.11, 0.54}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| constexpr std::array<float, 4> kWriteData = {0.125, 0.25, 0.5, 0.75}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the image |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the image |
| GLProgram readProgram; |
| createTextureVerifyProgram(writeResource, texture, &readProgram); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::textureFetchBitSamplerReadThenImageWrite( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.125, 0.25, 0.5, 0.75}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| // Use the image |
| GLProgram readProgram; |
| createTextureVerifyProgram(writeResource, texture, &readProgram); |
| |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the image |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {0.65, 0.20, 0.40, 0.95}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::createImageVerifyProgram(WriteResource writeResource, |
| GLuint texture, |
| GLProgram *programOut) |
| { |
| constexpr char kVS[] = R"(#version 310 es |
| void main() |
| { |
| // gl_VertexID x y |
| // 0 -1 -1 |
| // 1 1 -1 |
| // 2 -1 1 |
| // 3 1 1 |
| int bit0 = gl_VertexID & 1; |
| int bit1 = gl_VertexID >> 1; |
| gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1); |
| })"; |
| |
| constexpr char kImageFS[] = R"(#version 310 es |
| precision mediump float; |
| layout(rgba8, binding = 0) uniform highp readonly image2D img; |
| out vec4 colorOut; |
| void main() |
| { |
| if (all(lessThan(abs(imageLoad(img, ivec2(0, 0))- vec4(0.125, 0.25, 0.5, 0.75)), vec4(0.01)))) |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| else |
| colorOut = vec4(1.0, 0, 0, 1.0); |
| })"; |
| |
| constexpr char kImageBufferFS[] = R"(#version 310 es |
| #extension GL_OES_texture_buffer : require |
| precision mediump float; |
| layout(rgba32f, binding = 0) uniform highp readonly imageBuffer img; |
| out vec4 colorOut; |
| void main() |
| { |
| if (imageLoad(img, 0) == vec4(0.125, 0.25, 0.5, 0.75)) |
| colorOut = vec4(0, 1.0, 0, 1.0); |
| else |
| colorOut = vec4(1.0, 0, 0, 1.0); |
| })"; |
| |
| programOut->makeRaster(kVS, |
| writeResource == WriteResource::ImageBuffer ? kImageBufferFS : kImageFS); |
| ASSERT_TRUE(programOut->valid()); |
| glUseProgram(*programOut); |
| |
| if (writeResource == WriteResource::ImageBuffer) |
| { |
| glBindTexture(GL_TEXTURE_BUFFER, texture); |
| glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); |
| } |
| else |
| { |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); |
| } |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void MemoryBarrierTestBase::shaderImageAccessBitImageWriteThenImageRead( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.65, 0.92, 0.11, 0.54}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| constexpr std::array<float, 4> kWriteData = {0.125, 0.25, 0.5, 0.75}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the image |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Use the image |
| GLProgram readProgram; |
| createImageVerifyProgram(writeResource, texture, &readProgram); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::shaderImageAccessBitImageReadThenImageWrite( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::black); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.125, 0.25, 0.5, 0.75}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| // Use the image |
| GLProgram readProgram; |
| createImageVerifyProgram(writeResource, texture, &readProgram); |
| |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the image |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {0.65, 0.20, 0.40, 0.95}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::textureUpdateBitImageWriteThenCopy(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.65, 0.92, 0.11, 0.54}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| constexpr std::array<float, 4> kWriteData = {0.125, 0.25, 0.5, 0.75}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the image |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glDisable(GL_BLEND); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Copy from framebuffer over the texture |
| glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kTextureSize, kTextureSize); |
| |
| const std::array<float, 4> kExpectedData = { |
| 0, 1.0f, writePipeline == ShaderWritePipeline::Graphics ? 1.0f : 0, 1.0f}; |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kExpectedData); |
| } |
| |
| void MemoryBarrierTestBase::textureUpdateBitCopyThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.65, 0.92, 0.11, 0.54}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| // Copy from framebuffer over the texture |
| glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kTextureSize, kTextureSize); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the image |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {0.125, 0.25, 0.5, 0.75}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::framebufferBitImageWriteThenDraw(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.65, 0.92, 0.11, 0.54}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| constexpr std::array<float, 4> kWriteData = {0.125, 0.25, 0.5, 0.75}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the image |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glDisable(GL_BLEND); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Draw to image via framebuffer |
| ANGLE_GL_PROGRAM(verifyProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); |
| glUseProgram(verifyProgram); |
| GLint colorUniformLocation = |
| glGetUniformLocation(verifyProgram, angle::essl1_shaders::ColorUniform()); |
| ASSERT_NE(colorUniformLocation, -1); |
| setupVertexArray(ShaderWritePipeline::Graphics, verifyProgram); |
| |
| GLFramebuffer drawFbo; |
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); |
| glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); |
| |
| constexpr std::array<float, 4> kBlendData = {0.125, 0.25, 0.5, 0.25}; |
| glUniform4fv(colorUniformLocation, 1, kBlendData.data()); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glDisable(GL_BLEND); |
| EXPECT_GL_NO_ERROR(); |
| |
| const std::array<float, 4> kExpectedData = { |
| kWriteData[0] + kBlendData[0], |
| kWriteData[1] + kBlendData[1], |
| kWriteData[2] + kBlendData[2], |
| kWriteData[3] + kBlendData[3], |
| }; |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kExpectedData); |
| } |
| |
| void MemoryBarrierTestBase::framebufferBitImageWriteThenReadPixels( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.65, 0.92, 0.11, 0.54}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| constexpr std::array<float, 4> kWriteData = {1.0, 1.0, 0.0, 1.0}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the image |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glDisable(GL_BLEND); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Read from image via framebuffer |
| GLBuffer packBuffer; |
| glBindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer); |
| constexpr std::array<uint32_t, 4> kPBOInitData = {0x12345678u, 0x9ABCDEF0u, 0x13579BDFu, |
| 0x2468ACE0u}; |
| glBufferData(GL_PIXEL_PACK_BUFFER, sizeof(kInitData), kPBOInitData.data(), GL_STATIC_DRAW); |
| EXPECT_GL_NO_ERROR(); |
| |
| GLFramebuffer readFbo; |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); |
| glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); |
| |
| glReadPixels(0, 0, kTextureSize, kTextureSize, GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); |
| glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); |
| EXPECT_GL_NO_ERROR(); |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| |
| // Verify the PBO for completeness |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, packBuffer); |
| constexpr std::array<uint32_t, 4> kExpectedData = { |
| 0xFF00FFFFu, |
| kPBOInitData[1], |
| kPBOInitData[2], |
| kPBOInitData[3], |
| }; |
| verifyBufferContents(kExpectedData); |
| } |
| |
| void MemoryBarrierTestBase::framebufferBitImageWriteThenCopy(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.65, 0.92, 0.11, 0.54}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| constexpr std::array<float, 4> kWriteData = {1.0, 1.0, 0.0, 1.0}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the image |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glDisable(GL_BLEND); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Copy from framebuffer to another texture |
| GLFramebuffer readFbo; |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); |
| glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); |
| |
| GLTexture copyTexture; |
| glBindTexture(GL_TEXTURE_2D, copyTexture); |
| glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureSize, kTextureSize); |
| glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kTextureSize, kTextureSize); |
| |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); |
| EXPECT_GL_NO_ERROR(); |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| |
| // Verify the copy texture for completeness |
| verifyImageContents(copyTexture, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::framebufferBitImageWriteThenBlit(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp) |
| { |
| GLTexture blitColor; |
| GLFramebuffer blitFbo; |
| createFramebuffer(blitColor, blitFbo, GLColor::black); |
| |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.65, 0.92, 0.11, 0.54}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| constexpr std::array<float, 4> kWriteData = {1.0, 1.0, 0.0, 1.0}; |
| setUniformData(writeProgram, kWriteData); |
| |
| // Fill the image |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glDisable(GL_BLEND); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); |
| |
| noopOp(postBarrierOp); |
| |
| // Blit from framebuffer to another framebuffer |
| GLFramebuffer readFbo; |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); |
| glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); |
| |
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, blitFbo); |
| glBlitFramebuffer(0, 0, kTextureSize, kTextureSize, 0, 0, kTextureSize, kTextureSize, |
| GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); |
| EXPECT_GL_NO_ERROR(); |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| |
| // Verify the blit fbo for completeness |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, blitFbo); |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); |
| } |
| |
| void MemoryBarrierTestBase::framebufferBitDrawThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {0.65, 0.92, 0.11, 0.54}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| // Draw to image via framebuffer |
| ANGLE_GL_PROGRAM(verifyProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); |
| glUseProgram(verifyProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(ShaderWritePipeline::Graphics, verifyProgram); |
| |
| GLFramebuffer drawFbo; |
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo); |
| glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER); |
| |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the image |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {0.125, 0.25, 0.5, 0.75}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| } |
| |
| void MemoryBarrierTestBase::framebufferBitReadPixelsThenImageWrite( |
| ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {1.0, 1.0, 0.0, 1.0}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| // Read from image via framebuffer |
| GLBuffer packBuffer; |
| glBindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer); |
| constexpr std::array<uint32_t, 4> kPBOInitData = {0x12345678u, 0x9ABCDEF0u, 0x13579BDFu, |
| 0x2468ACE0u}; |
| glBufferData(GL_PIXEL_PACK_BUFFER, sizeof(kInitData), kPBOInitData.data(), GL_STATIC_DRAW); |
| EXPECT_GL_NO_ERROR(); |
| |
| GLFramebuffer readFbo; |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); |
| glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); |
| |
| glReadPixels(0, 0, kTextureSize, kTextureSize, GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); |
| glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the image |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {0.125, 0.25, 0.5, 0.75}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| |
| // Verify the PBO for completeness |
| glBindBuffer(GL_SHADER_STORAGE_BUFFER, packBuffer); |
| constexpr std::array<uint32_t, 4> kExpectedData = { |
| 0xFF00FFFFu, |
| kPBOInitData[1], |
| kPBOInitData[2], |
| kPBOInitData[3], |
| }; |
| verifyBufferContents(kExpectedData); |
| } |
| |
| void MemoryBarrierTestBase::framebufferBitCopyThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {1.0, 1.0, 0.0, 1.0}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| // Copy from framebuffer to another texture |
| GLFramebuffer readFbo; |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); |
| glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); |
| |
| GLTexture copyTexture; |
| glBindTexture(GL_TEXTURE_2D, copyTexture); |
| glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureSize, kTextureSize); |
| glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kTextureSize, kTextureSize); |
| |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the image |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {0.125, 0.25, 0.5, 0.75}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| |
| // Verify the copy texture for completeness |
| verifyImageContents(copyTexture, kInitData); |
| } |
| |
| void MemoryBarrierTestBase::framebufferBitBlitThenImageWrite(ShaderWritePipeline writePipeline, |
| WriteResource writeResource, |
| NoopOp preBarrierOp, |
| NoopOp postBarrierOp, |
| GLbitfield barrierBit) |
| { |
| GLTexture blitColor; |
| GLFramebuffer blitFbo; |
| createFramebuffer(blitColor, blitFbo, GLColor::black); |
| |
| GLTexture color; |
| GLFramebuffer fbo; |
| GLProgram writeProgram; |
| |
| createFramebuffer(color, fbo, GLColor::green); |
| |
| GLBuffer textureBufferStorage; |
| GLTexture texture; |
| constexpr std::array<float, 4> kInitData = {1.0, 1.0, 0.0, 1.0}; |
| createStorageImage(writeResource, textureBufferStorage, texture, kInitData); |
| |
| // Blit from framebuffer to another framebuffer |
| GLFramebuffer readFbo; |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo); |
| glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER); |
| |
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, blitFbo); |
| glBlitFramebuffer(0, 0, kTextureSize, kTextureSize, 0, 0, kTextureSize, kTextureSize, |
| GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| EXPECT_GL_NO_ERROR(); |
| |
| noopOp(preBarrierOp); |
| |
| // Issue the appropriate memory barrier |
| glMemoryBarrier(barrierBit); |
| |
| noopOp(postBarrierOp); |
| |
| // Fill the image |
| createProgram(writePipeline, writeResource, &writeProgram); |
| |
| GLBuffer positionBuffer; |
| createQuadVertexArray(positionBuffer); |
| setupVertexArray(writePipeline, writeProgram); |
| |
| constexpr std::array<float, 4> kWriteData = {0.125, 0.25, 0.5, 0.75}; |
| setUniformData(writeProgram, kWriteData); |
| |
| if (writePipeline == ShaderWritePipeline::Graphics) |
| { |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); |
| glDrawArrays(GL_TRIANGLES, 0, 6); |
| } |
| else |
| { |
| glDispatchCompute(1, 1, 1); |
| } |
| |
| verifyFramebufferAndImageContents(writePipeline, writeResource, texture, kWriteData); |
| |
| // Verify the blit fbo for completeness |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, blitFbo); |
| EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow); |
| } |
| |
| class MemoryBarrierBufferTest : public MemoryBarrierTestBase, |
| public ANGLETestWithParam<MemoryBarrierVariationsTestParams> |
| { |
| protected: |
| MemoryBarrierBufferTest() |
| { |
| setWindowWidth(16); |
| setWindowHeight(32); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| }; |
| |
| class MemoryBarrierImageTest : public MemoryBarrierTestBase, |
| public ANGLETestWithParam<MemoryBarrierVariationsTestParams> |
| { |
| protected: |
| MemoryBarrierImageTest() |
| { |
| setWindowWidth(16); |
| setWindowHeight(32); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| }; |
| |
| class MemoryBarrierImageBufferOnlyTest |
| : public MemoryBarrierTestBase, |
| public ANGLETestWithParam<MemoryBarrierVariationsTestParams> |
| { |
| protected: |
| MemoryBarrierImageBufferOnlyTest() |
| { |
| setWindowWidth(16); |
| setWindowHeight(32); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| }; |
| |
| class MemoryBarrierImageOnlyTest : public MemoryBarrierTestBase, |
| public ANGLETestWithParam<MemoryBarrierVariationsTestParams> |
| { |
| protected: |
| MemoryBarrierImageOnlyTest() |
| { |
| setWindowWidth(16); |
| setWindowHeight(32); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| }; |
| |
| class MemoryBarrierBufferOnlyTest : public MemoryBarrierTestBase, |
| public ANGLETestWithParam<MemoryBarrierVariationsTestParams> |
| { |
| protected: |
| MemoryBarrierBufferOnlyTest() |
| { |
| setWindowWidth(16); |
| setWindowHeight(32); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| }; |
| |
| // Test GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT; shader write -> vertex read |
| TEST_P(MemoryBarrierBufferTest, VertexAtrribArrayBitWriteThenVertexRead) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| vertexAttribArrayBitBufferWriteThenVertexRead(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_ELEMENT_ARRAY_BARRIER_BIT; shader write -> index read |
| TEST_P(MemoryBarrierBufferTest, ElementArrayBitWriteThenIndexRead) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| elementArrayBitBufferWriteThenIndexRead(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_UNIFORM_BARRIER_BIT; shader write -> ubo read |
| TEST_P(MemoryBarrierBufferTest, UniformBitWriteThenUBORead) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| uniformBitBufferWriteThenUBORead(writePipeline, writeResource, preBarrierOp, postBarrierOp); |
| } |
| |
| // Test GL_TEXTURE_FETCH_BARRIER_BIT; shader write -> sampler read |
| TEST_P(MemoryBarrierImageTest, TextureFetchBitWriteThenSamplerRead) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| textureFetchBitImageWriteThenSamplerRead(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; shader write -> image read |
| TEST_P(MemoryBarrierImageTest, ShaderImageAccessBitWriteThenImageRead) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| shaderImageAccessBitImageWriteThenImageRead(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; image read -> shader write |
| TEST_P(MemoryBarrierImageTest, ShaderImageAccessBitImageReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| // Looks like the implementation is missing this line from the spec: |
| // |
| // > Additionally, image stores issued after the barrier will not execute until all memory |
| // > accesses (e.g., loads, stores, texture fetches, vertex fetches) initiated prior to the |
| // > barrier complete. |
| // |
| // http://anglebug.com/5650 |
| ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA() && writeResource == WriteResource::Image); |
| |
| shaderImageAccessBitImageReadThenImageWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; vertex read -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitVertexReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| vertexAttribArrayBitVertexReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; index read -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitIndexReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| elementArrayBitIndexReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; ubo read -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitUBOReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| uniformBitUBOReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; sampler read -> shader write |
| TEST_P(MemoryBarrierImageTest, ShaderImageAccessBitSamplerReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| textureFetchBitSamplerReadThenImageWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; indirect read -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitIndirectReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| commandBitIndirectReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; pixel pack -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitPackThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| pixelBufferBitPackThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; pixel unpack -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitUnpackThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| pixelBufferBitUnpackThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; texture copy -> shader write |
| TEST_P(MemoryBarrierImageOnlyTest, ShaderImageAccessBitCopyThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| textureUpdateBitCopyThenImageWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; buffer copy -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitCopyThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| bufferUpdateBitCopyThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; draw -> shader write |
| TEST_P(MemoryBarrierImageOnlyTest, ShaderImageAccessBitDrawThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| framebufferBitDrawThenImageWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; read pixels -> shader write |
| TEST_P(MemoryBarrierImageOnlyTest, ShaderImageAccessBitReadPixelsThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| framebufferBitReadPixelsThenImageWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; fbo copy -> shader write |
| TEST_P(MemoryBarrierImageOnlyTest, ShaderImageAccessBitFBOCopyThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| framebufferBitCopyThenImageWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; blit -> shader write |
| TEST_P(MemoryBarrierImageOnlyTest, ShaderImageAccessBitBlitThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| framebufferBitBlitThenImageWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; xfb capture -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitCaptureThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| transformFeedbackBitCaptureThenBufferWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; atomic write -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitAtomicThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| atomicCounterBitAtomicThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; buffer read -> shader write |
| TEST_P(MemoryBarrierImageBufferOnlyTest, ShaderImageAccessBitBufferReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| shaderStorageBitBufferReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); |
| } |
| |
| // Test GL_COMMAND_BARRIER_BIT; shader write -> indirect read |
| TEST_P(MemoryBarrierBufferTest, CommandBitWriteThenIndirectRead) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| commandBitBufferWriteThenIndirectRead(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_PIXEL_BUFFER_BARRIER_BIT; shader write -> pixel pack |
| TEST_P(MemoryBarrierBufferTest, PixelBufferBitWriteThenPack) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| pixelBufferBitBufferWriteThenPack(writePipeline, writeResource, preBarrierOp, postBarrierOp); |
| } |
| |
| // Test GL_PIXEL_BUFFER_BARRIER_BIT; shader write -> pixel unpack |
| TEST_P(MemoryBarrierBufferTest, PixelBufferBitWriteThenUnpack) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| pixelBufferBitBufferWriteThenUnpack(writePipeline, writeResource, preBarrierOp, postBarrierOp); |
| } |
| |
| // Test GL_TEXTURE_UPDATE_BARRIER_BIT; shader write -> texture copy |
| TEST_P(MemoryBarrierImageOnlyTest, TextureUpdateBitWriteThenCopy) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| textureUpdateBitImageWriteThenCopy(writePipeline, writeResource, preBarrierOp, postBarrierOp); |
| } |
| |
| // Test GL_BUFFER_UPDATE_BARRIER_BIT; shader write -> buffer copy |
| TEST_P(MemoryBarrierBufferTest, BufferUpdateBitWriteThenCopy) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| bufferUpdateBitBufferWriteThenCopy(writePipeline, writeResource, preBarrierOp, postBarrierOp); |
| } |
| |
| // Test GL_FRAMEBUFFER_BARRIER_BIT; shader write -> draw |
| TEST_P(MemoryBarrierImageOnlyTest, FramebufferBitWriteThenDraw) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| framebufferBitImageWriteThenDraw(writePipeline, writeResource, preBarrierOp, postBarrierOp); |
| } |
| |
| // Test GL_FRAMEBUFFER_BARRIER_BIT; shader write -> read pixels |
| TEST_P(MemoryBarrierImageOnlyTest, FramebufferBitWriteThenReadPixels) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| framebufferBitImageWriteThenReadPixels(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_FRAMEBUFFER_BARRIER_BIT; shader write -> copy |
| TEST_P(MemoryBarrierImageOnlyTest, FramebufferBitWriteThenCopy) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| framebufferBitImageWriteThenCopy(writePipeline, writeResource, preBarrierOp, postBarrierOp); |
| } |
| |
| // Test GL_FRAMEBUFFER_BARRIER_BIT; shader write -> blit |
| TEST_P(MemoryBarrierImageOnlyTest, FramebufferBitWriteThenBlit) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| framebufferBitImageWriteThenBlit(writePipeline, writeResource, preBarrierOp, postBarrierOp); |
| } |
| |
| // Test GL_TRANSFORM_FEEDBACK_BARRIER_BIT; shader write -> xfb capture |
| TEST_P(MemoryBarrierBufferTest, TransformFeedbackBitWriteThenCapture) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| transformFeedbackBitBufferWriteThenCapture(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_ATOMIC_COUNTER_BARRIER_BIT; shader write -> atomic write |
| TEST_P(MemoryBarrierBufferTest, AtomicCounterBitWriteThenAtomic) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| atomicCounterBitBufferWriteThenAtomic(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; shader write -> shader read |
| TEST_P(MemoryBarrierBufferTest, ShaderStorageBitWriteThenRead) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| shaderStorageBitBufferWriteThenBufferRead(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; shader read -> buffer write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| shaderStorageBitBufferReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; vertex read -> shader write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitVertexReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| vertexAttribArrayBitVertexReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; index read -> shader write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitIndexReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| elementArrayBitIndexReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; ubo read -> shader write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitUBOReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| uniformBitUBOReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; indirect read -> shader write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitIndirectReadThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| commandBitIndirectReadThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; pixel pack -> shader write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitPackThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| pixelBufferBitPackThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; pixel unpack -> shader write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitUnpackThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| pixelBufferBitUnpackThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; buffer copy -> shader write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitCopyThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| bufferUpdateBitCopyThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; xfb capture -> shader write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitCaptureThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| transformFeedbackBitCaptureThenBufferWrite(writePipeline, writeResource, preBarrierOp, |
| postBarrierOp, GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| // Test GL_SHADER_STORAGE_BARRIER_BIT; atomic write -> shader write |
| TEST_P(MemoryBarrierBufferOnlyTest, ShaderStorageBitAtomicThenWrite) |
| { |
| ShaderWritePipeline writePipeline; |
| WriteResource writeResource; |
| NoopOp preBarrierOp; |
| NoopOp postBarrierOp; |
| ParseMemoryBarrierVariationsTestParams(GetParam(), &writePipeline, &writeResource, |
| &preBarrierOp, &postBarrierOp); |
| |
| ANGLE_SKIP_TEST_IF(!hasExtensions(writeResource)); |
| |
| atomicCounterBitAtomicThenBufferWrite(writePipeline, writeResource, preBarrierOp, postBarrierOp, |
| GL_SHADER_STORAGE_BARRIER_BIT); |
| } |
| |
| constexpr ShaderWritePipeline kWritePipelines[] = { |
| ShaderWritePipeline::Graphics, |
| ShaderWritePipeline::Compute, |
| }; |
| constexpr WriteResource kBufferWriteResources[] = { |
| WriteResource::Buffer, |
| WriteResource::ImageBuffer, |
| }; |
| constexpr WriteResource kImageWriteResources[] = { |
| WriteResource::Image, |
| WriteResource::ImageBuffer, |
| }; |
| constexpr WriteResource kImageBufferOnlyWriteResources[] = { |
| WriteResource::ImageBuffer, |
| }; |
| constexpr WriteResource kImageOnlyWriteResources[] = { |
| WriteResource::Image, |
| }; |
| constexpr WriteResource kBufferOnlyWriteResources[] = { |
| WriteResource::Buffer, |
| }; |
| constexpr NoopOp kNoopOps[] = { |
| NoopOp::None, |
| NoopOp::Draw, |
| NoopOp::Dispatch, |
| }; |
| |
| // Note: due to large number of tests, these are only run on Vulkan and a single configuration |
| // (swiftshader). |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemoryBarrierBufferTest); |
| ANGLE_INSTANTIATE_TEST_COMBINE_4(MemoryBarrierBufferTest, |
| MemoryBarrierVariationsTestPrint, |
| testing::ValuesIn(kWritePipelines), |
| testing::ValuesIn(kBufferWriteResources), |
| testing::ValuesIn(kNoopOps), |
| testing::ValuesIn(kNoopOps), |
| ES31_VULKAN_SWIFTSHADER()); |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemoryBarrierImageTest); |
| ANGLE_INSTANTIATE_TEST_COMBINE_4(MemoryBarrierImageTest, |
| MemoryBarrierVariationsTestPrint, |
| testing::ValuesIn(kWritePipelines), |
| testing::ValuesIn(kImageWriteResources), |
| testing::ValuesIn(kNoopOps), |
| testing::ValuesIn(kNoopOps), |
| ES31_VULKAN_SWIFTSHADER()); |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemoryBarrierImageBufferOnlyTest); |
| ANGLE_INSTANTIATE_TEST_COMBINE_4(MemoryBarrierImageBufferOnlyTest, |
| MemoryBarrierVariationsTestPrint, |
| testing::ValuesIn(kWritePipelines), |
| testing::ValuesIn(kImageBufferOnlyWriteResources), |
| testing::ValuesIn(kNoopOps), |
| testing::ValuesIn(kNoopOps), |
| ES31_VULKAN_SWIFTSHADER()); |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemoryBarrierImageOnlyTest); |
| ANGLE_INSTANTIATE_TEST_COMBINE_4(MemoryBarrierImageOnlyTest, |
| MemoryBarrierVariationsTestPrint, |
| testing::ValuesIn(kWritePipelines), |
| testing::ValuesIn(kImageOnlyWriteResources), |
| testing::ValuesIn(kNoopOps), |
| testing::ValuesIn(kNoopOps), |
| ES31_VULKAN_SWIFTSHADER()); |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemoryBarrierBufferOnlyTest); |
| ANGLE_INSTANTIATE_TEST_COMBINE_4(MemoryBarrierBufferOnlyTest, |
| MemoryBarrierVariationsTestPrint, |
| testing::ValuesIn(kWritePipelines), |
| testing::ValuesIn(kBufferOnlyWriteResources), |
| testing::ValuesIn(kNoopOps), |
| testing::ValuesIn(kNoopOps), |
| ES31_VULKAN_SWIFTSHADER()); |
| |
| } // anonymous namespace |