Commit 671809e6 by Qin Jiajia Committed by Commit Bot

ES31: Add vector and matrix support in SSBO for D3D

Bug: angleproject:1951 Change-Id: I19d4218b28770464e4cb38027cce694e2a817b5b Reviewed-on: https://chromium-review.googlesource.com/c/1269827 Commit-Queue: Jiajia Qin <jiajia.qin@intel.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 3026f115
......@@ -9,45 +9,100 @@
#include "compiler/translator/ShaderStorageBlockFunctionHLSL.h"
#include "compiler/translator/UtilsHLSL.h"
#include "compiler/translator/blocklayout.h"
#include "compiler/translator/blocklayoutHLSL.h"
#include "compiler/translator/util.h"
namespace sh
{
namespace
{
unsigned int GetMatrixStride(const TType &type)
{
sh::Std140BlockEncoder std140Encoder;
sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
sh::BlockLayoutEncoder *encoder = nullptr;
if (type.getLayoutQualifier().blockStorage == EbsStd140)
{
encoder = &std140Encoder;
}
else
{
// TODO(jiajia.qin@intel.com): add std430 support. http://anglebug.com/1951
encoder = &hlslEncoder;
}
const bool isRowMajorLayout = (type.getLayoutQualifier().matrixPacking == EmpRowMajor);
std::vector<unsigned int> arraySizes;
auto *typeArraySizes = type.getArraySizes();
if (typeArraySizes != nullptr)
{
arraySizes.assign(typeArraySizes->begin(), typeArraySizes->end());
}
const BlockMemberInfo &memberInfo =
encoder->encodeType(GLVariableType(type), arraySizes, isRowMajorLayout);
return memberInfo.matrixStride;
}
} // anonymous namespace
// static
void ShaderStorageBlockFunctionHLSL::OutputSSBOLoadFunctionBody(
TInfoSinkBase &out,
const ShaderStorageBlockFunction &ssboFunction)
{
const char *convertString;
switch (ssboFunction.type.getBasicType())
{
case EbtFloat:
convertString = "asfloat(";
break;
case EbtInt:
convertString = "asint(";
break;
case EbtUInt:
convertString = "asuint(";
break;
case EbtBool:
convertString = "asint(";
break;
default:
UNREACHABLE();
return;
}
out << " " << ssboFunction.typeString << " result";
if (ssboFunction.type.isScalar())
{
TString convertString;
switch (ssboFunction.type.getBasicType())
out << " = " << convertString << "buffer.Load(loc));\n";
}
else if (ssboFunction.type.isVector())
{
out << " = " << convertString << "buffer.Load" << ssboFunction.type.getNominalSize()
<< "(loc));\n";
}
else if (ssboFunction.type.isMatrix())
{
unsigned int matrixStride = GetMatrixStride(ssboFunction.type);
out << " = {";
for (int rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++)
{
case EbtFloat:
convertString = "asfloat(";
break;
case EbtInt:
convertString = "asint(";
break;
case EbtUInt:
convertString = "asuint(";
break;
case EbtBool:
convertString = "asint(";
break;
default:
UNREACHABLE();
break;
out << "asfloat(buffer.Load" << ssboFunction.type.getCols() << "(loc +"
<< rowIndex * matrixStride << ")), ";
}
out << " " << ssboFunction.typeString << " result = " << convertString
<< "buffer.Load(loc));\n";
out << " return result;\n";
return;
out << "};\n";
}
else
{
// TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951
out << ";\n";
}
// TODO(jiajia.qin@intel.com): Process all possible return types.
out << " return 1.0;\n";
out << " return result;\n";
return;
}
// static
......@@ -59,8 +114,24 @@ void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody(
{
out << " buffer.Store(loc, asuint(value));\n";
}
// TODO(jiajia.qin@intel.com): Process all possible return types.
else if (ssboFunction.type.isVector())
{
out << " buffer.Store" << ssboFunction.type.getNominalSize()
<< "(loc, asuint(value));\n";
}
else if (ssboFunction.type.isMatrix())
{
unsigned int matrixStride = GetMatrixStride(ssboFunction.type);
for (int rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++)
{
out << " buffer.Store" << ssboFunction.type.getCols() << "(loc +"
<< rowIndex * matrixStride << ", asuint(value[" << rowIndex << "]));\n";
}
}
else
{
// TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951
}
}
bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<(
......
......@@ -190,6 +190,129 @@ TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferReadWrite)
EXPECT_GL_NO_ERROR();
}
// Test that access/write to vector data in shader storage buffer.
TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferVector)
{
constexpr char kComputeShaderSource[] =
R"(#version 310 es
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(std140, binding = 0) buffer blockIn {
uvec2 data;
} instanceIn;
layout(std140, binding = 1) buffer blockOut {
uvec2 data;
} instanceOut;
void main()
{
instanceOut.data[0] = instanceIn.data[0];
instanceOut.data[1] = instanceIn.data[1];
}
)";
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
glUseProgram(program.get());
constexpr unsigned int kComponentCount = 2;
constexpr unsigned int kBytesPerComponent = sizeof(unsigned int);
constexpr unsigned int kExpectedValues[kComponentCount] = {3u, 4u};
// Create shader storage buffer
GLBuffer shaderStorageBuffer[2];
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
glBufferData(GL_SHADER_STORAGE_BUFFER, kComponentCount * kBytesPerComponent, kExpectedValues,
GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
glBufferData(GL_SHADER_STORAGE_BUFFER, kComponentCount * kBytesPerComponent, nullptr,
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, kComponentCount * kBytesPerComponent, GL_MAP_READ_BIT));
for (unsigned int idx = 0; idx < kComponentCount; idx++)
{
EXPECT_EQ(kExpectedValues[idx], *(ptr + idx));
}
EXPECT_GL_NO_ERROR();
}
// Test that access/write to matrix data in shader storage buffer.
TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferMatrix)
{
constexpr char kComputeShaderSource[] =
R"(#version 310 es
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(std140, binding = 0) buffer blockIn {
mat2x3 data;
} instanceIn;
layout(std140, binding = 1) buffer blockOut {
mat2x3 data;
} instanceOut;
void main()
{
instanceOut.data[0][0] = instanceIn.data[0][0];
instanceOut.data[0][1] = instanceIn.data[0][1];
instanceOut.data[0][2] = instanceIn.data[0][2];
instanceOut.data[1][0] = instanceIn.data[1][0];
instanceOut.data[1][1] = instanceIn.data[1][1];
instanceOut.data[1][2] = instanceIn.data[1][2];
}
)";
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
glUseProgram(program.get());
constexpr unsigned int kColumns = 2;
constexpr unsigned int kRows = 3;
constexpr unsigned int kBytesPerComponent = sizeof(float);
constexpr unsigned int kVectorStride = 16;
// kVectorStride / kBytesPerComponent is used instead of kRows is because std140 layout requires
// that base alignment and stride of arrays of scalars and vectors are rounded up a multiple of
// the base alignment of a vec4.
constexpr float kInputDada[kColumns][kVectorStride / kBytesPerComponent] = {
{0.1, 0.2, 0.3, 0.0}, {0.4, 0.5, 0.6, 0.0}};
// Create shader storage buffer
GLBuffer shaderStorageBuffer[2];
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
glBufferData(GL_SHADER_STORAGE_BUFFER, kColumns * kVectorStride, kInputDada, GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
glBufferData(GL_SHADER_STORAGE_BUFFER, kColumns * kVectorStride, nullptr, 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
constexpr float kExpectedValues[kColumns][kRows] = {{0.1, 0.2, 0.3}, {0.4, 0.5, 0.6}};
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kColumns * kVectorStride, GL_MAP_READ_BIT));
for (unsigned int idx = 0; idx < kColumns; idx++)
{
for (unsigned int idy = 0; idy < kRows; idy++)
{
EXPECT_EQ(kExpectedValues[idx][idy],
*(ptr + idx * (kVectorStride / kBytesPerComponent) + idy));
}
}
EXPECT_GL_NO_ERROR();
}
// Test atomic memory functions.
TEST_P(ShaderStorageBufferTest31, AtomicMemoryFunctions)
{
......
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