Commit ba7531da by Shahbaz Youssefi Committed by Commit Bot

Add tests that use, then update, then use buffers

This triggers vk::DynamicBuffer allocations in BufferVk. Bug: angleproject:5719 Change-Id: Ida855b23618497f76102e55f89ab1678f9c08753 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2809856Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent e249239c
...@@ -667,6 +667,7 @@ RendererVk::RendererVk() ...@@ -667,6 +667,7 @@ RendererVk::RendererVk()
mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod), mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod),
mPipelineCacheDirty(false), mPipelineCacheDirty(false),
mPipelineCacheInitialized(false), mPipelineCacheInitialized(false),
mValidationMessageCount(0),
mCommandProcessor(this), mCommandProcessor(this),
mSupportedVulkanPipelineStageMask(0) mSupportedVulkanPipelineStageMask(0)
{ {
......
...@@ -629,8 +629,6 @@ TEST_P(ComputeShaderTest, DispatchComputeIndirect) ...@@ -629,8 +629,6 @@ TEST_P(ComputeShaderTest, DispatchComputeIndirect)
// Flaky crash on teardown, see http://anglebug.com/3349 // Flaky crash on teardown, see http://anglebug.com/3349
ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows()); ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());
GLTexture texture;
GLFramebuffer framebuffer;
const char kCSSource[] = R"(#version 310 es const char kCSSource[] = R"(#version 310 es
layout(local_size_x=1, local_size_y=1, local_size_z=1) in; layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(r32ui, binding = 0) uniform highp uimage2D uImage; layout(r32ui, binding = 0) uniform highp uimage2D uImage;
...@@ -649,6 +647,7 @@ void main() ...@@ -649,6 +647,7 @@ void main()
GLuint params[] = {kWidth, kHeight, 1}; GLuint params[] = {kWidth, kHeight, 1};
glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(params), params, GL_STATIC_DRAW); glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(params), params, GL_STATIC_DRAW);
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight); glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
...@@ -662,21 +661,116 @@ void main() ...@@ -662,21 +661,116 @@ void main()
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
glUseProgram(0);
GLuint outputValues[kWidth][kHeight]; GLuint outputValues[kWidth][kHeight];
GLuint expectedValue = 100u;
GLFramebuffer framebuffer;
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer); glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
EXPECT_GL_NO_ERROR();
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
EXPECT_GL_NO_ERROR();
constexpr GLuint kExpectedValue = 100u;
for (int x = 0; x < kWidth; x++)
{
for (int y = 0; y < kHeight; y++)
{
EXPECT_EQ(kExpectedValue, outputValues[x][y]);
}
}
}
// Test that uploading data to buffer that's in use then using it as indirect buffer works.
TEST_P(ComputeShaderTest, UseAsUBOThenUpdateThenDispatchComputeIndirect)
{
// Flaky crash on teardown, see http://anglebug.com/3349
ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());
constexpr GLsizei kWidth = 4, kHeight = 6;
const std::array<uint32_t, 4> kInitialData = {1, 2, 3, 4};
const std::array<uint32_t, 4> kUpdateData = {kWidth, kHeight, 1, 0};
GLBuffer buffer;
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
EXPECT_GL_NO_ERROR();
constexpr char kVerifyUBO[] = R"(#version 310 es
precision mediump float;
layout(binding = 0) uniform block {
uvec4 data;
} ubo;
out vec4 colorOut;
void main()
{
if (all(equal(ubo.data, uvec4(1, 2, 3, 4))))
colorOut = vec4(0, 1.0, 0, 1.0);
else
colorOut = vec4(1.0, 0, 0, 1.0);
})";
ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
EXPECT_GL_NO_ERROR();
// Update buffer data
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
EXPECT_GL_NO_ERROR();
const char kCS[] = R"(#version 310 es
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(r32ui, binding = 0) uniform highp uimage2D uImage;
void main()
{
imageStore(uImage, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), uvec4(100, 0, 0, 0));
})";
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
glUseProgram(program.get());
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
const std::vector<GLuint> inputValues(kWidth * kHeight, 0);
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
inputValues.data());
EXPECT_GL_NO_ERROR();
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
EXPECT_GL_NO_ERROR();
glDispatchComputeIndirect(0);
EXPECT_GL_NO_ERROR();
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
GLuint outputValues[kWidth][kHeight];
GLFramebuffer framebuffer;
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues); glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
for (int i = 0; i < kWidth; i++) constexpr GLuint kExpectedValue = 100u;
for (int x = 0; x < kWidth; x++)
{ {
for (int j = 0; j < kHeight; j++) for (int y = 0; y < kHeight; y++)
{ {
EXPECT_EQ(expectedValue, outputValues[i][j]); EXPECT_EQ(kExpectedValue, outputValues[x][y]);
} }
} }
} }
......
...@@ -317,6 +317,9 @@ class ReadPixelsPBOTest : public ReadPixelsPBONVTest ...@@ -317,6 +317,9 @@ class ReadPixelsPBOTest : public ReadPixelsPBONVTest
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
mFBOWidth = fboWidth;
mFBOHeight = fboHeight;
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
}; };
...@@ -490,6 +493,77 @@ TEST_P(ReadPixelsPBOTest, SubDataOffsetPreservesContents) ...@@ -490,6 +493,77 @@ TEST_P(ReadPixelsPBOTest, SubDataOffsetPreservesContents)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that uploading data to buffer that's in use then writing to it as PBO works.
TEST_P(ReadPixelsPBOTest, UseAsUBOThenUpdateThenReadFromFBO)
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glViewport(0, 0, mFBOWidth, mFBOHeight);
const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
GLColor::red};
const std::array<GLColor, 4> kUpdateData = {GLColor::white, GLColor::white, GLColor::white,
GLColor::white};
GLBuffer buffer;
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_COPY);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
EXPECT_GL_NO_ERROR();
constexpr char kVerifyUBO[] = R"(#version 300 es
precision mediump float;
uniform block {
uvec4 data;
} ubo;
out vec4 colorOut;
void main()
{
if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
colorOut = vec4(0, 1.0, 0, 1.0);
else
colorOut = vec4(1.0, 0, 0, 1.0);
})";
ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
EXPECT_GL_NO_ERROR();
// Update buffer data
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
EXPECT_GL_NO_ERROR();
// Clear first pixel to blue
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glScissor(0, 0, 1, 1);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_GL_NO_ERROR();
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
// Read the framebuffer pixels
glReadPixels(0, 0, mFBOWidth, mFBOHeight, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
void *mappedPtr =
glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, sizeof(kInitialData), GL_MAP_READ_BIT);
GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(GLColor::blue, dataColor[0]);
EXPECT_EQ(GLColor::green, dataColor[1]);
EXPECT_EQ(GLColor::green, dataColor[2]);
EXPECT_EQ(GLColor::green, dataColor[3]);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
EXPECT_GL_NO_ERROR();
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
}
class ReadPixelsPBODrawTest : public ReadPixelsPBOTest class ReadPixelsPBODrawTest : public ReadPixelsPBOTest
{ {
protected: protected:
......
...@@ -8358,6 +8358,66 @@ TEST_P(Texture2DTestES3, NonZeroBaseEmulatedClear) ...@@ -8358,6 +8358,66 @@ TEST_P(Texture2DTestES3, NonZeroBaseEmulatedClear)
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
} }
// Test that uploading data to buffer that's in use then using it as PBO to update a texture works.
TEST_P(Texture2DTestES3, UseAsUBOThenUpdateThenAsPBO)
{
const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
GLColor::red};
const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
GLColor::blue};
GLBuffer buffer;
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_COPY);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
EXPECT_GL_NO_ERROR();
constexpr char kVerifyUBO[] = R"(#version 300 es
precision mediump float;
uniform block {
uvec4 data;
} ubo;
out vec4 colorOut;
void main()
{
if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
colorOut = vec4(0, 1.0, 0, 1.0);
else
colorOut = vec4(1.0, 0, 0, 1.0);
})";
ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
EXPECT_GL_NO_ERROR();
// Update buffer data
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
EXPECT_GL_NO_ERROR();
// Bind as PBO
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
EXPECT_GL_NO_ERROR();
// Upload from PBO to texture
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
EXPECT_GL_NO_ERROR();
// Make sure uniform data is correct.
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
// Make sure the texture data is correct.
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
EXPECT_GL_NO_ERROR();
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
}
// Draw a quad with an integer texture with a non-zero base level, and test that the color of the // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
// texture is output. // texture is output.
TEST_P(Texture2DIntegerTestES3, IntegerTextureNonZeroBaseLevel) TEST_P(Texture2DIntegerTestES3, IntegerTextureNonZeroBaseLevel)
...@@ -8884,6 +8944,75 @@ TEST_P(TextureBufferTestES31, QueryWidthAfterBufferResize) ...@@ -8884,6 +8944,75 @@ TEST_P(TextureBufferTestES31, QueryWidthAfterBufferResize)
} }
} }
// Test that uploading data to buffer that's in use then using it as texture buffer works.
TEST_P(TextureBufferTestES31, UseAsUBOThenUpdateThenAsTextureBuffer)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
// Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension
// 'GL_OES_texture_buffer' is not supported". http://anglebug.com/5832
ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
GLColor::red};
const std::array<GLColor, 4> kUpdateData = {GLColor::blue, GLColor::blue, GLColor::blue,
GLColor::blue};
GLBuffer buffer;
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
EXPECT_GL_NO_ERROR();
constexpr char kVerifyUBO[] = R"(#version 310 es
precision mediump float;
layout(binding = 0) uniform block {
uvec4 data;
} ubo;
out vec4 colorOut;
void main()
{
if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
colorOut = vec4(0, 1.0, 0, 1.0);
else
colorOut = vec4(1.0, 0, 0, 1.0);
})";
ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
EXPECT_GL_NO_ERROR();
// Update buffer data
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
EXPECT_GL_NO_ERROR();
// Bind as texture buffer
GLTexture texture;
glBindTexture(GL_TEXTURE_BUFFER, texture);
glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
EXPECT_GL_NO_ERROR();
constexpr char kVerifySamplerBuffer[] = R"(#version 310 es
#extension GL_OES_texture_buffer : require
precision mediump float;
uniform highp samplerBuffer s;
out vec4 colorOut;
void main()
{
colorOut = texelFetch(s, 0);
})";
ANGLE_GL_PROGRAM(verifySamplerBuffer, essl31_shaders::vs::Simple(), kVerifySamplerBuffer);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
drawQuad(verifySamplerBuffer, essl31_shaders::PositionAttrib(), 0.5);
EXPECT_GL_NO_ERROR();
// Make sure both draw calls succeed
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
}
class CopyImageTestES31 : public ANGLETest class CopyImageTestES31 : public ANGLETest
{ {
protected: protected:
......
...@@ -373,6 +373,102 @@ TEST_P(TransformFeedbackTest, SpanMultipleRenderPasses) ...@@ -373,6 +373,102 @@ TEST_P(TransformFeedbackTest, SpanMultipleRenderPasses)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that uploading data to buffer that's in use then using it for transform feedback works.
TEST_P(TransformFeedbackTest, UseAsUBOThenUpdateThenCapture)
{
// http://anglebug.com/5833
ANGLE_SKIP_TEST_IF(IsVulkan() && IsQualcomm());
// TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
// Fails on Mac GL drivers. http://anglebug.com/4992
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsOSX());
const std::array<uint32_t, 12> kInitialData = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
const std::array<uint32_t, 12> kUpdateData = {
0x12345678u, 0x9ABCDEF0u, 0x13579BDFu, 0x2468ACE0u, 0x23456781u, 0xABCDEF09u,
0x3579BDF1u, 0x468ACE02u, 0x34567812u, 0xBCDEF09Au, 0x579BDF13u, 0x68ACE024u,
};
GLBuffer buffer;
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
EXPECT_GL_NO_ERROR();
constexpr char kVerifyUBO[] = R"(#version 300 es
precision mediump float;
uniform block {
uvec4 data[3];
} ubo;
out vec4 colorOut;
void main()
{
bool data0Ok = all(equal(ubo.data[0], uvec4(0, 1, 2, 3)));
bool data1Ok = all(equal(ubo.data[1], uvec4(4, 5, 6, 7)));
bool data2Ok = all(equal(ubo.data[2], uvec4(8, 9, 10, 11)));
if (data0Ok && data1Ok && data2Ok)
colorOut = vec4(0, 1.0, 0, 1.0);
else
colorOut = vec4(0, 0, 1.0, 1.0);
})";
ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
EXPECT_GL_NO_ERROR();
// Update buffer data
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
EXPECT_GL_NO_ERROR();
// Set the program's transform feedback varyings (just gl_Position)
std::vector<std::string> tfVaryings;
tfVaryings.push_back("gl_Position");
compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS);
glUseProgram(mProgram);
GLint positionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
// First pass: draw 3 points to the XFB buffer
glEnable(GL_RASTERIZER_DISCARD);
const GLfloat vertices[] = {
-1.0f, 3.0f, 0.5f, -1.0f, -1.0f, 0.5f, 3.0f, -1.0f, 0.5f,
};
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(positionLocation);
// Bind the buffer for transform feedback output and start transform feedback
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, 3);
glDisableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
glEndTransformFeedback();
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
glDisable(GL_RASTERIZER_DISCARD);
// Second pass: draw from the feedback buffer
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(positionLocation);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glDrawArrays(GL_TRIANGLES, 0, 3);
EXPECT_GL_NO_ERROR();
// Make sure both draws succeeded
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::yellow);
}
void TransformFeedbackTest::midRecordOpDoesNotContributeTest(std::function<void()> op) void TransformFeedbackTest::midRecordOpDoesNotContributeTest(std::function<void()> op)
{ {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
......
...@@ -793,6 +793,82 @@ TEST_P(UniformBufferTest31, BindingMustBeBothSpecified) ...@@ -793,6 +793,82 @@ TEST_P(UniformBufferTest31, BindingMustBeBothSpecified)
ASSERT_EQ(0u, program); ASSERT_EQ(0u, program);
} }
// Test that uploading data to buffer that's in use then using it as indirect buffer works.
TEST_P(UniformBufferTest31, UseAsUBOThenUpdateThenDrawIndirect)
{
// http://anglebug.com/5826
ANGLE_SKIP_TEST_IF(IsD3D11());
const std::array<uint32_t, 4> kInitialData = {100, 200, 300, 400};
const std::array<uint32_t, 4> kUpdateData = {4, 1, 0, 0};
GLBuffer buffer;
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
EXPECT_GL_NO_ERROR();
constexpr char kVerifyUBO[] = R"(#version 310 es
precision mediump float;
layout(binding = 0) uniform block {
uvec4 data;
} ubo;
out vec4 colorOut;
void main()
{
if (all(equal(ubo.data, uvec4(100, 200, 300, 400))))
colorOut = vec4(0, 1.0, 0, 1.0);
else
colorOut = vec4(1.0, 0, 0, 1.0);
})";
ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
EXPECT_GL_NO_ERROR();
// Update buffer data
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
EXPECT_GL_NO_ERROR();
// Draw indirect using the updated parameters
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, 0, 1.0, 1.0);
})";
ANGLE_GL_PROGRAM(draw, kVS, kFS);
glUseProgram(draw);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
EXPECT_GL_NO_ERROR();
GLVertexArray vao;
glBindVertexArray(vao);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glDrawArraysIndirect(GL_TRIANGLE_STRIP, nullptr);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
}
// Test with a block containing an array of structs. // Test with a block containing an array of structs.
TEST_P(UniformBufferTest, BlockContainingArrayOfStructs) TEST_P(UniformBufferTest, BlockContainingArrayOfStructs)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment