~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/drivers/d3d12/d3d12_compute_transforms.cpp

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
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_compute_transforms.h"
25
 
#include "d3d12_nir_passes.h"
26
 
#include "d3d12_query.h"
27
 
#include "d3d12_screen.h"
28
 
 
29
 
#include "nir.h"
30
 
#include "nir_builder.h"
31
 
 
32
 
#include "util/u_memory.h"
33
 
 
34
 
nir_shader *
35
 
get_indirect_draw_base_vertex_transform(const nir_shader_compiler_options *options, const d3d12_compute_transform_key *args)
36
 
{
37
 
   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options, "TransformIndirectDrawBaseVertex");
38
 
 
39
 
   if (args->base_vertex.dynamic_count) {
40
 
      nir_variable *count_ubo = nir_variable_create(b.shader, nir_var_mem_ubo,
41
 
         glsl_uint_type(), "in_count");
42
 
      count_ubo->data.driver_location = 0;
43
 
   }
44
 
 
45
 
   nir_variable *input_ssbo = nir_variable_create(b.shader, nir_var_mem_ssbo,
46
 
      glsl_array_type(glsl_uint_type(), 0, 0), "input");
47
 
   nir_variable *output_ssbo = nir_variable_create(b.shader, nir_var_mem_ssbo,
48
 
      input_ssbo->type, "output");
49
 
   input_ssbo->data.driver_location = 0;
50
 
   output_ssbo->data.driver_location = 1;
51
 
 
52
 
   nir_ssa_def *draw_id = nir_channel(&b, nir_load_global_invocation_id(&b, 32), 0);
53
 
   if (args->base_vertex.dynamic_count) {
54
 
      nir_ssa_def *count = nir_load_ubo(&b, 1, 32, nir_imm_int(&b, 1), nir_imm_int(&b, 0),
55
 
         (gl_access_qualifier)0, 4, 0, 0, 4);
56
 
      nir_push_if(&b, nir_ilt(&b, draw_id, count));
57
 
   }
58
 
 
59
 
   nir_variable *stride_ubo = NULL;
60
 
   nir_ssa_def *in_stride_offset_and_base_drawid = d3d12_get_state_var(&b, D3D12_STATE_VAR_TRANSFORM_GENERIC0, "d3d12_Stride",
61
 
      glsl_uvec4_type(), &stride_ubo);
62
 
   nir_ssa_def *in_offset = nir_iadd(&b, nir_channel(&b, in_stride_offset_and_base_drawid, 1),
63
 
      nir_imul(&b, nir_channel(&b, in_stride_offset_and_base_drawid, 0), draw_id));
64
 
   nir_ssa_def *in_data0 = nir_load_ssbo(&b, 4, 32, nir_imm_int(&b, 0), in_offset, (gl_access_qualifier)0, 4, 0);
65
 
 
66
 
   nir_ssa_def *in_data1 = NULL;
67
 
   nir_ssa_def *base_vertex = NULL, *base_instance = NULL;
68
 
   if (args->base_vertex.indexed) {
69
 
      nir_ssa_def *in_offset1 = nir_iadd(&b, in_offset, nir_imm_int(&b, 16));
70
 
      in_data1 = nir_load_ssbo(&b, 1, 32, nir_imm_int(&b, 0), in_offset1, (gl_access_qualifier)0, 4, 0);
71
 
      base_vertex = nir_channel(&b, in_data0, 3);
72
 
      base_instance = in_data1;
73
 
   } else {
74
 
      base_vertex = nir_channel(&b, in_data0, 2);
75
 
      base_instance = nir_channel(&b, in_data0, 3);
76
 
   }
77
 
 
78
 
   /* 4 additional uints for base vertex, base instance, draw ID, and a bool for indexed draw */
79
 
   unsigned out_stride = sizeof(uint32_t) * ((args->base_vertex.indexed ? 5 : 4) + 4);
80
 
 
81
 
   nir_ssa_def *out_offset = nir_imul(&b, draw_id, nir_imm_int(&b, out_stride));
82
 
   nir_ssa_def *out_data0 = nir_vec4(&b, base_vertex, base_instance,
83
 
      nir_iadd(&b, draw_id, nir_channel(&b, in_stride_offset_and_base_drawid, 2)),
84
 
      nir_imm_int(&b, args->base_vertex.indexed ? -1 : 0));
85
 
   nir_ssa_def *out_data1 = in_data0;
86
 
 
87
 
   nir_store_ssbo(&b, out_data0, nir_imm_int(&b, 1), out_offset, 0xf, (gl_access_qualifier)0, 4, 0);
88
 
   nir_store_ssbo(&b, out_data1, nir_imm_int(&b, 1), nir_iadd(&b, out_offset, nir_imm_int(&b, 16)),
89
 
      (1u << out_data1->num_components) - 1, (gl_access_qualifier)0, 4, 0);
90
 
   if (args->base_vertex.indexed)
91
 
      nir_store_ssbo(&b, in_data1, nir_imm_int(&b, 1), nir_iadd(&b, out_offset, nir_imm_int(&b, 32)), 1, (gl_access_qualifier)0, 4, 0);
92
 
 
93
 
   if (args->base_vertex.dynamic_count)
94
 
      nir_pop_if(&b, NULL);
95
 
 
96
 
   nir_validate_shader(b.shader, "creation");
97
 
   b.shader->info.num_ssbos = 2;
98
 
   b.shader->info.num_ubos = (args->base_vertex.dynamic_count ? 1 : 0);
99
 
 
100
 
   return b.shader;
101
 
}
102
 
 
103
 
static struct nir_shader *
104
 
get_fake_so_buffer_copy_back(const nir_shader_compiler_options *options, const d3d12_compute_transform_key *key)
105
 
{
106
 
   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options, "FakeSOBufferCopyBack");
107
 
 
108
 
   nir_variable *output_so_data_var = nir_variable_create(b.shader, nir_var_mem_ssbo,
109
 
      glsl_array_type(glsl_uint_type(), 0, 0), "output_data");
110
 
   nir_variable *input_so_data_var = nir_variable_create(b.shader, nir_var_mem_ssbo, output_so_data_var->type, "input_data");
111
 
   output_so_data_var->data.driver_location = 0;
112
 
   input_so_data_var->data.driver_location = 1;
113
 
 
114
 
   /* UBO is [fake SO filled size, fake SO vertex count, 1, 1, original SO filled size] */
115
 
   nir_variable *input_ubo = nir_variable_create(b.shader, nir_var_mem_ubo,
116
 
      glsl_array_type(glsl_uint_type(), 5, 0), "input_ubo");
117
 
   input_ubo->data.driver_location = 0;
118
 
 
119
 
   nir_ssa_def *original_so_filled_size = nir_load_ubo(&b, 1, 32, nir_imm_int(&b, 0), nir_imm_int(&b, 4 * sizeof(uint32_t)),
120
 
      (gl_access_qualifier)0, 4, 0, 4 * sizeof(uint32_t), 4);
121
 
 
122
 
   nir_variable *state_var = nullptr;
123
 
   nir_ssa_def *fake_so_multiplier = d3d12_get_state_var(&b, D3D12_STATE_VAR_TRANSFORM_GENERIC0, "fake_so_multiplier", glsl_uint_type(), &state_var);
124
 
 
125
 
   nir_ssa_def *vertex_offset = nir_imul(&b, nir_imm_int(&b, key->fake_so_buffer_copy_back.stride),
126
 
      nir_channel(&b, nir_load_global_invocation_id(&b, 32), 0));
127
 
 
128
 
   nir_ssa_def *output_offset_base = nir_iadd(&b, original_so_filled_size, vertex_offset);
129
 
   nir_ssa_def *input_offset_base = nir_imul(&b, vertex_offset, fake_so_multiplier);
130
 
 
131
 
   for (unsigned i = 0; i < key->fake_so_buffer_copy_back.num_ranges; ++i) {
132
 
      auto& output = key->fake_so_buffer_copy_back.ranges[i];
133
 
      assert(output.size % 4 == 0 && output.offset % 4 == 0);
134
 
      nir_ssa_def *field_offset = nir_imm_int(&b, output.offset);
135
 
      nir_ssa_def *output_offset = nir_iadd(&b, output_offset_base, field_offset);
136
 
      nir_ssa_def *input_offset = nir_iadd(&b, input_offset_base, field_offset);
137
 
 
138
 
      for (unsigned loaded = 0; loaded < output.size; loaded += 16) {
139
 
         unsigned to_load = MIN2(output.size, 16);
140
 
         unsigned components = to_load / 4;
141
 
         nir_ssa_def *loaded_data = nir_load_ssbo(&b, components, 32, nir_imm_int(&b, 1),
142
 
            nir_iadd(&b, input_offset, nir_imm_int(&b, loaded)), (gl_access_qualifier)0, 4, 0);
143
 
         nir_store_ssbo(&b, loaded_data, nir_imm_int(&b, 0),
144
 
            nir_iadd(&b, output_offset, nir_imm_int(&b, loaded)), (1u << components) - 1, (gl_access_qualifier)0, 4, 0);
145
 
      }
146
 
   }
147
 
 
148
 
   nir_validate_shader(b.shader, "creation");
149
 
   b.shader->info.num_ssbos = 2;
150
 
   b.shader->info.num_ubos = 1;
151
 
 
152
 
   return b.shader;
153
 
}
154
 
 
155
 
static struct nir_shader *
156
 
get_fake_so_buffer_vertex_count(const nir_shader_compiler_options *options)
157
 
{
158
 
   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options, "FakeSOBufferVertexCount");
159
 
 
160
 
   nir_variable_create(b.shader, nir_var_mem_ssbo, glsl_array_type(glsl_uint_type(), 0, 0), "fake_so");
161
 
   nir_ssa_def *fake_buffer_filled_size = nir_load_ssbo(&b, 1, 32, nir_imm_int(&b, 0), nir_imm_int(&b, 0), (gl_access_qualifier)0, 4, 0);
162
 
 
163
 
   nir_variable *real_so_var = nir_variable_create(b.shader, nir_var_mem_ssbo,
164
 
      glsl_array_type(glsl_uint_type(), 0, 0), "real_so");
165
 
   real_so_var->data.driver_location = 1;
166
 
   nir_ssa_def *real_buffer_filled_size = nir_load_ssbo(&b, 1, 32, nir_imm_int(&b, 1), nir_imm_int(&b, 0), (gl_access_qualifier)0, 4, 0);
167
 
 
168
 
   nir_variable *state_var = nullptr;
169
 
   nir_ssa_def *state_var_data = d3d12_get_state_var(&b, D3D12_STATE_VAR_TRANSFORM_GENERIC0, "state_var", glsl_uvec4_type(), &state_var);
170
 
   nir_ssa_def *stride = nir_channel(&b, state_var_data, 0);
171
 
   nir_ssa_def *fake_so_multiplier = nir_channel(&b, state_var_data, 1);
172
 
 
173
 
   nir_ssa_def *real_so_bytes_added = nir_idiv(&b, fake_buffer_filled_size, fake_so_multiplier);
174
 
   nir_ssa_def *vertex_count = nir_idiv(&b, real_so_bytes_added, stride);
175
 
   nir_ssa_def *to_write_to_fake_buffer = nir_vec4(&b, vertex_count, nir_imm_int(&b, 1), nir_imm_int(&b, 1), real_buffer_filled_size);
176
 
   nir_store_ssbo(&b, to_write_to_fake_buffer, nir_imm_int(&b, 0), nir_imm_int(&b, 4), 0xf, (gl_access_qualifier)0, 4, 0);
177
 
 
178
 
   nir_ssa_def *updated_filled_size = nir_iadd(&b, real_buffer_filled_size, real_so_bytes_added);
179
 
   nir_store_ssbo(&b, updated_filled_size, nir_imm_int(&b, 1), nir_imm_int(&b, 0), 1, (gl_access_qualifier)0, 4, 0);
180
 
 
181
 
   nir_validate_shader(b.shader, "creation");
182
 
   b.shader->info.num_ssbos = 2;
183
 
   b.shader->info.num_ubos = 0;
184
 
 
185
 
   return b.shader;
186
 
}
187
 
 
188
 
static struct nir_shader *
189
 
get_draw_auto(const nir_shader_compiler_options *options)
190
 
{
191
 
   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options, "DrawAuto");
192
 
 
193
 
   nir_variable_create(b.shader, nir_var_mem_ssbo, glsl_array_type(glsl_uint_type(), 0, 0), "ssbo");
194
 
   nir_ssa_def *buffer_filled_size = nir_load_ssbo(&b, 1, 32, nir_imm_int(&b, 0), nir_imm_int(&b, 0), (gl_access_qualifier)0, 4, 0);
195
 
 
196
 
   nir_variable *state_var = nullptr;
197
 
   nir_ssa_def *state_var_data = d3d12_get_state_var(&b, D3D12_STATE_VAR_TRANSFORM_GENERIC0, "state_var", glsl_uvec4_type(), &state_var);
198
 
   nir_ssa_def *stride = nir_channel(&b, state_var_data, 0);
199
 
   nir_ssa_def *vb_offset = nir_channel(&b, state_var_data, 1);
200
 
 
201
 
   nir_ssa_def *vb_bytes = nir_bcsel(&b, nir_ilt(&b, vb_offset, buffer_filled_size),
202
 
      nir_isub(&b, buffer_filled_size, vb_offset), nir_imm_int(&b, 0));
203
 
 
204
 
   nir_ssa_def *vertex_count = nir_idiv(&b, vb_bytes, stride);
205
 
   nir_ssa_def *to_write = nir_vec4(&b, vertex_count, nir_imm_int(&b, 1), nir_imm_int(&b, 0), nir_imm_int(&b, 0));
206
 
   nir_store_ssbo(&b, to_write, nir_imm_int(&b, 0), nir_imm_int(&b, 4), 0xf, (gl_access_qualifier)0, 4, 0);
207
 
 
208
 
   nir_validate_shader(b.shader, "creation");
209
 
   b.shader->info.num_ssbos = 1;
210
 
   b.shader->info.num_ubos = 0;
211
 
 
212
 
   return b.shader;
213
 
}
214
 
 
215
 
static struct nir_shader *
216
 
create_compute_transform(const nir_shader_compiler_options *options, const d3d12_compute_transform_key *key)
217
 
{
218
 
   switch (key->type) {
219
 
   case d3d12_compute_transform_type::base_vertex:
220
 
      return get_indirect_draw_base_vertex_transform(options, key);
221
 
   case d3d12_compute_transform_type::fake_so_buffer_copy_back:
222
 
      return get_fake_so_buffer_copy_back(options, key);
223
 
   case d3d12_compute_transform_type::fake_so_buffer_vertex_count:
224
 
      return get_fake_so_buffer_vertex_count(options);
225
 
   case d3d12_compute_transform_type::draw_auto:
226
 
      return get_draw_auto(options);
227
 
   default:
228
 
      unreachable("Invalid transform");
229
 
   }
230
 
}
231
 
 
232
 
struct compute_transform
233
 
{
234
 
   d3d12_compute_transform_key key;
235
 
   d3d12_shader_selector *shader;
236
 
};
237
 
 
238
 
d3d12_shader_selector *
239
 
d3d12_get_compute_transform(struct d3d12_context *ctx, const d3d12_compute_transform_key *key)
240
 
{
241
 
   struct hash_entry *entry = _mesa_hash_table_search(ctx->compute_transform_cache, key);
242
 
   if (!entry) {
243
 
      compute_transform *data = (compute_transform *)MALLOC(sizeof(compute_transform));
244
 
      if (!data)
245
 
         return NULL;
246
 
      
247
 
      const nir_shader_compiler_options *options = &d3d12_screen(ctx->base.screen)->nir_options;
248
 
 
249
 
      memcpy(&data->key, key, sizeof(*key));
250
 
      nir_shader *s = create_compute_transform(options, key);
251
 
      if (!s) {
252
 
         FREE(data);
253
 
         return NULL;
254
 
      }
255
 
      struct pipe_compute_state shader_args = { PIPE_SHADER_IR_NIR, s };
256
 
      data->shader = d3d12_create_compute_shader(ctx, &shader_args);
257
 
      if (!data->shader) {
258
 
         ralloc_free(s);
259
 
         FREE(data);
260
 
         return NULL;
261
 
      }
262
 
 
263
 
      data->shader->is_variant = true;
264
 
      entry = _mesa_hash_table_insert(ctx->compute_transform_cache, &data->key, data);
265
 
      assert(entry);
266
 
   }
267
 
 
268
 
   return ((struct compute_transform *)entry->data)->shader;
269
 
}
270
 
 
271
 
static uint32_t
272
 
hash_compute_transform_key(const void *key)
273
 
{
274
 
   return _mesa_hash_data(key, sizeof(struct d3d12_compute_transform_key));
275
 
}
276
 
 
277
 
static bool
278
 
equals_compute_transform_key(const void *a, const void *b)
279
 
{
280
 
   return memcmp(a, b, sizeof(struct d3d12_compute_transform_key)) == 0;
281
 
}
282
 
 
283
 
void
284
 
d3d12_compute_transform_cache_init(struct d3d12_context *ctx)
285
 
{
286
 
   ctx->compute_transform_cache = _mesa_hash_table_create(NULL,
287
 
                                                          hash_compute_transform_key,
288
 
                                                          equals_compute_transform_key);
289
 
}
290
 
 
291
 
static void
292
 
delete_entry(struct hash_entry *entry)
293
 
{
294
 
   struct compute_transform *data = (struct compute_transform *)entry->data;
295
 
   d3d12_shader_free(data->shader);
296
 
   FREE(data);
297
 
}
298
 
 
299
 
void
300
 
d3d12_compute_transform_cache_destroy(struct d3d12_context *ctx)
301
 
{
302
 
   _mesa_hash_table_destroy(ctx->compute_transform_cache, delete_entry);
303
 
}
304
 
 
305
 
void
306
 
d3d12_save_compute_transform_state(struct d3d12_context *ctx, d3d12_compute_transform_save_restore *save)
307
 
{
308
 
   if (ctx->current_predication)
309
 
      ctx->cmdlist->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
310
 
 
311
 
   memset(save, 0, sizeof(*save));
312
 
   save->cs = ctx->compute_state;
313
 
 
314
 
   pipe_resource_reference(&save->cbuf0.buffer, ctx->cbufs[PIPE_SHADER_COMPUTE][1].buffer);
315
 
   save->cbuf0 = ctx->cbufs[PIPE_SHADER_COMPUTE][1];
316
 
 
317
 
   for (unsigned i = 0; i < ARRAY_SIZE(save->ssbos); ++i) {
318
 
      pipe_resource_reference(&save->ssbos[i].buffer, ctx->ssbo_views[PIPE_SHADER_COMPUTE][i].buffer);
319
 
      save->ssbos[i] = ctx->ssbo_views[PIPE_SHADER_COMPUTE][i];
320
 
   }
321
 
}
322
 
 
323
 
void
324
 
d3d12_restore_compute_transform_state(struct d3d12_context *ctx, d3d12_compute_transform_save_restore *save)
325
 
{
326
 
   ctx->base.bind_compute_state(&ctx->base, save->cs);
327
 
 
328
 
   ctx->base.set_constant_buffer(&ctx->base, PIPE_SHADER_COMPUTE, 1, true, &save->cbuf0);
329
 
   ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, ARRAY_SIZE(save->ssbos), save->ssbos, (1u << ARRAY_SIZE(save->ssbos)) - 1);
330
 
 
331
 
   if (ctx->current_predication)
332
 
      d3d12_enable_predication(ctx);
333
 
}