mesa: add support for glUniformHandleui64*ARB()
Bindless sampler/image handles are represented using 64-bit unsigned integers. The ARB_bindless_texture spec says: "The error INVALID_OPERATION is generated by UniformHandleui64{v}ARB if the sampler or image uniform being updated has the "bound_sampler" or "bound_image" layout qualifier"." Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
This commit is contained in:
@@ -201,6 +201,12 @@ struct gl_uniform_storage {
|
|||||||
* top-level shader storage block member. (GL_TOP_LEVEL_ARRAY_STRIDE).
|
* top-level shader storage block member. (GL_TOP_LEVEL_ARRAY_STRIDE).
|
||||||
*/
|
*/
|
||||||
unsigned top_level_array_stride;
|
unsigned top_level_array_stride;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this uniform variable has the bindless_sampler or bindless_image
|
||||||
|
* layout qualifier as specified by ARB_bindless_texture.
|
||||||
|
*/
|
||||||
|
bool is_bindless;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@@ -754,6 +754,7 @@ private:
|
|||||||
|
|
||||||
this->uniforms[id].is_shader_storage =
|
this->uniforms[id].is_shader_storage =
|
||||||
current_var->is_in_shader_storage_block();
|
current_var->is_in_shader_storage_block();
|
||||||
|
this->uniforms[id].is_bindless = current_var->data.bindless;
|
||||||
|
|
||||||
/* Do not assign storage if the uniform is a builtin or buffer object */
|
/* Do not assign storage if the uniform is a builtin or buffer object */
|
||||||
if (!this->uniforms[id].builtin &&
|
if (!this->uniforms[id].builtin &&
|
||||||
|
@@ -578,6 +578,7 @@ write_uniforms(struct blob *metadata, struct gl_shader_program *prog)
|
|||||||
blob_write_uint32(metadata, prog->data->UniformStorage[i].is_shader_storage);
|
blob_write_uint32(metadata, prog->data->UniformStorage[i].is_shader_storage);
|
||||||
blob_write_uint32(metadata, prog->data->UniformStorage[i].matrix_stride);
|
blob_write_uint32(metadata, prog->data->UniformStorage[i].matrix_stride);
|
||||||
blob_write_uint32(metadata, prog->data->UniformStorage[i].row_major);
|
blob_write_uint32(metadata, prog->data->UniformStorage[i].row_major);
|
||||||
|
blob_write_uint32(metadata, prog->data->UniformStorage[i].is_bindless);
|
||||||
blob_write_uint32(metadata,
|
blob_write_uint32(metadata,
|
||||||
prog->data->UniformStorage[i].num_compatible_subroutines);
|
prog->data->UniformStorage[i].num_compatible_subroutines);
|
||||||
blob_write_uint32(metadata,
|
blob_write_uint32(metadata,
|
||||||
@@ -642,6 +643,7 @@ read_uniforms(struct blob_reader *metadata, struct gl_shader_program *prog)
|
|||||||
uniforms[i].is_shader_storage = blob_read_uint32(metadata);
|
uniforms[i].is_shader_storage = blob_read_uint32(metadata);
|
||||||
uniforms[i].matrix_stride = blob_read_uint32(metadata);
|
uniforms[i].matrix_stride = blob_read_uint32(metadata);
|
||||||
uniforms[i].row_major = blob_read_uint32(metadata);
|
uniforms[i].row_major = blob_read_uint32(metadata);
|
||||||
|
uniforms[i].is_bindless = blob_read_uint32(metadata);
|
||||||
uniforms[i].num_compatible_subroutines = blob_read_uint32(metadata);
|
uniforms[i].num_compatible_subroutines = blob_read_uint32(metadata);
|
||||||
uniforms[i].top_level_array_size = blob_read_uint32(metadata);
|
uniforms[i].top_level_array_size = blob_read_uint32(metadata);
|
||||||
uniforms[i].top_level_array_stride = blob_read_uint32(metadata);
|
uniforms[i].top_level_array_stride = blob_read_uint32(metadata);
|
||||||
|
@@ -1274,6 +1274,70 @@ _mesa_uniform_matrix(GLint location, GLsizei count,
|
|||||||
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
|
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called via glUniformHandleui64*ARB() functions.
|
||||||
|
*/
|
||||||
|
extern "C" void
|
||||||
|
_mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values,
|
||||||
|
struct gl_context *ctx, struct gl_shader_program *shProg)
|
||||||
|
{
|
||||||
|
unsigned offset;
|
||||||
|
struct gl_uniform_storage *const uni =
|
||||||
|
validate_uniform_parameters(location, count, &offset,
|
||||||
|
ctx, shProg, "glUniformHandleui64*ARB");
|
||||||
|
if (uni == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!uni->is_bindless) {
|
||||||
|
/* From section "Errors" of the ARB_bindless_texture spec:
|
||||||
|
*
|
||||||
|
* "The error INVALID_OPERATION is generated by
|
||||||
|
* UniformHandleui64{v}ARB if the sampler or image uniform being
|
||||||
|
* updated has the "bound_sampler" or "bound_image" layout qualifier."
|
||||||
|
*
|
||||||
|
* From section 4.4.6 of the ARB_bindless_texture spec:
|
||||||
|
*
|
||||||
|
* "In the absence of these qualifiers, sampler and image uniforms are
|
||||||
|
* considered "bound". Additionally, if GL_ARB_bindless_texture is not
|
||||||
|
* enabled, these uniforms are considered "bound"."
|
||||||
|
*/
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"glUniformHandleui64*ARB(non-bindless sampler/image uniform)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned components = uni->type->vector_elements;
|
||||||
|
const int size_mul = 2;
|
||||||
|
|
||||||
|
if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
|
||||||
|
log_uniform(values, GLSL_TYPE_UINT64, components, 1, count,
|
||||||
|
false, shProg, location, uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
|
||||||
|
*
|
||||||
|
* "When loading N elements starting at an arbitrary position k in a
|
||||||
|
* uniform declared as an array, elements k through k + N - 1 in the
|
||||||
|
* array will be replaced with the new values. Values for any array
|
||||||
|
* element that exceeds the highest array element index used, as
|
||||||
|
* reported by GetActiveUniform, will be ignored by the GL."
|
||||||
|
*
|
||||||
|
* Clamp 'count' to a valid value. Note that for non-arrays a count > 1
|
||||||
|
* will have already generated an error.
|
||||||
|
*/
|
||||||
|
if (uni->array_elements != 0) {
|
||||||
|
count = MIN2(count, (int) (uni->array_elements - offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
|
||||||
|
|
||||||
|
/* Store the data in the "actual type" backing storage for the uniform.
|
||||||
|
*/
|
||||||
|
memcpy(&uni->storage[size_mul * components * offset], values,
|
||||||
|
sizeof(uni->storage[0]) * components * count * size_mul);
|
||||||
|
|
||||||
|
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" bool
|
extern "C" bool
|
||||||
_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
|
_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
|
||||||
|
@@ -297,12 +297,17 @@ _mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value)
|
|||||||
void GLAPIENTRY
|
void GLAPIENTRY
|
||||||
_mesa_UniformHandleui64ARB(GLint location, GLuint64 value)
|
_mesa_UniformHandleui64ARB(GLint location, GLuint64 value)
|
||||||
{
|
{
|
||||||
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
_mesa_uniform_handle(location, 1, &value, ctx, ctx->_Shader->ActiveProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLAPIENTRY
|
void GLAPIENTRY
|
||||||
_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
|
_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
|
||||||
const GLuint64 *value)
|
const GLuint64 *value)
|
||||||
{
|
{
|
||||||
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
_mesa_uniform_handle(location, count, value, ctx,
|
||||||
|
ctx->_Shader->ActiveProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -501,12 +506,22 @@ void GLAPIENTRY
|
|||||||
_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
|
_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
|
||||||
GLuint64 value)
|
GLuint64 value)
|
||||||
{
|
{
|
||||||
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
struct gl_shader_program *shProg =
|
||||||
|
_mesa_lookup_shader_program_err(ctx, program,
|
||||||
|
"glProgramUniformHandleui64ARB");
|
||||||
|
_mesa_uniform_handle(location, 1, &value, ctx, shProg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLAPIENTRY
|
void GLAPIENTRY
|
||||||
_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
|
_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
|
||||||
GLsizei count, const GLuint64 *values)
|
GLsizei count, const GLuint64 *values)
|
||||||
{
|
{
|
||||||
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
struct gl_shader_program *shProg =
|
||||||
|
_mesa_lookup_shader_program_err(ctx, program,
|
||||||
|
"glProgramUniformHandleui64vARB");
|
||||||
|
_mesa_uniform_handle(location, count, values, ctx, shProg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -452,6 +452,10 @@ _mesa_uniform_matrix(GLint location, GLsizei count,
|
|||||||
struct gl_context *, struct gl_shader_program *,
|
struct gl_context *, struct gl_shader_program *,
|
||||||
GLuint cols, GLuint rows, enum glsl_base_type basicType);
|
GLuint cols, GLuint rows, enum glsl_base_type basicType);
|
||||||
|
|
||||||
|
void
|
||||||
|
_mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values,
|
||||||
|
struct gl_context *, struct gl_shader_program *);
|
||||||
|
|
||||||
void
|
void
|
||||||
_mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
|
_mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
|
||||||
GLsizei bufSize, enum glsl_base_type returnType,
|
GLsizei bufSize, enum glsl_base_type returnType,
|
||||||
|
Reference in New Issue
Block a user