for (unsigned int j = 0; j < sh->NumUniformBlocks; j++) {
int index = link_cross_validate_uniform_block(prog,
&prog->UniformBlocks,
- &prog->NumUniformBlocks,
+ &prog->NumBufferInterfaceBlocks,
&sh->UniformBlocks[j]);
if (index == -1) {
if (!ok) {
- ctx->Driver.DeleteShader(ctx, linked);
+ _mesa_delete_shader(ctx, linked);
return NULL;
}
unsigned shader_blocks[MESA_SHADER_STAGES] = {0};
unsigned total_shader_storage_blocks = 0;
- for (unsigned i = 0; i < prog->NumUniformBlocks; i++) {
+ for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) {
/* Don't check SSBOs for Uniform Block Size */
if (!prog->UniformBlocks[i].IsShaderStorage &&
prog->UniformBlocks[i].UniformBufferSize > ctx->Const.MaxUniformBlockSize) {
if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) {
linker_error(prog, "Too many combined uniform blocks (%d/%d)\n",
- prog->NumUniformBlocks,
+ total_uniform_blocks,
ctx->Const.MaxCombinedUniformBlocks);
} else {
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
total_image_units += sh->NumImages;
- for (unsigned j = 0; j < prog->NumUniformBlocks; j++) {
+ for (unsigned j = 0; j < prog->NumBufferInterfaceBlocks; j++) {
int stage_index = prog->UniformBlockStageIndex[i][j];
if (stage_index != -1 && sh->UniformBlocks[stage_index].IsShaderStorage)
total_shader_storage_blocks++;
delete uniform_map;
}
+static bool
+should_add_buffer_variable(struct gl_shader_program *shProg,
+ GLenum type, const char *name)
+{
+ bool found_interface = false;
+ const char *block_name = NULL;
+
+ /* These rules only apply to buffer variables. So we return
+ * true for the rest of types.
+ */
+ if (type != GL_BUFFER_VARIABLE)
+ return true;
+
+ for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) {
+ block_name = shProg->UniformBlocks[i].Name;
+ if (strncmp(block_name, name, strlen(block_name)) == 0) {
+ found_interface = true;
+ break;
+ }
+ }
+
+ /* We remove the interface name from the buffer variable name,
+ * including the dot that follows it.
+ */
+ if (found_interface)
+ name = name + strlen(block_name) + 1;
+
+ /* From: ARB_program_interface_query extension:
+ *
+ * "For an active shader storage block member declared as an array, an
+ * entry will be generated only for the first array element, regardless
+ * of its type. For arrays of aggregate types, the enumeration rules are
+ * applied recursively for the single enumerated array element.
+ */
+ const char *first_dot = strchr(name, '.');
+ const char *first_square_bracket = strchr(name, '[');
+
+ /* The buffer variable is on top level and it is not an array */
+ if (!first_square_bracket) {
+ return true;
+ /* The shader storage block member is a struct, then generate the entry */
+ } else if (first_dot && first_dot < first_square_bracket) {
+ return true;
+ } else {
+ /* Shader storage block member is an array, only generate an entry for the
+ * first array element.
+ */
+ if (strncmp(first_square_bracket, "[0]", 3) == 0)
+ return true;
+ }
+
+ return false;
+}
+
static bool
add_program_resource(struct gl_shader_program *prog, GLenum type,
const void *data, uint8_t stages)
switch (var->data.mode) {
case ir_var_shader_in:
iface = GL_PROGRAM_INPUT;
+ break;
case ir_var_shader_out:
iface = GL_PROGRAM_OUTPUT;
+ break;
+ default:
+ unreachable("unexpected type");
}
if (!add_program_resource(shProg, iface, var,
build_stageref(shProg, var->name,
if (input_stage == MESA_SHADER_STAGES && output_stage == 0)
return;
- if (!add_packed_varyings(shProg, input_stage))
- return;
- if (!add_packed_varyings(shProg, output_stage))
- return;
+ /* Program interface needs to expose varyings in case of SSO. */
+ if (shProg->SeparateShader) {
+ if (!add_packed_varyings(shProg, input_stage))
+ return;
+ if (!add_packed_varyings(shProg, output_stage))
+ return;
+ }
/* Add inputs and outputs to the resource list. */
if (!add_interface_variables(shProg, shProg->_LinkedShaders[input_stage]->ir,
bool is_shader_storage = shProg->UniformStorage[i].is_shader_storage;
GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM;
+ if (!should_add_buffer_variable(shProg, type,
+ shProg->UniformStorage[i].name))
+ continue;
+
if (!add_program_resource(shProg, type,
&shProg->UniformStorage[i], stageref))
return;
}
/* Add program uniform blocks and shader storage blocks. */
- for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) {
+ for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) {
bool is_shader_storage = shProg->UniformBlocks[i].IsShaderStorage;
GLenum type = is_shader_storage ? GL_SHADER_STORAGE_BLOCK : GL_UNIFORM_BLOCK;
if (!add_program_resource(shProg, type,
continue;
for (int j = MESA_SHADER_VERTEX; j < MESA_SHADER_STAGES; j++) {
- if (!shProg->UniformStorage[i].subroutine[j].active)
+ if (!shProg->UniformStorage[i].opaque[j].active)
continue;
type = _mesa_shader_stage_to_subroutine_uniform((gl_shader_stage)j);
for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] != NULL)
- ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
+ _mesa_delete_shader(ctx, prog->_LinkedShaders[i]);
prog->_LinkedShaders[i] = NULL;
}
if (!prog->LinkStatus) {
if (sh)
- ctx->Driver.DeleteShader(ctx, sh);
+ _mesa_delete_shader(ctx, sh);
goto done;
}
}
if (!prog->LinkStatus) {
if (sh)
- ctx->Driver.DeleteShader(ctx, sh);
+ _mesa_delete_shader(ctx, sh);
goto done;
}