summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/linker.cpp64
-rw-r--r--src/mesa/main/mtypes.h17
-rw-r--r--src/mesa/main/shaderapi.c7
3 files changed, 88 insertions, 0 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 32825ba41cc..6a07e4ab0d1 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1287,6 +1287,69 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog,
prog->Geom.VerticesOut = linked_shader->Geom.VerticesOut;
}
+
+/**
+ * Perform cross-validation of compute shader local_size_{x,y,z} layout
+ * qualifiers for the attached compute shaders, and propagate them to the
+ * linked CS and linked shader program.
+ */
+static void
+link_cs_input_layout_qualifiers(struct gl_shader_program *prog,
+ struct gl_shader *linked_shader,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
+{
+ for (int i = 0; i < 3; i++)
+ linked_shader->Comp.LocalSize[i] = 0;
+
+ /* This function is called for all shader stages, but it only has an effect
+ * for compute shaders.
+ */
+ if (linked_shader->Stage != MESA_SHADER_COMPUTE)
+ return;
+
+ /* From the ARB_compute_shader spec, in the section describing local size
+ * declarations:
+ *
+ * If multiple compute shaders attached to a single program object
+ * declare local work-group size, the declarations must be identical;
+ * otherwise a link-time error results. Furthermore, if a program
+ * object contains any compute shaders, at least one must contain an
+ * input layout qualifier specifying the local work sizes of the
+ * program, or a link-time error will occur.
+ */
+ for (unsigned sh = 0; sh < num_shaders; sh++) {
+ struct gl_shader *shader = shader_list[sh];
+
+ if (shader->Comp.LocalSize[0] != 0) {
+ if (linked_shader->Comp.LocalSize[0] != 0) {
+ for (int i = 0; i < 3; i++) {
+ if (linked_shader->Comp.LocalSize[i] !=
+ shader->Comp.LocalSize[i]) {
+ linker_error(prog, "compute shader defined with conflicting "
+ "local sizes\n");
+ return;
+ }
+ }
+ }
+ for (int i = 0; i < 3; i++)
+ linked_shader->Comp.LocalSize[i] = shader->Comp.LocalSize[i];
+ }
+ }
+
+ /* Just do the intrastage -> interstage propagation right now,
+ * since we already know we're in the right type of shader program
+ * for doing it.
+ */
+ if (linked_shader->Comp.LocalSize[0] == 0) {
+ linker_error(prog, "compute shader didn't declare local size\n");
+ return;
+ }
+ for (int i = 0; i < 3; i++)
+ prog->Comp.LocalSize[i] = linked_shader->Comp.LocalSize[i];
+}
+
+
/**
* Combine a group of shaders for a single stage to generate a linked shader
*
@@ -1391,6 +1454,7 @@ link_intrastage_shaders(void *mem_ctx,
ralloc_steal(linked, linked->UniformBlocks);
link_gs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders);
+ link_cs_input_layout_qualifiers(prog, linked, shader_list, num_shaders);
populate_symbol_table(linked);
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 36d98eeef87..8d81aa1592c 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2185,6 +2185,11 @@ struct gl_fragment_program
struct gl_compute_program
{
struct gl_program Base; /**< base class */
+
+ /**
+ * Size specified using local_size_{x,y,z}.
+ */
+ unsigned LocalSize[3];
};
@@ -2646,6 +2651,18 @@ struct gl_shader_program
0 if not present. */
} Vert;
+ /**
+ * Compute shader state - copied into gl_compute_program by
+ * _mesa_copy_linked_program_data().
+ */
+ struct {
+ /**
+ * If this shader contains a compute stage, size specified using
+ * local_size_{x,y,z}. Otherwise undefined.
+ */
+ unsigned LocalSize[3];
+ } Comp;
+
/* post-link info: */
unsigned NumUserUniformStorage;
struct gl_uniform_storage *UniformStorage;
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 987c48aff34..571e13ca9b9 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -1846,6 +1846,13 @@ _mesa_copy_linked_program_data(gl_shader_stage type,
dst_gp->UsesEndPrimitive = src->Geom.UsesEndPrimitive;
}
break;
+ case MESA_SHADER_COMPUTE: {
+ struct gl_compute_program *dst_cp = (struct gl_compute_program *) dst;
+ int i;
+ for (i = 0; i < 3; i++)
+ dst_cp->LocalSize[i] = src->Comp.LocalSize[i];
+ }
+ break;
default:
break;
}