diff options
-rw-r--r-- | src/glsl/ir_uniform.h | 7 | ||||
-rw-r--r-- | src/glsl/link_uniforms.cpp | 1 | ||||
-rw-r--r-- | src/mesa/main/bufferobj.c | 58 | ||||
-rw-r--r-- | src/mesa/main/config.h | 5 | ||||
-rw-r--r-- | src/mesa/main/context.c | 9 | ||||
-rw-r--r-- | src/mesa/main/extensions.c | 1 | ||||
-rw-r--r-- | src/mesa/main/get.c | 40 | ||||
-rw-r--r-- | src/mesa/main/get_hash_params.py | 12 | ||||
-rw-r--r-- | src/mesa/main/mtypes.h | 59 | ||||
-rw-r--r-- | src/mesa/main/shaderapi.c | 6 | ||||
-rw-r--r-- | src/mesa/main/uniform_query.cpp | 14 | ||||
-rw-r--r-- | src/mesa/main/uniforms.c | 62 |
12 files changed, 271 insertions, 3 deletions
diff --git a/src/glsl/ir_uniform.h b/src/glsl/ir_uniform.h index 8198c481983..13faab7c0a1 100644 --- a/src/glsl/ir_uniform.h +++ b/src/glsl/ir_uniform.h @@ -166,6 +166,13 @@ struct gl_uniform_storage { bool row_major; /** @} */ + + /** + * Index within gl_shader_program::AtomicBuffers[] of the atomic + * counter buffer this uniform is stored in, or -1 if this is not + * an atomic counter. + */ + int atomic_buffer_index; }; #ifdef __cplusplus diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp index ea71b3063ca..0a15739c265 100644 --- a/src/glsl/link_uniforms.cpp +++ b/src/glsl/link_uniforms.cpp @@ -513,6 +513,7 @@ private: this->uniforms[id].num_driver_storage = 0; this->uniforms[id].driver_storage = NULL; this->uniforms[id].storage = this->values; + this->uniforms[id].atomic_buffer_index = -1; if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this->ubo_block_index; diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 312ffb78888..1f5506157ca 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -102,6 +102,11 @@ get_buffer_target(struct gl_context *ctx, GLenum target) return &ctx->UniformBuffer; } break; + case GL_ATOMIC_COUNTER_BUFFER: + if (ctx->Extensions.ARB_shader_atomic_counters) { + return &ctx->AtomicBuffer; + } + break; default: return NULL; } @@ -2119,6 +2124,51 @@ bind_buffer_base_uniform_buffer(struct gl_context *ctx, set_ubo_binding(ctx, index, bufObj, 0, 0, GL_TRUE); } +static void +set_atomic_buffer_binding(struct gl_context *ctx, + unsigned index, + struct gl_buffer_object *bufObj, + GLintptr offset, + GLsizeiptr size, + const char *name) +{ + struct gl_atomic_buffer_binding *binding; + + if (index >= ctx->Const.MaxAtomicBufferBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d)", name, index); + return; + } + + if (offset & (ATOMIC_COUNTER_SIZE - 1)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(offset misalgned %d/%d)", name, (int) offset, + ATOMIC_COUNTER_SIZE); + return; + } + + _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj); + + binding = &ctx->AtomicBufferBindings[index]; + if (binding->BufferObject == bufObj && + binding->Offset == offset && + binding->Size == size) { + return; + } + + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer; + + _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj); + + if (bufObj == ctx->Shared->NullBufferObj) { + binding->Offset = -1; + binding->Size = -1; + } else { + binding->Offset = offset; + binding->Size = size; + } +} + void GLAPIENTRY _mesa_BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) @@ -2156,6 +2206,10 @@ _mesa_BindBufferRange(GLenum target, GLuint index, case GL_UNIFORM_BUFFER: bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size); return; + case GL_ATOMIC_COUNTER_BUFFER: + set_atomic_buffer_binding(ctx, index, bufObj, offset, size, + "glBindBufferRange"); + return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)"); return; @@ -2215,6 +2269,10 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) case GL_UNIFORM_BUFFER: bind_buffer_base_uniform_buffer(ctx, index, bufObj); return; + case GL_ATOMIC_COUNTER_BUFFER: + set_atomic_buffer_binding(ctx, index, bufObj, 0, 0, + "glBindBufferBase"); + return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)"); return; diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h index 0bcf27c345b..22bbfa0cf31 100644 --- a/src/mesa/main/config.h +++ b/src/mesa/main/config.h @@ -170,6 +170,11 @@ #define MAX_UNIFORM_BUFFERS 15 /* + 1 default uniform buffer */ /* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */ #define MAX_COMBINED_UNIFORM_BUFFERS (MAX_UNIFORM_BUFFERS * 6) +#define MAX_ATOMIC_COUNTERS 4096 +/* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */ +#define MAX_COMBINED_ATOMIC_BUFFERS (MAX_UNIFORM_BUFFERS * 6) +/* Size of an atomic counter in bytes according to ARB_shader_atomic_counters */ +#define ATOMIC_COUNTER_SIZE 4 /*@}*/ /** diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 0d1f71c7142..6cdeed19b0a 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -537,6 +537,9 @@ init_program_limits(struct gl_context *ctx, GLenum type, prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents + ctx->Const.MaxUniformBlockSize / 4 * prog->MaxUniformBlocks); + + prog->MaxAtomicBuffers = 0; + prog->MaxAtomicCounters = 0; } @@ -669,6 +672,12 @@ _mesa_init_constants(struct gl_context *ctx) ctx->Const.MaxColorTextureSamples = 1; ctx->Const.MaxDepthTextureSamples = 1; ctx->Const.MaxIntegerSamples = 1; + + /* GL_ARB_shader_atomic_counters */ + ctx->Const.MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS; + ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE; + ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS; + ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS; } diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 00d65ccb04d..285ec377cfd 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -120,6 +120,7 @@ static const struct extension extension_table[] = { { "GL_ARB_robustness", o(dummy_true), GL, 2010 }, { "GL_ARB_sampler_objects", o(dummy_true), GL, 2009 }, { "GL_ARB_seamless_cube_map", o(ARB_seamless_cube_map), GL, 2009 }, + { "GL_ARB_shader_atomic_counters", o(ARB_shader_atomic_counters), GL, 2011 }, { "GL_ARB_shader_bit_encoding", o(ARB_shader_bit_encoding), GL, 2010 }, { "GL_ARB_shader_objects", o(dummy_true), GL, 2002 }, { "GL_ARB_shader_stencil_export", o(ARB_shader_stencil_export), GL, 2009 }, diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index 89b3bf09ddb..6e72ff5c298 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -143,6 +143,7 @@ enum value_extra { EXTRA_FLUSH_CURRENT, EXTRA_GLSL_130, EXTRA_EXT_UBO_GS4, + EXTRA_EXT_ATOMICS_GS4, }; #define NO_EXTRA NULL @@ -331,6 +332,11 @@ static const int extra_MESA_texture_array_es3[] = { EXTRA_END }; +static const int extra_ARB_shader_atomic_counters_and_geometry_shader[] = { + EXTRA_EXT_ATOMICS_GS4, + EXTRA_END +}; + EXTRA_EXT(ARB_texture_cube_map); EXTRA_EXT(MESA_texture_array); EXTRA_EXT(NV_fog_distance); @@ -367,6 +373,7 @@ EXTRA_EXT(ARB_texture_cube_map_array); EXTRA_EXT(ARB_texture_buffer_range); EXTRA_EXT(ARB_texture_multisample); EXTRA_EXT(ARB_texture_gather); +EXTRA_EXT(ARB_shader_atomic_counters); static const int extra_ARB_color_buffer_float_or_glcore[] = { @@ -894,6 +901,10 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu _mesa_problem(ctx, "driver doesn't implement GetTimestamp"); } break; + /* GL_ARB_shader_atomic_counters */ + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + v->value_int = ctx->AtomicBuffer->Name; + break; } } @@ -999,6 +1010,11 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d api_found = (ctx->Extensions.ARB_uniform_buffer_object && _mesa_has_geometry_shaders(ctx)); break; + case EXTRA_EXT_ATOMICS_GS4: + api_check = GL_TRUE; + api_found = (ctx->Extensions.ARB_shader_atomic_counters && + _mesa_has_geometry_shaders(ctx)); + break; case EXTRA_END: break; default: /* *e is a offset into the extension struct */ @@ -1692,6 +1708,30 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) goto invalid_enum; v->value_int = ctx->Multisample.SampleMaskValue; return TYPE_INT; + + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + if (!ctx->Extensions.ARB_shader_atomic_counters) + goto invalid_enum; + if (index >= ctx->Const.MaxAtomicBufferBindings) + goto invalid_value; + v->value_int = ctx->AtomicBufferBindings[index].BufferObject->Name; + return TYPE_INT; + + case GL_ATOMIC_COUNTER_BUFFER_START: + if (!ctx->Extensions.ARB_shader_atomic_counters) + goto invalid_enum; + if (index >= ctx->Const.MaxAtomicBufferBindings) + goto invalid_value; + v->value_int64 = ctx->AtomicBufferBindings[index].Offset; + return TYPE_INT64; + + case GL_ATOMIC_COUNTER_BUFFER_SIZE: + if (!ctx->Extensions.ARB_shader_atomic_counters) + goto invalid_enum; + if (index >= ctx->Const.MaxAtomicBufferBindings) + goto invalid_value; + v->value_int64 = ctx->AtomicBufferBindings[index].Size; + return TYPE_INT64; } invalid_enum: diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py index 9c54af094d7..9f79f340683 100644 --- a/src/mesa/main/get_hash_params.py +++ b/src/mesa/main/get_hash_params.py @@ -722,6 +722,18 @@ descriptor=[ [ "MAX_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MaxProgramTextureGatherOffset), extra_ARB_texture_gather"], [ "MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB", "CONTEXT_INT(Const.MaxProgramTextureGatherComponents), extra_ARB_texture_gather"], +# GL_ARB_shader_atomic_counters + [ "ATOMIC_COUNTER_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_atomic_counters" ], + [ "MAX_ATOMIC_COUNTER_BUFFER_BINDINGS", "CONTEXT_INT(Const.MaxAtomicBufferBindings), extra_ARB_shader_atomic_counters" ], + [ "MAX_ATOMIC_COUNTER_BUFFER_SIZE", "CONTEXT_INT(Const.MaxAtomicBufferSize), extra_ARB_shader_atomic_counters" ], + [ "MAX_VERTEX_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.VertexProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ], + [ "MAX_VERTEX_ATOMIC_COUNTERS", "CONTEXT_INT(Const.VertexProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters" ], + [ "MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.FragmentProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ], + [ "MAX_FRAGMENT_ATOMIC_COUNTERS", "CONTEXT_INT(Const.FragmentProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters" ], + [ "MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters_and_geometry_shader" ], + [ "MAX_GEOMETRY_ATOMIC_COUNTERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_geometry_shader" ], + [ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters" ], + [ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters" ], ]}, # Enums restricted to OpenGL Core profile diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 824e33906fd..a1a5eb4bf13 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2375,6 +2375,25 @@ struct gl_uniform_block enum gl_uniform_block_packing _Packing; }; +/** + * Structure that represents a reference to an atomic buffer from some + * shader program. + */ +struct gl_active_atomic_buffer +{ + /** Uniform indices of the atomic counters declared within it. */ + GLuint *Uniforms; + GLuint NumUniforms; + + /** Binding point index associated with it. */ + GLuint Binding; + + /** Minimum reasonable size it is expected to have. */ + GLuint MinimumSize; + + /** Shader stages making use of it. */ + GLboolean StageReferences[MESA_SHADER_TYPES]; +}; /** * A GLSL program object. @@ -2523,6 +2542,9 @@ struct gl_shader_program */ struct string_to_uint_map *UniformHash; + struct gl_active_atomic_buffer *AtomicBuffers; + unsigned NumAtomicBuffers; + GLboolean LinkStatus; /**< GL_LINK_STATUS */ GLboolean Validated; GLboolean _Used; /**< Ever used for drawing? */ @@ -2960,6 +2982,9 @@ struct gl_program_constants GLuint MaxUniformBlocks; GLuint MaxCombinedUniformComponents; GLuint MaxTextureImageUnits; + /* GL_ARB_shader_atomic_counters */ + GLuint MaxAtomicBuffers; + GLuint MaxAtomicCounters; }; @@ -3166,6 +3191,12 @@ struct gl_constants GLint MaxColorTextureSamples; GLint MaxDepthTextureSamples; GLint MaxIntegerSamples; + + /** GL_ARB_shader_atomic_counters */ + GLuint MaxAtomicBufferBindings; + GLuint MaxAtomicBufferSize; + GLuint MaxCombinedAtomicBuffers; + GLuint MaxCombinedAtomicCounters; }; @@ -3209,6 +3240,7 @@ struct gl_extensions GLboolean ARB_occlusion_query2; GLboolean ARB_point_sprite; GLboolean ARB_seamless_cube_map; + GLboolean ARB_shader_atomic_counters; GLboolean ARB_shader_bit_encoding; GLboolean ARB_shader_stencil_export; GLboolean ARB_shader_texture_lod; @@ -3582,6 +3614,11 @@ struct gl_driver_flags * gl_shader_program::UniformBlocks */ GLbitfield NewUniformBuffer; + + /** + * gl_context::AtomicBufferBindings + */ + GLbitfield NewAtomicBuffer; }; struct gl_uniform_buffer_binding @@ -3599,6 +3636,16 @@ struct gl_uniform_buffer_binding }; /** + * Binding point for an atomic counter buffer object. + */ +struct gl_atomic_buffer_binding +{ + struct gl_buffer_object *BufferObject; + GLintptr Offset; + GLsizeiptr Size; +}; + +/** * Mesa rendering context. * * This is the central context data structure for Mesa. Almost all @@ -3766,6 +3813,18 @@ struct gl_context struct gl_uniform_buffer_binding UniformBufferBindings[MAX_COMBINED_UNIFORM_BUFFERS]; + /** + * Object currently associated with the GL_ATOMIC_COUNTER_BUFFER + * target. + */ + struct gl_buffer_object *AtomicBuffer; + + /** + * Array of atomic counter buffer binding points. + */ + struct gl_atomic_buffer_binding + AtomicBufferBindings[MAX_COMBINED_ATOMIC_BUFFERS]; + /*@}*/ struct gl_meta_state *Meta; /**< for "meta" operations */ diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index f5c04b9f38f..4a6bd73d446 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -648,6 +648,12 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param case GL_PROGRAM_BINARY_LENGTH: *params = 0; return; + case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS: + if (!ctx->Extensions.ARB_shader_atomic_counters) + break; + + *params = shProg->NumAtomicBuffers; + return; default: break; } diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp index 3c460042eee..88ad476acb9 100644 --- a/src/mesa/main/uniform_query.cpp +++ b/src/mesa/main/uniform_query.cpp @@ -154,11 +154,21 @@ _mesa_GetActiveUniformsiv(GLuint program, params[i] = uni->row_major; break; + case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX: + if (!ctx->Extensions.ARB_shader_atomic_counters) + goto invalid_enum; + params[i] = uni->atomic_buffer_index; + break; + default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)"); - return; + goto invalid_enum; } } + + return; + + invalid_enum: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)"); } static bool diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index 07e7ea37998..2e847fe3147 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -535,7 +535,8 @@ _mesa_GetUniformLocation(GLhandleARB programObj, const GLcharARB *name) * with a named uniform block, or if <name> starts with the reserved * prefix "gl_"." */ - if (shProg->UniformStorage[index].block_index != -1) + if (shProg->UniformStorage[index].block_index != -1 || + shProg->UniformStorage[index].atomic_buffer_index != -1) return -1; return _mesa_uniform_merge_location_offset(shProg, index, offset); @@ -849,4 +850,63 @@ void GLAPIENTRY _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex, GLenum pname, GLint *params) { + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg; + struct gl_active_atomic_buffer *ab; + int i; + + if (!ctx->Extensions.ARB_shader_atomic_counters) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetActiveAtomicCounterBufferiv"); + return; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glGetActiveAtomicCounterBufferiv"); + if (!shProg) + return; + + if (bufferIndex >= shProg->NumAtomicBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetActiveAtomicCounterBufferiv(bufferIndex)"); + return; + } + + ab = &shProg->AtomicBuffers[bufferIndex]; + + switch (pname) { + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + params[0] = ab->Binding; + return; + case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE: + params[0] = ab->MinimumSize; + return; + case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS: + params[0] = ab->NumUniforms; + return; + case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES: + for (i = 0; i < ab->NumUniforms; ++i) + params[i] = ab->Uniforms[i]; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER: + params[0] = ab->StageReferences[MESA_SHADER_VERTEX]; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER: + params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY]; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER: + params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT]; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER: + params[0] = GL_FALSE; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER: + params[0] = GL_FALSE; + return; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))", + pname, _mesa_lookup_enum_by_nr(pname)); + return; + } } |