mesa: add support for ARB_indirect_parameters draw functions
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Reviewed-by: Marek Olšák <marek.olsak@amd.com>
This commit is contained in:
@@ -920,6 +920,121 @@ _mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
|
|||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLboolean
|
||||||
|
valid_draw_indirect_parameters(struct gl_context *ctx,
|
||||||
|
const char *name,
|
||||||
|
GLintptr drawcount)
|
||||||
|
{
|
||||||
|
/* From the ARB_indirect_parameters specification:
|
||||||
|
* "INVALID_VALUE is generated by MultiDrawArraysIndirectCountARB or
|
||||||
|
* MultiDrawElementsIndirectCountARB if <drawcount> is not a multiple of
|
||||||
|
* four."
|
||||||
|
*/
|
||||||
|
if (drawcount & 3) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_VALUE,
|
||||||
|
"%s(drawcount is not a multiple of 4)", name);
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* From the ARB_indirect_parameters specification:
|
||||||
|
* "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
|
||||||
|
* MultiDrawElementsIndirectCountARB if no buffer is bound to the
|
||||||
|
* PARAMETER_BUFFER_ARB binding point."
|
||||||
|
*/
|
||||||
|
if (!_mesa_is_bufferobj(ctx->ParameterBuffer)) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"%s: no buffer bound to PARAMETER_BUFFER", name);
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mesa_check_disallowed_mapping(ctx->ParameterBuffer)) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"%s(PARAMETER_BUFFER is mapped)", name);
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* From the ARB_indirect_parameters specification:
|
||||||
|
* "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
|
||||||
|
* MultiDrawElementsIndirectCountARB if reading a <sizei> typed value
|
||||||
|
* from the buffer bound to the PARAMETER_BUFFER_ARB target at the offset
|
||||||
|
* specified by <drawcount> would result in an out-of-bounds access."
|
||||||
|
*/
|
||||||
|
if (ctx->ParameterBuffer->Size < drawcount + sizeof(GLsizei)) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"%s(PARAMETER_BUFFER too small)", name);
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLboolean
|
||||||
|
_mesa_validate_MultiDrawArraysIndirectCount(struct gl_context *ctx,
|
||||||
|
GLenum mode,
|
||||||
|
GLintptr indirect,
|
||||||
|
GLintptr drawcount,
|
||||||
|
GLsizei maxdrawcount,
|
||||||
|
GLsizei stride)
|
||||||
|
{
|
||||||
|
GLsizeiptr size = 0;
|
||||||
|
const unsigned drawArraysNumParams = 4;
|
||||||
|
|
||||||
|
FLUSH_CURRENT(ctx, 0);
|
||||||
|
|
||||||
|
/* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
|
||||||
|
assert(stride != 0);
|
||||||
|
|
||||||
|
if (!valid_draw_indirect_multi(ctx, maxdrawcount, stride,
|
||||||
|
"glMultiDrawArraysIndirectCountARB"))
|
||||||
|
return GL_FALSE;
|
||||||
|
|
||||||
|
/* number of bytes of the indirect buffer which will be read */
|
||||||
|
size = maxdrawcount
|
||||||
|
? (maxdrawcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if (!valid_draw_indirect(ctx, mode, (void *)indirect, size,
|
||||||
|
"glMultiDrawArraysIndirectCountARB"))
|
||||||
|
return GL_FALSE;
|
||||||
|
|
||||||
|
return valid_draw_indirect_parameters(
|
||||||
|
ctx, "glMultiDrawArraysIndirectCountARB", drawcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLboolean
|
||||||
|
_mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx,
|
||||||
|
GLenum mode, GLenum type,
|
||||||
|
GLintptr indirect,
|
||||||
|
GLintptr drawcount,
|
||||||
|
GLsizei maxdrawcount,
|
||||||
|
GLsizei stride)
|
||||||
|
{
|
||||||
|
GLsizeiptr size = 0;
|
||||||
|
const unsigned drawElementsNumParams = 5;
|
||||||
|
|
||||||
|
FLUSH_CURRENT(ctx, 0);
|
||||||
|
|
||||||
|
/* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
|
||||||
|
assert(stride != 0);
|
||||||
|
|
||||||
|
if (!valid_draw_indirect_multi(ctx, maxdrawcount, stride,
|
||||||
|
"glMultiDrawElementsIndirectCountARB"))
|
||||||
|
return GL_FALSE;
|
||||||
|
|
||||||
|
/* number of bytes of the indirect buffer which will be read */
|
||||||
|
size = maxdrawcount
|
||||||
|
? (maxdrawcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if (!valid_draw_indirect_elements(ctx, mode, type,
|
||||||
|
(void *)indirect, size,
|
||||||
|
"glMultiDrawElementsIndirectCountARB"))
|
||||||
|
return GL_FALSE;
|
||||||
|
|
||||||
|
return valid_draw_indirect_parameters(
|
||||||
|
ctx, "glMultiDrawElementsIndirectCountARB", drawcount);
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
check_valid_to_compute(struct gl_context *ctx, const char *function)
|
check_valid_to_compute(struct gl_context *ctx, const char *function)
|
||||||
{
|
{
|
||||||
|
@@ -105,6 +105,22 @@ _mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
|
|||||||
GLsizei primcount,
|
GLsizei primcount,
|
||||||
GLsizei stride);
|
GLsizei stride);
|
||||||
|
|
||||||
|
extern GLboolean
|
||||||
|
_mesa_validate_MultiDrawArraysIndirectCount(struct gl_context *ctx,
|
||||||
|
GLenum mode,
|
||||||
|
GLintptr indirect,
|
||||||
|
GLintptr drawcount,
|
||||||
|
GLsizei maxdrawcount,
|
||||||
|
GLsizei stride);
|
||||||
|
|
||||||
|
extern GLboolean
|
||||||
|
_mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx,
|
||||||
|
GLenum mode, GLenum type,
|
||||||
|
GLintptr indirect,
|
||||||
|
GLintptr drawcount,
|
||||||
|
GLsizei maxdrawcount,
|
||||||
|
GLsizei stride);
|
||||||
|
|
||||||
extern GLboolean
|
extern GLboolean
|
||||||
_mesa_validate_DispatchCompute(struct gl_context *ctx,
|
_mesa_validate_DispatchCompute(struct gl_context *ctx,
|
||||||
const GLuint *num_groups);
|
const GLuint *num_groups);
|
||||||
|
@@ -1732,13 +1732,96 @@ vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type,
|
|||||||
primcount, stride);
|
primcount, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vbo_validated_multidrawarraysindirectcount(struct gl_context *ctx,
|
||||||
|
GLenum mode,
|
||||||
|
GLintptr indirect,
|
||||||
|
GLintptr drawcount,
|
||||||
|
GLsizei maxdrawcount,
|
||||||
|
GLsizei stride)
|
||||||
|
{
|
||||||
|
struct vbo_context *vbo = vbo_context(ctx);
|
||||||
|
struct vbo_exec_context *exec = &vbo->exec;
|
||||||
|
GLsizeiptr offset = indirect;
|
||||||
|
|
||||||
|
if (maxdrawcount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vbo_bind_arrays(ctx);
|
||||||
|
|
||||||
|
check_buffers_are_unmapped(exec->array.inputs);
|
||||||
|
vbo->draw_indirect_prims(ctx, mode,
|
||||||
|
ctx->DrawIndirectBuffer, offset,
|
||||||
|
maxdrawcount, stride,
|
||||||
|
ctx->ParameterBuffer, drawcount,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
|
||||||
|
_mesa_flush(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vbo_validated_multidrawelementsindirectcount(struct gl_context *ctx,
|
||||||
|
GLenum mode, GLenum type,
|
||||||
|
GLintptr indirect,
|
||||||
|
GLintptr drawcount,
|
||||||
|
GLsizei maxdrawcount,
|
||||||
|
GLsizei stride)
|
||||||
|
{
|
||||||
|
struct vbo_context *vbo = vbo_context(ctx);
|
||||||
|
struct vbo_exec_context *exec = &vbo->exec;
|
||||||
|
struct _mesa_index_buffer ib;
|
||||||
|
GLsizeiptr offset = (GLsizeiptr)indirect;
|
||||||
|
|
||||||
|
if (maxdrawcount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vbo_bind_arrays(ctx);
|
||||||
|
|
||||||
|
/* NOTE: IndexBufferObj is guaranteed to be a VBO. */
|
||||||
|
|
||||||
|
ib.count = 0; /* unknown */
|
||||||
|
ib.type = type;
|
||||||
|
ib.obj = ctx->Array.VAO->IndexBufferObj;
|
||||||
|
ib.ptr = NULL;
|
||||||
|
|
||||||
|
check_buffers_are_unmapped(exec->array.inputs);
|
||||||
|
vbo->draw_indirect_prims(ctx, mode,
|
||||||
|
ctx->DrawIndirectBuffer, offset,
|
||||||
|
maxdrawcount, stride,
|
||||||
|
ctx->ParameterBuffer, drawcount,
|
||||||
|
&ib);
|
||||||
|
|
||||||
|
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
|
||||||
|
_mesa_flush(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
static void GLAPIENTRY
|
static void GLAPIENTRY
|
||||||
vbo_exec_MultiDrawArraysIndirectCount(GLenum mode,
|
vbo_exec_MultiDrawArraysIndirectCount(GLenum mode,
|
||||||
GLintptr indirect,
|
GLintptr indirect,
|
||||||
GLintptr drawcount,
|
GLintptr drawcount,
|
||||||
GLsizei maxdrawcount, GLsizei stride)
|
GLsizei maxdrawcount, GLsizei stride)
|
||||||
{
|
{
|
||||||
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
|
||||||
|
if (MESA_VERBOSE & VERBOSE_DRAW)
|
||||||
|
_mesa_debug(ctx, "glMultiDrawArraysIndirectCountARB"
|
||||||
|
"(%s, %lx, %lx, %i, %i)\n",
|
||||||
|
_mesa_enum_to_string(mode), indirect,
|
||||||
|
drawcount, maxdrawcount, stride);
|
||||||
|
|
||||||
|
/* If <stride> is zero, the array elements are treated as tightly packed. */
|
||||||
|
if (stride == 0)
|
||||||
|
stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
|
||||||
|
|
||||||
|
if (!_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode,
|
||||||
|
indirect, drawcount,
|
||||||
|
maxdrawcount, stride))
|
||||||
|
return;
|
||||||
|
|
||||||
|
vbo_validated_multidrawarraysindirectcount(ctx, mode,
|
||||||
|
indirect, drawcount,
|
||||||
|
maxdrawcount, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GLAPIENTRY
|
static void GLAPIENTRY
|
||||||
@@ -1747,7 +1830,27 @@ vbo_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type,
|
|||||||
GLintptr drawcount,
|
GLintptr drawcount,
|
||||||
GLsizei maxdrawcount, GLsizei stride)
|
GLsizei maxdrawcount, GLsizei stride)
|
||||||
{
|
{
|
||||||
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
|
||||||
|
if (MESA_VERBOSE & VERBOSE_DRAW)
|
||||||
|
_mesa_debug(ctx, "glMultiDrawElementsIndirectCountARB"
|
||||||
|
"(%s, %s, %lx, %lx, %i, %i)\n",
|
||||||
|
_mesa_enum_to_string(mode),
|
||||||
|
_mesa_enum_to_string(type), indirect,
|
||||||
|
drawcount, maxdrawcount, stride);
|
||||||
|
|
||||||
|
/* If <stride> is zero, the array elements are treated as tightly packed. */
|
||||||
|
if (stride == 0)
|
||||||
|
stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */
|
||||||
|
|
||||||
|
if (!_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type,
|
||||||
|
indirect, drawcount,
|
||||||
|
maxdrawcount, stride))
|
||||||
|
return;
|
||||||
|
|
||||||
|
vbo_validated_multidrawelementsindirectcount(ctx, mode, type,
|
||||||
|
indirect, drawcount,
|
||||||
|
maxdrawcount, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user