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 "d3d12_compiler.h"
25 #include "d3d12_context.h"
26 #include "d3d12_debug.h"
27 #include "d3d12_screen.h"
28
29 #include "nir.h"
30 #include "compiler/nir/nir_builder.h"
31 #include "compiler/nir/nir_builtin_builder.h"
32
33 #include "util/u_memory.h"
34 #include "util/u_simple_shaders.h"
35
36 static nir_def *
nir_cull_face(nir_builder * b,nir_variable * vertices,bool ccw)37 nir_cull_face(nir_builder *b, nir_variable *vertices, bool ccw)
38 {
39 nir_def *v0 =
40 nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, vertices), nir_imm_int(b, 0)));
41 nir_def *v1 =
42 nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, vertices), nir_imm_int(b, 1)));
43 nir_def *v2 =
44 nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, vertices), nir_imm_int(b, 2)));
45
46 nir_def *dir = nir_fdot(b, nir_cross4(b, nir_fsub(b, v1, v0),
47 nir_fsub(b, v2, v0)),
48 nir_imm_vec4(b, 0.0, 0.0, -1.0, 0.0));
49 if (ccw)
50 return nir_fle_imm(b, dir, 0.0f);
51 else
52 return nir_fgt_imm(b, dir, 0.0f);
53 }
54
55 static void
copy_vars(nir_builder * b,nir_deref_instr * dst,nir_deref_instr * src)56 copy_vars(nir_builder *b, nir_deref_instr *dst, nir_deref_instr *src)
57 {
58 assert(glsl_get_bare_type(dst->type) == glsl_get_bare_type(src->type));
59 if (glsl_type_is_struct(dst->type)) {
60 for (unsigned i = 0; i < glsl_get_length(dst->type); ++i) {
61 copy_vars(b, nir_build_deref_struct(b, dst, i), nir_build_deref_struct(b, src, i));
62 }
63 } else if (glsl_type_is_array_or_matrix(dst->type)) {
64 copy_vars(b, nir_build_deref_array_wildcard(b, dst), nir_build_deref_array_wildcard(b, src));
65 } else {
66 nir_copy_deref(b, dst, src);
67 }
68 }
69
70 static d3d12_shader_selector*
d3d12_make_passthrough_gs(struct d3d12_context * ctx,struct d3d12_gs_variant_key * key)71 d3d12_make_passthrough_gs(struct d3d12_context *ctx, struct d3d12_gs_variant_key *key)
72 {
73 struct d3d12_shader_selector *gs;
74 uint64_t varyings = key->varyings->mask;
75 nir_shader *nir;
76 struct pipe_shader_state templ;
77
78 nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_GEOMETRY,
79 &d3d12_screen(ctx->base.screen)->nir_options,
80 "passthrough");
81
82 nir = b.shader;
83 nir->info.inputs_read = varyings;
84 nir->info.outputs_written = varyings;
85 nir->info.gs.input_primitive = MESA_PRIM_POINTS;
86 nir->info.gs.output_primitive = MESA_PRIM_POINTS;
87 nir->info.gs.vertices_in = 1;
88 nir->info.gs.vertices_out = 1;
89 nir->info.gs.invocations = 1;
90 nir->info.gs.active_stream_mask = 1;
91 nir->num_outputs = 0;
92
93 /* Copy inputs to outputs. */
94 while (varyings) {
95 char tmp[100];
96 const int i = u_bit_scan64(&varyings);
97
98 unsigned frac_slots = key->varyings->slots[i].location_frac_mask;
99 while (frac_slots) {
100 nir_variable *in, *out;
101 int j = u_bit_scan(&frac_slots);
102
103 snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", key->varyings->slots[i].vars[j].driver_location);
104 in = nir_variable_create(nir,
105 nir_var_shader_in,
106 glsl_array_type(key->varyings->slots[i].types[j], 1, false),
107 tmp);
108 in->data.location = i;
109 in->data.location_frac = j;
110 in->data.driver_location = key->varyings->slots[i].vars[j].driver_location;
111 in->data.interpolation = key->varyings->slots[i].vars[j].interpolation;
112 in->data.compact = key->varyings->slots[i].vars[j].compact;
113
114 snprintf(tmp, ARRAY_SIZE(tmp), "out_%d", key->varyings->slots[i].vars[j].driver_location);
115 out = nir_variable_create(nir,
116 nir_var_shader_out,
117 key->varyings->slots[i].types[j],
118 tmp);
119 out->data.location = i;
120 out->data.location_frac = j;
121 out->data.driver_location = key->varyings->slots[i].vars[j].driver_location;
122 out->data.interpolation = key->varyings->slots[i].vars[j].interpolation;
123 out->data.compact = key->varyings->slots[i].vars[j].compact;
124 out->data.always_active_io = key->varyings->slots[i].vars[j].always_active_io;
125
126 nir_deref_instr *in_value = nir_build_deref_array(&b, nir_build_deref_var(&b, in),
127 nir_imm_int(&b, 0));
128 copy_vars(&b, nir_build_deref_var(&b, out), in_value);
129 nir->num_outputs++;
130 }
131 }
132
133 if (key->has_front_face) {
134 nir_variable *front_facing_var = nir_variable_create(nir,
135 nir_var_shader_out,
136 glsl_uint_type(),
137 "gl_FrontFacing");
138 front_facing_var->data.location = VARYING_SLOT_VAR12;
139 front_facing_var->data.driver_location = nir->num_outputs++;
140 front_facing_var->data.interpolation = INTERP_MODE_FLAT;
141 nir_store_deref(&b, nir_build_deref_var(&b, front_facing_var), nir_imm_int(&b, 1), 1);
142 }
143
144 nir_emit_vertex(&b, 0);
145 nir_end_primitive(&b, 0);
146
147 NIR_PASS_V(nir, nir_lower_var_copies);
148 nir_validate_shader(nir, "in d3d12_create_passthrough_gs");
149
150 templ.type = PIPE_SHADER_IR_NIR;
151 templ.ir.nir = nir;
152 templ.stream_output.num_outputs = 0;
153
154 gs = d3d12_create_shader(ctx, PIPE_SHADER_GEOMETRY, &templ);
155
156 return gs;
157 }
158
159 struct emit_primitives_context
160 {
161 struct d3d12_context *ctx;
162 nir_builder b;
163
164 unsigned num_vars;
165 nir_variable *in[VARYING_SLOT_MAX * 4];
166 nir_variable *out[VARYING_SLOT_MAX * 4];
167 nir_variable *front_facing_var;
168
169 nir_loop *loop;
170 nir_deref_instr *loop_index_deref;
171 nir_def *loop_index;
172 nir_def *edgeflag_cmp;
173 nir_def *front_facing;
174 };
175
176 static bool
d3d12_begin_emit_primitives_gs(struct emit_primitives_context * emit_ctx,struct d3d12_context * ctx,struct d3d12_gs_variant_key * key,enum mesa_prim output_primitive,unsigned vertices_out)177 d3d12_begin_emit_primitives_gs(struct emit_primitives_context *emit_ctx,
178 struct d3d12_context *ctx,
179 struct d3d12_gs_variant_key *key,
180 enum mesa_prim output_primitive,
181 unsigned vertices_out)
182 {
183 nir_builder *b = &emit_ctx->b;
184 nir_variable *edgeflag_var = NULL;
185 nir_variable *pos_var = NULL;
186 uint64_t varyings = key->varyings->mask;
187
188 emit_ctx->ctx = ctx;
189
190 emit_ctx->b = nir_builder_init_simple_shader(MESA_SHADER_GEOMETRY,
191 &d3d12_screen(ctx->base.screen)->nir_options,
192 "edgeflags");
193
194 nir_shader *nir = b->shader;
195 nir->info.inputs_read = varyings;
196 nir->info.outputs_written = varyings;
197 nir->info.gs.input_primitive = MESA_PRIM_TRIANGLES;
198 nir->info.gs.output_primitive = output_primitive;
199 nir->info.gs.vertices_in = 3;
200 nir->info.gs.vertices_out = vertices_out;
201 nir->info.gs.invocations = 1;
202 nir->info.gs.active_stream_mask = 1;
203
204 while (varyings) {
205 char tmp[100];
206 const int i = u_bit_scan64(&varyings);
207
208 unsigned frac_slots = key->varyings->slots[i].location_frac_mask;
209 while (frac_slots) {
210 int j = u_bit_scan(&frac_slots);
211 snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", emit_ctx->num_vars);
212 emit_ctx->in[emit_ctx->num_vars] = nir_variable_create(nir,
213 nir_var_shader_in,
214 glsl_array_type(key->varyings->slots[i].types[j], 3, 0),
215 tmp);
216 emit_ctx->in[emit_ctx->num_vars]->data.location = i;
217 emit_ctx->in[emit_ctx->num_vars]->data.location_frac = j;
218 emit_ctx->in[emit_ctx->num_vars]->data.driver_location = key->varyings->slots[i].vars[j].driver_location;
219 emit_ctx->in[emit_ctx->num_vars]->data.interpolation = key->varyings->slots[i].vars[j].interpolation;
220 emit_ctx->in[emit_ctx->num_vars]->data.compact = key->varyings->slots[i].vars[j].compact;
221
222 /* Don't create an output for the edge flag variable */
223 if (i == VARYING_SLOT_EDGE) {
224 edgeflag_var = emit_ctx->in[emit_ctx->num_vars];
225 continue;
226 } else if (i == VARYING_SLOT_POS) {
227 pos_var = emit_ctx->in[emit_ctx->num_vars];
228 }
229
230 snprintf(tmp, ARRAY_SIZE(tmp), "out_%d", emit_ctx->num_vars);
231 emit_ctx->out[emit_ctx->num_vars] = nir_variable_create(nir,
232 nir_var_shader_out,
233 key->varyings->slots[i].types[j],
234 tmp);
235 emit_ctx->out[emit_ctx->num_vars]->data.location = i;
236 emit_ctx->out[emit_ctx->num_vars]->data.location_frac = j;
237 emit_ctx->out[emit_ctx->num_vars]->data.driver_location = key->varyings->slots[i].vars[j].driver_location;
238 emit_ctx->out[emit_ctx->num_vars]->data.interpolation = key->varyings->slots[i].vars[j].interpolation;
239 emit_ctx->out[emit_ctx->num_vars]->data.compact = key->varyings->slots[i].vars[j].compact;
240 emit_ctx->out[emit_ctx->num_vars]->data.always_active_io = key->varyings->slots[i].vars[j].always_active_io;
241
242 emit_ctx->num_vars++;
243 }
244 }
245
246 if (key->has_front_face) {
247 emit_ctx->front_facing_var = nir_variable_create(nir,
248 nir_var_shader_out,
249 glsl_uint_type(),
250 "gl_FrontFacing");
251 emit_ctx->front_facing_var->data.location = VARYING_SLOT_VAR12;
252 emit_ctx->front_facing_var->data.driver_location = emit_ctx->num_vars;
253 emit_ctx->front_facing_var->data.interpolation = INTERP_MODE_FLAT;
254 }
255
256 /* Temporary variable "loop_index" to loop over input vertices */
257 nir_function_impl *impl = nir_shader_get_entrypoint(nir);
258 nir_variable *loop_index_var =
259 nir_local_variable_create(impl, glsl_uint_type(), "loop_index");
260 emit_ctx->loop_index_deref = nir_build_deref_var(b, loop_index_var);
261 nir_store_deref(b, emit_ctx->loop_index_deref, nir_imm_int(b, 0), 1);
262
263 nir_def *diagonal_vertex = NULL;
264 if (key->edge_flag_fix) {
265 nir_def *prim_id = nir_load_primitive_id(b);
266 nir_def *odd = nir_build_alu(b, nir_op_imod,
267 prim_id,
268 nir_imm_int(b, 2),
269 NULL, NULL);
270 diagonal_vertex = nir_bcsel(b, nir_i2b(b, odd),
271 nir_imm_int(b, 2),
272 nir_imm_int(b, 1));
273 }
274
275 if (key->cull_mode != PIPE_FACE_NONE || key->has_front_face) {
276 if (key->cull_mode == PIPE_FACE_BACK)
277 emit_ctx->edgeflag_cmp = nir_cull_face(b, pos_var, key->front_ccw);
278 else if (key->cull_mode == PIPE_FACE_FRONT)
279 emit_ctx->edgeflag_cmp = nir_cull_face(b, pos_var, !key->front_ccw);
280
281 if (key->has_front_face) {
282 if (key->cull_mode == PIPE_FACE_BACK)
283 emit_ctx->front_facing = emit_ctx->edgeflag_cmp;
284 else
285 emit_ctx->front_facing = nir_cull_face(b, pos_var, key->front_ccw);
286 emit_ctx->front_facing = nir_i2i32(b, emit_ctx->front_facing);
287 }
288 }
289
290 /**
291 * while {
292 * if (loop_index >= 3)
293 * break;
294 */
295 emit_ctx->loop = nir_push_loop(b);
296
297 emit_ctx->loop_index = nir_load_deref(b, emit_ctx->loop_index_deref);
298 nir_def *cmp = nir_ige_imm(b, emit_ctx->loop_index, 3);
299 nir_if *loop_check = nir_push_if(b, cmp);
300 nir_jump(b, nir_jump_break);
301 nir_pop_if(b, loop_check);
302
303 if (edgeflag_var) {
304 nir_def *edge_flag =
305 nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, edgeflag_var), emit_ctx->loop_index));
306 nir_def *is_edge = nir_feq_imm(b, nir_channel(b, edge_flag, 0), 1.0);
307 if (emit_ctx->edgeflag_cmp)
308 emit_ctx->edgeflag_cmp = nir_iand(b, emit_ctx->edgeflag_cmp, is_edge);
309 else
310 emit_ctx->edgeflag_cmp = is_edge;
311 }
312
313 if (key->edge_flag_fix) {
314 nir_def *is_edge = nir_ine(b, emit_ctx->loop_index, diagonal_vertex);
315 if (emit_ctx->edgeflag_cmp)
316 emit_ctx->edgeflag_cmp = nir_iand(b, emit_ctx->edgeflag_cmp, is_edge);
317 else
318 emit_ctx->edgeflag_cmp = is_edge;
319 }
320
321 return true;
322 }
323
324 static struct d3d12_shader_selector *
d3d12_finish_emit_primitives_gs(struct emit_primitives_context * emit_ctx,bool end_primitive)325 d3d12_finish_emit_primitives_gs(struct emit_primitives_context *emit_ctx, bool end_primitive)
326 {
327 struct pipe_shader_state templ;
328 nir_builder *b = &emit_ctx->b;
329 nir_shader *nir = b->shader;
330
331 /**
332 * loop_index++;
333 * }
334 */
335 nir_store_deref(b, emit_ctx->loop_index_deref, nir_iadd_imm(b, emit_ctx->loop_index, 1), 1);
336 nir_pop_loop(b, emit_ctx->loop);
337
338 if (end_primitive)
339 nir_end_primitive(b, 0);
340
341 nir_validate_shader(nir, "in d3d12_lower_edge_flags");
342
343 NIR_PASS_V(nir, nir_lower_var_copies);
344
345 templ.type = PIPE_SHADER_IR_NIR;
346 templ.ir.nir = nir;
347 templ.stream_output.num_outputs = 0;
348
349 return d3d12_create_shader(emit_ctx->ctx, PIPE_SHADER_GEOMETRY, &templ);
350 }
351
352 static d3d12_shader_selector*
d3d12_emit_points(struct d3d12_context * ctx,struct d3d12_gs_variant_key * key)353 d3d12_emit_points(struct d3d12_context *ctx, struct d3d12_gs_variant_key *key)
354 {
355 struct emit_primitives_context emit_ctx = {0};
356 nir_builder *b = &emit_ctx.b;
357
358 d3d12_begin_emit_primitives_gs(&emit_ctx, ctx, key, MESA_PRIM_POINTS, 3);
359
360 /**
361 * if (edge_flag)
362 * out_position = in_position;
363 * else
364 * out_position = vec4(-2.0, -2.0, 0.0, 1.0); // Invalid position
365 *
366 * [...] // Copy other variables
367 *
368 * EmitVertex();
369 */
370 for (unsigned i = 0; i < emit_ctx.num_vars; ++i) {
371 nir_def *index = (key->flat_varyings & (1ull << emit_ctx.in[i]->data.location)) ?
372 nir_imm_int(b, (key->flatshade_first ? 0 : 2)) : emit_ctx.loop_index;
373 nir_deref_instr *in_value = nir_build_deref_array(b, nir_build_deref_var(b, emit_ctx.in[i]), index);
374 if (emit_ctx.in[i]->data.location == VARYING_SLOT_POS && emit_ctx.edgeflag_cmp) {
375 nir_if *edge_check = nir_push_if(b, emit_ctx.edgeflag_cmp);
376 copy_vars(b, nir_build_deref_var(b, emit_ctx.out[i]), in_value);
377 nir_if *edge_else = nir_push_else(b, edge_check);
378 nir_store_deref(b, nir_build_deref_var(b, emit_ctx.out[i]),
379 nir_imm_vec4(b, -2.0, -2.0, 0.0, 1.0), 0xf);
380 nir_pop_if(b, edge_else);
381 } else {
382 copy_vars(b, nir_build_deref_var(b, emit_ctx.out[i]), in_value);
383 }
384 }
385 if (key->has_front_face)
386 nir_store_var(b, emit_ctx.front_facing_var, emit_ctx.front_facing, 0x1);
387 nir_emit_vertex(b, 0);
388
389 return d3d12_finish_emit_primitives_gs(&emit_ctx, false);
390 }
391
392 static d3d12_shader_selector*
d3d12_emit_lines(struct d3d12_context * ctx,struct d3d12_gs_variant_key * key)393 d3d12_emit_lines(struct d3d12_context *ctx, struct d3d12_gs_variant_key *key)
394 {
395 struct emit_primitives_context emit_ctx = {0};
396 nir_builder *b = &emit_ctx.b;
397
398 d3d12_begin_emit_primitives_gs(&emit_ctx, ctx, key, MESA_PRIM_LINE_STRIP, 6);
399
400 nir_def *next_index = nir_imod_imm(b, nir_iadd_imm(b, emit_ctx.loop_index, 1), 3);
401
402 /* First vertex */
403 for (unsigned i = 0; i < emit_ctx.num_vars; ++i) {
404 nir_def *index = (key->flat_varyings & (1ull << emit_ctx.in[i]->data.location)) ?
405 nir_imm_int(b, (key->flatshade_first ? 0 : 2)) : emit_ctx.loop_index;
406 nir_deref_instr *in_value = nir_build_deref_array(b, nir_build_deref_var(b, emit_ctx.in[i]), index);
407 copy_vars(b, nir_build_deref_var(b, emit_ctx.out[i]), in_value);
408 }
409 if (key->has_front_face)
410 nir_store_var(b, emit_ctx.front_facing_var, emit_ctx.front_facing, 0x1);
411 nir_emit_vertex(b, 0);
412
413 /* Second vertex. If not an edge, use same position as first vertex */
414 for (unsigned i = 0; i < emit_ctx.num_vars; ++i) {
415 nir_def *index = next_index;
416 if (emit_ctx.in[i]->data.location == VARYING_SLOT_POS)
417 index = nir_bcsel(b, emit_ctx.edgeflag_cmp, next_index, emit_ctx.loop_index);
418 else if (key->flat_varyings & (1ull << emit_ctx.in[i]->data.location))
419 index = nir_imm_int(b, 2);
420 copy_vars(b, nir_build_deref_var(b, emit_ctx.out[i]),
421 nir_build_deref_array(b, nir_build_deref_var(b, emit_ctx.in[i]), index));
422 }
423 if (key->has_front_face)
424 nir_store_var(b, emit_ctx.front_facing_var, emit_ctx.front_facing, 0x1);
425 nir_emit_vertex(b, 0);
426
427 nir_end_primitive(b, 0);
428
429 return d3d12_finish_emit_primitives_gs(&emit_ctx, false);
430 }
431
432 static d3d12_shader_selector*
d3d12_emit_triangles(struct d3d12_context * ctx,struct d3d12_gs_variant_key * key)433 d3d12_emit_triangles(struct d3d12_context *ctx, struct d3d12_gs_variant_key *key)
434 {
435 struct emit_primitives_context emit_ctx = {0};
436 nir_builder *b = &emit_ctx.b;
437
438 d3d12_begin_emit_primitives_gs(&emit_ctx, ctx, key, MESA_PRIM_TRIANGLE_STRIP, 3);
439
440 /**
441 * [...] // Copy variables
442 *
443 * EmitVertex();
444 */
445
446 nir_def *incr = NULL;
447
448 if (key->provoking_vertex > 0)
449 incr = nir_imm_int(b, key->provoking_vertex);
450 else
451 incr = nir_imm_int(b, 3);
452
453 if (key->alternate_tri) {
454 nir_def *odd = nir_imod_imm(b, nir_load_primitive_id(b), 2);
455 incr = nir_isub(b, incr, odd);
456 }
457
458 assert(incr != NULL);
459 nir_def *index = nir_imod_imm(b, nir_iadd(b, emit_ctx.loop_index, incr), 3);
460 for (unsigned i = 0; i < emit_ctx.num_vars; ++i) {
461 nir_deref_instr *in_value = nir_build_deref_array(b, nir_build_deref_var(b, emit_ctx.in[i]), index);
462 copy_vars(b, nir_build_deref_var(b, emit_ctx.out[i]), in_value);
463 }
464 nir_emit_vertex(b, 0);
465
466 return d3d12_finish_emit_primitives_gs(&emit_ctx, true);
467 }
468
469 static uint32_t
hash_gs_variant_key(const void * key)470 hash_gs_variant_key(const void *key)
471 {
472 d3d12_gs_variant_key *v = (d3d12_gs_variant_key*)key;
473 uint32_t hash = _mesa_hash_data(v, offsetof(d3d12_gs_variant_key, varyings));
474 if (v->varyings)
475 hash = _mesa_hash_data_with_seed(v->varyings->slots, sizeof(v->varyings->slots[0]) * v->varyings->max, hash);
476 return hash;
477 }
478
479 static bool
equals_gs_variant_key(const void * a,const void * b)480 equals_gs_variant_key(const void *a, const void *b)
481 {
482 return memcmp(a, b, sizeof(d3d12_gs_variant_key)) == 0;
483 }
484
485 void
d3d12_gs_variant_cache_init(struct d3d12_context * ctx)486 d3d12_gs_variant_cache_init(struct d3d12_context *ctx)
487 {
488 ctx->gs_variant_cache = _mesa_hash_table_create(NULL, NULL, equals_gs_variant_key);
489 }
490
491 static void
delete_entry(struct hash_entry * entry)492 delete_entry(struct hash_entry *entry)
493 {
494 d3d12_shader_free((d3d12_shader_selector *)entry->data);
495 }
496
497 void
d3d12_gs_variant_cache_destroy(struct d3d12_context * ctx)498 d3d12_gs_variant_cache_destroy(struct d3d12_context *ctx)
499 {
500 _mesa_hash_table_destroy(ctx->gs_variant_cache, delete_entry);
501 }
502
503 static struct d3d12_shader_selector *
create_geometry_shader_variant(struct d3d12_context * ctx,struct d3d12_gs_variant_key * key)504 create_geometry_shader_variant(struct d3d12_context *ctx, struct d3d12_gs_variant_key *key)
505 {
506 d3d12_shader_selector *gs = NULL;
507
508 if (key->passthrough)
509 gs = d3d12_make_passthrough_gs(ctx, key);
510 else if (key->provoking_vertex > 0 || key->alternate_tri)
511 gs = d3d12_emit_triangles(ctx, key);
512 else if (key->fill_mode == PIPE_POLYGON_MODE_POINT)
513 gs = d3d12_emit_points(ctx, key);
514 else if (key->fill_mode == PIPE_POLYGON_MODE_LINE)
515 gs = d3d12_emit_lines(ctx, key);
516
517 if (gs) {
518 gs->is_variant = true;
519 gs->gs_key = *key;
520 }
521
522 return gs;
523 }
524
525 d3d12_shader_selector *
d3d12_get_gs_variant(struct d3d12_context * ctx,struct d3d12_gs_variant_key * key)526 d3d12_get_gs_variant(struct d3d12_context *ctx, struct d3d12_gs_variant_key *key)
527 {
528 uint32_t hash = hash_gs_variant_key(key);
529 struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ctx->gs_variant_cache,
530 hash, key);
531 if (!entry) {
532 d3d12_shader_selector *gs = create_geometry_shader_variant(ctx, key);
533 entry = _mesa_hash_table_insert_pre_hashed(ctx->gs_variant_cache,
534 hash, &gs->gs_key, gs);
535 assert(entry);
536 }
537
538 return (d3d12_shader_selector *)entry->data;
539 }
540