summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler/glsl/gl_nir_link_xfb.c17
-rw-r--r--src/compiler/nir/nir_gather_xfb_info.c60
-rw-r--r--src/compiler/nir/nir_xfb_info.h17
3 files changed, 64 insertions, 30 deletions
diff --git a/src/compiler/glsl/gl_nir_link_xfb.c b/src/compiler/glsl/gl_nir_link_xfb.c
index 7623492ba96..5b80a3e0373 100644
--- a/src/compiler/glsl/gl_nir_link_xfb.c
+++ b/src/compiler/glsl/gl_nir_link_xfb.c
@@ -68,13 +68,14 @@ gl_nir_link_assign_xfb_resources(struct gl_context *ctx,
free(prog->TransformFeedback.VaryingNames);
nir_xfb_info *xfb_info = NULL;
+ nir_xfb_varyings_info *varyings_info = NULL;
/* Find last stage before fragment shader */
for (int stage = MESA_SHADER_FRAGMENT - 1; stage >= 0; stage--) {
struct gl_linked_shader *sh = prog->_LinkedShaders[stage];
if (sh && stage != MESA_SHADER_TESS_CTRL) {
- xfb_info = nir_gather_xfb_info(sh->Program->nir, NULL);
+ xfb_info = nir_gather_xfb_info_with_varyings(sh->Program->nir, NULL, &varyings_info);
break;
}
}
@@ -94,9 +95,9 @@ gl_nir_link_assign_xfb_resources(struct gl_context *ctx,
for (unsigned buf = 0; buf < MAX_FEEDBACK_BUFFERS; buf++)
prog->TransformFeedback.BufferStride[buf] = xfb_info->buffers[buf].stride;
- prog->TransformFeedback.NumVarying = xfb_info->varying_count;
+ prog->TransformFeedback.NumVarying = varyings_info->varying_count;
prog->TransformFeedback.VaryingNames =
- malloc(sizeof(GLchar *) * xfb_info->varying_count);
+ malloc(sizeof(GLchar *) * varyings_info->varying_count);
linked_xfb->Outputs =
rzalloc_array(xfb_prog,
@@ -107,16 +108,16 @@ gl_nir_link_assign_xfb_resources(struct gl_context *ctx,
linked_xfb->Varyings =
rzalloc_array(xfb_prog,
struct gl_transform_feedback_varying_info,
- xfb_info->varying_count);
- linked_xfb->NumVarying = xfb_info->varying_count;
+ varyings_info->varying_count);
+ linked_xfb->NumVarying = varyings_info->varying_count;
int buffer_index = 0; /* Corresponds to GL_TRANSFORM_FEEDBACK_BUFFER_INDEX */
int xfb_buffer =
- (xfb_info->varying_count > 0) ?
+ (varyings_info->varying_count > 0) ?
xfb_info->outputs[0].buffer : 0;
- for (unsigned i = 0; i < xfb_info->varying_count; i++) {
- nir_xfb_varying_info *xfb_varying = &xfb_info->varyings[i];
+ for (unsigned i = 0; i < varyings_info->varying_count; i++) {
+ nir_xfb_varying_info *xfb_varying = &varyings_info->varyings[i];
/* From ARB_gl_spirv spec:
*
diff --git a/src/compiler/nir/nir_gather_xfb_info.c b/src/compiler/nir/nir_gather_xfb_info.c
index 53f12fe9dbb..962f4801a67 100644
--- a/src/compiler/nir/nir_gather_xfb_info.c
+++ b/src/compiler/nir/nir_gather_xfb_info.c
@@ -27,11 +27,15 @@
static void
add_var_xfb_varying(nir_xfb_info *xfb,
+ nir_xfb_varyings_info *varyings,
nir_variable *var,
unsigned offset,
const struct glsl_type *type)
{
- nir_xfb_varying_info *varying = &xfb->varyings[xfb->varying_count++];
+ if (varyings == NULL)
+ return;
+
+ nir_xfb_varying_info *varying = &varyings->varyings[varyings->varying_count++];
varying->type = type;
varying->buffer = var->data.xfb_buffer;
@@ -41,18 +45,26 @@ add_var_xfb_varying(nir_xfb_info *xfb,
static nir_xfb_info *
-nir_gather_xfb_info_create(void *mem_ctx, uint16_t output_count, uint16_t varying_count)
+nir_xfb_info_create(void *mem_ctx, uint16_t output_count)
{
- nir_xfb_info *xfb = rzalloc_size(mem_ctx, sizeof(nir_xfb_info));
+ return rzalloc_size(mem_ctx, nir_xfb_info_size(output_count));
+}
- xfb->varyings = rzalloc_size(xfb, sizeof(nir_xfb_varying_info) * varying_count);
- xfb->outputs = rzalloc_size(xfb, sizeof(nir_xfb_output_info) * output_count);
+static size_t
+nir_xfb_varyings_info_size(uint16_t varying_count)
+{
+ return sizeof(nir_xfb_info) + sizeof(nir_xfb_varying_info) * varying_count;
+}
- return xfb;
+static nir_xfb_varyings_info *
+nir_xfb_varyings_info_create(void *mem_ctx, uint16_t varying_count)
+{
+ return rzalloc_size(mem_ctx, nir_xfb_varyings_info_size(varying_count));
}
static void
add_var_xfb_outputs(nir_xfb_info *xfb,
+ nir_xfb_varyings_info *varyings,
nir_variable *var,
unsigned buffer,
unsigned *location,
@@ -71,17 +83,19 @@ add_var_xfb_outputs(nir_xfb_info *xfb,
if (!glsl_type_is_array(child_type) &&
!glsl_type_is_struct(child_type)) {
- add_var_xfb_varying(xfb, var, *offset, type);
+ add_var_xfb_varying(xfb, varyings, var, *offset, type);
varying_added = true;
}
for (unsigned i = 0; i < length; i++)
- add_var_xfb_outputs(xfb, var, buffer, location, offset, child_type, varying_added);
+ add_var_xfb_outputs(xfb, varyings, var, buffer, location, offset,
+ child_type, varying_added);
} else if (glsl_type_is_struct_or_ifc(type)) {
unsigned length = glsl_get_length(type);
for (unsigned i = 0; i < length; i++) {
const struct glsl_type *child_type = glsl_get_struct_field(type, i);
- add_var_xfb_outputs(xfb, var, buffer, location, offset, child_type, varying_added);
+ add_var_xfb_outputs(xfb, varyings, var, buffer, location, offset,
+ child_type, varying_added);
}
} else {
assert(buffer < NIR_MAX_XFB_BUFFERS);
@@ -124,7 +138,7 @@ add_var_xfb_outputs(nir_xfb_info *xfb,
unsigned comp_offset = var->data.location_frac;
if (!varying_added) {
- add_var_xfb_varying(xfb, var, *offset, type);
+ add_var_xfb_varying(xfb, varyings, var, *offset, type);
}
while (comp_mask) {
@@ -166,6 +180,14 @@ compare_xfb_output_offsets(const void *_a, const void *_b)
nir_xfb_info *
nir_gather_xfb_info(const nir_shader *shader, void *mem_ctx)
{
+ return nir_gather_xfb_info_with_varyings(shader, mem_ctx, NULL);
+}
+
+nir_xfb_info *
+nir_gather_xfb_info_with_varyings(const nir_shader *shader,
+ void *mem_ctx,
+ nir_xfb_varyings_info **varyings_info_out)
+{
assert(shader->info.stage == MESA_SHADER_VERTEX ||
shader->info.stage == MESA_SHADER_TESS_EVAL ||
shader->info.stage == MESA_SHADER_GEOMETRY);
@@ -179,6 +201,7 @@ nir_gather_xfb_info(const nir_shader *shader, void *mem_ctx)
*/
unsigned num_outputs = 0;
unsigned num_varyings = 0;
+ nir_xfb_varyings_info *varyings_info = NULL;
nir_foreach_variable(var, &shader->outputs) {
if (var->data.explicit_xfb_buffer) {
num_outputs += glsl_count_attribute_slots(var->type, false);
@@ -188,7 +211,11 @@ nir_gather_xfb_info(const nir_shader *shader, void *mem_ctx)
if (num_outputs == 0 || num_varyings == 0)
return NULL;
- nir_xfb_info *xfb = nir_gather_xfb_info_create(mem_ctx, num_outputs, num_varyings);
+ nir_xfb_info *xfb = nir_xfb_info_create(mem_ctx, num_outputs);
+ if (varyings_info_out != NULL) {
+ *varyings_info_out = nir_xfb_varyings_info_create(mem_ctx, num_varyings);
+ varyings_info = *varyings_info_out;
+ }
/* Walk the list of outputs and add them to the array */
nir_foreach_variable(var, &shader->outputs) {
@@ -208,7 +235,7 @@ nir_gather_xfb_info(const nir_shader *shader, void *mem_ctx)
if (var->data.explicit_offset && !is_array_block) {
unsigned offset = var->data.offset;
- add_var_xfb_outputs(xfb, var, var->data.xfb_buffer,
+ add_var_xfb_outputs(xfb, varyings_info, var, var->data.xfb_buffer,
&location, &offset, var->type, false);
} else if (is_array_block) {
assert(glsl_type_is_struct_or_ifc(var->interface_type));
@@ -226,7 +253,7 @@ nir_gather_xfb_info(const nir_shader *shader, void *mem_ctx)
}
unsigned offset = foffset;
- add_var_xfb_outputs(xfb, var, var->data.xfb_buffer + b,
+ add_var_xfb_outputs(xfb, varyings_info, var, var->data.xfb_buffer + b,
&location, &offset, ftype, false);
}
}
@@ -239,8 +266,11 @@ nir_gather_xfb_info(const nir_shader *shader, void *mem_ctx)
qsort(xfb->outputs, xfb->output_count, sizeof(xfb->outputs[0]),
compare_xfb_output_offsets);
- qsort(xfb->varyings, xfb->varying_count, sizeof(xfb->varyings[0]),
- compare_xfb_varying_offsets);
+ if (varyings_info != NULL) {
+ qsort(varyings_info->varyings, varyings_info->varying_count,
+ sizeof(varyings_info->varyings[0]),
+ compare_xfb_varying_offsets);
+ }
#ifndef NDEBUG
/* Finally, do a sanity check */
diff --git a/src/compiler/nir/nir_xfb_info.h b/src/compiler/nir/nir_xfb_info.h
index f0b222b325d..8bdfa808062 100644
--- a/src/compiler/nir/nir_xfb_info.h
+++ b/src/compiler/nir/nir_xfb_info.h
@@ -55,16 +55,15 @@ typedef struct nir_xfb_info {
nir_xfb_buffer_info buffers[NIR_MAX_XFB_BUFFERS];
uint8_t buffer_to_stream[NIR_MAX_XFB_STREAMS];
- uint16_t varying_count;
- nir_xfb_varying_info *varyings;
-
uint16_t output_count;
- nir_xfb_output_info *outputs;
+ nir_xfb_output_info outputs[0];
} nir_xfb_info;
-/* This method doesn't take into account varyings, as it is used to compute
- * how much size is needed to copy only the outputs.
- */
+typedef struct nir_xfb_varyings_info {
+ uint16_t varying_count;
+ nir_xfb_varying_info varyings[0];
+} nir_xfb_varyings_info;
+
static inline size_t
nir_xfb_info_size(uint16_t output_count)
{
@@ -74,4 +73,8 @@ nir_xfb_info_size(uint16_t output_count)
nir_xfb_info *
nir_gather_xfb_info(const nir_shader *shader, void *mem_ctx);
+nir_xfb_info *
+nir_gather_xfb_info_with_varyings(const nir_shader *shader,
+ void *mem_ctx,
+ nir_xfb_varyings_info **varyings_info);
#endif /* NIR_XFB_INFO_H */