Commit 7270a6d5 by Kimmo Kinnunen Committed by Commit Bot

Fix ShaderStorageBufferTest31.LoadAndStoreBooleanVarAndArray to be more correct

The test contained bugs which made it fail on multiple platforms. After mapping SSBO, access the data with GLuint instead of GLboolean. The elements in the SSBO are 4 machine units, even though the SSB talks about bools. A bvec2 declared after bool in the SSB has alignment requirements. The test asserts that a shader written result is zero. In this case it needs to initialize the result buffer to non-zero in order to prove that the shader put the zero there. Bug: angleproject:3749, angleproject:1951 Change-Id: Iad8301be7f9e9df6bbed6b390d9c415d4e437c1a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1738909 Commit-Queue: Kimmo Kinnunen FI <kkinnunen@nvidia.com> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 0fec5eab
...@@ -1593,35 +1593,34 @@ void main() ...@@ -1593,35 +1593,34 @@ void main()
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Tests that alignment is correct for bools inside a SSB and that the values
// are written correctly by a trivial shader. Currently tests only the alignment
// of the initial block.
TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanValue) TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanValue)
{ {
// TODO(jiajia.qin@intel.com): Figure out why it fails on Intel Linux platform. // TODO(jiajia.qin@intel.com): Figure out why it fails on Intel Linux platform.
// http://anglebug.com/1951 // http://anglebug.com/1951
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux()); ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
// Seems to fail on Windows NVIDIA GL when tests are run without interruption. It also happens
// on Vulkan. http://anglebug.com/3694
ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsOpenGL());
ANGLE_SKIP_TEST_IF(IsWindows() && IsVulkan());
// Fails on 431.02 driver. http://anglebug.com/3749
ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsD3D11());
constexpr char kComputeShaderSource[] = R"(#version 310 es constexpr char kComputeShaderSource[] = R"(#version 310 es
layout (local_size_x=1) in; layout (local_size_x=1) in;
layout(binding=0, std140) buffer Storage0 layout(binding=0, std140) buffer Storage0
{ {
bool b1; bool b1;
bvec2 b2; bool b2;
bool b3;
} sb_load; } sb_load;
layout(binding=1, std140) buffer Storage1 layout(binding=1, std140) buffer Storage1
{ {
bool b1; bool b1;
bvec2 b2; bool b2;
bool b3;
} sb_store; } sb_store;
void main() void main()
{ {
sb_store.b1 = sb_load.b1; sb_store.b1 = sb_load.b1;
sb_store.b2 = sb_load.b2; sb_store.b2 = sb_load.b2;
sb_store.b3 = sb_load.b3;
} }
)"; )";
...@@ -1644,8 +1643,73 @@ void main() ...@@ -1644,8 +1643,73 @@ void main()
// upload data to sb_load.b2 // upload data to sb_load.b2
glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, 2 * kBytesPerComponent, kB2Value); glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, 2 * kBytesPerComponent, kB2Value);
constexpr GLuint kStoreBufferContents[3] = {0x1BCD1234, 0x2BCD1234, 0x3BCD1234};
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, kStoreBufferContents,
GL_STATIC_DRAW);
// Bind shader storage buffer
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
glDispatchCompute(1, 1, 1);
glFinish();
// Read back shader storage buffer
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]); glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
const GLuint *ptr = reinterpret_cast<const GLuint *>(
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, GL_MAP_READ_BIT));
EXPECT_EQ(kB1Value, ptr[0]);
EXPECT_EQ(kB2Value[0], ptr[1]);
EXPECT_EQ(kB2Value[1], ptr[2]);
EXPECT_GL_NO_ERROR();
}
// Tests that alignment is correct for bvecs3 inside a SSB and that the
// values are written correctly by a trivial shader. Currently tests only the
// alignment of the initial block.
TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanVec3)
{
// TODO(jiajia.qin@intel.com): Figure out why it fails on Intel Linux platform.
// http://anglebug.com/1951
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
constexpr char kComputeShaderSource[] = R"(#version 310 es
layout (local_size_x=1) in;
layout(binding=0, std140) buffer Storage0
{
bvec3 b;
} sb_load;
layout(binding=1, std140) buffer Storage1
{
bvec3 b;
} sb_store;
void main()
{
sb_store.b = sb_load.b;
}
)";
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
EXPECT_GL_NO_ERROR();
glUseProgram(program);
constexpr GLuint kBValues[3] = {1u, 0u, 1u};
constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
// Create shader storage buffer
GLBuffer shaderStorageBuffer[2];
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, nullptr, GL_STATIC_DRAW); glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, &kBValues);
constexpr GLuint kStoreBufferContents[3] = {0x1BCD1234, 0x2BCD1234, 0x3BCD1234};
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, kStoreBufferContents,
GL_STATIC_DRAW);
// Bind shader storage buffer // Bind shader storage buffer
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
...@@ -1656,13 +1720,98 @@ void main() ...@@ -1656,13 +1720,98 @@ void main()
// Read back shader storage buffer // Read back shader storage buffer
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]); glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
const GLboolean *ptr = reinterpret_cast<const GLboolean *>( const GLuint *ptr = reinterpret_cast<const GLuint *>(
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, GL_MAP_READ_BIT)); glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, GL_MAP_READ_BIT));
EXPECT_EQ(GL_TRUE, *ptr); EXPECT_EQ(kBValues[0], ptr[0]);
ptr += kBytesPerComponent; EXPECT_EQ(kBValues[1], ptr[1]);
EXPECT_EQ(GL_FALSE, *ptr); EXPECT_EQ(kBValues[2], ptr[2]);
ptr += kBytesPerComponent;
EXPECT_EQ(GL_TRUE, *ptr); EXPECT_GL_NO_ERROR();
}
// Tests that alignment is correct for bool + bvecs2 inside a SSB and that the
// values are written correctly by a trivial shader. Currently tests only the
// alignment of the initial block. Compare to LoadAndStoreBooleanVec3 to see how
// the alignment rules affect the memory layout.
TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanVarAndVec2)
{
// TODO(jiajia.qin@intel.com): Figure out why it fails on Intel Linux platform.
// http://anglebug.com/1951
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
constexpr char kComputeShaderSource[] = R"(#version 310 es
layout (local_size_x=1) in;
layout(binding=0, std140) buffer Storage0
{
bool b1;
bvec2 b2;
} sb_load;
layout(binding=1, std140) buffer Storage1
{
bool b1;
bvec2 b2;
} sb_store;
void main()
{
sb_store.b1 = sb_load.b1;
sb_store.b2 = sb_load.b2;
}
)";
// https://www.khronos.org/registry/OpenGL/specs/es/3.1/es_spec_3.1.pdf
// 7.6.2.2 Standard Uniform Block Layout
// ... A structure and each structure member have a base offset and a base
// alignment, from which an aligned offset is computed by rounding the base
// offset up to a multiple of the base alignment. The base offset of the
// first member of a structure is taken from the aligned offset of the
// structure itself. ... The members of a toplevel uniform block are laid
// out in buffer storage by treating the uniform block as a structure with a
// base offset of zero.
// 1. If the member is a scalar consuming N basic machine units, the base
// alignment is N.
// 2. If the member is a two- or four-component vector with components
// consuming N basic machine units, the base alignment is 2N or 4N,
// respectively
// b1 N == 4, basic offset 0, alignment 4, is at 0..3
// b2 N == 4, basic offset 4, alignment 2*4 = 8, is at 8..16.
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
EXPECT_GL_NO_ERROR();
glUseProgram(program);
constexpr GLuint kAlignPadding = 0x1abcd789u;
constexpr GLuint kBValues[] = {1u, kAlignPadding, 0u, 1u};
constexpr unsigned int kSsbSize = sizeof(kBValues);
// Create shader storage buffer
GLBuffer shaderStorageBuffer[2];
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
glBufferData(GL_SHADER_STORAGE_BUFFER, kSsbSize, nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kSsbSize, &kBValues);
constexpr GLuint kStoreBufferContents[4] = {0x1BCD1234, 0x2BCD1234, 0x3BCD1234, 0x3BCD1277};
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
glBufferData(GL_SHADER_STORAGE_BUFFER, kSsbSize, kStoreBufferContents, GL_STATIC_DRAW);
// Bind shader storage buffer
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
glDispatchCompute(1, 1, 1);
glFinish();
// Read back shader storage buffer
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
const GLuint *ptr = reinterpret_cast<const GLuint *>(
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSsbSize, GL_MAP_READ_BIT));
EXPECT_EQ(kBValues[0], ptr[0]);
// Index 1 is padding.
EXPECT_EQ(kBValues[2], ptr[2]);
EXPECT_EQ(kBValues[3], ptr[3]);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
......
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