ES31: Fix some bugs in ShaderStorageBlockOutputHLSL

When EOpIndexDirect/EOpIndexIndirect/EOpIndexDirectStruct/TIntermSwizzle
appear in [] in ssbo access chain, we should transfer the process of them to
OutputHLSL.

For example:
    instance.v[gl_GlobalInvocationID.x] = data;
    // becomes
    float_Store(dx_instance, 0 + 16 * gl_GlobalInvocationID.x, _data);

    instance.v[s.index[0].x] = data;
    // becomes
    float_Store(dx_instance, 0 + 16 * _s.index[0].x, _data);

Bug: angleproject:1951
Change-Id: I333e238400a10a799a6294f8759cf9c4ef2451c8
Reviewed-on: https://chromium-review.googlesource.com/c/1250661
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jiajia Qin <jiajia.qin@intel.com>
This commit is contained in:
Qin Jiajia 2018-09-28 14:16:06 +08:00 коммит произвёл Commit Bot
Родитель 19b51d2983
Коммит 6d765b07f8
3 изменённых файлов: 107 добавлений и 1 удалений

Просмотреть файл

@ -227,9 +227,14 @@ void ShaderStorageBlockOutputHLSL::visitConstantUnion(TIntermConstantUnion *node
bool ShaderStorageBlockOutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *node) bool ShaderStorageBlockOutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *node)
{ {
TInfoSinkBase &out = mOutputHLSL->getInfoSink();
if (visit == PostVisit) if (visit == PostVisit)
{ {
if (!IsInShaderStorageBlock(node))
{
return mOutputHLSL->visitSwizzle(visit, node);
}
TInfoSinkBase &out = mOutputHLSL->getInfoSink();
// TODO(jiajia.qin@intel.com): add swizzle process. // TODO(jiajia.qin@intel.com): add swizzle process.
if (mIsLoadFunctionCall) if (mIsLoadFunctionCall)
{ {
@ -247,6 +252,11 @@ bool ShaderStorageBlockOutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
{ {
case EOpIndexDirect: case EOpIndexDirect:
{ {
if (!IsInShaderStorageBlock(node->getLeft()))
{
return mOutputHLSL->visitBinary(visit, node);
}
const TType &leftType = node->getLeft()->getType(); const TType &leftType = node->getLeft()->getType();
if (leftType.isInterfaceBlock()) if (leftType.isInterfaceBlock())
{ {
@ -276,21 +286,36 @@ bool ShaderStorageBlockOutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
break; break;
} }
case EOpIndexIndirect: case EOpIndexIndirect:
{
if (!IsInShaderStorageBlock(node->getLeft()))
{
return mOutputHLSL->visitBinary(visit, node);
}
// We do not currently support indirect references to interface blocks // We do not currently support indirect references to interface blocks
ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock); ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock);
writeEOpIndexDirectOrIndirectOutput(out, visit, node); writeEOpIndexDirectOrIndirectOutput(out, visit, node);
break; break;
}
case EOpIndexDirectStruct: case EOpIndexDirectStruct:
{
if (!IsInShaderStorageBlock(node->getLeft()))
{
return mOutputHLSL->visitBinary(visit, node);
}
if (visit == InVisit) if (visit == InVisit)
{ {
ASSERT(IsInShaderStorageBlock(node->getLeft())); ASSERT(IsInShaderStorageBlock(node->getLeft()));
const TStructure *structure = node->getLeft()->getType().getStruct(); const TStructure *structure = node->getLeft()->getType().getStruct();
const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
const TField *field = structure->fields()[index->getIConst(0)]; const TField *field = structure->fields()[index->getIConst(0)];
out << " + ";
writeDotOperatorOutput(out, field); writeDotOperatorOutput(out, field);
return false; return false;
} }
break; break;
}
case EOpIndexDirectInterfaceBlock: case EOpIndexDirectInterfaceBlock:
if (visit == InVisit) if (visit == InVisit)
{ {

Просмотреть файл

@ -762,6 +762,11 @@ bool IsInShaderStorageBlock(TIntermTyped *node)
{ {
return IsInShaderStorageBlock(binaryNode->getLeft()); return IsInShaderStorageBlock(binaryNode->getLeft());
} }
TIntermSymbol *symbolNode = swizzleNode->getOperand()->getAsSymbolNode();
if (symbolNode)
{
return symbolNode->getQualifier() == EvqBuffer;
}
} }
binaryNode = node->getAsBinaryNode(); binaryNode = node->getAsBinaryNode();

Просмотреть файл

@ -2190,6 +2190,82 @@ TEST_P(ComputeShaderTest, ShaderStorageBlocksWithUnsizedArray)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that EOpIndexDirect/EOpIndexIndirect/EOpIndexDirectStruct nodes in ssbo EOpIndexInDirect
// don't need to calculate the offset and should be translated by OutputHLSL directly.
TEST_P(ComputeShaderTest, IndexAndDotOperatorsInSSBOIndexIndirectOperator)
{
constexpr char kComputeShaderSource[] =
R"(#version 310 es
layout(local_size_x=1) in;
layout(std140, binding = 0) buffer blockA {
float v[4];
};
layout(std140, binding = 1) buffer blockB {
float v[4];
} instanceB[1];
struct S
{
uvec4 index[2];
} s;
void main()
{
s.index[0] = uvec4(0u, 1u, 2u, 3u);
float data = v[s.index[0].y];
instanceB[0].v[s.index[0].x] = data;
}
)";
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
EXPECT_GL_NO_ERROR();
}
// Test that swizzle node in non-SSBO symbol works well.
TEST_P(ComputeShaderTest, ShaderStorageBlocksWithNonSSBOSwizzle)
{
constexpr char kComputeShaderSource[] =
R"(#version 310 es
layout(local_size_x=8) in;
layout(std140, binding = 0) buffer blockA {
float v[8];
};
layout(std140, binding = 1) buffer blockB {
float v[8];
} instanceB[1];
void main()
{
float data = v[gl_GlobalInvocationID.x];
instanceB[0].v[gl_GlobalInvocationID.x] = data;
}
)";
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
EXPECT_GL_NO_ERROR();
}
// Test that swizzle node in SSBO symbol works well.
TEST_P(ComputeShaderTest, ShaderStorageBlocksWithSSBOSwizzle)
{
constexpr char kComputeShaderSource[] =
R"(#version 310 es
layout(local_size_x=1) in;
layout(std140, binding = 0) buffer blockA {
vec2 v;
};
layout(std140, binding = 1) buffer blockB {
float v;
} instanceB[1];
void main()
{
instanceB[0].v = v.x;
}
)";
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
EXPECT_GL_NO_ERROR();
}
// Check that it is not possible to create a compute shader when the context does not support ES // Check that it is not possible to create a compute shader when the context does not support ES
// 3.10 // 3.10
TEST_P(ComputeShaderTestES3, NotSupported) TEST_P(ComputeShaderTestES3, NotSupported)