summaryrefslogtreecommitdiffstats
path: root/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main')
-rw-r--r--src/mesa/main/bufferobj.c58
-rw-r--r--src/mesa/main/config.h5
-rw-r--r--src/mesa/main/context.c9
-rw-r--r--src/mesa/main/extensions.c1
-rw-r--r--src/mesa/main/get.c40
-rw-r--r--src/mesa/main/get_hash_params.py12
-rw-r--r--src/mesa/main/mtypes.h59
-rw-r--r--src/mesa/main/shaderapi.c6
-rw-r--r--src/mesa/main/uniform_query.cpp14
-rw-r--r--src/mesa/main/uniforms.c62
10 files changed, 263 insertions, 3 deletions
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;
+ }
}