struct gl_atomic_buffer_binding *binding,
struct gl_buffer_object *bufObj,
GLintptr offset,
- GLsizeiptr size)
+ GLsizeiptr size,
+ bool autoSize)
{
_mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
- if (bufObj == ctx->Shared->NullBufferObj) {
- binding->Offset = 0;
- binding->Size = 0;
- } else {
- binding->Offset = offset;
- binding->Size = size;
- bufObj->UsageHistory |= USAGE_ATOMIC_COUNTER_BUFFER;
- }
+ binding->Offset = offset;
+ binding->Size = size;
+ binding->AutomaticSize = autoSize;
+
+ /* If this is a real buffer object, mark it has having been used
+ * at some point as an atomic counter buffer.
+ */
+ if (size >= 0)
+ bufObj->UsageHistory |= USAGE_ATOMIC_COUNTER_BUFFER;
}
/**
set_ssbo_binding(ctx, binding, bufObj, offset, size, autoSize);
}
+/**
+ * Binds a buffer object to an atomic buffer binding point.
+ *
+ * Unlike set_atomic_binding(), this function also flushes vertices
+ * and updates NewDriverState. It also checks if the binding
+ * has actually changed before updating it.
+ */
+static void
+bind_atomic_buffer(struct gl_context *ctx, unsigned index,
+ struct gl_buffer_object *bufObj, GLintptr offset,
+ GLsizeiptr size, GLboolean autoSize)
+{
+ struct gl_atomic_buffer_binding *binding =
+ &ctx->AtomicBufferBindings[index];
+
+ if (binding->BufferObject == bufObj &&
+ binding->Offset == offset &&
+ binding->Size == size &&
+ binding->AutomaticSize == autoSize) {
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, 0);
+ ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
+
+ set_atomic_buffer_binding(ctx, binding, bufObj, offset, size, autoSize);
+}
+
/**
* Bind a buffer object to a uniform block binding point.
* As above, but offset = 0.
bind_shader_storage_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
}
+/**
+ * Bind a buffer object to a shader storage block binding point.
+ * As above, but offset = 0.
+ */
static void
-bind_atomic_buffer(struct gl_context *ctx, unsigned index,
- struct gl_buffer_object *bufObj, GLintptr offset,
- GLsizeiptr size)
+bind_buffer_base_atomic_buffer(struct gl_context *ctx,
+ GLuint index,
+ struct gl_buffer_object *bufObj)
{
- _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
-
- struct gl_atomic_buffer_binding *binding =
- &ctx->AtomicBufferBindings[index];
- if (binding->BufferObject == bufObj &&
- binding->Offset == offset &&
- binding->Size == size) {
+ if (index >= ctx->Const.MaxAtomicBufferBindings) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
return;
}
- FLUSH_VERTICES(ctx, 0);
- ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
+ _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
- set_atomic_buffer_binding(ctx, binding, bufObj, offset, size);
+ if (bufObj == ctx->Shared->NullBufferObj)
+ bind_atomic_buffer(ctx, index, bufObj, -1, -1, GL_TRUE);
+ else
+ bind_atomic_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
}
/**
/* unbind Atomci Buffer binding points */
for (j = 0; j < ctx->Const.MaxAtomicBufferBindings; j++) {
if (ctx->AtomicBufferBindings[j].BufferObject == bufObj) {
- _mesa_BindBufferBase( GL_ATOMIC_COUNTER_BUFFER, j, 0 );
- bind_atomic_buffer(ctx, j, ctx->Shared->NullBufferObj, 0, 0);
+ bind_buffer_base_atomic_buffer(ctx, j,
+ ctx->Shared->NullBufferObj);
}
}
bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset, size);
}
+static void
+bind_buffer_range_atomic_buffer(struct gl_context *ctx, GLuint index,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size)
+{
+ if (bufObj == ctx->Shared->NullBufferObj) {
+ offset = -1;
+ size = -1;
+ }
+
+ _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
+ bind_atomic_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
+}
+
/**
- * Binds a buffer object to an atomic buffer binding point.
- *
- * Unlike set_atomic_buffer_binding(), this function also validates the
- * index and offset, flushes vertices, and updates NewDriverState.
- * It also checks if the binding has actually changing before
- * updating it.
+ * Bind a region of a buffer object to an atomic storage block binding point.
+ * \param index the shader storage buffer binding point index
+ * \param bufObj the buffer object
+ * \param offset offset to the start of buffer object region
+ * \param size size of the buffer object region
*/
static void
-bind_atomic_buffer_err(struct gl_context *ctx, unsigned index,
- struct gl_buffer_object *bufObj, GLintptr offset,
- GLsizeiptr size, const char *name)
+bind_buffer_range_atomic_buffer_err(struct gl_context *ctx,
+ GLuint index,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size)
{
if (index >= ctx->Const.MaxAtomicBufferBindings) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d)", name, index);
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
return;
}
if (offset & (ATOMIC_COUNTER_SIZE - 1)) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "%s(offset misaligned %d/%d)", name, (int) offset,
- ATOMIC_COUNTER_SIZE);
+ "glBindBufferRange(offset misaligned %d/%d)", (int) offset,
+ ATOMIC_COUNTER_SIZE);
return;
}
- bind_atomic_buffer(ctx, index, bufObj, offset, size);
+ bind_buffer_range_atomic_buffer(ctx, index, bufObj, offset, size);
}
static inline bool
for (int i = 0; i < count; i++)
set_atomic_buffer_binding(ctx, &ctx->AtomicBufferBindings[first + i],
- bufObj, -1, -1);
+ bufObj, -1, -1, GL_TRUE);
}
static void
bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, caller);
if (bufObj)
- set_atomic_buffer_binding(ctx, binding, bufObj, offset, size);
+ if (bufObj == ctx->Shared->NullBufferObj)
+ set_atomic_buffer_binding(ctx, binding, bufObj, -1, -1, !range);
+ else
+ set_atomic_buffer_binding(ctx, binding, bufObj, offset, size, !range);
}
_mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
size);
return;
case GL_ATOMIC_COUNTER_BUFFER:
- bind_atomic_buffer(ctx, index, bufObj, offset, size);
+ bind_buffer_range_atomic_buffer(ctx, index, bufObj, offset, size);
return;
default:
unreachable("invalid BindBufferRange target with KHR_no_error");
offset, size);
return;
case GL_ATOMIC_COUNTER_BUFFER:
- bind_atomic_buffer_err(ctx, index, bufObj, offset, size,
- "glBindBufferRange");
+ bind_buffer_range_atomic_buffer_err(ctx, index, bufObj,
+ offset, size);
return;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
bind_buffer_base_shader_storage_buffer(ctx, index, bufObj);
return;
case GL_ATOMIC_COUNTER_BUFFER:
- bind_atomic_buffer_err(ctx, index, bufObj, 0, 0,
- "glBindBufferBase");
+ bind_buffer_base_atomic_buffer(ctx, index, bufObj);
return;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");