Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/compiler/glsl/gl_nir_link_xfb.c
4545 views
1
/*
2
* Copyright © 2018 Intel Corporation
3
*
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:
10
*
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
13
* Software.
14
*
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
21
* IN THE SOFTWARE.
22
*/
23
24
#include "nir.h"
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"
30
31
/**
32
* This file does the linking of GLSL transform feedback using NIR.
33
*/
34
35
void
36
gl_nir_link_assign_xfb_resources(struct gl_context *ctx,
37
struct gl_shader_program *prog)
38
{
39
/*
40
* From ARB_gl_spirv spec:
41
*
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*"
51
*
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.
55
*/
56
57
struct gl_program *xfb_prog = prog->last_vert_prog;
58
59
if (xfb_prog == NULL)
60
return;
61
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);
66
67
nir_xfb_info *xfb_info = NULL;
68
nir_xfb_varyings_info *varyings_info = NULL;
69
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];
73
74
if (sh && stage != MESA_SHADER_TESS_CTRL) {
75
xfb_info = nir_gather_xfb_info_with_varyings(sh->Program->nir, NULL, &varyings_info);
76
break;
77
}
78
}
79
80
struct gl_transform_feedback_info *linked_xfb =
81
rzalloc(xfb_prog, struct gl_transform_feedback_info);
82
xfb_prog->sh.LinkedTransformFeedback = linked_xfb;
83
84
if (!xfb_info) {
85
prog->TransformFeedback.NumVarying = 0;
86
linked_xfb->NumOutputs = 0;
87
linked_xfb->NumVarying = 0;
88
linked_xfb->ActiveBuffers = 0;
89
return;
90
}
91
92
for (unsigned buf = 0; buf < MAX_FEEDBACK_BUFFERS; buf++)
93
prog->TransformFeedback.BufferStride[buf] = xfb_info->buffers[buf].stride;
94
95
prog->TransformFeedback.NumVarying = varyings_info->varying_count;
96
prog->TransformFeedback.VaryingNames =
97
malloc(sizeof(GLchar *) * varyings_info->varying_count);
98
99
linked_xfb->Outputs =
100
rzalloc_array(xfb_prog,
101
struct gl_transform_feedback_output,
102
xfb_info->output_count);
103
linked_xfb->NumOutputs = xfb_info->output_count;
104
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;
110
111
int buffer_index = 0; /* Corresponds to GL_TRANSFORM_FEEDBACK_BUFFER_INDEX */
112
int xfb_buffer =
113
(varyings_info->varying_count > 0) ?
114
xfb_info->outputs[0].buffer : 0;
115
116
for (unsigned i = 0; i < varyings_info->varying_count; i++) {
117
nir_xfb_varying_info *xfb_varying = &varyings_info->varyings[i];
118
119
/* From ARB_gl_spirv spec:
120
*
121
* "19. How should the program interface query operations behave for
122
* program objects created from SPIR-V shaders?
123
*
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."
131
*
132
* Options:"
133
*
134
* <skip>
135
*
136
* "RESOLVED. Pick (c), but also allow debug names to be returned
137
* if an implementation wants to."
138
*
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
142
*/
143
prog->TransformFeedback.VaryingNames[i] = NULL;
144
145
if (xfb_buffer != xfb_varying->buffer) {
146
buffer_index++;
147
xfb_buffer = xfb_varying->buffer;
148
}
149
150
struct gl_transform_feedback_varying_info *varying =
151
linked_xfb->Varyings + i;
152
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;
160
}
161
162
for (unsigned i = 0; i < xfb_info->output_count; i++) {
163
nir_xfb_output_info *xfb_output = &xfb_info->outputs[i];
164
165
struct gl_transform_feedback_output *output =
166
linked_xfb->Outputs + i;
167
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;
174
}
175
176
/* Make sure MaxTransformFeedbackBuffers is <= 32 so the bitmask for
177
* tracking the number of buffers doesn't overflow.
178
*/
179
unsigned buffers = 0;
180
assert(ctx->Const.MaxTransformFeedbackBuffers <= sizeof(buffers) * 8);
181
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;
186
buffers |= 1 << buf;
187
}
188
}
189
190
linked_xfb->ActiveBuffers = buffers;
191
192
ralloc_free(xfb_info);
193
}
194
195