Commit 361df070 by Jiawei Shao Committed by Commit Bot

ES31: Implement Geometry Shader resource queries on OpenGL

This patch intends to implement all geometry shader related resource queries on OpenGL back-ends. This patch also fixes a memory leak by releasing the geometry shader compiler handle in the destructor of the Compiler. BUG=angleproject:1941, angleproject:2261 TEST=angle_end2end_tests Change-Id: Ieb69c162d2fc6c6550e145d1ec7948c3d36d4d15 Reviewed-on: https://chromium-review.googlesource.com/784552Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
parent 94f1e89f
...@@ -228,9 +228,7 @@ Extensions::Extensions() ...@@ -228,9 +228,7 @@ Extensions::Extensions()
robustResourceInitialization(false), robustResourceInitialization(false),
programCacheControl(false), programCacheControl(false),
textureRectangle(false), textureRectangle(false),
geometryShader(false), geometryShader(false)
maxGeometryOutputVertices(0),
maxGeometryShaderInvocations(0)
{ {
} }
...@@ -849,7 +847,28 @@ Caps::Caps() ...@@ -849,7 +847,28 @@ Caps::Caps()
maxTransformFeedbackSeparateComponents(0), maxTransformFeedbackSeparateComponents(0),
// Table 20.49 // Table 20.49
maxSamples(0) maxSamples(0),
// Table 20.40 (cont.) (GL_EXT_geometry_shader)
maxFramebufferLayers(0),
layerProvokingVertex(0),
// Table 20.43gs (GL_EXT_geometry_shader)
maxGeometryUniformComponents(0),
maxGeometryUniformBlocks(0),
maxGeometryInputComponents(0),
maxGeometryOutputComponents(0),
maxGeometryOutputVertices(0),
maxGeometryTotalOutputComponents(0),
maxGeometryTextureImageUnits(0),
maxGeometryAtomicCounterBuffers(0),
maxGeometryAtomicCounters(0),
maxGeometryShaderStorageBlocks(0),
maxGeometryShaderInvocations(0),
// Table 20.46 (GL_EXT_geometry_shader)
maxGeometryImageUniforms(0),
maxCombinedGeometryUniformComponents(0)
{ {
for (size_t i = 0; i < 3; ++i) for (size_t i = 0; i < 3; ++i)
{ {
...@@ -1053,6 +1072,37 @@ Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensi ...@@ -1053,6 +1072,37 @@ Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensi
caps.maxRectangleTextureSize = 64; caps.maxRectangleTextureSize = 64;
} }
if (extensions.geometryShader)
{
// Table 20.40 (GL_EXT_geometry_shader)
caps.maxFramebufferLayers = 256;
caps.layerProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
// Table 20.43gs (GL_EXT_geometry_shader)
caps.maxGeometryUniformComponents = 1024;
caps.maxGeometryUniformBlocks = 12;
caps.maxGeometryInputComponents = 64;
caps.maxGeometryOutputComponents = 64;
caps.maxGeometryOutputVertices = 256;
caps.maxGeometryTotalOutputComponents = 1024;
caps.maxGeometryTextureImageUnits = 16;
caps.maxGeometryAtomicCounterBuffers = 0;
caps.maxGeometryAtomicCounters = 0;
caps.maxGeometryShaderStorageBlocks = 0;
caps.maxGeometryShaderInvocations = 32;
// Table 20.46 (GL_EXT_geometry_shader)
caps.maxGeometryImageUniforms = 0;
caps.maxCombinedGeometryUniformComponents =
caps.maxGeometryUniformBlocks * static_cast<GLuint>(caps.maxUniformBlockSize / 4) +
caps.maxGeometryUniformComponents;
// Table 20.46 (GL_EXT_geometry_shader)
caps.maxUniformBufferBindings = 48;
caps.maxCombinedUniformBlocks = 36;
caps.maxCombinedTextureImageUnits = 64;
}
return caps; return caps;
} }
} }
......
...@@ -373,11 +373,6 @@ struct Extensions ...@@ -373,11 +373,6 @@ struct Extensions
// GL_EXT_geometry_shader // GL_EXT_geometry_shader
bool geometryShader; bool geometryShader;
// GL_EXT_geometry_shader (May 31, 2016) Table 20.43gs: Implementation dependent geometry shader
// limits
// TODO(jiawei.shao@intel.com): add all implementation dependent geometry shader limits.
GLuint maxGeometryOutputVertices;
GLuint maxGeometryShaderInvocations;
}; };
struct ExtensionInfo struct ExtensionInfo
...@@ -562,6 +557,29 @@ struct Caps ...@@ -562,6 +557,29 @@ struct Caps
// ES 3.1 (April 29, 2015) Table 20.49: Framebuffer Dependent Values // ES 3.1 (April 29, 2015) Table 20.49: Framebuffer Dependent Values
GLuint maxSamples; GLuint maxSamples;
// GL_EXT_geometry_shader (May 31, 2016) Table 20.40: Implementation-Dependent Values (cont.)
GLuint maxFramebufferLayers;
GLuint layerProvokingVertex;
// GL_EXT_geometry_shader (May 31, 2016) Table 20.43gs: Implementation dependent geometry shader
// limits
GLuint maxGeometryUniformComponents;
GLuint maxGeometryUniformBlocks;
GLuint maxGeometryInputComponents;
GLuint maxGeometryOutputComponents;
GLuint maxGeometryOutputVertices;
GLuint maxGeometryTotalOutputComponents;
GLuint maxGeometryTextureImageUnits;
GLuint maxGeometryAtomicCounterBuffers;
GLuint maxGeometryAtomicCounters;
GLuint maxGeometryShaderStorageBlocks;
GLuint maxGeometryShaderInvocations;
// GL_EXT_geometry_shader (May 31, 2016) Table 20.46: Implementation dependent aggregate shader
// limits
GLuint maxGeometryImageUniforms;
GLuint maxCombinedGeometryUniformComponents;
}; };
Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensions); Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensions);
......
...@@ -132,10 +132,20 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state) ...@@ -132,10 +132,20 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
} }
// Geometry Shader constants // Geometry Shader constants
// TODO(jiawei.shao@intel.com): use EXT_geometry_shader everywhere in compiler.
mResources.OES_geometry_shader = extensions.geometryShader; mResources.OES_geometry_shader = extensions.geometryShader;
// TODO(jiawei.shao@intel.com): initialize all implementation dependent geometry shader limits. mResources.MaxGeometryUniformComponents = caps.maxGeometryUniformComponents;
mResources.MaxGeometryOutputVertices = extensions.maxGeometryOutputVertices; mResources.MaxGeometryUniformBlocks = caps.maxGeometryUniformBlocks;
mResources.MaxGeometryShaderInvocations = extensions.maxGeometryShaderInvocations; mResources.MaxGeometryInputComponents = caps.maxGeometryInputComponents;
mResources.MaxGeometryOutputComponents = caps.maxGeometryOutputComponents;
mResources.MaxGeometryOutputVertices = caps.maxGeometryOutputVertices;
mResources.MaxGeometryTotalOutputComponents = caps.maxGeometryTotalOutputComponents;
mResources.MaxGeometryTextureImageUnits = caps.maxGeometryTextureImageUnits;
mResources.MaxGeometryAtomicCounterBuffers = caps.maxGeometryAtomicCounterBuffers;
mResources.MaxGeometryAtomicCounters = caps.maxGeometryAtomicCounters;
mResources.MaxGeometryShaderStorageBlocks = caps.maxGeometryShaderStorageBlocks;
mResources.MaxGeometryShaderInvocations = caps.maxGeometryShaderInvocations;
mResources.MaxGeometryImageUniforms = caps.maxGeometryImageUniforms;
} }
Compiler::~Compiler() Compiler::~Compiler()
...@@ -167,6 +177,15 @@ Compiler::~Compiler() ...@@ -167,6 +177,15 @@ Compiler::~Compiler()
activeCompilerHandles--; activeCompilerHandles--;
} }
if (mGeometryCompiler)
{
sh::Destruct(mGeometryCompiler);
mGeometryCompiler = nullptr;
ASSERT(activeCompilerHandles > 0);
activeCompilerHandles--;
}
if (activeCompilerHandles == 0) if (activeCompilerHandles == 0)
{ {
sh::Finalize(); sh::Finalize();
......
...@@ -1508,6 +1508,53 @@ void Context::getIntegervImpl(GLenum pname, GLint *params) ...@@ -1508,6 +1508,53 @@ void Context::getIntegervImpl(GLenum pname, GLint *params)
case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT: case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
*params = mCaps.shaderStorageBufferOffsetAlignment; *params = mCaps.shaderStorageBufferOffsetAlignment;
break; break;
// GL_EXT_geometry_shader
case GL_MAX_FRAMEBUFFER_LAYERS_EXT:
*params = mCaps.maxFramebufferLayers;
break;
case GL_LAYER_PROVOKING_VERTEX_EXT:
*params = mCaps.layerProvokingVertex;
break;
case GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT:
*params = mCaps.maxGeometryUniformComponents;
break;
case GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT:
*params = mCaps.maxGeometryUniformBlocks;
break;
case GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT:
*params = mCaps.maxCombinedGeometryUniformComponents;
break;
case GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT:
*params = mCaps.maxGeometryInputComponents;
break;
case GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT:
*params = mCaps.maxGeometryOutputComponents;
break;
case GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT:
*params = mCaps.maxGeometryOutputVertices;
break;
case GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT:
*params = mCaps.maxGeometryTotalOutputComponents;
break;
case GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT:
*params = mCaps.maxGeometryShaderInvocations;
break;
case GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT:
*params = mCaps.maxGeometryTextureImageUnits;
break;
case GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT:
*params = mCaps.maxGeometryAtomicCounterBuffers;
break;
case GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT:
*params = mCaps.maxGeometryAtomicCounters;
break;
case GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT:
*params = mCaps.maxGeometryImageUniforms;
break;
case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT:
*params = mCaps.maxGeometryShaderStorageBlocks;
break;
default: default:
mGLState.getIntegerv(this, pname, params); mGLState.getIntegerv(this, pname, params);
break; break;
......
...@@ -721,6 +721,31 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign ...@@ -721,6 +721,31 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
return true; return true;
} }
if (getExtensions().geometryShader)
{
switch (pname)
{
case GL_MAX_FRAMEBUFFER_LAYERS_EXT:
case GL_LAYER_PROVOKING_VERTEX_EXT:
case GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT:
case GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT:
case GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT:
case GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT:
case GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT:
case GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT:
case GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT:
case GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT:
case GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT:
case GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT:
case GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT:
case GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT:
case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT:
*type = GL_INT;
*numParams = 1;
return true;
}
}
return false; return false;
} }
......
...@@ -1017,20 +1017,69 @@ void GenerateCaps(const FunctionsGL *functions, ...@@ -1017,20 +1017,69 @@ void GenerateCaps(const FunctionsGL *functions,
QuerySingleGLInt(functions, GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE); QuerySingleGLInt(functions, GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE);
} }
// We need at least OpenGL 4.3 to support all features and constants defined in // OpenGL 4.3 (and above) can support all features and constants defined in
// GL_EXT_geometry_shader. // GL_EXT_geometry_shader.
if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 2)) || if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 2)) ||
functions->hasGLESExtension("GL_OES_geometry_shader") || functions->hasGLESExtension("GL_OES_geometry_shader") ||
functions->hasGLESExtension("GL_EXT_geometry_shader")) functions->hasGLESExtension("GL_EXT_geometry_shader") ||
// OpenGL 4.0 adds the support for instanced geometry shader
// GL_ARB_shader_atomic_counters adds atomic counters to geometry shader
// GL_ARB_shader_storage_buffer_object adds shader storage buffers to geometry shader
// GL_ARB_shader_image_load_store adds images to geometry shader
(functions->isAtLeastGL(gl::Version(4, 0)) &&
functions->hasGLExtension("GL_ARB_shader_atomic_counters") &&
functions->hasGLExtension("GL_ARB_shader_storage_buffer_object") &&
functions->hasGLExtension("GL_ARB_shader_image_load_store")))
{ {
extensions->geometryShader = true; extensions->geometryShader = true;
// TODO(jiawei.shao@intel.com): initialize all implementation dependent geometry shader caps->maxFramebufferLayers = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_LAYERS_EXT);
// limits.
extensions->maxGeometryOutputVertices = // GL_PROVOKING_VERTEX isn't a valid return value of GL_LAYER_PROVOKING_VERTEX_EXT in
// GL_EXT_geometry_shader SPEC, however it is legal in desktop OpenGL, which means the value
// follows the one set by glProvokingVertex.
// [OpenGL 4.3] Chapter 11.3.4.6
// The vertex conventions followed for gl_Layer and gl_ViewportIndex may be determined by
// calling GetIntegerv with the symbolic constants LAYER_PROVOKING_VERTEX and
// VIEWPORT_INDEX_PROVOKING_VERTEX, respectively. For either query, if the value returned is
// PROVOKING_VERTEX, then vertex selection follows the convention specified by
// ProvokingVertex.
caps->layerProvokingVertex = QuerySingleGLInt(functions, GL_LAYER_PROVOKING_VERTEX_EXT);
if (caps->layerProvokingVertex == GL_PROVOKING_VERTEX)
{
// We should use GL_LAST_VERTEX_CONVENTION_EXT instead because desktop OpenGL SPEC
// requires the initial value of provoking vertex mode is LAST_VERTEX_CONVENTION.
// [OpenGL 4.3] Chapter 13.4
// The initial value of the provoking vertex mode is LAST_VERTEX_CONVENTION.
caps->layerProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
}
caps->maxGeometryUniformComponents =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT);
caps->maxGeometryUniformBlocks =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT);
caps->maxCombinedGeometryUniformComponents =
QuerySingleGLInt(functions, GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT);
caps->maxGeometryInputComponents =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT);
caps->maxGeometryOutputComponents =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT);
caps->maxGeometryOutputVertices =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT); QuerySingleGLInt(functions, GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT);
extensions->maxGeometryShaderInvocations = caps->maxGeometryTotalOutputComponents =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT);
caps->maxGeometryShaderInvocations =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT); QuerySingleGLInt(functions, GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT);
caps->maxGeometryTextureImageUnits =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT);
caps->maxGeometryAtomicCounterBuffers =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT);
caps->maxGeometryAtomicCounters =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT);
caps->maxGeometryImageUniforms =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT);
caps->maxGeometryShaderStorageBlocks =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT);
} }
} }
......
...@@ -87,6 +87,7 @@ ContextNULL::ContextNULL(const gl::ContextState &state, AllocationTrackerNULL *a ...@@ -87,6 +87,7 @@ ContextNULL::ContextNULL(const gl::ContextState &state, AllocationTrackerNULL *a
mExtensions.textureCompressionASTCLDR = true; mExtensions.textureCompressionASTCLDR = true;
mExtensions.compressedETC1RGB8Texture = true; mExtensions.compressedETC1RGB8Texture = true;
mExtensions.lossyETCDecode = true; mExtensions.lossyETCDecode = true;
mExtensions.geometryShader = true;
const gl::Version maxClientVersion(3, 1); const gl::Version maxClientVersion(3, 1);
mCaps = GenerateMinimumCaps(maxClientVersion, mExtensions); mCaps = GenerateMinimumCaps(maxClientVersion, mExtensions);
......
...@@ -69,6 +69,64 @@ TEST_P(GeometryShaderTest, CreateAndAttachGeometryShader) ...@@ -69,6 +69,64 @@ TEST_P(GeometryShaderTest, CreateAndAttachGeometryShader)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Verify that all the implementation dependent geometry shader related resource limits meet the
// requirement of GL_EXT_geometry_shader SPEC.
TEST_P(GeometryShaderTest, GeometryShaderImplementationDependentLimits)
{
ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_geometry_shader"));
const std::map<GLenum, int> limits = {{GL_MAX_FRAMEBUFFER_LAYERS_EXT, 256},
{GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT, 1024},
{GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT, 12},
{GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT, 64},
{GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT, 64},
{GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, 256},
{GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT, 1024},
{GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT, 16},
{GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT, 0},
{GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT, 0},
{GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, 0},
{GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT, 0},
{GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT, 32}};
GLint value;
for (const auto &limit : limits)
{
value = 0;
glGetIntegerv(limit.first, &value);
EXPECT_GL_NO_ERROR();
EXPECT_GE(value, limit.second);
}
value = 0;
glGetIntegerv(GL_LAYER_PROVOKING_VERTEX_EXT, &value);
EXPECT_GL_NO_ERROR();
EXPECT_TRUE(value == GL_FIRST_VERTEX_CONVENTION_EXT || value == GL_LAST_VERTEX_CONVENTION_EXT ||
value == GL_UNDEFINED_VERTEX_EXT);
}
// Verify that all the combined resource limits meet the requirement of GL_EXT_geometry_shader SPEC.
TEST_P(GeometryShaderTest, CombinedResourceLimits)
{
ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_geometry_shader"));
// See http://anglebug.com/2261.
ANGLE_SKIP_TEST_IF(IsAndroid());
const std::map<GLenum, int> limits = {{GL_MAX_UNIFORM_BUFFER_BINDINGS, 48},
{GL_MAX_COMBINED_UNIFORM_BLOCKS, 36},
{GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 64}};
GLint value;
for (const auto &limit : limits)
{
value = 0;
glGetIntegerv(limit.first, &value);
EXPECT_GL_NO_ERROR();
EXPECT_GE(value, limit.second);
}
}
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