2 * Copyright © 2018 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 #include "nir_xfb_info.h"
26 #include "gl_nir_linker.h"
27 #include "linker_util.h"
28 #include "main/context.h"
29 #include "util/u_math.h"
32 * This file does the linking of GLSL transform feedback using NIR.
36 gl_nir_link_assign_xfb_resources(struct gl_context
*ctx
,
37 struct gl_shader_program
*prog
)
40 * From ARB_gl_spirv spec:
42 * "- If the *Xfb* Execution Mode is set, any output variable that is at
43 * least partially captured:
44 * * must be decorated with an *XfbBuffer*, declaring the capturing buffer
45 * * must have at least one captured output variable in the capturing
46 * buffer decorated with an *XfbStride* (and all such *XfbStride* values
47 * for the capturing buffer must be equal)
48 * - If the *Xfb* Execution Mode is set, any captured output:
49 * * must be a non-structure decorated with *Offset* or a member of a
50 * structure whose type member is decorated with *Offset*"
52 * Note the "must be", meaning that explicit buffer, offset and stride are
53 * mandatory. So as this is intended to work with SPIR-V shaders we don't
54 * need to calculate the offset or the stride.
57 struct gl_program
*xfb_prog
= prog
->last_vert_prog
;
62 /* free existing varyings, if any */
63 for (unsigned i
= 0; i
< prog
->TransformFeedback
.NumVarying
; i
++)
64 free(prog
->TransformFeedback
.VaryingNames
[i
]);
65 free(prog
->TransformFeedback
.VaryingNames
);
67 nir_xfb_info
*xfb_info
= NULL
;
68 nir_xfb_varyings_info
*varyings_info
= NULL
;
70 /* Find last stage before fragment shader */
71 for (int stage
= MESA_SHADER_FRAGMENT
- 1; stage
>= 0; stage
--) {
72 struct gl_linked_shader
*sh
= prog
->_LinkedShaders
[stage
];
74 if (sh
&& stage
!= MESA_SHADER_TESS_CTRL
) {
75 xfb_info
= nir_gather_xfb_info_with_varyings(sh
->Program
->nir
, NULL
, &varyings_info
);
80 struct gl_transform_feedback_info
*linked_xfb
=
81 rzalloc(xfb_prog
, struct gl_transform_feedback_info
);
82 xfb_prog
->sh
.LinkedTransformFeedback
= linked_xfb
;
85 prog
->TransformFeedback
.NumVarying
= 0;
86 linked_xfb
->NumOutputs
= 0;
87 linked_xfb
->NumVarying
= 0;
88 linked_xfb
->ActiveBuffers
= 0;
92 for (unsigned buf
= 0; buf
< MAX_FEEDBACK_BUFFERS
; buf
++)
93 prog
->TransformFeedback
.BufferStride
[buf
] = xfb_info
->buffers
[buf
].stride
;
95 prog
->TransformFeedback
.NumVarying
= varyings_info
->varying_count
;
96 prog
->TransformFeedback
.VaryingNames
=
97 malloc(sizeof(GLchar
*) * varyings_info
->varying_count
);
100 rzalloc_array(xfb_prog
,
101 struct gl_transform_feedback_output
,
102 xfb_info
->output_count
);
103 linked_xfb
->NumOutputs
= xfb_info
->output_count
;
105 linked_xfb
->Varyings
=
106 rzalloc_array(xfb_prog
,
107 struct gl_transform_feedback_varying_info
,
108 varyings_info
->varying_count
);
109 linked_xfb
->NumVarying
= varyings_info
->varying_count
;
111 int buffer_index
= 0; /* Corresponds to GL_TRANSFORM_FEEDBACK_BUFFER_INDEX */
113 (varyings_info
->varying_count
> 0) ?
114 xfb_info
->outputs
[0].buffer
: 0;
116 for (unsigned i
= 0; i
< varyings_info
->varying_count
; i
++) {
117 nir_xfb_varying_info
*xfb_varying
= &varyings_info
->varyings
[i
];
119 /* From ARB_gl_spirv spec:
121 * "19. How should the program interface query operations behave for
122 * program objects created from SPIR-V shaders?
124 * DISCUSSION: we previously said we didn't need reflection to work
125 * for SPIR-V shaders (at least for the first version), however we
126 * are left with specifying how it should "not work". The primary
127 * issue is that SPIR-V binaries are not required to have names
128 * associated with variables. They can be associated in debug
129 * information, but there is no requirement for that to be present,
130 * and it should not be relied upon."
136 * "RESOLVED. Pick (c), but also allow debug names to be returned
137 * if an implementation wants to."
139 * So names are considered optional debug info, so the linker needs to
140 * work without them, and returning them is optional. For simplicity at
141 * this point we are ignoring names
143 prog
->TransformFeedback
.VaryingNames
[i
] = NULL
;
145 if (xfb_buffer
!= xfb_varying
->buffer
) {
147 xfb_buffer
= xfb_varying
->buffer
;
150 struct gl_transform_feedback_varying_info
*varying
=
151 linked_xfb
->Varyings
+ i
;
153 /* ARB_gl_spirv: see above. */
154 varying
->Name
= NULL
;
155 varying
->Type
= glsl_get_gl_type(xfb_varying
->type
);
156 varying
->BufferIndex
= buffer_index
;
157 varying
->Size
= glsl_type_is_array(xfb_varying
->type
) ?
158 glsl_get_length(xfb_varying
->type
) : 1;
159 varying
->Offset
= xfb_varying
->offset
;
162 for (unsigned i
= 0; i
< xfb_info
->output_count
; i
++) {
163 nir_xfb_output_info
*xfb_output
= &xfb_info
->outputs
[i
];
165 struct gl_transform_feedback_output
*output
=
166 linked_xfb
->Outputs
+ i
;
168 output
->OutputRegister
= xfb_output
->location
;
169 output
->OutputBuffer
= xfb_output
->buffer
;
170 output
->NumComponents
= util_bitcount(xfb_output
->component_mask
);
171 output
->StreamId
= xfb_info
->buffer_to_stream
[xfb_output
->buffer
];
172 output
->DstOffset
= xfb_output
->offset
/ 4;
173 output
->ComponentOffset
= xfb_output
->component_offset
;
176 /* Make sure MaxTransformFeedbackBuffers is <= 32 so the bitmask for
177 * tracking the number of buffers doesn't overflow.
179 unsigned buffers
= 0;
180 assert(ctx
->Const
.MaxTransformFeedbackBuffers
<= sizeof(buffers
) * 8);
182 for (unsigned buf
= 0; buf
< MAX_FEEDBACK_BUFFERS
; buf
++) {
183 if (xfb_info
->buffers
[buf
].stride
> 0) {
184 linked_xfb
->Buffers
[buf
].Stride
= xfb_info
->buffers
[buf
].stride
/ 4;
185 linked_xfb
->Buffers
[buf
].NumVaryings
= xfb_info
->buffers
[buf
].varying_count
;
190 linked_xfb
->ActiveBuffers
= buffers
;
192 ralloc_free(xfb_info
);