1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "nir.h" 25bf215546Sopenharmony_ci#include "nir_builder.h" 26bf215546Sopenharmony_ci#include "d3d12_context.h" 27bf215546Sopenharmony_ci#include "d3d12_compiler.h" 28bf215546Sopenharmony_ci#include "d3d12_nir_passes.h" 29bf215546Sopenharmony_ci#include "d3d12_screen.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_cistatic uint32_t 32bf215546Sopenharmony_cihash_tcs_variant_key(const void *key) 33bf215546Sopenharmony_ci{ 34bf215546Sopenharmony_ci return _mesa_hash_data(key, sizeof(struct d3d12_tcs_variant_key)); 35bf215546Sopenharmony_ci} 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistatic bool 38bf215546Sopenharmony_ciequals_tcs_variant_key(const void *a, const void *b) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci return memcmp(a, b, sizeof(struct d3d12_tcs_variant_key)) == 0; 41bf215546Sopenharmony_ci} 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_civoid 44bf215546Sopenharmony_cid3d12_tcs_variant_cache_init(struct d3d12_context *ctx) 45bf215546Sopenharmony_ci{ 46bf215546Sopenharmony_ci ctx->tcs_variant_cache = _mesa_hash_table_create(NULL, NULL, equals_tcs_variant_key); 47bf215546Sopenharmony_ci} 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_cistatic void 50bf215546Sopenharmony_cidelete_entry(struct hash_entry *entry) 51bf215546Sopenharmony_ci{ 52bf215546Sopenharmony_ci d3d12_shader_free((d3d12_shader_selector *)entry->data); 53bf215546Sopenharmony_ci} 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_civoid 56bf215546Sopenharmony_cid3d12_tcs_variant_cache_destroy(struct d3d12_context *ctx) 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci _mesa_hash_table_destroy(ctx->tcs_variant_cache, delete_entry); 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_cistatic void 62bf215546Sopenharmony_cicopy_vars(nir_builder *b, nir_deref_instr *dst, nir_deref_instr *src) 63bf215546Sopenharmony_ci{ 64bf215546Sopenharmony_ci assert(glsl_get_bare_type(dst->type) == glsl_get_bare_type(src->type)); 65bf215546Sopenharmony_ci if (glsl_type_is_struct(dst->type)) { 66bf215546Sopenharmony_ci for (unsigned i = 0; i < glsl_get_length(dst->type); ++i) { 67bf215546Sopenharmony_ci copy_vars(b, nir_build_deref_struct(b, dst, i), nir_build_deref_struct(b, src, i)); 68bf215546Sopenharmony_ci } 69bf215546Sopenharmony_ci } else if (glsl_type_is_array_or_matrix(dst->type)) { 70bf215546Sopenharmony_ci copy_vars(b, nir_build_deref_array_wildcard(b, dst), nir_build_deref_array_wildcard(b, src)); 71bf215546Sopenharmony_ci } else { 72bf215546Sopenharmony_ci nir_copy_deref(b, dst, src); 73bf215546Sopenharmony_ci } 74bf215546Sopenharmony_ci} 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_cistatic struct d3d12_shader_selector * 77bf215546Sopenharmony_cicreate_tess_ctrl_shader_variant(struct d3d12_context *ctx, struct d3d12_tcs_variant_key *key) 78bf215546Sopenharmony_ci{ 79bf215546Sopenharmony_ci nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_TESS_CTRL, &d3d12_screen(ctx->base.screen)->nir_options, "passthrough"); 80bf215546Sopenharmony_ci nir_shader *nir = b.shader; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci nir_ssa_def *invocation_id = nir_load_invocation_id(&b); 83bf215546Sopenharmony_ci uint64_t varying_mask = key->varyings.mask; 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci while(varying_mask) { 86bf215546Sopenharmony_ci int var_idx = u_bit_scan64(&varying_mask); 87bf215546Sopenharmony_ci auto slot = &key->varyings.slots[var_idx]; 88bf215546Sopenharmony_ci unsigned frac_mask = slot->location_frac_mask; 89bf215546Sopenharmony_ci while (frac_mask) { 90bf215546Sopenharmony_ci int frac = u_bit_scan(&frac_mask); 91bf215546Sopenharmony_ci auto var = &slot->vars[frac]; 92bf215546Sopenharmony_ci const struct glsl_type *type = glsl_array_type(slot->types[frac], key->vertices_out, 0); 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci char buf[1024]; 95bf215546Sopenharmony_ci snprintf(buf, sizeof(buf), "in_%d", var->driver_location); 96bf215546Sopenharmony_ci nir_variable *in = nir_variable_create(nir, nir_var_shader_in, type, buf); 97bf215546Sopenharmony_ci snprintf(buf, sizeof(buf), "out_%d", var->driver_location); 98bf215546Sopenharmony_ci nir_variable *out = nir_variable_create(nir, nir_var_shader_out, type, buf); 99bf215546Sopenharmony_ci out->data.location = in->data.location = var_idx; 100bf215546Sopenharmony_ci out->data.location_frac = in->data.location_frac = frac; 101bf215546Sopenharmony_ci out->data.driver_location = in->data.driver_location = var->driver_location; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci for (unsigned i = 0; i < key->vertices_out; i++) { 104bf215546Sopenharmony_ci nir_if *start_block = nir_push_if(&b, nir_ieq(&b, invocation_id, nir_imm_int(&b, i))); 105bf215546Sopenharmony_ci nir_deref_instr *in_array_var = nir_build_deref_array(&b, nir_build_deref_var(&b, in), invocation_id); 106bf215546Sopenharmony_ci nir_deref_instr *out_array_var = nir_build_deref_array_imm(&b, nir_build_deref_var(&b, out), i); 107bf215546Sopenharmony_ci copy_vars(&b, out_array_var, in_array_var); 108bf215546Sopenharmony_ci nir_pop_if(&b, start_block); 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci } 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci nir_variable *gl_TessLevelInner = nir_variable_create(nir, nir_var_shader_out, glsl_array_type(glsl_float_type(), 2, 0), "gl_TessLevelInner"); 113bf215546Sopenharmony_ci gl_TessLevelInner->data.location = VARYING_SLOT_TESS_LEVEL_INNER; 114bf215546Sopenharmony_ci gl_TessLevelInner->data.patch = 1; 115bf215546Sopenharmony_ci gl_TessLevelInner->data.compact = 1; 116bf215546Sopenharmony_ci nir_variable *gl_TessLevelOuter = nir_variable_create(nir, nir_var_shader_out, glsl_array_type(glsl_float_type(), 4, 0), "gl_TessLevelOuter"); 117bf215546Sopenharmony_ci gl_TessLevelOuter->data.location = VARYING_SLOT_TESS_LEVEL_OUTER; 118bf215546Sopenharmony_ci gl_TessLevelOuter->data.patch = 1; 119bf215546Sopenharmony_ci gl_TessLevelOuter->data.compact = 1; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci nir_variable *state_var_inner = NULL, *state_var_outer = NULL; 122bf215546Sopenharmony_ci nir_ssa_def *load_inner = d3d12_get_state_var(&b, D3D12_STATE_VAR_DEFAULT_INNER_TESS_LEVEL, "d3d12_TessLevelInner", glsl_vec_type(2), &state_var_inner); 123bf215546Sopenharmony_ci nir_ssa_def *load_outer = d3d12_get_state_var(&b, D3D12_STATE_VAR_DEFAULT_OUTER_TESS_LEVEL, "d3d12_TessLevelOuter", glsl_vec4_type(), &state_var_outer); 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci for (unsigned i = 0; i < 2; i++) { 126bf215546Sopenharmony_ci nir_deref_instr *store_idx = nir_build_deref_array_imm(&b, nir_build_deref_var(&b, gl_TessLevelInner), i); 127bf215546Sopenharmony_ci nir_store_deref(&b, store_idx, nir_channel(&b, load_inner, i), 0xff); 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci for (unsigned i = 0; i < 4; i++) { 130bf215546Sopenharmony_ci nir_deref_instr *store_idx = nir_build_deref_array_imm(&b, nir_build_deref_var(&b, gl_TessLevelOuter), i); 131bf215546Sopenharmony_ci nir_store_deref(&b, store_idx, nir_channel(&b, load_outer, i), 0xff); 132bf215546Sopenharmony_ci } 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci nir->info.tess.tcs_vertices_out = key->vertices_out; 135bf215546Sopenharmony_ci nir_validate_shader(nir, "created"); 136bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_var_copies); 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci struct pipe_shader_state templ; 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci templ.type = PIPE_SHADER_IR_NIR; 141bf215546Sopenharmony_ci templ.ir.nir = nir; 142bf215546Sopenharmony_ci templ.stream_output.num_outputs = 0; 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci d3d12_shader_selector *tcs = d3d12_create_shader(ctx, PIPE_SHADER_TESS_CTRL, &templ); 145bf215546Sopenharmony_ci if (tcs) { 146bf215546Sopenharmony_ci tcs->is_variant = true; 147bf215546Sopenharmony_ci memcpy(&tcs->tcs_key, key, sizeof(*key)); 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci return tcs; 150bf215546Sopenharmony_ci} 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_cid3d12_shader_selector * 153bf215546Sopenharmony_cid3d12_get_tcs_variant(struct d3d12_context *ctx, struct d3d12_tcs_variant_key *key) 154bf215546Sopenharmony_ci{ 155bf215546Sopenharmony_ci uint32_t hash = hash_tcs_variant_key(key); 156bf215546Sopenharmony_ci struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ctx->tcs_variant_cache, 157bf215546Sopenharmony_ci hash, key); 158bf215546Sopenharmony_ci if (!entry) { 159bf215546Sopenharmony_ci d3d12_shader_selector *tcs = create_tess_ctrl_shader_variant(ctx, key); 160bf215546Sopenharmony_ci entry = _mesa_hash_table_insert_pre_hashed(ctx->tcs_variant_cache, 161bf215546Sopenharmony_ci hash, &tcs->tcs_key, tcs); 162bf215546Sopenharmony_ci assert(entry); 163bf215546Sopenharmony_ci } 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci return (d3d12_shader_selector *)entry->data; 166bf215546Sopenharmony_ci} 167