Commit 427071ea by Jiawei Shao Committed by Commit Bot

ES31: Add link validation on geometry shader interface block limits

This patch adds link validation on the maximum number of active uniform blocks and shader storage blocks defined in the geometry shader. BUG=angleproject:1941 TEST=angle_end2end_tests Change-Id: Ieffc234981a3f32a569392786e8fa1c6623a7a23 Reviewed-on: https://chromium-review.googlesource.com/966491 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJiajia Qin <jiajia.qin@intel.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent a0648780
...@@ -205,7 +205,7 @@ bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::st ...@@ -205,7 +205,7 @@ bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::st
return false; return false;
} }
bool validateInterfaceBlocksCount(GLuint maxInterfaceBlocks, bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
const std::vector<sh::InterfaceBlock> &interfaceBlocks, const std::vector<sh::InterfaceBlock> &interfaceBlocks,
const std::string &errorMessage, const std::string &errorMessage,
InfoLog &infoLog) InfoLog &infoLog)
...@@ -2744,7 +2744,7 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog) ...@@ -2744,7 +2744,7 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
Shader &computeShader = *mState.mAttachedComputeShader; Shader &computeShader = *mState.mAttachedComputeShader;
const auto &computeUniformBlocks = computeShader.getUniformBlocks(context); const auto &computeUniformBlocks = computeShader.getUniformBlocks(context);
if (!validateInterfaceBlocksCount( if (!ValidateInterfaceBlocksCount(
caps.maxComputeUniformBlocks, computeUniformBlocks, caps.maxComputeUniformBlocks, computeUniformBlocks,
"Compute shader uniform block count exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS (", "Compute shader uniform block count exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS (",
infoLog)) infoLog))
...@@ -2753,7 +2753,7 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog) ...@@ -2753,7 +2753,7 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
} }
const auto &computeShaderStorageBlocks = computeShader.getShaderStorageBlocks(context); const auto &computeShaderStorageBlocks = computeShader.getShaderStorageBlocks(context);
if (!validateInterfaceBlocksCount(caps.maxComputeShaderStorageBlocks, if (!ValidateInterfaceBlocksCount(caps.maxComputeShaderStorageBlocks,
computeShaderStorageBlocks, computeShaderStorageBlocks,
"Compute shader shader storage block count exceeds " "Compute shader shader storage block count exceeds "
"GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS (", "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS (",
...@@ -2770,13 +2770,13 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog) ...@@ -2770,13 +2770,13 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
const auto &vertexUniformBlocks = vertexShader.getUniformBlocks(context); const auto &vertexUniformBlocks = vertexShader.getUniformBlocks(context);
const auto &fragmentUniformBlocks = fragmentShader.getUniformBlocks(context); const auto &fragmentUniformBlocks = fragmentShader.getUniformBlocks(context);
if (!validateInterfaceBlocksCount( if (!ValidateInterfaceBlocksCount(
caps.maxVertexUniformBlocks, vertexUniformBlocks, caps.maxVertexUniformBlocks, vertexUniformBlocks,
"Vertex shader uniform block count exceeds GL_MAX_VERTEX_UNIFORM_BLOCKS (", infoLog)) "Vertex shader uniform block count exceeds GL_MAX_VERTEX_UNIFORM_BLOCKS (", infoLog))
{ {
return false; return false;
} }
if (!validateInterfaceBlocksCount( if (!ValidateInterfaceBlocksCount(
caps.maxFragmentUniformBlocks, fragmentUniformBlocks, caps.maxFragmentUniformBlocks, fragmentUniformBlocks,
"Fragment shader uniform block count exceeds GL_MAX_FRAGMENT_UNIFORM_BLOCKS (", "Fragment shader uniform block count exceeds GL_MAX_FRAGMENT_UNIFORM_BLOCKS (",
infoLog)) infoLog))
...@@ -2785,6 +2785,20 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog) ...@@ -2785,6 +2785,20 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
return false; return false;
} }
Shader *geometryShader = mState.mAttachedGeometryShader;
if (geometryShader)
{
const auto &geometryUniformBlocks = geometryShader->getUniformBlocks(context);
if (!ValidateInterfaceBlocksCount(
caps.maxGeometryUniformBlocks, geometryUniformBlocks,
"Geometry shader uniform block count exceeds GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT (",
infoLog))
{
return false;
}
}
// TODO(jiawei.shao@intel.com): validate geometry shader uniform blocks.
bool webglCompatibility = context->getExtensions().webglCompatibility; bool webglCompatibility = context->getExtensions().webglCompatibility;
if (!ValidateGraphicsInterfaceBlocks(vertexUniformBlocks, fragmentUniformBlocks, infoLog, if (!ValidateGraphicsInterfaceBlocks(vertexUniformBlocks, fragmentUniformBlocks, infoLog,
webglCompatibility, sh::BlockType::BLOCK_UNIFORM, webglCompatibility, sh::BlockType::BLOCK_UNIFORM,
...@@ -2798,7 +2812,7 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog) ...@@ -2798,7 +2812,7 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
const auto &vertexShaderStorageBlocks = vertexShader.getShaderStorageBlocks(context); const auto &vertexShaderStorageBlocks = vertexShader.getShaderStorageBlocks(context);
const auto &fragmentShaderStorageBlocks = fragmentShader.getShaderStorageBlocks(context); const auto &fragmentShaderStorageBlocks = fragmentShader.getShaderStorageBlocks(context);
if (!validateInterfaceBlocksCount(caps.maxVertexShaderStorageBlocks, if (!ValidateInterfaceBlocksCount(caps.maxVertexShaderStorageBlocks,
vertexShaderStorageBlocks, vertexShaderStorageBlocks,
"Vertex shader shader storage block count exceeds " "Vertex shader shader storage block count exceeds "
"GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS (", "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS (",
...@@ -2806,7 +2820,7 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog) ...@@ -2806,7 +2820,7 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
{ {
return false; return false;
} }
if (!validateInterfaceBlocksCount(caps.maxFragmentShaderStorageBlocks, if (!ValidateInterfaceBlocksCount(caps.maxFragmentShaderStorageBlocks,
fragmentShaderStorageBlocks, fragmentShaderStorageBlocks,
"Fragment shader shader storage block count exceeds " "Fragment shader shader storage block count exceeds "
"GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS (", "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS (",
...@@ -2816,6 +2830,21 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog) ...@@ -2816,6 +2830,21 @@ bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
return false; return false;
} }
if (geometryShader)
{
const auto &geometryShaderStorageBlocks =
geometryShader->getShaderStorageBlocks(context);
if (!ValidateInterfaceBlocksCount(caps.maxGeometryShaderStorageBlocks,
geometryShaderStorageBlocks,
"Geometry shader shader storage block count exceeds "
"GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT (",
infoLog))
{
return false;
}
}
// TODO(jiawei.shao@intel.com): validate geometry shader shader storage blocks.
if (!ValidateGraphicsInterfaceBlocks( if (!ValidateGraphicsInterfaceBlocks(
vertexShaderStorageBlocks, fragmentShaderStorageBlocks, infoLog, webglCompatibility, vertexShaderStorageBlocks, fragmentShaderStorageBlocks, infoLog, webglCompatibility,
sh::BlockType::BLOCK_BUFFER, caps.maxCombinedShaderStorageBlocks)) sh::BlockType::BLOCK_BUFFER, caps.maxCombinedShaderStorageBlocks))
......
...@@ -365,6 +365,84 @@ TEST_P(GeometryShaderTest, UniformMismatchBetweenGeometryAndFragmentShader) ...@@ -365,6 +365,84 @@ TEST_P(GeometryShaderTest, UniformMismatchBetweenGeometryAndFragmentShader)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Verify that an link error occurs when the number of uniform blocks in a geometry shader exceeds
// MAX_GEOMETRY_UNIFORM_BLOCKS_EXT.
TEST_P(GeometryShaderTest, TooManyUniformBlocks)
{
ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_geometry_shader"));
GLint maxGeometryUniformBlocks = 0;
glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT, &maxGeometryUniformBlocks);
GLint numUniformBlocks = maxGeometryUniformBlocks + 1;
std::ostringstream stream;
stream << "#version 310 es\n"
"#extension GL_EXT_geometry_shader : require\n"
"uniform ubo\n"
"{\n"
" vec4 value1;\n"
"} block0["
<< numUniformBlocks
<< "];\n"
"layout (triangles) in;\n"
"layout (points, max_vertices = 1) out;\n"
"void main()\n"
"{\n"
" gl_Position = gl_in[0].gl_Position;\n";
for (GLint i = 0; i < numUniformBlocks; ++i)
{
stream << " gl_Position += block0[" << i << "].value1;\n";
}
stream << " EmitVertex();\n"
"}\n";
GLuint program =
CompileProgramWithGS(kDefaultVertexShader, stream.str(), kDefaultFragmentShader);
EXPECT_EQ(0u, program);
EXPECT_GL_NO_ERROR();
}
// Verify that an link error occurs when the number of shader storage blocks in a geometry shader
// exceeds MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT.
TEST_P(GeometryShaderTest, TooManyShaderStorageBlocks)
{
ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_geometry_shader"));
GLint maxGeometryShaderStorageBlocks = 0;
glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
GLint numSSBOs = maxGeometryShaderStorageBlocks + 1;
std::ostringstream stream;
stream << "#version 310 es\n"
"#extension GL_EXT_geometry_shader : require\n"
"buffer ssbo\n"
"{\n"
" vec4 value1;\n"
"} block0["
<< numSSBOs
<< "];\n"
"layout (triangles) in;\n"
"layout (points, max_vertices = 1) out;\n"
"void main()\n"
"{\n"
" gl_Position = gl_in[0].gl_Position;\n";
for (GLint i = 0; i < numSSBOs; ++i)
{
stream << " gl_Position += block0[" << i << "].value1;\n";
}
stream << " EmitVertex();\n"
"}\n";
GLuint program =
CompileProgramWithGS(kDefaultVertexShader, stream.str(), kDefaultFragmentShader);
EXPECT_EQ(0u, program);
EXPECT_GL_NO_ERROR();
}
ANGLE_INSTANTIATE_TEST(GeometryShaderTestES3, ES3_OPENGL(), ES3_OPENGLES(), ES3_D3D11()); ANGLE_INSTANTIATE_TEST(GeometryShaderTestES3, ES3_OPENGL(), ES3_OPENGLES(), ES3_D3D11());
ANGLE_INSTANTIATE_TEST(GeometryShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11()); ANGLE_INSTANTIATE_TEST(GeometryShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
} }
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