Commit cd47a379 by jchen10 Committed by Commit Bot

Add SH_INIT_SHARED_VARIABLES flag

This option is used to initialize shared variables to zero at the beginning of shader execution to avoid compute shaders being able to read undefined values that could be coming from another webpage or application. It's implemented by declaring variables with initial value for HLSL. For GLSL, it's not allowed to use declaraction initializer for shared variables, so we need to explicitly assign them to zero at the beginning of main(). This implementation is only for HLSL. Bug: chromium:898030 Change-Id: Ic5906500bf4a35cd9a071923f82f32c5e2991be3 Reviewed-on: https://chromium-review.googlesource.com/c/1330310 Commit-Queue: Jie A Chen <jie.a.chen@intel.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 29843628
......@@ -25,7 +25,7 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 201
#define ANGLE_SH_VERSION 202
enum ShShaderSpec
{
......@@ -268,6 +268,11 @@ const ShCompileOptions SH_REWRITE_REPEATED_ASSIGN_TO_SWIZZLED = UINT64_C(1) << 3
// Rewrite gl_DrawID as a uniform int
const ShCompileOptions SH_EMULATE_GL_DRAW_ID = UINT64_C(1) << 40;
// This flag initializes shared variables to 0.
// It is to avoid ompute shaders being able to read undefined values that could be coming from
// another webpage/application.
const ShCompileOptions SH_INIT_SHARED_VARIABLES = UINT64_C(1) << 41;
// Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy
{
......
......@@ -2028,12 +2028,11 @@ bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
symbol->traverse(this);
out << ArrayString(symbol->getType());
// We don't initialize shared variables because:
// 1. It is very slow for D3D11 drivers to compile a compute shader if we add
// code to initialize a groupshared array variable with a large array size.
// 2. It is unnecessary to initialize shared variables, as GLSL even does not
// allow initializing shared variables at all.
if (declarator->getQualifier() != EvqShared)
// Add initializer only when requested. It is very slow for D3D11 drivers to
// compile a compute shader if we add code to initialize a groupshared array
// variable with a large array size.
if (declarator->getQualifier() != EvqShared ||
mCompileOptions & SH_INIT_SHARED_VARIABLES)
{
out << " = " + zeroInitializer(symbol->getType());
}
......
......@@ -369,6 +369,7 @@ void Shader::compile(const Context *context)
options |= SH_LIMIT_CALL_STACK_DEPTH;
options |= SH_LIMIT_EXPRESSION_COMPLEXITY;
options |= SH_ENFORCE_PACKING_RESTRICTIONS;
options |= SH_INIT_SHARED_VARIABLES;
}
// Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes
......
......@@ -79,6 +79,12 @@ class ComputeShaderTestES3 : public ANGLETest
ComputeShaderTestES3() {}
};
class WebGL2ComputeTest : public ComputeShaderTest
{
protected:
WebGL2ComputeTest() { setWebGLCompatibilityEnabled(true); }
};
// link a simple compute program. It should be successful.
TEST_P(ComputeShaderTest, LinkComputeProgram)
{
......@@ -2275,7 +2281,48 @@ TEST_P(ComputeShaderTestES3, NotSupported)
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
// The contents of shared variables should be cleared to zero at the beginning of shader execution.
TEST_P(WebGL2ComputeTest, sharedVariablesShouldBeZero)
{
const char kCSShader[] =
R"(#version 310 es
layout (local_size_x = 4, local_size_y = 4, local_size_z = 1) in;
layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
struct S {
float f;
int i;
uint u;
bool b;
vec4 v[64];
};
shared S vars[16];
void main()
{
S zeroS;
zeroS.f = 0.0f;
zeroS.i = 0;
zeroS.u = 0u;
zeroS.b = false;
for (int i = 0; i < 64; i++)
{
zeroS.v[i] = vec4(0.0f);
}
uint tid = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 4u;
uint value = (zeroS == vars[tid] ? 127u : 0u);
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(value));
})";
const std::array<GLuint, 16> inputData = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
const std::array<GLuint, 16> expectedValues = {
{127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127}};
runSharedMemoryTest<GLuint, 4, 4>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
expectedValues);
}
ANGLE_INSTANTIATE_TEST(ComputeShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
ANGLE_INSTANTIATE_TEST(ComputeShaderTestES3, ES3_OPENGL(), ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(WebGL2ComputeTest, ES31_D3D11());
} // namespace
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