diff options
-rw-r--r-- | src/compiler/glsl/gl_nir_link_xfb.c | 17 | ||||
-rw-r--r-- | src/compiler/nir/nir_gather_xfb_info.c | 60 | ||||
-rw-r--r-- | src/compiler/nir/nir_xfb_info.h | 17 |
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 */ |