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()
robustResourceInitialization(false),
programCacheControl(false),
textureRectangle(false),
geometryShader(false),
maxGeometryOutputVertices(0),
maxGeometryShaderInvocations(0)
geometryShader(false)
{
}
......@@ -849,7 +847,28 @@ Caps::Caps()
maxTransformFeedbackSeparateComponents(0),
// 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)
{
......@@ -1053,6 +1072,37 @@ Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensi
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;
}
}
......
......@@ -373,11 +373,6 @@ struct Extensions
// GL_EXT_geometry_shader
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
......@@ -562,6 +557,29 @@ struct Caps
// ES 3.1 (April 29, 2015) Table 20.49: Framebuffer Dependent Values
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);
......
......@@ -132,10 +132,20 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
}
// Geometry Shader constants
// TODO(jiawei.shao@intel.com): use EXT_geometry_shader everywhere in compiler.
mResources.OES_geometry_shader = extensions.geometryShader;
// TODO(jiawei.shao@intel.com): initialize all implementation dependent geometry shader limits.
mResources.MaxGeometryOutputVertices = extensions.maxGeometryOutputVertices;
mResources.MaxGeometryShaderInvocations = extensions.maxGeometryShaderInvocations;
mResources.MaxGeometryUniformComponents = caps.maxGeometryUniformComponents;
mResources.MaxGeometryUniformBlocks = caps.maxGeometryUniformBlocks;
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()
......@@ -167,6 +177,15 @@ Compiler::~Compiler()
activeCompilerHandles--;
}
if (mGeometryCompiler)
{
sh::Destruct(mGeometryCompiler);
mGeometryCompiler = nullptr;
ASSERT(activeCompilerHandles > 0);
activeCompilerHandles--;
}
if (activeCompilerHandles == 0)
{
sh::Finalize();
......
......@@ -1508,6 +1508,53 @@ void Context::getIntegervImpl(GLenum pname, GLint *params)
case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
*params = mCaps.shaderStorageBufferOffsetAlignment;
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:
mGLState.getIntegerv(this, pname, params);
break;
......
......@@ -721,6 +721,31 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
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;
}
......
......@@ -1017,20 +1017,69 @@ void GenerateCaps(const FunctionsGL *functions,
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.
if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 2)) ||
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;
// TODO(jiawei.shao@intel.com): initialize all implementation dependent geometry shader
// limits.
extensions->maxGeometryOutputVertices =
caps->maxFramebufferLayers = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_LAYERS_EXT);
// 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);
extensions->maxGeometryShaderInvocations =
caps->maxGeometryTotalOutputComponents =
QuerySingleGLInt(functions, GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT);
caps->maxGeometryShaderInvocations =
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
mExtensions.textureCompressionASTCLDR = true;
mExtensions.compressedETC1RGB8Texture = true;
mExtensions.lossyETCDecode = true;
mExtensions.geometryShader = true;
const gl::Version maxClientVersion(3, 1);
mCaps = GenerateMinimumCaps(maxClientVersion, mExtensions);
......
......@@ -69,6 +69,64 @@ TEST_P(GeometryShaderTest, CreateAndAttachGeometryShader)
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(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