#include <util/u_math.h>
+static nir_xfb_info *
+nir_gather_xfb_info_create(void *mem_ctx, uint16_t output_count, uint16_t varying_count)
+{
+ nir_xfb_info *xfb = rzalloc_size(mem_ctx, sizeof(nir_xfb_info));
+
+ xfb->varyings = rzalloc_size(xfb, sizeof(nir_xfb_varying_info) * varying_count);
+ xfb->outputs = rzalloc_size(xfb, sizeof(nir_xfb_output_info) * output_count);
+
+ return xfb;
+}
+
static void
add_var_xfb_outputs(nir_xfb_info *xfb,
nir_variable *var,
} else {
assert(buffer < NIR_MAX_XFB_BUFFERS);
if (xfb->buffers_written & (1 << buffer)) {
- assert(xfb->strides[buffer] == var->data.xfb_stride);
+ assert(xfb->buffers[buffer].stride == var->data.xfb_stride);
assert(xfb->buffer_to_stream[buffer] == var->data.stream);
} else {
xfb->buffers_written |= (1 << buffer);
- xfb->strides[buffer] = var->data.xfb_stride;
+ xfb->buffers[buffer].stride = var->data.xfb_stride;
xfb->buffer_to_stream[buffer] = var->data.stream;
}
uint8_t comp_mask = ((1 << comp_slots) - 1) << var->data.location_frac;
unsigned comp_offset = var->data.location_frac;
+ nir_xfb_varying_info *varying = &xfb->varyings[xfb->varying_count++];
+ varying->type = type;
+ varying->buffer = var->data.xfb_buffer;
+ varying->offset = *offset;
+ xfb->buffers[var->data.xfb_buffer].varying_count++;
+
while (comp_mask) {
nir_xfb_output_info *output = &xfb->outputs[xfb->output_count++];
* it should be good enough for allocation.
*/
unsigned num_outputs = 0;
+ unsigned num_varyings = 0;
nir_foreach_variable(var, &shader->outputs) {
- if (var->data.explicit_xfb_buffer)
+ if (var->data.explicit_xfb_buffer) {
num_outputs += glsl_count_attribute_slots(var->type, false);
+ num_varyings += glsl_varying_count(var->type);
+ }
}
- if (num_outputs == 0)
+ if (num_outputs == 0 || num_varyings == 0)
return NULL;
- nir_xfb_info *xfb = rzalloc_size(mem_ctx, nir_xfb_info_size(num_outputs));
+ nir_xfb_info *xfb = nir_gather_xfb_info_create(mem_ctx, num_outputs, num_varyings);
/* Walk the list of outputs and add them to the array */
nir_foreach_variable(var, &shader->outputs) {
#define NIR_MAX_XFB_BUFFERS 4
#define NIR_MAX_XFB_STREAMS 4
+typedef struct {
+ uint16_t stride;
+ uint16_t varying_count;
+} nir_xfb_buffer_info;
+
typedef struct {
uint8_t buffer;
uint16_t offset;
uint8_t component_offset;
} nir_xfb_output_info;
+typedef struct {
+ const struct glsl_type *type;
+ uint8_t buffer;
+ uint16_t offset;
+} nir_xfb_varying_info;
+
typedef struct nir_xfb_info {
uint8_t buffers_written;
uint8_t streams_written;
- uint16_t strides[NIR_MAX_XFB_BUFFERS];
+ 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[0];
+ nir_xfb_output_info *outputs;
} 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.
+ */
static inline size_t
nir_xfb_info_size(uint16_t output_count)
{
so.RenderStreamSelect = stream_info ?
stream_info->rasterizationStream : 0;
- so.Buffer0SurfacePitch = xfb_info->strides[0];
- so.Buffer1SurfacePitch = xfb_info->strides[1];
- so.Buffer2SurfacePitch = xfb_info->strides[2];
- so.Buffer3SurfacePitch = xfb_info->strides[3];
+ so.Buffer0SurfacePitch = xfb_info->buffers[0].stride;
+ so.Buffer1SurfacePitch = xfb_info->buffers[1].stride;
+ so.Buffer2SurfacePitch = xfb_info->buffers[2].stride;
+ so.Buffer3SurfacePitch = xfb_info->buffers[3].stride;
int urb_entry_read_offset = 0;
int urb_entry_read_length =