Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_lower_point_sprite.c
4570 views
1
/*
2
* Copyright © Microsoft 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_builder.h"
26
#include "d3d12_compiler.h"
27
#include "d3d12_nir_passes.h"
28
#include "dxil_nir.h"
29
#include "program/prog_statevars.h"
30
31
struct lower_state {
32
nir_variable *uniform; /* (1/w, 1/h, pt_sz, max_sz) */
33
nir_variable *pos_out;
34
nir_variable *psiz_out;
35
nir_variable *point_coord_out[9];
36
unsigned num_point_coords;
37
nir_variable *varying_out[VARYING_SLOT_MAX];
38
39
nir_ssa_def *point_dir_imm[4];
40
nir_ssa_def *point_coord_imm[4];
41
42
/* Current point primitive */
43
nir_ssa_def *point_pos;
44
nir_ssa_def *point_size;
45
nir_ssa_def *varying[VARYING_SLOT_MAX];
46
unsigned varying_write_mask[VARYING_SLOT_MAX];
47
48
bool sprite_origin_lower_left;
49
bool point_size_per_vertex;
50
bool aa_point;
51
};
52
53
static void
54
find_outputs(nir_shader *shader, struct lower_state *state)
55
{
56
nir_foreach_variable_with_modes(var, shader, nir_var_shader_out) {
57
switch (var->data.location) {
58
case VARYING_SLOT_POS:
59
state->pos_out = var;
60
break;
61
case VARYING_SLOT_PSIZ:
62
state->psiz_out = var;
63
break;
64
default:
65
state->varying_out[var->data.location] = var;
66
break;
67
}
68
}
69
}
70
71
static nir_ssa_def *
72
get_point_dir(nir_builder *b, struct lower_state *state, unsigned i)
73
{
74
if (state->point_dir_imm[0] == NULL) {
75
state->point_dir_imm[0] = nir_imm_vec2(b, -1, -1);
76
state->point_dir_imm[1] = nir_imm_vec2(b, -1, 1);
77
state->point_dir_imm[2] = nir_imm_vec2(b, 1, -1);
78
state->point_dir_imm[3] = nir_imm_vec2(b, 1, 1);
79
}
80
81
return state->point_dir_imm[i];
82
}
83
84
static nir_ssa_def *
85
get_point_coord(nir_builder *b, struct lower_state *state, unsigned i)
86
{
87
if (state->point_coord_imm[0] == NULL) {
88
if (state->sprite_origin_lower_left) {
89
state->point_coord_imm[0] = nir_imm_vec4(b, 0, 0, 0, 1);
90
state->point_coord_imm[1] = nir_imm_vec4(b, 0, 1, 0, 1);
91
state->point_coord_imm[2] = nir_imm_vec4(b, 1, 0, 0, 1);
92
state->point_coord_imm[3] = nir_imm_vec4(b, 1, 1, 0, 1);
93
} else {
94
state->point_coord_imm[0] = nir_imm_vec4(b, 0, 1, 0, 1);
95
state->point_coord_imm[1] = nir_imm_vec4(b, 0, 0, 0, 1);
96
state->point_coord_imm[2] = nir_imm_vec4(b, 1, 1, 0, 1);
97
state->point_coord_imm[3] = nir_imm_vec4(b, 1, 0, 0, 1);
98
}
99
}
100
101
return state->point_coord_imm[i];
102
}
103
104
/**
105
* scaled_point_size = pointSize * pos.w * ViewportSizeRcp
106
*/
107
static void
108
get_scaled_point_size(nir_builder *b, struct lower_state *state,
109
nir_ssa_def **x, nir_ssa_def **y)
110
{
111
/* State uniform contains: (1/ViewportWidth, 1/ViewportHeight, PointSize, MaxPointSize) */
112
nir_ssa_def *uniform = nir_load_var(b, state->uniform);
113
nir_ssa_def *point_size = state->point_size;
114
115
/* clamp point-size to valid range */
116
if (point_size && state->point_size_per_vertex) {
117
point_size = nir_fmax(b, point_size, nir_imm_float(b, 1.0f));
118
point_size = nir_fmin(b, point_size, nir_imm_float(b, D3D12_MAX_POINT_SIZE));
119
} else {
120
/* Use static point size (from uniform) if the shader output was not set */
121
point_size = nir_channel(b, uniform, 2);
122
}
123
124
point_size = nir_fmul(b, point_size, nir_channel(b, state->point_pos, 3));
125
*x = nir_fmul(b, point_size, nir_channel(b, uniform, 0));
126
*y = nir_fmul(b, point_size, nir_channel(b, uniform, 1));
127
}
128
129
static bool
130
lower_store(nir_intrinsic_instr *instr, nir_builder *b, struct lower_state *state)
131
{
132
nir_deref_instr *deref = nir_src_as_deref(instr->src[0]);
133
if (nir_deref_mode_is(deref, nir_var_shader_out)) {
134
nir_variable *var = nir_deref_instr_get_variable(deref);
135
136
switch (var->data.location) {
137
case VARYING_SLOT_POS:
138
state->point_pos = instr->src[1].ssa;
139
break;
140
case VARYING_SLOT_PSIZ:
141
state->point_size = instr->src[1].ssa;
142
break;
143
default:
144
state->varying[var->data.location] = instr->src[1].ssa;
145
state->varying_write_mask[var->data.location] = nir_intrinsic_write_mask(instr);
146
break;
147
}
148
149
nir_instr_remove(&instr->instr);
150
return true;
151
}
152
153
return false;
154
}
155
156
static bool
157
lower_emit_vertex(nir_intrinsic_instr *instr, nir_builder *b, struct lower_state *state)
158
{
159
unsigned stream_id = nir_intrinsic_stream_id(instr);
160
161
nir_ssa_def *point_width, *point_height;
162
get_scaled_point_size(b, state, &point_width, &point_height);
163
164
nir_instr_remove(&instr->instr);
165
166
for (unsigned i = 0; i < 4; i++) {
167
/* All outputs need to be emitted for each vertex */
168
for (unsigned slot = 0; slot < VARYING_SLOT_MAX; ++slot) {
169
if (state->varying[slot] != NULL) {
170
nir_store_var(b, state->varying_out[slot], state->varying[slot],
171
state->varying_write_mask[slot]);
172
}
173
}
174
175
/* pos = scaled_point_size * point_dir + point_pos */
176
nir_ssa_def *point_dir = get_point_dir(b, state, i);
177
nir_ssa_def *pos = nir_vec4(b,
178
nir_ffma(b,
179
point_width,
180
nir_channel(b, point_dir, 0),
181
nir_channel(b, state->point_pos, 0)),
182
nir_ffma(b,
183
point_height,
184
nir_channel(b, point_dir, 1),
185
nir_channel(b, state->point_pos, 1)),
186
nir_channel(b, state->point_pos, 2),
187
nir_channel(b, state->point_pos, 3));
188
nir_store_var(b, state->pos_out, pos, 0xf);
189
190
/* point coord */
191
nir_ssa_def *point_coord = get_point_coord(b, state, i);
192
for (unsigned j = 0; j < state->num_point_coords; ++j)
193
nir_store_var(b, state->point_coord_out[j], point_coord, 0xf);
194
195
/* EmitVertex */
196
nir_emit_vertex(b, .stream_id = stream_id);
197
}
198
199
/* EndPrimitive */
200
nir_end_primitive(b, .stream_id = stream_id);
201
202
/* Reset everything */
203
state->point_pos = NULL;
204
state->point_size = NULL;
205
for (unsigned i = 0; i < VARYING_SLOT_MAX; ++i)
206
state->varying[i] = NULL;
207
208
return true;
209
}
210
211
static bool
212
lower_instr(nir_intrinsic_instr *instr, nir_builder *b, struct lower_state *state)
213
{
214
b->cursor = nir_before_instr(&instr->instr);
215
216
if (instr->intrinsic == nir_intrinsic_store_deref) {
217
return lower_store(instr, b, state);
218
} else if (instr->intrinsic == nir_intrinsic_emit_vertex) {
219
return lower_emit_vertex(instr, b, state);
220
} else if (instr->intrinsic == nir_intrinsic_end_primitive) {
221
nir_instr_remove(&instr->instr);
222
return true;
223
}
224
225
return false;
226
}
227
228
bool
229
d3d12_lower_point_sprite(nir_shader *shader,
230
bool sprite_origin_lower_left,
231
bool point_size_per_vertex,
232
unsigned point_coord_enable,
233
uint64_t next_inputs_read)
234
{
235
const gl_state_index16 tokens[4] = { STATE_INTERNAL_DRIVER,
236
D3D12_STATE_VAR_PT_SPRITE };
237
struct lower_state state;
238
bool progress = false;
239
240
assert(shader->info.gs.output_primitive == GL_POINTS);
241
242
memset(&state, 0, sizeof(state));
243
find_outputs(shader, &state);
244
state.sprite_origin_lower_left = sprite_origin_lower_left;
245
state.point_size_per_vertex = point_size_per_vertex;
246
247
/* Create uniform to retrieve inverse of viewport size and point size:
248
* (1/ViewportWidth, 1/ViewportHeight, PointSize, MaxPointSize) */
249
state.uniform = nir_variable_create(shader,
250
nir_var_uniform,
251
glsl_vec4_type(),
252
"d3d12_ViewportSizeRcp");
253
state.uniform->num_state_slots = 1;
254
state.uniform->state_slots = ralloc_array(state.uniform, nir_state_slot, 1);
255
memcpy(state.uniform->state_slots[0].tokens, tokens,
256
sizeof(state.uniform->state_slots[0].tokens));
257
shader->num_uniforms++;
258
259
/* Create new outputs for point tex coordinates */
260
unsigned count = 0;
261
for (unsigned int sem = 0; sem < 9; sem++) {
262
if (point_coord_enable & BITFIELD64_BIT(sem)) {
263
char tmp[100];
264
unsigned location = VARYING_SLOT_VAR0 + sem;
265
266
snprintf(tmp, ARRAY_SIZE(tmp), "gl_TexCoord%dMESA", count);
267
268
nir_variable *var = nir_variable_create(shader,
269
nir_var_shader_out,
270
glsl_vec4_type(),
271
tmp);
272
var->data.location = location;
273
state.point_coord_out[count++] = var;
274
}
275
}
276
state.num_point_coords = count;
277
if (point_coord_enable) {
278
dxil_reassign_driver_locations(shader, nir_var_shader_out,
279
next_inputs_read);
280
}
281
282
nir_foreach_function(function, shader) {
283
if (function->impl) {
284
nir_builder builder;
285
nir_builder_init(&builder, function->impl);
286
nir_foreach_block(block, function->impl) {
287
nir_foreach_instr_safe(instr, block) {
288
if (instr->type == nir_instr_type_intrinsic)
289
progress |= lower_instr(nir_instr_as_intrinsic(instr),
290
&builder,
291
&state);
292
}
293
}
294
295
nir_metadata_preserve(function->impl, nir_metadata_block_index |
296
nir_metadata_dominance);
297
}
298
}
299
300
shader->info.gs.output_primitive = GL_TRIANGLE_STRIP;
301
shader->info.gs.vertices_out *= 4;
302
303
return progress;
304
}
305
306