Commit 6494c415 by Qin Jiajia Committed by Commit Bot

ES31: Add swizzle support in SSBO (Part 1)

This patch adds the swizzle process if the swizzle node is the last node in ssbo access chain. Bug: angleproject:1951 Change-Id: Iecc95baa45e8cc40be9111a15398c7e858bfb99e Reviewed-on: https://chromium-review.googlesource.com/c/1341234 Commit-Queue: Jiajia Qin <jiajia.qin@intel.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 471b8d4c
...@@ -420,12 +420,13 @@ class TIntermSwizzle : public TIntermExpression ...@@ -420,12 +420,13 @@ class TIntermSwizzle : public TIntermExpression
TIntermTyped *getOperand() { return mOperand; } TIntermTyped *getOperand() { return mOperand; }
void writeOffsetsAsXYZW(TInfoSinkBase *out) const; void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
const TVector<int> &getSwizzleOffsets() { return mSwizzleOffsets; }
bool hasDuplicateOffsets() const; bool hasDuplicateOffsets() const;
void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets); void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets);
bool offsetsMatch(int offset) const; bool offsetsMatch(int offset) const;
TIntermTyped *fold(TDiagnostics *diagnostics) override; TIntermTyped *fold(TDiagnostics *diagnostics) override;
protected: protected:
TIntermTyped *mOperand; TIntermTyped *mOperand;
TVector<int> mSwizzleOffsets; TVector<int> mSwizzleOffsets;
...@@ -574,8 +575,7 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase ...@@ -574,8 +575,7 @@ class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
// This covers all built-in function calls - whether they are associated with an op or not. // This covers all built-in function calls - whether they are associated with an op or not.
static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func, static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
TIntermSequence *arguments); TIntermSequence *arguments);
static TIntermAggregate *CreateConstructor(const TType &type, static TIntermAggregate *CreateConstructor(const TType &type, TIntermSequence *arguments);
TIntermSequence *arguments);
~TIntermAggregate() {} ~TIntermAggregate() {}
// Note: only supported for nodes that can be a part of an expression. // Note: only supported for nodes that can be a part of an expression.
...@@ -760,6 +760,7 @@ class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase ...@@ -760,6 +760,7 @@ class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
TIntermSequence *getSequence() override { return &mDeclarators; } TIntermSequence *getSequence() override { return &mDeclarators; }
const TIntermSequence *getSequence() const override { return &mDeclarators; } const TIntermSequence *getSequence() const override { return &mDeclarators; }
protected: protected:
TIntermSequence mDeclarators; TIntermSequence mDeclarators;
}; };
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "compiler/translator/ShaderStorageBlockFunctionHLSL.h" #include "compiler/translator/ShaderStorageBlockFunctionHLSL.h"
#include "common/utilities.h"
#include "compiler/translator/UtilsHLSL.h" #include "compiler/translator/UtilsHLSL.h"
#include "compiler/translator/blocklayout.h" #include "compiler/translator/blocklayout.h"
#include "compiler/translator/blocklayoutHLSL.h" #include "compiler/translator/blocklayoutHLSL.h"
...@@ -41,20 +42,29 @@ void ShaderStorageBlockFunctionHLSL::OutputSSBOLoadFunctionBody( ...@@ -41,20 +42,29 @@ void ShaderStorageBlockFunctionHLSL::OutputSSBOLoadFunctionBody(
return; return;
} }
size_t bytesPerComponent =
gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type)));
out << " " << ssboFunction.typeString << " result"; out << " " << ssboFunction.typeString << " result";
if (ssboFunction.type.isScalar()) if (ssboFunction.type.isScalar())
{ {
out << " = " << convertString << "buffer.Load(loc));\n"; size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent;
out << " = " << convertString << "buffer.Load(loc + " << offset << "));\n ";
} }
else if (ssboFunction.type.isVector()) else if (ssboFunction.type.isVector())
{ {
if (ssboFunction.rowMajor) if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle)
{ {
size_t componentStride = bytesPerComponent;
if (ssboFunction.rowMajor)
{
componentStride = ssboFunction.matrixStride;
}
out << " = {"; out << " = {";
for (int index = 0; index < ssboFunction.type.getNominalSize(); index++) for (const int offset : ssboFunction.swizzleOffsets)
{ {
out << convertString << "buffer.Load(loc + " << index * ssboFunction.matrixStride size_t offsetInBytes = offset * componentStride;
<< ")),"; out << convertString << "buffer.Load(loc + " << offsetInBytes << ")),";
} }
out << "};\n"; out << "};\n";
} }
...@@ -105,43 +115,50 @@ void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody( ...@@ -105,43 +115,50 @@ void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody(
TInfoSinkBase &out, TInfoSinkBase &out,
const ShaderStorageBlockFunction &ssboFunction) const ShaderStorageBlockFunction &ssboFunction)
{ {
size_t bytesPerComponent =
gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type)));
if (ssboFunction.type.isScalar()) if (ssboFunction.type.isScalar())
{ {
size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent;
if (ssboFunction.type.getBasicType() == EbtBool) if (ssboFunction.type.getBasicType() == EbtBool)
{ {
out << " uint _tmp = uint(value);\n" out << " buffer.Store(loc + " << offset << ", uint(value));\n";
<< " buffer.Store(loc, _tmp);\n";
} }
else else
{ {
out << " buffer.Store(loc, asuint(value));\n"; out << " buffer.Store(loc + " << offset << ", asuint(value));\n";
} }
} }
else if (ssboFunction.type.isVector()) else if (ssboFunction.type.isVector())
{ {
if (ssboFunction.rowMajor) out << " uint" << ssboFunction.type.getNominalSize() << " _value;\n";
if (ssboFunction.type.getBasicType() == EbtBool)
{ {
for (int index = 0; index < ssboFunction.type.getNominalSize(); index++) out << " _value = uint" << ssboFunction.type.getNominalSize() << "(value);\n";
{
// Don't need to worry about bool value since there is no bool matrix.
out << "buffer.Store(loc + " << index * ssboFunction.matrixStride
<< ", asuint(value[" << index << "]));\n";
}
} }
else else
{ {
if (ssboFunction.type.getBasicType() == EbtBool) out << " _value = asuint(value);\n";
}
if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle)
{
size_t componentStride = bytesPerComponent;
if (ssboFunction.rowMajor)
{ {
out << " uint" << ssboFunction.type.getNominalSize() << " _tmp = uint" componentStride = ssboFunction.matrixStride;
<< ssboFunction.type.getNominalSize() << "(value);\n";
out << " buffer.Store" << ssboFunction.type.getNominalSize() << "(loc, _tmp);\n";
} }
else const TVector<int> &swizzleOffsets = ssboFunction.swizzleOffsets;
for (int index = 0; index < static_cast<int>(swizzleOffsets.size()); index++)
{ {
out << " buffer.Store" << ssboFunction.type.getNominalSize() size_t offsetInBytes = swizzleOffsets[index] * componentStride;
<< "(loc, asuint(value));\n"; out << "buffer.Store(loc + " << offsetInBytes << ", _value[" << index << "]);\n";
} }
} }
else
{
out << " buffer.Store" << ssboFunction.type.getNominalSize() << "(loc, _value);\n";
}
} }
else if (ssboFunction.type.isMatrix()) else if (ssboFunction.type.isMatrix())
{ {
...@@ -175,8 +192,7 @@ void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody( ...@@ -175,8 +192,7 @@ void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody(
bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<( bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<(
const ShaderStorageBlockFunction &rhs) const const ShaderStorageBlockFunction &rhs) const
{ {
return std::tie(functionName, typeString, method) < return functionName < rhs.functionName;
std::tie(rhs.functionName, rhs.typeString, rhs.method);
} }
TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction( TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction(
...@@ -184,12 +200,34 @@ TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction( ...@@ -184,12 +200,34 @@ TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction(
SSBOMethod method, SSBOMethod method,
TLayoutBlockStorage storage, TLayoutBlockStorage storage,
bool rowMajor, bool rowMajor,
int matrixStride) int matrixStride,
TIntermSwizzle *swizzleNode)
{ {
ShaderStorageBlockFunction ssboFunction; ShaderStorageBlockFunction ssboFunction;
ssboFunction.typeString = TypeString(type); ssboFunction.typeString = TypeString(type);
ssboFunction.method = method; ssboFunction.method = method;
ssboFunction.type = type; ssboFunction.type = type;
if (swizzleNode != nullptr)
{
ssboFunction.swizzleOffsets = swizzleNode->getSwizzleOffsets();
ssboFunction.isDefaultSwizzle = false;
}
else
{
if (ssboFunction.type.getNominalSize() > 1)
{
for (int index = 0; index < ssboFunction.type.getNominalSize(); index++)
{
ssboFunction.swizzleOffsets.push_back(index);
}
}
else
{
ssboFunction.swizzleOffsets.push_back(0);
}
ssboFunction.isDefaultSwizzle = true;
}
ssboFunction.rowMajor = rowMajor; ssboFunction.rowMajor = rowMajor;
ssboFunction.matrixStride = matrixStride; ssboFunction.matrixStride = matrixStride;
ssboFunction.functionName = ssboFunction.functionName =
...@@ -215,6 +253,28 @@ TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction( ...@@ -215,6 +253,28 @@ TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction(
{ {
ssboFunction.functionName += "_cm_"; ssboFunction.functionName += "_cm_";
} }
for (const int offset : ssboFunction.swizzleOffsets)
{
switch (offset)
{
case 0:
ssboFunction.functionName += "x";
break;
case 1:
ssboFunction.functionName += "y";
break;
case 2:
ssboFunction.functionName += "z";
break;
case 3:
ssboFunction.functionName += "w";
break;
default:
UNREACHABLE();
}
}
mRegisteredShaderStorageBlockFunctions.insert(ssboFunction); mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
return ssboFunction.functionName; return ssboFunction.functionName;
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
namespace sh namespace sh
{ {
class TIntermSwizzle;
enum class SSBOMethod enum class SSBOMethod
{ {
LOAD, LOAD,
...@@ -47,7 +48,8 @@ class ShaderStorageBlockFunctionHLSL final : angle::NonCopyable ...@@ -47,7 +48,8 @@ class ShaderStorageBlockFunctionHLSL final : angle::NonCopyable
SSBOMethod method, SSBOMethod method,
TLayoutBlockStorage storage, TLayoutBlockStorage storage,
bool rowMajor, bool rowMajor,
int matrixStride); int matrixStride,
TIntermSwizzle *node);
void shaderStorageBlockFunctionHeader(TInfoSinkBase &out); void shaderStorageBlockFunctionHeader(TInfoSinkBase &out);
...@@ -59,9 +61,10 @@ class ShaderStorageBlockFunctionHLSL final : angle::NonCopyable ...@@ -59,9 +61,10 @@ class ShaderStorageBlockFunctionHLSL final : angle::NonCopyable
TString typeString; TString typeString;
SSBOMethod method; SSBOMethod method;
TType type; TType type;
TLayoutBlockStorage storage;
bool rowMajor; bool rowMajor;
int matrixStride; int matrixStride;
TVector<int> swizzleOffsets;
bool isDefaultSwizzle;
}; };
static void OutputSSBOLoadFunctionBody(TInfoSinkBase &out, static void OutputSSBOLoadFunctionBody(TInfoSinkBase &out,
......
...@@ -323,42 +323,53 @@ void ShaderStorageBlockOutputHLSL::outputLoadFunctionCall(TIntermTyped *node) ...@@ -323,42 +323,53 @@ void ShaderStorageBlockOutputHLSL::outputLoadFunctionCall(TIntermTyped *node)
traverseSSBOAccess(node, SSBOMethod::LOAD); traverseSSBOAccess(node, SSBOMethod::LOAD);
} }
void ShaderStorageBlockOutputHLSL::traverseSSBOAccess(TIntermTyped *node, SSBOMethod method) // Note that we must calculate the matrix stride here instead of ShaderStorageBlockFunctionHLSL.
// It's because that if the current node's type is a vector which comes from a matrix, we will
// lose the matrix type info once we enter ShaderStorageBlockFunctionHLSL.
void ShaderStorageBlockOutputHLSL::setMatrixStride(TIntermTyped *node,
TLayoutBlockStorage storage,
bool rowMajor)
{ {
mMatrixStride = 0; if (node->getType().isMatrix())
mRowMajor = false; {
mMatrixStride = GetMatrixStride(node->getType(), storage, rowMajor);
// Note that we don't have correct BlockMemberInfo from mBlockMemberInfoMap at the current mRowMajor = rowMajor;
// point. But we must use those information to generate the right function name. So here we have return;
// to calculate them again. }
TLayoutBlockStorage storage;
bool rowMajor;
GetBlockLayoutInfo(node, false, &storage, &rowMajor);
// Note that we must calculate the matrix stride here instead of ShaderStorageBlockFunctionHLSL.
// It's because that if the current node's type is a vector which comes from a matrix, we will
// lost the matrix type info once we enter ShaderStorageBlockFunctionHLSL.
if (node->getType().isVector()) if (node->getType().isVector())
{ {
TIntermBinary *binaryNode = node->getAsBinaryNode(); TIntermBinary *binaryNode = node->getAsBinaryNode();
if (binaryNode) if (binaryNode)
{ {
const TType &leftType = binaryNode->getLeft()->getType(); return setMatrixStride(binaryNode->getLeft(), storage, rowMajor);
if (leftType.isMatrix()) }
else
{
TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
if (swizzleNode)
{ {
mMatrixStride = GetMatrixStride(leftType, storage, rowMajor); return setMatrixStride(swizzleNode->getOperand(), storage, rowMajor);
mRowMajor = rowMajor;
} }
} }
} }
else if (node->getType().isMatrix()) }
{
mMatrixStride = GetMatrixStride(node->getType(), storage, rowMajor); void ShaderStorageBlockOutputHLSL::traverseSSBOAccess(TIntermTyped *node, SSBOMethod method)
mRowMajor = rowMajor; {
} mMatrixStride = 0;
mRowMajor = false;
// Note that we don't have correct BlockMemberInfo from mBlockMemberInfoMap at the current
// point. But we must use those information to generate the right function name. So here we have
// to calculate them again.
TLayoutBlockStorage storage;
bool rowMajor;
GetBlockLayoutInfo(node, false, &storage, &rowMajor);
setMatrixStride(node, storage, rowMajor);
const TString &functionName = mSSBOFunctionHLSL->registerShaderStorageBlockFunction( const TString &functionName = mSSBOFunctionHLSL->registerShaderStorageBlockFunction(
node->getType(), method, storage, mRowMajor, mMatrixStride); node->getType(), method, storage, mRowMajor, mMatrixStride, node->getAsSwizzleNode());
TInfoSinkBase &out = mOutputHLSL->getInfoSink(); TInfoSinkBase &out = mOutputHLSL->getInfoSink();
out << functionName; out << functionName;
out << "("; out << "(";
...@@ -475,8 +486,9 @@ bool ShaderStorageBlockOutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *nod ...@@ -475,8 +486,9 @@ bool ShaderStorageBlockOutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *nod
} }
TInfoSinkBase &out = mOutputHLSL->getInfoSink(); TInfoSinkBase &out = mOutputHLSL->getInfoSink();
// TODO(jiajia.qin@intel.com): add swizzle process. // TODO(jiajia.qin@intel.com): add swizzle process if the swizzle node is not the last node
if (mIsLoadFunctionCall) // of ssbo access chain. Such as, data.xy[0]
if (mIsLoadFunctionCall && isEndOfSSBOAccessChain())
{ {
out << ")"; out << ")";
} }
......
...@@ -63,6 +63,7 @@ class ShaderStorageBlockOutputHLSL : public TIntermTraverser ...@@ -63,6 +63,7 @@ class ShaderStorageBlockOutputHLSL : public TIntermTraverser
private: private:
void traverseSSBOAccess(TIntermTyped *node, SSBOMethod method); void traverseSSBOAccess(TIntermTyped *node, SSBOMethod method);
void setMatrixStride(TIntermTyped *node, TLayoutBlockStorage storage, bool rowMajor);
bool isEndOfSSBOAccessChain(); bool isEndOfSSBOAccessChain();
void writeEOpIndexDirectOrIndirectOutput(TInfoSinkBase &out, Visit visit, TIntermBinary *node); void writeEOpIndexDirectOrIndirectOutput(TInfoSinkBase &out, Visit visit, TIntermBinary *node);
// Common part in dot operations. // Common part in dot operations.
......
...@@ -37,6 +37,25 @@ struct MatrixCase ...@@ -37,6 +37,25 @@ struct MatrixCase
const unsigned int kBytesPerComponent = sizeof(float); const unsigned int kBytesPerComponent = sizeof(float);
}; };
struct VectorCase
{
VectorCase(unsigned components,
const char *computeShaderSource,
const GLuint *inputData,
const GLuint *expectedData)
: mComponents(components),
mComputeShaderSource(computeShaderSource),
mInputdata(inputData),
mExpectedData(expectedData)
{
}
unsigned int mComponents;
const char *mComputeShaderSource;
const GLuint *mInputdata;
const GLuint *mExpectedData;
const unsigned int kBytesPerComponent = sizeof(GLuint);
};
class ShaderStorageBufferTest31 : public ANGLETest class ShaderStorageBufferTest31 : public ANGLETest
{ {
protected: protected:
...@@ -90,6 +109,42 @@ class ShaderStorageBufferTest31 : public ANGLETest ...@@ -90,6 +109,42 @@ class ShaderStorageBufferTest31 : public ANGLETest
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
void runVectorTest(const VectorCase &vectorCase)
{
ANGLE_GL_COMPUTE_PROGRAM(program, vectorCase.mComputeShaderSource);
glUseProgram(program);
// Create shader storage buffer
GLBuffer shaderStorageBuffer[2];
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
glBufferData(GL_SHADER_STORAGE_BUFFER,
vectorCase.mComponents * vectorCase.kBytesPerComponent, vectorCase.mInputdata,
GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
glBufferData(GL_SHADER_STORAGE_BUFFER,
vectorCase.mComponents * vectorCase.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, vectorCase.mComponents * vectorCase.kBytesPerComponent,
GL_MAP_READ_BIT));
for (unsigned int idx = 0; idx < vectorCase.mComponents; idx++)
{
EXPECT_EQ(vectorCase.mExpectedData[idx], *(ptr + idx));
}
EXPECT_GL_NO_ERROR();
}
}; };
// Matched block names within a shader interface must match in terms of having the same number of // Matched block names within a shader interface must match in terms of having the same number of
...@@ -272,40 +327,126 @@ TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferVector) ...@@ -272,40 +327,126 @@ TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferVector)
} }
)"; )";
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource); constexpr unsigned int kComponentCount = 2;
constexpr GLuint kInputValues[kComponentCount] = {3u, 4u};
glUseProgram(program.get()); VectorCase vectorCase(kComponentCount, kComputeShaderSource, kInputValues, kInputValues);
runVectorTest(vectorCase);
}
constexpr unsigned int kComponentCount = 2; // Test that access/write to swizzle scalar data in shader storage block.
constexpr unsigned int kBytesPerComponent = sizeof(unsigned int); TEST_P(ShaderStorageBufferTest31, ScalarSwizzleTest)
constexpr unsigned int kExpectedValues[kComponentCount] = {3u, 4u}; {
// Create shader storage buffer constexpr char kComputeShaderSource[] =
GLBuffer shaderStorageBuffer[2]; R"(#version 310 es
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]); layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
glBufferData(GL_SHADER_STORAGE_BUFFER, kComponentCount * kBytesPerComponent, kExpectedValues, layout(std140, binding = 0) buffer blockIn {
GL_STATIC_DRAW); uvec2 data;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]); } instanceIn;
glBufferData(GL_SHADER_STORAGE_BUFFER, kComponentCount * kBytesPerComponent, nullptr, layout(std140, binding = 1) buffer blockOut {
GL_STATIC_DRAW); uvec2 data;
} instanceOut;
void main()
{
instanceOut.data.x = instanceIn.data.y;
instanceOut.data.y = instanceIn.data.x;
}
)";
// Bind shader storage buffer constexpr unsigned int kComponentCount = 2;
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]); constexpr GLuint kInputValues[kComponentCount] = {3u, 4u};
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]); constexpr GLuint kExpectedValues[kComponentCount] = {4u, 3u};
glDispatchCompute(1, 1, 1); VectorCase vectorCase(kComponentCount, kComputeShaderSource, kInputValues, kExpectedValues);
runVectorTest(vectorCase);
}
glFinish(); // Test that access/write to swizzle vector data in shader storage block.
TEST_P(ShaderStorageBufferTest31, VectorSwizzleTest)
{
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.yx = instanceIn.data.xy;
}
)";
// Read back shader storage buffer constexpr unsigned int kComponentCount = 2;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]); constexpr GLuint kInputValues[kComponentCount] = {3u, 4u};
const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange( constexpr GLuint kExpectedValues[kComponentCount] = {4u, 3u};
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(); VectorCase vectorCase(kComponentCount, kComputeShaderSource, kInputValues, kExpectedValues);
runVectorTest(vectorCase);
}
// Test that access/write to swizzle vector data in column_major matrix in shader storage block.
TEST_P(ShaderStorageBufferTest31, VectorSwizzleInColumnMajorMatrixTest)
{
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 {
layout(column_major) mat2x3 data;
} instanceIn;
layout(std140, binding = 1) buffer blockOut {
layout(column_major) mat2x3 data;
} instanceOut;
void main()
{
instanceOut.data[0].xyz = instanceIn.data[0].xyz;
instanceOut.data[1].xyz = instanceIn.data[1].xyz;
}
)";
constexpr unsigned int kColumns = 2;
constexpr unsigned int kRows = 3;
constexpr unsigned int kBytesPerComponent = sizeof(float);
constexpr unsigned int kMatrixStride = 16;
constexpr float kInputDada[kColumns * (kMatrixStride / kBytesPerComponent)] = {
0.1, 0.2, 0.3, 0.0, 0.4, 0.5, 0.6, 0.0};
MatrixCase matrixCase(kRows, kColumns, kMatrixStride, kComputeShaderSource, kInputDada);
runMatrixTest(matrixCase);
}
// Test that access/write to swizzle vector data in row_major matrix in shader storage block.
TEST_P(ShaderStorageBufferTest31, VectorSwizzleInRowMajorMatrixTest)
{
ANGLE_SKIP_TEST_IF(IsAndroid());
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 {
layout(row_major) mat2x3 data;
} instanceIn;
layout(std140, binding = 1) buffer blockOut {
layout(row_major) mat2x3 data;
} instanceOut;
void main()
{
instanceOut.data[0].xyz = instanceIn.data[0].xyz;
instanceOut.data[1].xyz = instanceIn.data[1].xyz;
}
)";
constexpr unsigned int kColumns = 2;
constexpr unsigned int kRows = 3;
constexpr unsigned int kBytesPerComponent = sizeof(float);
// 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 unsigned int kMatrixStride = 16;
constexpr float kInputDada[kRows * (kMatrixStride / kBytesPerComponent)] = {
0.1, 0.2, 0.0, 0.0, 0.3, 0.4, 0.0, 0.0, 0.5, 0.6, 0.0, 0.0};
MatrixCase matrixCase(kColumns, kRows, kMatrixStride, kComputeShaderSource, kInputDada);
runMatrixTest(matrixCase);
} }
// Test that access/write to scalar data in matrix in shader storage block with row major. // Test that access/write to scalar data in matrix in shader storage block with row major.
......
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