#include "main/glheader.h"
#include "main/context.h"
-#include "main/dispatch.h"
#include "main/shaderapi.h"
#include "main/shaderobj.h"
#include "main/uniforms.h"
* TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
* We'll use that info for state validation before rendering.
*/
+static inline void
+update_single_shader_texture_used(struct gl_shader_program *shProg,
+ struct gl_program *prog,
+ GLuint unit, GLuint target)
+{
+ gl_shader_stage prog_stage =
+ _mesa_program_enum_to_shader_stage(prog->Target);
+
+ assert(unit < ARRAY_SIZE(prog->TexturesUsed));
+ assert(target < NUM_TEXTURE_TARGETS);
+
+ /* From section 7.10 (Samplers) of the OpenGL 4.5 spec:
+ *
+ * "It is not allowed to have variables of different sampler types pointing
+ * to the same texture image unit within a program object."
+ */
+ unsigned stages_mask = shProg->data->linked_stages;
+ while (stages_mask) {
+ const int stage = u_bit_scan(&stages_mask);
+
+ /* Skip validation if we are yet to update textures used in this
+ * stage.
+ */
+ if (prog_stage < stage)
+ break;
+
+ struct gl_program *glprog = shProg->_LinkedShaders[stage]->Program;
+ if (glprog->TexturesUsed[unit] & ~(1 << target))
+ shProg->SamplersValidated = GL_FALSE;
+ }
+
+ prog->TexturesUsed[unit] |= (1 << target);
+}
+
void
_mesa_update_shader_textures_used(struct gl_shader_program *shProg,
struct gl_program *prog)
{
GLbitfield mask = prog->SamplersUsed;
- gl_shader_stage prog_stage =
+ ASSERTED gl_shader_stage prog_stage =
_mesa_program_enum_to_shader_stage(prog->Target);
- struct gl_linked_shader *shader = shProg->_LinkedShaders[prog_stage];
+ GLuint s;
- assert(shader);
+ assert(shProg->_LinkedShaders[prog_stage]);
memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
while (mask) {
- const int s = u_bit_scan(&mask);
- GLuint unit = prog->SamplerUnits[s];
- GLuint tgt = prog->sh.SamplerTargets[s];
- assert(unit < ARRAY_SIZE(prog->TexturesUsed));
- assert(tgt < NUM_TEXTURE_TARGETS);
-
- /* The types of the samplers associated with a particular texture
- * unit must be an exact match. Page 74 (page 89 of the PDF) of the
- * OpenGL 3.3 core spec says:
- *
- * "It is not allowed to have variables of different sampler
- * types pointing to the same texture image unit within a program
- * object."
+ s = u_bit_scan(&mask);
+
+ update_single_shader_texture_used(shProg, prog,
+ prog->SamplerUnits[s],
+ prog->sh.SamplerTargets[s]);
+ }
+
+ if (unlikely(prog->sh.HasBoundBindlessSampler)) {
+ /* Loop over bindless samplers bound to texture units.
*/
- unsigned stages_mask = shProg->data->linked_stages;
- while (stages_mask) {
- const int stage = u_bit_scan(&stages_mask);
-
- /* Skip validation if we are yet to update textures used in this
- * stage.
- */
- if (prog_stage < stage)
- break;
-
- struct gl_program *glprog = shProg->_LinkedShaders[stage]->Program;
- if (glprog->TexturesUsed[unit] & ~(1 << tgt))
- shProg->SamplersValidated = GL_FALSE;
- }
+ for (s = 0; s < prog->sh.NumBindlessSamplers; s++) {
+ struct gl_bindless_sampler *sampler = &prog->sh.BindlessSamplers[s];
+
+ if (!sampler->bound)
+ continue;
- prog->TexturesUsed[unit] |= (1 << tgt);
+ update_single_shader_texture_used(shProg, prog, sampler->unit,
+ sampler->target);
+ }
}
}
_mesa_uniform(location, count, value, ctx, ctx->_Shader->ActiveProgram, GLSL_TYPE_INT, 4);
}
+void GLAPIENTRY
+_mesa_UniformHandleui64ARB(GLint location, GLuint64 value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_uniform_handle(location, 1, &value, ctx, ctx->_Shader->ActiveProgram);
+}
+
+void GLAPIENTRY
+_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
+ const GLuint64 *value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_uniform_handle(location, count, value, ctx,
+ ctx->_Shader->ActiveProgram);
+}
+
+
/** Same as above with direct state access **/
void GLAPIENTRY
_mesa_ProgramUniform1f(GLuint program, GLint location, GLfloat v0)
_mesa_uniform(location, count, value, ctx, shProg, GLSL_TYPE_INT, 4);
}
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
+ 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
+_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
+ 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);
+}
+
/** OpenGL 3.0 GLuint-valued functions **/
void GLAPIENTRY
shProg = _mesa_lookup_shader_program_err(ctx, programObj,
"glGetUniformLocation");
- if (!shProg)
+ if (!shProg || !name)
return -1;
/* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says:
* "If program has not been successfully linked, the error
* INVALID_OPERATION is generated."
*/
- if (shProg->data->LinkStatus == linking_failure) {
+ if (shProg->data->LinkStatus == LINKING_FAILURE) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetUniformLocation(program not linked)");
return -1;
return _mesa_program_resource_location(shProg, GL_UNIFORM, name);
}
+GLint GLAPIENTRY
+_mesa_GetUniformLocation_no_error(GLuint programObj, const GLcharARB *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program(ctx, programObj);
+
+ return _mesa_program_resource_location(shProg, GL_UNIFORM, name);
+}
+
GLuint GLAPIENTRY
_mesa_GetUniformBlockIndex(GLuint program,
const GLchar *uniformBlockName)
}
}
+static void
+uniform_block_binding(struct gl_context *ctx, struct gl_shader_program *shProg,
+ GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+ if (shProg->data->UniformBlocks[uniformBlockIndex].Binding !=
+ uniformBlockBinding) {
+
+ FLUSH_VERTICES(ctx, 0);
+ ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
+
+ shProg->data->UniformBlocks[uniformBlockIndex].Binding =
+ uniformBlockBinding;
+ }
+}
+
+void GLAPIENTRY
+_mesa_UniformBlockBinding_no_error(GLuint program, GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program);
+ uniform_block_binding(ctx, shProg, uniformBlockIndex, uniformBlockBinding);
+}
+
void GLAPIENTRY
_mesa_UniformBlockBinding(GLuint program,
GLuint uniformBlockIndex,
return;
}
- if (shProg->data->UniformBlocks[uniformBlockIndex].Binding !=
- uniformBlockBinding) {
+ uniform_block_binding(ctx, shProg, uniformBlockIndex, uniformBlockBinding);
+}
+
+static void
+shader_storage_block_binding(struct gl_context *ctx,
+ struct gl_shader_program *shProg,
+ GLuint shaderStorageBlockIndex,
+ GLuint shaderStorageBlockBinding)
+{
+ if (shProg->data->ShaderStorageBlocks[shaderStorageBlockIndex].Binding !=
+ shaderStorageBlockBinding) {
FLUSH_VERTICES(ctx, 0);
- ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
+ ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer;
- shProg->data->UniformBlocks[uniformBlockIndex].Binding =
- uniformBlockBinding;
+ shProg->data->ShaderStorageBlocks[shaderStorageBlockIndex].Binding =
+ shaderStorageBlockBinding;
}
}
+void GLAPIENTRY
+_mesa_ShaderStorageBlockBinding_no_error(GLuint program,
+ GLuint shaderStorageBlockIndex,
+ GLuint shaderStorageBlockBinding)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program);
+ shader_storage_block_binding(ctx, shProg, shaderStorageBlockIndex,
+ shaderStorageBlockBinding);
+}
+
void GLAPIENTRY
_mesa_ShaderStorageBlockBinding(GLuint program,
GLuint shaderStorageBlockIndex,
return;
}
- if (shProg->data->ShaderStorageBlocks[shaderStorageBlockIndex].Binding !=
- shaderStorageBlockBinding) {
-
- FLUSH_VERTICES(ctx, 0);
- ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer;
-
- shProg->data->ShaderStorageBlocks[shaderStorageBlockIndex].Binding =
- shaderStorageBlockBinding;
- }
+ shader_storage_block_binding(ctx, shProg, shaderStorageBlockIndex,
+ shaderStorageBlockBinding);
}
/**