1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2015 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg * 23b8e80941Smrg * Authors: 24b8e80941Smrg * Jason Ekstrand (jason@jlekstrand.net) 25b8e80941Smrg * 26b8e80941Smrg */ 27b8e80941Smrg 28b8e80941Smrg#include "vtn_private.h" 29b8e80941Smrg#include "nir/nir_vla.h" 30b8e80941Smrg#include "nir/nir_control_flow.h" 31b8e80941Smrg#include "nir/nir_constant_expressions.h" 32b8e80941Smrg#include "nir/nir_deref.h" 33b8e80941Smrg#include "spirv_info.h" 34b8e80941Smrg 35b8e80941Smrg#include "util/u_math.h" 36b8e80941Smrg 37b8e80941Smrg#include <stdio.h> 38b8e80941Smrg 39b8e80941Smrgvoid 40b8e80941Smrgvtn_log(struct vtn_builder *b, enum nir_spirv_debug_level level, 41b8e80941Smrg size_t spirv_offset, const char *message) 42b8e80941Smrg{ 43b8e80941Smrg if (b->options->debug.func) { 44b8e80941Smrg b->options->debug.func(b->options->debug.private_data, 45b8e80941Smrg level, spirv_offset, message); 46b8e80941Smrg } 47b8e80941Smrg 48b8e80941Smrg#ifndef NDEBUG 49b8e80941Smrg if (level >= NIR_SPIRV_DEBUG_LEVEL_WARNING) 50b8e80941Smrg fprintf(stderr, "%s\n", message); 51b8e80941Smrg#endif 52b8e80941Smrg} 53b8e80941Smrg 54b8e80941Smrgvoid 55b8e80941Smrgvtn_logf(struct vtn_builder *b, enum nir_spirv_debug_level level, 56b8e80941Smrg size_t spirv_offset, const char *fmt, ...) 57b8e80941Smrg{ 58b8e80941Smrg va_list args; 59b8e80941Smrg char *msg; 60b8e80941Smrg 61b8e80941Smrg va_start(args, fmt); 62b8e80941Smrg msg = ralloc_vasprintf(NULL, fmt, args); 63b8e80941Smrg va_end(args); 64b8e80941Smrg 65b8e80941Smrg vtn_log(b, level, spirv_offset, msg); 66b8e80941Smrg 67b8e80941Smrg ralloc_free(msg); 68b8e80941Smrg} 69b8e80941Smrg 70b8e80941Smrgstatic void 71b8e80941Smrgvtn_log_err(struct vtn_builder *b, 72b8e80941Smrg enum nir_spirv_debug_level level, const char *prefix, 73b8e80941Smrg const char *file, unsigned line, 74b8e80941Smrg const char *fmt, va_list args) 75b8e80941Smrg{ 76b8e80941Smrg char *msg; 77b8e80941Smrg 78b8e80941Smrg msg = ralloc_strdup(NULL, prefix); 79b8e80941Smrg 80b8e80941Smrg#ifndef NDEBUG 81b8e80941Smrg ralloc_asprintf_append(&msg, " In file %s:%u\n", file, line); 82b8e80941Smrg#endif 83b8e80941Smrg 84b8e80941Smrg ralloc_asprintf_append(&msg, " "); 85b8e80941Smrg 86b8e80941Smrg ralloc_vasprintf_append(&msg, fmt, args); 87b8e80941Smrg 88b8e80941Smrg ralloc_asprintf_append(&msg, "\n %zu bytes into the SPIR-V binary", 89b8e80941Smrg b->spirv_offset); 90b8e80941Smrg 91b8e80941Smrg if (b->file) { 92b8e80941Smrg ralloc_asprintf_append(&msg, 93b8e80941Smrg "\n in SPIR-V source file %s, line %d, col %d", 94b8e80941Smrg b->file, b->line, b->col); 95b8e80941Smrg } 96b8e80941Smrg 97b8e80941Smrg vtn_log(b, level, b->spirv_offset, msg); 98b8e80941Smrg 99b8e80941Smrg ralloc_free(msg); 100b8e80941Smrg} 101b8e80941Smrg 102b8e80941Smrgstatic void 103b8e80941Smrgvtn_dump_shader(struct vtn_builder *b, const char *path, const char *prefix) 104b8e80941Smrg{ 105b8e80941Smrg static int idx = 0; 106b8e80941Smrg 107b8e80941Smrg char filename[1024]; 108b8e80941Smrg int len = snprintf(filename, sizeof(filename), "%s/%s-%d.spirv", 109b8e80941Smrg path, prefix, idx++); 110b8e80941Smrg if (len < 0 || len >= sizeof(filename)) 111b8e80941Smrg return; 112b8e80941Smrg 113b8e80941Smrg FILE *f = fopen(filename, "w"); 114b8e80941Smrg if (f == NULL) 115b8e80941Smrg return; 116b8e80941Smrg 117b8e80941Smrg fwrite(b->spirv, sizeof(*b->spirv), b->spirv_word_count, f); 118b8e80941Smrg fclose(f); 119b8e80941Smrg 120b8e80941Smrg vtn_info("SPIR-V shader dumped to %s", filename); 121b8e80941Smrg} 122b8e80941Smrg 123b8e80941Smrgvoid 124b8e80941Smrg_vtn_warn(struct vtn_builder *b, const char *file, unsigned line, 125b8e80941Smrg const char *fmt, ...) 126b8e80941Smrg{ 127b8e80941Smrg va_list args; 128b8e80941Smrg 129b8e80941Smrg va_start(args, fmt); 130b8e80941Smrg vtn_log_err(b, NIR_SPIRV_DEBUG_LEVEL_WARNING, "SPIR-V WARNING:\n", 131b8e80941Smrg file, line, fmt, args); 132b8e80941Smrg va_end(args); 133b8e80941Smrg} 134b8e80941Smrg 135b8e80941Smrgvoid 136b8e80941Smrg_vtn_err(struct vtn_builder *b, const char *file, unsigned line, 137b8e80941Smrg const char *fmt, ...) 138b8e80941Smrg{ 139b8e80941Smrg va_list args; 140b8e80941Smrg 141b8e80941Smrg va_start(args, fmt); 142b8e80941Smrg vtn_log_err(b, NIR_SPIRV_DEBUG_LEVEL_ERROR, "SPIR-V ERROR:\n", 143b8e80941Smrg file, line, fmt, args); 144b8e80941Smrg va_end(args); 145b8e80941Smrg} 146b8e80941Smrg 147b8e80941Smrgvoid 148b8e80941Smrg_vtn_fail(struct vtn_builder *b, const char *file, unsigned line, 149b8e80941Smrg const char *fmt, ...) 150b8e80941Smrg{ 151b8e80941Smrg va_list args; 152b8e80941Smrg 153b8e80941Smrg va_start(args, fmt); 154b8e80941Smrg vtn_log_err(b, NIR_SPIRV_DEBUG_LEVEL_ERROR, "SPIR-V parsing FAILED:\n", 155b8e80941Smrg file, line, fmt, args); 156b8e80941Smrg va_end(args); 157b8e80941Smrg 158b8e80941Smrg const char *dump_path = getenv("MESA_SPIRV_FAIL_DUMP_PATH"); 159b8e80941Smrg if (dump_path) 160b8e80941Smrg vtn_dump_shader(b, dump_path, "fail"); 161b8e80941Smrg 162b8e80941Smrg longjmp(b->fail_jump, 1); 163b8e80941Smrg} 164b8e80941Smrg 165b8e80941Smrgstruct spec_constant_value { 166b8e80941Smrg bool is_double; 167b8e80941Smrg union { 168b8e80941Smrg uint32_t data32; 169b8e80941Smrg uint64_t data64; 170b8e80941Smrg }; 171b8e80941Smrg}; 172b8e80941Smrg 173b8e80941Smrgstatic struct vtn_ssa_value * 174b8e80941Smrgvtn_undef_ssa_value(struct vtn_builder *b, const struct glsl_type *type) 175b8e80941Smrg{ 176b8e80941Smrg struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value); 177b8e80941Smrg val->type = type; 178b8e80941Smrg 179b8e80941Smrg if (glsl_type_is_vector_or_scalar(type)) { 180b8e80941Smrg unsigned num_components = glsl_get_vector_elements(val->type); 181b8e80941Smrg unsigned bit_size = glsl_get_bit_size(val->type); 182b8e80941Smrg val->def = nir_ssa_undef(&b->nb, num_components, bit_size); 183b8e80941Smrg } else { 184b8e80941Smrg unsigned elems = glsl_get_length(val->type); 185b8e80941Smrg val->elems = ralloc_array(b, struct vtn_ssa_value *, elems); 186b8e80941Smrg if (glsl_type_is_matrix(type)) { 187b8e80941Smrg const struct glsl_type *elem_type = 188b8e80941Smrg glsl_vector_type(glsl_get_base_type(type), 189b8e80941Smrg glsl_get_vector_elements(type)); 190b8e80941Smrg 191b8e80941Smrg for (unsigned i = 0; i < elems; i++) 192b8e80941Smrg val->elems[i] = vtn_undef_ssa_value(b, elem_type); 193b8e80941Smrg } else if (glsl_type_is_array(type)) { 194b8e80941Smrg const struct glsl_type *elem_type = glsl_get_array_element(type); 195b8e80941Smrg for (unsigned i = 0; i < elems; i++) 196b8e80941Smrg val->elems[i] = vtn_undef_ssa_value(b, elem_type); 197b8e80941Smrg } else { 198b8e80941Smrg for (unsigned i = 0; i < elems; i++) { 199b8e80941Smrg const struct glsl_type *elem_type = glsl_get_struct_field(type, i); 200b8e80941Smrg val->elems[i] = vtn_undef_ssa_value(b, elem_type); 201b8e80941Smrg } 202b8e80941Smrg } 203b8e80941Smrg } 204b8e80941Smrg 205b8e80941Smrg return val; 206b8e80941Smrg} 207b8e80941Smrg 208b8e80941Smrgstatic struct vtn_ssa_value * 209b8e80941Smrgvtn_const_ssa_value(struct vtn_builder *b, nir_constant *constant, 210b8e80941Smrg const struct glsl_type *type) 211b8e80941Smrg{ 212b8e80941Smrg struct hash_entry *entry = _mesa_hash_table_search(b->const_table, constant); 213b8e80941Smrg 214b8e80941Smrg if (entry) 215b8e80941Smrg return entry->data; 216b8e80941Smrg 217b8e80941Smrg struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value); 218b8e80941Smrg val->type = type; 219b8e80941Smrg 220b8e80941Smrg switch (glsl_get_base_type(type)) { 221b8e80941Smrg case GLSL_TYPE_INT: 222b8e80941Smrg case GLSL_TYPE_UINT: 223b8e80941Smrg case GLSL_TYPE_INT16: 224b8e80941Smrg case GLSL_TYPE_UINT16: 225b8e80941Smrg case GLSL_TYPE_UINT8: 226b8e80941Smrg case GLSL_TYPE_INT8: 227b8e80941Smrg case GLSL_TYPE_INT64: 228b8e80941Smrg case GLSL_TYPE_UINT64: 229b8e80941Smrg case GLSL_TYPE_BOOL: 230b8e80941Smrg case GLSL_TYPE_FLOAT: 231b8e80941Smrg case GLSL_TYPE_FLOAT16: 232b8e80941Smrg case GLSL_TYPE_DOUBLE: { 233b8e80941Smrg int bit_size = glsl_get_bit_size(type); 234b8e80941Smrg if (glsl_type_is_vector_or_scalar(type)) { 235b8e80941Smrg unsigned num_components = glsl_get_vector_elements(val->type); 236b8e80941Smrg nir_load_const_instr *load = 237b8e80941Smrg nir_load_const_instr_create(b->shader, num_components, bit_size); 238b8e80941Smrg 239b8e80941Smrg memcpy(load->value, constant->values[0], 240b8e80941Smrg sizeof(nir_const_value) * load->def.num_components); 241b8e80941Smrg 242b8e80941Smrg nir_instr_insert_before_cf_list(&b->nb.impl->body, &load->instr); 243b8e80941Smrg val->def = &load->def; 244b8e80941Smrg } else { 245b8e80941Smrg assert(glsl_type_is_matrix(type)); 246b8e80941Smrg unsigned rows = glsl_get_vector_elements(val->type); 247b8e80941Smrg unsigned columns = glsl_get_matrix_columns(val->type); 248b8e80941Smrg val->elems = ralloc_array(b, struct vtn_ssa_value *, columns); 249b8e80941Smrg 250b8e80941Smrg for (unsigned i = 0; i < columns; i++) { 251b8e80941Smrg struct vtn_ssa_value *col_val = rzalloc(b, struct vtn_ssa_value); 252b8e80941Smrg col_val->type = glsl_get_column_type(val->type); 253b8e80941Smrg nir_load_const_instr *load = 254b8e80941Smrg nir_load_const_instr_create(b->shader, rows, bit_size); 255b8e80941Smrg 256b8e80941Smrg memcpy(load->value, constant->values[i], 257b8e80941Smrg sizeof(nir_const_value) * load->def.num_components); 258b8e80941Smrg 259b8e80941Smrg nir_instr_insert_before_cf_list(&b->nb.impl->body, &load->instr); 260b8e80941Smrg col_val->def = &load->def; 261b8e80941Smrg 262b8e80941Smrg val->elems[i] = col_val; 263b8e80941Smrg } 264b8e80941Smrg } 265b8e80941Smrg break; 266b8e80941Smrg } 267b8e80941Smrg 268b8e80941Smrg case GLSL_TYPE_ARRAY: { 269b8e80941Smrg unsigned elems = glsl_get_length(val->type); 270b8e80941Smrg val->elems = ralloc_array(b, struct vtn_ssa_value *, elems); 271b8e80941Smrg const struct glsl_type *elem_type = glsl_get_array_element(val->type); 272b8e80941Smrg for (unsigned i = 0; i < elems; i++) 273b8e80941Smrg val->elems[i] = vtn_const_ssa_value(b, constant->elements[i], 274b8e80941Smrg elem_type); 275b8e80941Smrg break; 276b8e80941Smrg } 277b8e80941Smrg 278b8e80941Smrg case GLSL_TYPE_STRUCT: { 279b8e80941Smrg unsigned elems = glsl_get_length(val->type); 280b8e80941Smrg val->elems = ralloc_array(b, struct vtn_ssa_value *, elems); 281b8e80941Smrg for (unsigned i = 0; i < elems; i++) { 282b8e80941Smrg const struct glsl_type *elem_type = 283b8e80941Smrg glsl_get_struct_field(val->type, i); 284b8e80941Smrg val->elems[i] = vtn_const_ssa_value(b, constant->elements[i], 285b8e80941Smrg elem_type); 286b8e80941Smrg } 287b8e80941Smrg break; 288b8e80941Smrg } 289b8e80941Smrg 290b8e80941Smrg default: 291b8e80941Smrg vtn_fail("bad constant type"); 292b8e80941Smrg } 293b8e80941Smrg 294b8e80941Smrg return val; 295b8e80941Smrg} 296b8e80941Smrg 297b8e80941Smrgstruct vtn_ssa_value * 298b8e80941Smrgvtn_ssa_value(struct vtn_builder *b, uint32_t value_id) 299b8e80941Smrg{ 300b8e80941Smrg struct vtn_value *val = vtn_untyped_value(b, value_id); 301b8e80941Smrg switch (val->value_type) { 302b8e80941Smrg case vtn_value_type_undef: 303b8e80941Smrg return vtn_undef_ssa_value(b, val->type->type); 304b8e80941Smrg 305b8e80941Smrg case vtn_value_type_constant: 306b8e80941Smrg return vtn_const_ssa_value(b, val->constant, val->type->type); 307b8e80941Smrg 308b8e80941Smrg case vtn_value_type_ssa: 309b8e80941Smrg return val->ssa; 310b8e80941Smrg 311b8e80941Smrg case vtn_value_type_pointer: 312b8e80941Smrg vtn_assert(val->pointer->ptr_type && val->pointer->ptr_type->type); 313b8e80941Smrg struct vtn_ssa_value *ssa = 314b8e80941Smrg vtn_create_ssa_value(b, val->pointer->ptr_type->type); 315b8e80941Smrg ssa->def = vtn_pointer_to_ssa(b, val->pointer); 316b8e80941Smrg return ssa; 317b8e80941Smrg 318b8e80941Smrg default: 319b8e80941Smrg vtn_fail("Invalid type for an SSA value"); 320b8e80941Smrg } 321b8e80941Smrg} 322b8e80941Smrg 323b8e80941Smrgstatic char * 324b8e80941Smrgvtn_string_literal(struct vtn_builder *b, const uint32_t *words, 325b8e80941Smrg unsigned word_count, unsigned *words_used) 326b8e80941Smrg{ 327b8e80941Smrg char *dup = ralloc_strndup(b, (char *)words, word_count * sizeof(*words)); 328b8e80941Smrg if (words_used) { 329b8e80941Smrg /* Ammount of space taken by the string (including the null) */ 330b8e80941Smrg unsigned len = strlen(dup) + 1; 331b8e80941Smrg *words_used = DIV_ROUND_UP(len, sizeof(*words)); 332b8e80941Smrg } 333b8e80941Smrg return dup; 334b8e80941Smrg} 335b8e80941Smrg 336b8e80941Smrgconst uint32_t * 337b8e80941Smrgvtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start, 338b8e80941Smrg const uint32_t *end, vtn_instruction_handler handler) 339b8e80941Smrg{ 340b8e80941Smrg b->file = NULL; 341b8e80941Smrg b->line = -1; 342b8e80941Smrg b->col = -1; 343b8e80941Smrg 344b8e80941Smrg const uint32_t *w = start; 345b8e80941Smrg while (w < end) { 346b8e80941Smrg SpvOp opcode = w[0] & SpvOpCodeMask; 347b8e80941Smrg unsigned count = w[0] >> SpvWordCountShift; 348b8e80941Smrg vtn_assert(count >= 1 && w + count <= end); 349b8e80941Smrg 350b8e80941Smrg b->spirv_offset = (uint8_t *)w - (uint8_t *)b->spirv; 351b8e80941Smrg 352b8e80941Smrg switch (opcode) { 353b8e80941Smrg case SpvOpNop: 354b8e80941Smrg break; /* Do nothing */ 355b8e80941Smrg 356b8e80941Smrg case SpvOpLine: 357b8e80941Smrg b->file = vtn_value(b, w[1], vtn_value_type_string)->str; 358b8e80941Smrg b->line = w[2]; 359b8e80941Smrg b->col = w[3]; 360b8e80941Smrg break; 361b8e80941Smrg 362b8e80941Smrg case SpvOpNoLine: 363b8e80941Smrg b->file = NULL; 364b8e80941Smrg b->line = -1; 365b8e80941Smrg b->col = -1; 366b8e80941Smrg break; 367b8e80941Smrg 368b8e80941Smrg default: 369b8e80941Smrg if (!handler(b, opcode, w, count)) 370b8e80941Smrg return w; 371b8e80941Smrg break; 372b8e80941Smrg } 373b8e80941Smrg 374b8e80941Smrg w += count; 375b8e80941Smrg } 376b8e80941Smrg 377b8e80941Smrg b->spirv_offset = 0; 378b8e80941Smrg b->file = NULL; 379b8e80941Smrg b->line = -1; 380b8e80941Smrg b->col = -1; 381b8e80941Smrg 382b8e80941Smrg assert(w == end); 383b8e80941Smrg return w; 384b8e80941Smrg} 385b8e80941Smrg 386b8e80941Smrgstatic void 387b8e80941Smrgvtn_handle_extension(struct vtn_builder *b, SpvOp opcode, 388b8e80941Smrg const uint32_t *w, unsigned count) 389b8e80941Smrg{ 390b8e80941Smrg const char *ext = (const char *)&w[2]; 391b8e80941Smrg switch (opcode) { 392b8e80941Smrg case SpvOpExtInstImport: { 393b8e80941Smrg struct vtn_value *val = vtn_push_value(b, w[1], vtn_value_type_extension); 394b8e80941Smrg if (strcmp(ext, "GLSL.std.450") == 0) { 395b8e80941Smrg val->ext_handler = vtn_handle_glsl450_instruction; 396b8e80941Smrg } else if ((strcmp(ext, "SPV_AMD_gcn_shader") == 0) 397b8e80941Smrg && (b->options && b->options->caps.gcn_shader)) { 398b8e80941Smrg val->ext_handler = vtn_handle_amd_gcn_shader_instruction; 399b8e80941Smrg } else if ((strcmp(ext, "SPV_AMD_shader_trinary_minmax") == 0) 400b8e80941Smrg && (b->options && b->options->caps.trinary_minmax)) { 401b8e80941Smrg val->ext_handler = vtn_handle_amd_shader_trinary_minmax_instruction; 402b8e80941Smrg } else if (strcmp(ext, "OpenCL.std") == 0) { 403b8e80941Smrg val->ext_handler = vtn_handle_opencl_instruction; 404b8e80941Smrg } else { 405b8e80941Smrg vtn_fail("Unsupported extension: %s", ext); 406b8e80941Smrg } 407b8e80941Smrg break; 408b8e80941Smrg } 409b8e80941Smrg 410b8e80941Smrg case SpvOpExtInst: { 411b8e80941Smrg struct vtn_value *val = vtn_value(b, w[3], vtn_value_type_extension); 412b8e80941Smrg bool handled = val->ext_handler(b, w[4], w, count); 413b8e80941Smrg vtn_assert(handled); 414b8e80941Smrg break; 415b8e80941Smrg } 416b8e80941Smrg 417b8e80941Smrg default: 418b8e80941Smrg vtn_fail_with_opcode("Unhandled opcode", opcode); 419b8e80941Smrg } 420b8e80941Smrg} 421b8e80941Smrg 422b8e80941Smrgstatic void 423b8e80941Smrg_foreach_decoration_helper(struct vtn_builder *b, 424b8e80941Smrg struct vtn_value *base_value, 425b8e80941Smrg int parent_member, 426b8e80941Smrg struct vtn_value *value, 427b8e80941Smrg vtn_decoration_foreach_cb cb, void *data) 428b8e80941Smrg{ 429b8e80941Smrg for (struct vtn_decoration *dec = value->decoration; dec; dec = dec->next) { 430b8e80941Smrg int member; 431b8e80941Smrg if (dec->scope == VTN_DEC_DECORATION) { 432b8e80941Smrg member = parent_member; 433b8e80941Smrg } else if (dec->scope >= VTN_DEC_STRUCT_MEMBER0) { 434b8e80941Smrg vtn_fail_if(value->value_type != vtn_value_type_type || 435b8e80941Smrg value->type->base_type != vtn_base_type_struct, 436b8e80941Smrg "OpMemberDecorate and OpGroupMemberDecorate are only " 437b8e80941Smrg "allowed on OpTypeStruct"); 438b8e80941Smrg /* This means we haven't recursed yet */ 439b8e80941Smrg assert(value == base_value); 440b8e80941Smrg 441b8e80941Smrg member = dec->scope - VTN_DEC_STRUCT_MEMBER0; 442b8e80941Smrg 443b8e80941Smrg vtn_fail_if(member >= base_value->type->length, 444b8e80941Smrg "OpMemberDecorate specifies member %d but the " 445b8e80941Smrg "OpTypeStruct has only %u members", 446b8e80941Smrg member, base_value->type->length); 447b8e80941Smrg } else { 448b8e80941Smrg /* Not a decoration */ 449b8e80941Smrg assert(dec->scope == VTN_DEC_EXECUTION_MODE); 450b8e80941Smrg continue; 451b8e80941Smrg } 452b8e80941Smrg 453b8e80941Smrg if (dec->group) { 454b8e80941Smrg assert(dec->group->value_type == vtn_value_type_decoration_group); 455b8e80941Smrg _foreach_decoration_helper(b, base_value, member, dec->group, 456b8e80941Smrg cb, data); 457b8e80941Smrg } else { 458b8e80941Smrg cb(b, base_value, member, dec, data); 459b8e80941Smrg } 460b8e80941Smrg } 461b8e80941Smrg} 462b8e80941Smrg 463b8e80941Smrg/** Iterates (recursively if needed) over all of the decorations on a value 464b8e80941Smrg * 465b8e80941Smrg * This function iterates over all of the decorations applied to a given 466b8e80941Smrg * value. If it encounters a decoration group, it recurses into the group 467b8e80941Smrg * and iterates over all of those decorations as well. 468b8e80941Smrg */ 469b8e80941Smrgvoid 470b8e80941Smrgvtn_foreach_decoration(struct vtn_builder *b, struct vtn_value *value, 471b8e80941Smrg vtn_decoration_foreach_cb cb, void *data) 472b8e80941Smrg{ 473b8e80941Smrg _foreach_decoration_helper(b, value, -1, value, cb, data); 474b8e80941Smrg} 475b8e80941Smrg 476b8e80941Smrgvoid 477b8e80941Smrgvtn_foreach_execution_mode(struct vtn_builder *b, struct vtn_value *value, 478b8e80941Smrg vtn_execution_mode_foreach_cb cb, void *data) 479b8e80941Smrg{ 480b8e80941Smrg for (struct vtn_decoration *dec = value->decoration; dec; dec = dec->next) { 481b8e80941Smrg if (dec->scope != VTN_DEC_EXECUTION_MODE) 482b8e80941Smrg continue; 483b8e80941Smrg 484b8e80941Smrg assert(dec->group == NULL); 485b8e80941Smrg cb(b, value, dec, data); 486b8e80941Smrg } 487b8e80941Smrg} 488b8e80941Smrg 489b8e80941Smrgvoid 490b8e80941Smrgvtn_handle_decoration(struct vtn_builder *b, SpvOp opcode, 491b8e80941Smrg const uint32_t *w, unsigned count) 492b8e80941Smrg{ 493b8e80941Smrg const uint32_t *w_end = w + count; 494b8e80941Smrg const uint32_t target = w[1]; 495b8e80941Smrg w += 2; 496b8e80941Smrg 497b8e80941Smrg switch (opcode) { 498b8e80941Smrg case SpvOpDecorationGroup: 499b8e80941Smrg vtn_push_value(b, target, vtn_value_type_decoration_group); 500b8e80941Smrg break; 501b8e80941Smrg 502b8e80941Smrg case SpvOpDecorate: 503b8e80941Smrg case SpvOpDecorateId: 504b8e80941Smrg case SpvOpMemberDecorate: 505b8e80941Smrg case SpvOpDecorateStringGOOGLE: 506b8e80941Smrg case SpvOpMemberDecorateStringGOOGLE: 507b8e80941Smrg case SpvOpExecutionMode: 508b8e80941Smrg case SpvOpExecutionModeId: { 509b8e80941Smrg struct vtn_value *val = vtn_untyped_value(b, target); 510b8e80941Smrg 511b8e80941Smrg struct vtn_decoration *dec = rzalloc(b, struct vtn_decoration); 512b8e80941Smrg switch (opcode) { 513b8e80941Smrg case SpvOpDecorate: 514b8e80941Smrg case SpvOpDecorateId: 515b8e80941Smrg case SpvOpDecorateStringGOOGLE: 516b8e80941Smrg dec->scope = VTN_DEC_DECORATION; 517b8e80941Smrg break; 518b8e80941Smrg case SpvOpMemberDecorate: 519b8e80941Smrg case SpvOpMemberDecorateStringGOOGLE: 520b8e80941Smrg dec->scope = VTN_DEC_STRUCT_MEMBER0 + *(w++); 521b8e80941Smrg vtn_fail_if(dec->scope < VTN_DEC_STRUCT_MEMBER0, /* overflow */ 522b8e80941Smrg "Member argument of OpMemberDecorate too large"); 523b8e80941Smrg break; 524b8e80941Smrg case SpvOpExecutionMode: 525b8e80941Smrg case SpvOpExecutionModeId: 526b8e80941Smrg dec->scope = VTN_DEC_EXECUTION_MODE; 527b8e80941Smrg break; 528b8e80941Smrg default: 529b8e80941Smrg unreachable("Invalid decoration opcode"); 530b8e80941Smrg } 531b8e80941Smrg dec->decoration = *(w++); 532b8e80941Smrg dec->operands = w; 533b8e80941Smrg 534b8e80941Smrg /* Link into the list */ 535b8e80941Smrg dec->next = val->decoration; 536b8e80941Smrg val->decoration = dec; 537b8e80941Smrg break; 538b8e80941Smrg } 539b8e80941Smrg 540b8e80941Smrg case SpvOpGroupMemberDecorate: 541b8e80941Smrg case SpvOpGroupDecorate: { 542b8e80941Smrg struct vtn_value *group = 543b8e80941Smrg vtn_value(b, target, vtn_value_type_decoration_group); 544b8e80941Smrg 545b8e80941Smrg for (; w < w_end; w++) { 546b8e80941Smrg struct vtn_value *val = vtn_untyped_value(b, *w); 547b8e80941Smrg struct vtn_decoration *dec = rzalloc(b, struct vtn_decoration); 548b8e80941Smrg 549b8e80941Smrg dec->group = group; 550b8e80941Smrg if (opcode == SpvOpGroupDecorate) { 551b8e80941Smrg dec->scope = VTN_DEC_DECORATION; 552b8e80941Smrg } else { 553b8e80941Smrg dec->scope = VTN_DEC_STRUCT_MEMBER0 + *(++w); 554b8e80941Smrg vtn_fail_if(dec->scope < 0, /* Check for overflow */ 555b8e80941Smrg "Member argument of OpGroupMemberDecorate too large"); 556b8e80941Smrg } 557b8e80941Smrg 558b8e80941Smrg /* Link into the list */ 559b8e80941Smrg dec->next = val->decoration; 560b8e80941Smrg val->decoration = dec; 561b8e80941Smrg } 562b8e80941Smrg break; 563b8e80941Smrg } 564b8e80941Smrg 565b8e80941Smrg default: 566b8e80941Smrg unreachable("Unhandled opcode"); 567b8e80941Smrg } 568b8e80941Smrg} 569b8e80941Smrg 570b8e80941Smrgstruct member_decoration_ctx { 571b8e80941Smrg unsigned num_fields; 572b8e80941Smrg struct glsl_struct_field *fields; 573b8e80941Smrg struct vtn_type *type; 574b8e80941Smrg}; 575b8e80941Smrg 576b8e80941Smrg/** 577b8e80941Smrg * Returns true if the given type contains a struct decorated Block or 578b8e80941Smrg * BufferBlock 579b8e80941Smrg */ 580b8e80941Smrgbool 581b8e80941Smrgvtn_type_contains_block(struct vtn_builder *b, struct vtn_type *type) 582b8e80941Smrg{ 583b8e80941Smrg switch (type->base_type) { 584b8e80941Smrg case vtn_base_type_array: 585b8e80941Smrg return vtn_type_contains_block(b, type->array_element); 586b8e80941Smrg case vtn_base_type_struct: 587b8e80941Smrg if (type->block || type->buffer_block) 588b8e80941Smrg return true; 589b8e80941Smrg for (unsigned i = 0; i < type->length; i++) { 590b8e80941Smrg if (vtn_type_contains_block(b, type->members[i])) 591b8e80941Smrg return true; 592b8e80941Smrg } 593b8e80941Smrg return false; 594b8e80941Smrg default: 595b8e80941Smrg return false; 596b8e80941Smrg } 597b8e80941Smrg} 598b8e80941Smrg 599b8e80941Smrg/** Returns true if two types are "compatible", i.e. you can do an OpLoad, 600b8e80941Smrg * OpStore, or OpCopyMemory between them without breaking anything. 601b8e80941Smrg * Technically, the SPIR-V rules require the exact same type ID but this lets 602b8e80941Smrg * us internally be a bit looser. 603b8e80941Smrg */ 604b8e80941Smrgbool 605b8e80941Smrgvtn_types_compatible(struct vtn_builder *b, 606b8e80941Smrg struct vtn_type *t1, struct vtn_type *t2) 607b8e80941Smrg{ 608b8e80941Smrg if (t1->id == t2->id) 609b8e80941Smrg return true; 610b8e80941Smrg 611b8e80941Smrg if (t1->base_type != t2->base_type) 612b8e80941Smrg return false; 613b8e80941Smrg 614b8e80941Smrg switch (t1->base_type) { 615b8e80941Smrg case vtn_base_type_void: 616b8e80941Smrg case vtn_base_type_scalar: 617b8e80941Smrg case vtn_base_type_vector: 618b8e80941Smrg case vtn_base_type_matrix: 619b8e80941Smrg case vtn_base_type_image: 620b8e80941Smrg case vtn_base_type_sampler: 621b8e80941Smrg case vtn_base_type_sampled_image: 622b8e80941Smrg return t1->type == t2->type; 623b8e80941Smrg 624b8e80941Smrg case vtn_base_type_array: 625b8e80941Smrg return t1->length == t2->length && 626b8e80941Smrg vtn_types_compatible(b, t1->array_element, t2->array_element); 627b8e80941Smrg 628b8e80941Smrg case vtn_base_type_pointer: 629b8e80941Smrg return vtn_types_compatible(b, t1->deref, t2->deref); 630b8e80941Smrg 631b8e80941Smrg case vtn_base_type_struct: 632b8e80941Smrg if (t1->length != t2->length) 633b8e80941Smrg return false; 634b8e80941Smrg 635b8e80941Smrg for (unsigned i = 0; i < t1->length; i++) { 636b8e80941Smrg if (!vtn_types_compatible(b, t1->members[i], t2->members[i])) 637b8e80941Smrg return false; 638b8e80941Smrg } 639b8e80941Smrg return true; 640b8e80941Smrg 641b8e80941Smrg case vtn_base_type_function: 642b8e80941Smrg /* This case shouldn't get hit since you can't copy around function 643b8e80941Smrg * types. Just require them to be identical. 644b8e80941Smrg */ 645b8e80941Smrg return false; 646b8e80941Smrg } 647b8e80941Smrg 648b8e80941Smrg vtn_fail("Invalid base type"); 649b8e80941Smrg} 650b8e80941Smrg 651b8e80941Smrg/* does a shallow copy of a vtn_type */ 652b8e80941Smrg 653b8e80941Smrgstatic struct vtn_type * 654b8e80941Smrgvtn_type_copy(struct vtn_builder *b, struct vtn_type *src) 655b8e80941Smrg{ 656b8e80941Smrg struct vtn_type *dest = ralloc(b, struct vtn_type); 657b8e80941Smrg *dest = *src; 658b8e80941Smrg 659b8e80941Smrg switch (src->base_type) { 660b8e80941Smrg case vtn_base_type_void: 661b8e80941Smrg case vtn_base_type_scalar: 662b8e80941Smrg case vtn_base_type_vector: 663b8e80941Smrg case vtn_base_type_matrix: 664b8e80941Smrg case vtn_base_type_array: 665b8e80941Smrg case vtn_base_type_pointer: 666b8e80941Smrg case vtn_base_type_image: 667b8e80941Smrg case vtn_base_type_sampler: 668b8e80941Smrg case vtn_base_type_sampled_image: 669b8e80941Smrg /* Nothing more to do */ 670b8e80941Smrg break; 671b8e80941Smrg 672b8e80941Smrg case vtn_base_type_struct: 673b8e80941Smrg dest->members = ralloc_array(b, struct vtn_type *, src->length); 674b8e80941Smrg memcpy(dest->members, src->members, 675b8e80941Smrg src->length * sizeof(src->members[0])); 676b8e80941Smrg 677b8e80941Smrg dest->offsets = ralloc_array(b, unsigned, src->length); 678b8e80941Smrg memcpy(dest->offsets, src->offsets, 679b8e80941Smrg src->length * sizeof(src->offsets[0])); 680b8e80941Smrg break; 681b8e80941Smrg 682b8e80941Smrg case vtn_base_type_function: 683b8e80941Smrg dest->params = ralloc_array(b, struct vtn_type *, src->length); 684b8e80941Smrg memcpy(dest->params, src->params, src->length * sizeof(src->params[0])); 685b8e80941Smrg break; 686b8e80941Smrg } 687b8e80941Smrg 688b8e80941Smrg return dest; 689b8e80941Smrg} 690b8e80941Smrg 691b8e80941Smrgstatic struct vtn_type * 692b8e80941Smrgmutable_matrix_member(struct vtn_builder *b, struct vtn_type *type, int member) 693b8e80941Smrg{ 694b8e80941Smrg type->members[member] = vtn_type_copy(b, type->members[member]); 695b8e80941Smrg type = type->members[member]; 696b8e80941Smrg 697b8e80941Smrg /* We may have an array of matrices.... Oh, joy! */ 698b8e80941Smrg while (glsl_type_is_array(type->type)) { 699b8e80941Smrg type->array_element = vtn_type_copy(b, type->array_element); 700b8e80941Smrg type = type->array_element; 701b8e80941Smrg } 702b8e80941Smrg 703b8e80941Smrg vtn_assert(glsl_type_is_matrix(type->type)); 704b8e80941Smrg 705b8e80941Smrg return type; 706b8e80941Smrg} 707b8e80941Smrg 708b8e80941Smrgstatic void 709b8e80941Smrgvtn_handle_access_qualifier(struct vtn_builder *b, struct vtn_type *type, 710b8e80941Smrg int member, enum gl_access_qualifier access) 711b8e80941Smrg{ 712b8e80941Smrg type->members[member] = vtn_type_copy(b, type->members[member]); 713b8e80941Smrg type = type->members[member]; 714b8e80941Smrg 715b8e80941Smrg type->access |= access; 716b8e80941Smrg} 717b8e80941Smrg 718b8e80941Smrgstatic void 719b8e80941Smrgarray_stride_decoration_cb(struct vtn_builder *b, 720b8e80941Smrg struct vtn_value *val, int member, 721b8e80941Smrg const struct vtn_decoration *dec, void *void_ctx) 722b8e80941Smrg{ 723b8e80941Smrg struct vtn_type *type = val->type; 724b8e80941Smrg 725b8e80941Smrg if (dec->decoration == SpvDecorationArrayStride) { 726b8e80941Smrg vtn_fail_if(dec->operands[0] == 0, "ArrayStride must be non-zero"); 727b8e80941Smrg type->stride = dec->operands[0]; 728b8e80941Smrg } 729b8e80941Smrg} 730b8e80941Smrg 731b8e80941Smrgstatic void 732b8e80941Smrgstruct_member_decoration_cb(struct vtn_builder *b, 733b8e80941Smrg struct vtn_value *val, int member, 734b8e80941Smrg const struct vtn_decoration *dec, void *void_ctx) 735b8e80941Smrg{ 736b8e80941Smrg struct member_decoration_ctx *ctx = void_ctx; 737b8e80941Smrg 738b8e80941Smrg if (member < 0) 739b8e80941Smrg return; 740b8e80941Smrg 741b8e80941Smrg assert(member < ctx->num_fields); 742b8e80941Smrg 743b8e80941Smrg switch (dec->decoration) { 744b8e80941Smrg case SpvDecorationRelaxedPrecision: 745b8e80941Smrg case SpvDecorationUniform: 746b8e80941Smrg break; /* FIXME: Do nothing with this for now. */ 747b8e80941Smrg case SpvDecorationNonWritable: 748b8e80941Smrg vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_NON_WRITEABLE); 749b8e80941Smrg break; 750b8e80941Smrg case SpvDecorationNonReadable: 751b8e80941Smrg vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_NON_READABLE); 752b8e80941Smrg break; 753b8e80941Smrg case SpvDecorationVolatile: 754b8e80941Smrg vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_VOLATILE); 755b8e80941Smrg break; 756b8e80941Smrg case SpvDecorationCoherent: 757b8e80941Smrg vtn_handle_access_qualifier(b, ctx->type, member, ACCESS_COHERENT); 758b8e80941Smrg break; 759b8e80941Smrg case SpvDecorationNoPerspective: 760b8e80941Smrg ctx->fields[member].interpolation = INTERP_MODE_NOPERSPECTIVE; 761b8e80941Smrg break; 762b8e80941Smrg case SpvDecorationFlat: 763b8e80941Smrg ctx->fields[member].interpolation = INTERP_MODE_FLAT; 764b8e80941Smrg break; 765b8e80941Smrg case SpvDecorationCentroid: 766b8e80941Smrg ctx->fields[member].centroid = true; 767b8e80941Smrg break; 768b8e80941Smrg case SpvDecorationSample: 769b8e80941Smrg ctx->fields[member].sample = true; 770b8e80941Smrg break; 771b8e80941Smrg case SpvDecorationStream: 772b8e80941Smrg /* Vulkan only allows one GS stream */ 773b8e80941Smrg vtn_assert(dec->operands[0] == 0); 774b8e80941Smrg break; 775b8e80941Smrg case SpvDecorationLocation: 776b8e80941Smrg ctx->fields[member].location = dec->operands[0]; 777b8e80941Smrg break; 778b8e80941Smrg case SpvDecorationComponent: 779b8e80941Smrg break; /* FIXME: What should we do with these? */ 780b8e80941Smrg case SpvDecorationBuiltIn: 781b8e80941Smrg ctx->type->members[member] = vtn_type_copy(b, ctx->type->members[member]); 782b8e80941Smrg ctx->type->members[member]->is_builtin = true; 783b8e80941Smrg ctx->type->members[member]->builtin = dec->operands[0]; 784b8e80941Smrg ctx->type->builtin_block = true; 785b8e80941Smrg break; 786b8e80941Smrg case SpvDecorationOffset: 787b8e80941Smrg ctx->type->offsets[member] = dec->operands[0]; 788b8e80941Smrg ctx->fields[member].offset = dec->operands[0]; 789b8e80941Smrg break; 790b8e80941Smrg case SpvDecorationMatrixStride: 791b8e80941Smrg /* Handled as a second pass */ 792b8e80941Smrg break; 793b8e80941Smrg case SpvDecorationColMajor: 794b8e80941Smrg break; /* Nothing to do here. Column-major is the default. */ 795b8e80941Smrg case SpvDecorationRowMajor: 796b8e80941Smrg mutable_matrix_member(b, ctx->type, member)->row_major = true; 797b8e80941Smrg break; 798b8e80941Smrg 799b8e80941Smrg case SpvDecorationPatch: 800b8e80941Smrg break; 801b8e80941Smrg 802b8e80941Smrg case SpvDecorationSpecId: 803b8e80941Smrg case SpvDecorationBlock: 804b8e80941Smrg case SpvDecorationBufferBlock: 805b8e80941Smrg case SpvDecorationArrayStride: 806b8e80941Smrg case SpvDecorationGLSLShared: 807b8e80941Smrg case SpvDecorationGLSLPacked: 808b8e80941Smrg case SpvDecorationInvariant: 809b8e80941Smrg case SpvDecorationRestrict: 810b8e80941Smrg case SpvDecorationAliased: 811b8e80941Smrg case SpvDecorationConstant: 812b8e80941Smrg case SpvDecorationIndex: 813b8e80941Smrg case SpvDecorationBinding: 814b8e80941Smrg case SpvDecorationDescriptorSet: 815b8e80941Smrg case SpvDecorationLinkageAttributes: 816b8e80941Smrg case SpvDecorationNoContraction: 817b8e80941Smrg case SpvDecorationInputAttachmentIndex: 818b8e80941Smrg vtn_warn("Decoration not allowed on struct members: %s", 819b8e80941Smrg spirv_decoration_to_string(dec->decoration)); 820b8e80941Smrg break; 821b8e80941Smrg 822b8e80941Smrg case SpvDecorationXfbBuffer: 823b8e80941Smrg case SpvDecorationXfbStride: 824b8e80941Smrg vtn_warn("Vulkan does not have transform feedback"); 825b8e80941Smrg break; 826b8e80941Smrg 827b8e80941Smrg case SpvDecorationCPacked: 828b8e80941Smrg if (b->shader->info.stage != MESA_SHADER_KERNEL) 829b8e80941Smrg vtn_warn("Decoration only allowed for CL-style kernels: %s", 830b8e80941Smrg spirv_decoration_to_string(dec->decoration)); 831b8e80941Smrg else 832b8e80941Smrg ctx->type->packed = true; 833b8e80941Smrg break; 834b8e80941Smrg 835b8e80941Smrg case SpvDecorationSaturatedConversion: 836b8e80941Smrg case SpvDecorationFuncParamAttr: 837b8e80941Smrg case SpvDecorationFPRoundingMode: 838b8e80941Smrg case SpvDecorationFPFastMathMode: 839b8e80941Smrg case SpvDecorationAlignment: 840b8e80941Smrg if (b->shader->info.stage != MESA_SHADER_KERNEL) { 841b8e80941Smrg vtn_warn("Decoration only allowed for CL-style kernels: %s", 842b8e80941Smrg spirv_decoration_to_string(dec->decoration)); 843b8e80941Smrg } 844b8e80941Smrg break; 845b8e80941Smrg 846b8e80941Smrg case SpvDecorationHlslSemanticGOOGLE: 847b8e80941Smrg /* HLSL semantic decorations can safely be ignored by the driver. */ 848b8e80941Smrg break; 849b8e80941Smrg 850b8e80941Smrg default: 851b8e80941Smrg vtn_fail_with_decoration("Unhandled decoration", dec->decoration); 852b8e80941Smrg } 853b8e80941Smrg} 854b8e80941Smrg 855b8e80941Smrg/** Chases the array type all the way down to the tail and rewrites the 856b8e80941Smrg * glsl_types to be based off the tail's glsl_type. 857b8e80941Smrg */ 858b8e80941Smrgstatic void 859b8e80941Smrgvtn_array_type_rewrite_glsl_type(struct vtn_type *type) 860b8e80941Smrg{ 861b8e80941Smrg if (type->base_type != vtn_base_type_array) 862b8e80941Smrg return; 863b8e80941Smrg 864b8e80941Smrg vtn_array_type_rewrite_glsl_type(type->array_element); 865b8e80941Smrg 866b8e80941Smrg type->type = glsl_array_type(type->array_element->type, 867b8e80941Smrg type->length, type->stride); 868b8e80941Smrg} 869b8e80941Smrg 870b8e80941Smrg/* Matrix strides are handled as a separate pass because we need to know 871b8e80941Smrg * whether the matrix is row-major or not first. 872b8e80941Smrg */ 873b8e80941Smrgstatic void 874b8e80941Smrgstruct_member_matrix_stride_cb(struct vtn_builder *b, 875b8e80941Smrg struct vtn_value *val, int member, 876b8e80941Smrg const struct vtn_decoration *dec, 877b8e80941Smrg void *void_ctx) 878b8e80941Smrg{ 879b8e80941Smrg if (dec->decoration != SpvDecorationMatrixStride) 880b8e80941Smrg return; 881b8e80941Smrg 882b8e80941Smrg vtn_fail_if(member < 0, 883b8e80941Smrg "The MatrixStride decoration is only allowed on members " 884b8e80941Smrg "of OpTypeStruct"); 885b8e80941Smrg vtn_fail_if(dec->operands[0] == 0, "MatrixStride must be non-zero"); 886b8e80941Smrg 887b8e80941Smrg struct member_decoration_ctx *ctx = void_ctx; 888b8e80941Smrg 889b8e80941Smrg struct vtn_type *mat_type = mutable_matrix_member(b, ctx->type, member); 890b8e80941Smrg if (mat_type->row_major) { 891b8e80941Smrg mat_type->array_element = vtn_type_copy(b, mat_type->array_element); 892b8e80941Smrg mat_type->stride = mat_type->array_element->stride; 893b8e80941Smrg mat_type->array_element->stride = dec->operands[0]; 894b8e80941Smrg 895b8e80941Smrg mat_type->type = glsl_explicit_matrix_type(mat_type->type, 896b8e80941Smrg dec->operands[0], true); 897b8e80941Smrg mat_type->array_element->type = glsl_get_column_type(mat_type->type); 898b8e80941Smrg } else { 899b8e80941Smrg vtn_assert(mat_type->array_element->stride > 0); 900b8e80941Smrg mat_type->stride = dec->operands[0]; 901b8e80941Smrg 902b8e80941Smrg mat_type->type = glsl_explicit_matrix_type(mat_type->type, 903b8e80941Smrg dec->operands[0], false); 904b8e80941Smrg } 905b8e80941Smrg 906b8e80941Smrg /* Now that we've replaced the glsl_type with a properly strided matrix 907b8e80941Smrg * type, rewrite the member type so that it's an array of the proper kind 908b8e80941Smrg * of glsl_type. 909b8e80941Smrg */ 910b8e80941Smrg vtn_array_type_rewrite_glsl_type(ctx->type->members[member]); 911b8e80941Smrg ctx->fields[member].type = ctx->type->members[member]->type; 912b8e80941Smrg} 913b8e80941Smrg 914b8e80941Smrgstatic void 915b8e80941Smrgstruct_block_decoration_cb(struct vtn_builder *b, 916b8e80941Smrg struct vtn_value *val, int member, 917b8e80941Smrg const struct vtn_decoration *dec, void *ctx) 918b8e80941Smrg{ 919b8e80941Smrg if (member != -1) 920b8e80941Smrg return; 921b8e80941Smrg 922b8e80941Smrg struct vtn_type *type = val->type; 923b8e80941Smrg if (dec->decoration == SpvDecorationBlock) 924b8e80941Smrg type->block = true; 925b8e80941Smrg else if (dec->decoration == SpvDecorationBufferBlock) 926b8e80941Smrg type->buffer_block = true; 927b8e80941Smrg} 928b8e80941Smrg 929b8e80941Smrgstatic void 930b8e80941Smrgtype_decoration_cb(struct vtn_builder *b, 931b8e80941Smrg struct vtn_value *val, int member, 932b8e80941Smrg const struct vtn_decoration *dec, void *ctx) 933b8e80941Smrg{ 934b8e80941Smrg struct vtn_type *type = val->type; 935b8e80941Smrg 936b8e80941Smrg if (member != -1) { 937b8e80941Smrg /* This should have been handled by OpTypeStruct */ 938b8e80941Smrg assert(val->type->base_type == vtn_base_type_struct); 939b8e80941Smrg assert(member >= 0 && member < val->type->length); 940b8e80941Smrg return; 941b8e80941Smrg } 942b8e80941Smrg 943b8e80941Smrg switch (dec->decoration) { 944b8e80941Smrg case SpvDecorationArrayStride: 945b8e80941Smrg vtn_assert(type->base_type == vtn_base_type_array || 946b8e80941Smrg type->base_type == vtn_base_type_pointer); 947b8e80941Smrg break; 948b8e80941Smrg case SpvDecorationBlock: 949b8e80941Smrg vtn_assert(type->base_type == vtn_base_type_struct); 950b8e80941Smrg vtn_assert(type->block); 951b8e80941Smrg break; 952b8e80941Smrg case SpvDecorationBufferBlock: 953b8e80941Smrg vtn_assert(type->base_type == vtn_base_type_struct); 954b8e80941Smrg vtn_assert(type->buffer_block); 955b8e80941Smrg break; 956b8e80941Smrg case SpvDecorationGLSLShared: 957b8e80941Smrg case SpvDecorationGLSLPacked: 958b8e80941Smrg /* Ignore these, since we get explicit offsets anyways */ 959b8e80941Smrg break; 960b8e80941Smrg 961b8e80941Smrg case SpvDecorationRowMajor: 962b8e80941Smrg case SpvDecorationColMajor: 963b8e80941Smrg case SpvDecorationMatrixStride: 964b8e80941Smrg case SpvDecorationBuiltIn: 965b8e80941Smrg case SpvDecorationNoPerspective: 966b8e80941Smrg case SpvDecorationFlat: 967b8e80941Smrg case SpvDecorationPatch: 968b8e80941Smrg case SpvDecorationCentroid: 969b8e80941Smrg case SpvDecorationSample: 970b8e80941Smrg case SpvDecorationVolatile: 971b8e80941Smrg case SpvDecorationCoherent: 972b8e80941Smrg case SpvDecorationNonWritable: 973b8e80941Smrg case SpvDecorationNonReadable: 974b8e80941Smrg case SpvDecorationUniform: 975b8e80941Smrg case SpvDecorationLocation: 976b8e80941Smrg case SpvDecorationComponent: 977b8e80941Smrg case SpvDecorationOffset: 978b8e80941Smrg case SpvDecorationXfbBuffer: 979b8e80941Smrg case SpvDecorationXfbStride: 980b8e80941Smrg case SpvDecorationHlslSemanticGOOGLE: 981b8e80941Smrg vtn_warn("Decoration only allowed for struct members: %s", 982b8e80941Smrg spirv_decoration_to_string(dec->decoration)); 983b8e80941Smrg break; 984b8e80941Smrg 985b8e80941Smrg case SpvDecorationStream: 986b8e80941Smrg /* We don't need to do anything here, as stream is filled up when 987b8e80941Smrg * aplying the decoration to a variable, just check that if it is not a 988b8e80941Smrg * struct member, it should be a struct. 989b8e80941Smrg */ 990b8e80941Smrg vtn_assert(type->base_type == vtn_base_type_struct); 991b8e80941Smrg break; 992b8e80941Smrg 993b8e80941Smrg case SpvDecorationRelaxedPrecision: 994b8e80941Smrg case SpvDecorationSpecId: 995b8e80941Smrg case SpvDecorationInvariant: 996b8e80941Smrg case SpvDecorationRestrict: 997b8e80941Smrg case SpvDecorationAliased: 998b8e80941Smrg case SpvDecorationConstant: 999b8e80941Smrg case SpvDecorationIndex: 1000b8e80941Smrg case SpvDecorationBinding: 1001b8e80941Smrg case SpvDecorationDescriptorSet: 1002b8e80941Smrg case SpvDecorationLinkageAttributes: 1003b8e80941Smrg case SpvDecorationNoContraction: 1004b8e80941Smrg case SpvDecorationInputAttachmentIndex: 1005b8e80941Smrg vtn_warn("Decoration not allowed on types: %s", 1006b8e80941Smrg spirv_decoration_to_string(dec->decoration)); 1007b8e80941Smrg break; 1008b8e80941Smrg 1009b8e80941Smrg case SpvDecorationCPacked: 1010b8e80941Smrg if (b->shader->info.stage != MESA_SHADER_KERNEL) 1011b8e80941Smrg vtn_warn("Decoration only allowed for CL-style kernels: %s", 1012b8e80941Smrg spirv_decoration_to_string(dec->decoration)); 1013b8e80941Smrg else 1014b8e80941Smrg type->packed = true; 1015b8e80941Smrg break; 1016b8e80941Smrg 1017b8e80941Smrg case SpvDecorationSaturatedConversion: 1018b8e80941Smrg case SpvDecorationFuncParamAttr: 1019b8e80941Smrg case SpvDecorationFPRoundingMode: 1020b8e80941Smrg case SpvDecorationFPFastMathMode: 1021b8e80941Smrg case SpvDecorationAlignment: 1022b8e80941Smrg vtn_warn("Decoration only allowed for CL-style kernels: %s", 1023b8e80941Smrg spirv_decoration_to_string(dec->decoration)); 1024b8e80941Smrg break; 1025b8e80941Smrg 1026b8e80941Smrg default: 1027b8e80941Smrg vtn_fail_with_decoration("Unhandled decoration", dec->decoration); 1028b8e80941Smrg } 1029b8e80941Smrg} 1030b8e80941Smrg 1031b8e80941Smrgstatic unsigned 1032b8e80941Smrgtranslate_image_format(struct vtn_builder *b, SpvImageFormat format) 1033b8e80941Smrg{ 1034b8e80941Smrg switch (format) { 1035b8e80941Smrg case SpvImageFormatUnknown: return 0; /* GL_NONE */ 1036b8e80941Smrg case SpvImageFormatRgba32f: return 0x8814; /* GL_RGBA32F */ 1037b8e80941Smrg case SpvImageFormatRgba16f: return 0x881A; /* GL_RGBA16F */ 1038b8e80941Smrg case SpvImageFormatR32f: return 0x822E; /* GL_R32F */ 1039b8e80941Smrg case SpvImageFormatRgba8: return 0x8058; /* GL_RGBA8 */ 1040b8e80941Smrg case SpvImageFormatRgba8Snorm: return 0x8F97; /* GL_RGBA8_SNORM */ 1041b8e80941Smrg case SpvImageFormatRg32f: return 0x8230; /* GL_RG32F */ 1042b8e80941Smrg case SpvImageFormatRg16f: return 0x822F; /* GL_RG16F */ 1043b8e80941Smrg case SpvImageFormatR11fG11fB10f: return 0x8C3A; /* GL_R11F_G11F_B10F */ 1044b8e80941Smrg case SpvImageFormatR16f: return 0x822D; /* GL_R16F */ 1045b8e80941Smrg case SpvImageFormatRgba16: return 0x805B; /* GL_RGBA16 */ 1046b8e80941Smrg case SpvImageFormatRgb10A2: return 0x8059; /* GL_RGB10_A2 */ 1047b8e80941Smrg case SpvImageFormatRg16: return 0x822C; /* GL_RG16 */ 1048b8e80941Smrg case SpvImageFormatRg8: return 0x822B; /* GL_RG8 */ 1049b8e80941Smrg case SpvImageFormatR16: return 0x822A; /* GL_R16 */ 1050b8e80941Smrg case SpvImageFormatR8: return 0x8229; /* GL_R8 */ 1051b8e80941Smrg case SpvImageFormatRgba16Snorm: return 0x8F9B; /* GL_RGBA16_SNORM */ 1052b8e80941Smrg case SpvImageFormatRg16Snorm: return 0x8F99; /* GL_RG16_SNORM */ 1053b8e80941Smrg case SpvImageFormatRg8Snorm: return 0x8F95; /* GL_RG8_SNORM */ 1054b8e80941Smrg case SpvImageFormatR16Snorm: return 0x8F98; /* GL_R16_SNORM */ 1055b8e80941Smrg case SpvImageFormatR8Snorm: return 0x8F94; /* GL_R8_SNORM */ 1056b8e80941Smrg case SpvImageFormatRgba32i: return 0x8D82; /* GL_RGBA32I */ 1057b8e80941Smrg case SpvImageFormatRgba16i: return 0x8D88; /* GL_RGBA16I */ 1058b8e80941Smrg case SpvImageFormatRgba8i: return 0x8D8E; /* GL_RGBA8I */ 1059b8e80941Smrg case SpvImageFormatR32i: return 0x8235; /* GL_R32I */ 1060b8e80941Smrg case SpvImageFormatRg32i: return 0x823B; /* GL_RG32I */ 1061b8e80941Smrg case SpvImageFormatRg16i: return 0x8239; /* GL_RG16I */ 1062b8e80941Smrg case SpvImageFormatRg8i: return 0x8237; /* GL_RG8I */ 1063b8e80941Smrg case SpvImageFormatR16i: return 0x8233; /* GL_R16I */ 1064b8e80941Smrg case SpvImageFormatR8i: return 0x8231; /* GL_R8I */ 1065b8e80941Smrg case SpvImageFormatRgba32ui: return 0x8D70; /* GL_RGBA32UI */ 1066b8e80941Smrg case SpvImageFormatRgba16ui: return 0x8D76; /* GL_RGBA16UI */ 1067b8e80941Smrg case SpvImageFormatRgba8ui: return 0x8D7C; /* GL_RGBA8UI */ 1068b8e80941Smrg case SpvImageFormatR32ui: return 0x8236; /* GL_R32UI */ 1069b8e80941Smrg case SpvImageFormatRgb10a2ui: return 0x906F; /* GL_RGB10_A2UI */ 1070b8e80941Smrg case SpvImageFormatRg32ui: return 0x823C; /* GL_RG32UI */ 1071b8e80941Smrg case SpvImageFormatRg16ui: return 0x823A; /* GL_RG16UI */ 1072b8e80941Smrg case SpvImageFormatRg8ui: return 0x8238; /* GL_RG8UI */ 1073b8e80941Smrg case SpvImageFormatR16ui: return 0x8234; /* GL_R16UI */ 1074b8e80941Smrg case SpvImageFormatR8ui: return 0x8232; /* GL_R8UI */ 1075b8e80941Smrg default: 1076b8e80941Smrg vtn_fail("Invalid image format: %s (%u)", 1077b8e80941Smrg spirv_imageformat_to_string(format), format); 1078b8e80941Smrg } 1079b8e80941Smrg} 1080b8e80941Smrg 1081b8e80941Smrgstatic struct vtn_type * 1082b8e80941Smrgvtn_type_layout_std430(struct vtn_builder *b, struct vtn_type *type, 1083b8e80941Smrg uint32_t *size_out, uint32_t *align_out) 1084b8e80941Smrg{ 1085b8e80941Smrg switch (type->base_type) { 1086b8e80941Smrg case vtn_base_type_scalar: { 1087b8e80941Smrg uint32_t comp_size = glsl_type_is_boolean(type->type) 1088b8e80941Smrg ? 4 : glsl_get_bit_size(type->type) / 8; 1089b8e80941Smrg *size_out = comp_size; 1090b8e80941Smrg *align_out = comp_size; 1091b8e80941Smrg return type; 1092b8e80941Smrg } 1093b8e80941Smrg 1094b8e80941Smrg case vtn_base_type_vector: { 1095b8e80941Smrg uint32_t comp_size = glsl_type_is_boolean(type->type) 1096b8e80941Smrg ? 4 : glsl_get_bit_size(type->type) / 8; 1097b8e80941Smrg unsigned align_comps = type->length == 3 ? 4 : type->length; 1098b8e80941Smrg *size_out = comp_size * type->length, 1099b8e80941Smrg *align_out = comp_size * align_comps; 1100b8e80941Smrg return type; 1101b8e80941Smrg } 1102b8e80941Smrg 1103b8e80941Smrg case vtn_base_type_matrix: 1104b8e80941Smrg case vtn_base_type_array: { 1105b8e80941Smrg /* We're going to add an array stride */ 1106b8e80941Smrg type = vtn_type_copy(b, type); 1107b8e80941Smrg uint32_t elem_size, elem_align; 1108b8e80941Smrg type->array_element = vtn_type_layout_std430(b, type->array_element, 1109b8e80941Smrg &elem_size, &elem_align); 1110b8e80941Smrg type->stride = vtn_align_u32(elem_size, elem_align); 1111b8e80941Smrg *size_out = type->stride * type->length; 1112b8e80941Smrg *align_out = elem_align; 1113b8e80941Smrg return type; 1114b8e80941Smrg } 1115b8e80941Smrg 1116b8e80941Smrg case vtn_base_type_struct: { 1117b8e80941Smrg /* We're going to add member offsets */ 1118b8e80941Smrg type = vtn_type_copy(b, type); 1119b8e80941Smrg uint32_t offset = 0; 1120b8e80941Smrg uint32_t align = 0; 1121b8e80941Smrg for (unsigned i = 0; i < type->length; i++) { 1122b8e80941Smrg uint32_t mem_size, mem_align; 1123b8e80941Smrg type->members[i] = vtn_type_layout_std430(b, type->members[i], 1124b8e80941Smrg &mem_size, &mem_align); 1125b8e80941Smrg offset = vtn_align_u32(offset, mem_align); 1126b8e80941Smrg type->offsets[i] = offset; 1127b8e80941Smrg offset += mem_size; 1128b8e80941Smrg align = MAX2(align, mem_align); 1129b8e80941Smrg } 1130b8e80941Smrg *size_out = offset; 1131b8e80941Smrg *align_out = align; 1132b8e80941Smrg return type; 1133b8e80941Smrg } 1134b8e80941Smrg 1135b8e80941Smrg default: 1136b8e80941Smrg unreachable("Invalid SPIR-V type for std430"); 1137b8e80941Smrg } 1138b8e80941Smrg} 1139b8e80941Smrg 1140b8e80941Smrgstatic void 1141b8e80941Smrgvtn_handle_type(struct vtn_builder *b, SpvOp opcode, 1142b8e80941Smrg const uint32_t *w, unsigned count) 1143b8e80941Smrg{ 1144b8e80941Smrg struct vtn_value *val = NULL; 1145b8e80941Smrg 1146b8e80941Smrg /* In order to properly handle forward declarations, we have to defer 1147b8e80941Smrg * allocation for pointer types. 1148b8e80941Smrg */ 1149b8e80941Smrg if (opcode != SpvOpTypePointer && opcode != SpvOpTypeForwardPointer) { 1150b8e80941Smrg val = vtn_push_value(b, w[1], vtn_value_type_type); 1151b8e80941Smrg vtn_fail_if(val->type != NULL, 1152b8e80941Smrg "Only pointers can have forward declarations"); 1153b8e80941Smrg val->type = rzalloc(b, struct vtn_type); 1154b8e80941Smrg val->type->id = w[1]; 1155b8e80941Smrg } 1156b8e80941Smrg 1157b8e80941Smrg switch (opcode) { 1158b8e80941Smrg case SpvOpTypeVoid: 1159b8e80941Smrg val->type->base_type = vtn_base_type_void; 1160b8e80941Smrg val->type->type = glsl_void_type(); 1161b8e80941Smrg break; 1162b8e80941Smrg case SpvOpTypeBool: 1163b8e80941Smrg val->type->base_type = vtn_base_type_scalar; 1164b8e80941Smrg val->type->type = glsl_bool_type(); 1165b8e80941Smrg val->type->length = 1; 1166b8e80941Smrg break; 1167b8e80941Smrg case SpvOpTypeInt: { 1168b8e80941Smrg int bit_size = w[2]; 1169b8e80941Smrg const bool signedness = w[3]; 1170b8e80941Smrg val->type->base_type = vtn_base_type_scalar; 1171b8e80941Smrg switch (bit_size) { 1172b8e80941Smrg case 64: 1173b8e80941Smrg val->type->type = (signedness ? glsl_int64_t_type() : glsl_uint64_t_type()); 1174b8e80941Smrg break; 1175b8e80941Smrg case 32: 1176b8e80941Smrg val->type->type = (signedness ? glsl_int_type() : glsl_uint_type()); 1177b8e80941Smrg break; 1178b8e80941Smrg case 16: 1179b8e80941Smrg val->type->type = (signedness ? glsl_int16_t_type() : glsl_uint16_t_type()); 1180b8e80941Smrg break; 1181b8e80941Smrg case 8: 1182b8e80941Smrg val->type->type = (signedness ? glsl_int8_t_type() : glsl_uint8_t_type()); 1183b8e80941Smrg break; 1184b8e80941Smrg default: 1185b8e80941Smrg vtn_fail("Invalid int bit size: %u", bit_size); 1186b8e80941Smrg } 1187b8e80941Smrg val->type->length = 1; 1188b8e80941Smrg break; 1189b8e80941Smrg } 1190b8e80941Smrg 1191b8e80941Smrg case SpvOpTypeFloat: { 1192b8e80941Smrg int bit_size = w[2]; 1193b8e80941Smrg val->type->base_type = vtn_base_type_scalar; 1194b8e80941Smrg switch (bit_size) { 1195b8e80941Smrg case 16: 1196b8e80941Smrg val->type->type = glsl_float16_t_type(); 1197b8e80941Smrg break; 1198b8e80941Smrg case 32: 1199b8e80941Smrg val->type->type = glsl_float_type(); 1200b8e80941Smrg break; 1201b8e80941Smrg case 64: 1202b8e80941Smrg val->type->type = glsl_double_type(); 1203b8e80941Smrg break; 1204b8e80941Smrg default: 1205b8e80941Smrg vtn_fail("Invalid float bit size: %u", bit_size); 1206b8e80941Smrg } 1207b8e80941Smrg val->type->length = 1; 1208b8e80941Smrg break; 1209b8e80941Smrg } 1210b8e80941Smrg 1211b8e80941Smrg case SpvOpTypeVector: { 1212b8e80941Smrg struct vtn_type *base = vtn_value(b, w[2], vtn_value_type_type)->type; 1213b8e80941Smrg unsigned elems = w[3]; 1214b8e80941Smrg 1215b8e80941Smrg vtn_fail_if(base->base_type != vtn_base_type_scalar, 1216b8e80941Smrg "Base type for OpTypeVector must be a scalar"); 1217b8e80941Smrg vtn_fail_if((elems < 2 || elems > 4) && (elems != 8) && (elems != 16), 1218b8e80941Smrg "Invalid component count for OpTypeVector"); 1219b8e80941Smrg 1220b8e80941Smrg val->type->base_type = vtn_base_type_vector; 1221b8e80941Smrg val->type->type = glsl_vector_type(glsl_get_base_type(base->type), elems); 1222b8e80941Smrg val->type->length = elems; 1223b8e80941Smrg val->type->stride = glsl_type_is_boolean(val->type->type) 1224b8e80941Smrg ? 4 : glsl_get_bit_size(base->type) / 8; 1225b8e80941Smrg val->type->array_element = base; 1226b8e80941Smrg break; 1227b8e80941Smrg } 1228b8e80941Smrg 1229b8e80941Smrg case SpvOpTypeMatrix: { 1230b8e80941Smrg struct vtn_type *base = vtn_value(b, w[2], vtn_value_type_type)->type; 1231b8e80941Smrg unsigned columns = w[3]; 1232b8e80941Smrg 1233b8e80941Smrg vtn_fail_if(base->base_type != vtn_base_type_vector, 1234b8e80941Smrg "Base type for OpTypeMatrix must be a vector"); 1235b8e80941Smrg vtn_fail_if(columns < 2 || columns > 4, 1236b8e80941Smrg "Invalid column count for OpTypeMatrix"); 1237b8e80941Smrg 1238b8e80941Smrg val->type->base_type = vtn_base_type_matrix; 1239b8e80941Smrg val->type->type = glsl_matrix_type(glsl_get_base_type(base->type), 1240b8e80941Smrg glsl_get_vector_elements(base->type), 1241b8e80941Smrg columns); 1242b8e80941Smrg vtn_fail_if(glsl_type_is_error(val->type->type), 1243b8e80941Smrg "Unsupported base type for OpTypeMatrix"); 1244b8e80941Smrg assert(!glsl_type_is_error(val->type->type)); 1245b8e80941Smrg val->type->length = columns; 1246b8e80941Smrg val->type->array_element = base; 1247b8e80941Smrg val->type->row_major = false; 1248b8e80941Smrg val->type->stride = 0; 1249b8e80941Smrg break; 1250b8e80941Smrg } 1251b8e80941Smrg 1252b8e80941Smrg case SpvOpTypeRuntimeArray: 1253b8e80941Smrg case SpvOpTypeArray: { 1254b8e80941Smrg struct vtn_type *array_element = 1255b8e80941Smrg vtn_value(b, w[2], vtn_value_type_type)->type; 1256b8e80941Smrg 1257b8e80941Smrg if (opcode == SpvOpTypeRuntimeArray) { 1258b8e80941Smrg /* A length of 0 is used to denote unsized arrays */ 1259b8e80941Smrg val->type->length = 0; 1260b8e80941Smrg } else { 1261b8e80941Smrg val->type->length = 1262b8e80941Smrg vtn_value(b, w[3], vtn_value_type_constant)->constant->values[0][0].u32; 1263b8e80941Smrg } 1264b8e80941Smrg 1265b8e80941Smrg val->type->base_type = vtn_base_type_array; 1266b8e80941Smrg val->type->array_element = array_element; 1267b8e80941Smrg if (b->shader->info.stage == MESA_SHADER_KERNEL) 1268b8e80941Smrg val->type->stride = glsl_get_cl_size(array_element->type); 1269b8e80941Smrg 1270b8e80941Smrg vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL); 1271b8e80941Smrg val->type->type = glsl_array_type(array_element->type, val->type->length, 1272b8e80941Smrg val->type->stride); 1273b8e80941Smrg break; 1274b8e80941Smrg } 1275b8e80941Smrg 1276b8e80941Smrg case SpvOpTypeStruct: { 1277b8e80941Smrg unsigned num_fields = count - 2; 1278b8e80941Smrg val->type->base_type = vtn_base_type_struct; 1279b8e80941Smrg val->type->length = num_fields; 1280b8e80941Smrg val->type->members = ralloc_array(b, struct vtn_type *, num_fields); 1281b8e80941Smrg val->type->offsets = ralloc_array(b, unsigned, num_fields); 1282b8e80941Smrg val->type->packed = false; 1283b8e80941Smrg 1284b8e80941Smrg NIR_VLA(struct glsl_struct_field, fields, count); 1285b8e80941Smrg for (unsigned i = 0; i < num_fields; i++) { 1286b8e80941Smrg val->type->members[i] = 1287b8e80941Smrg vtn_value(b, w[i + 2], vtn_value_type_type)->type; 1288b8e80941Smrg fields[i] = (struct glsl_struct_field) { 1289b8e80941Smrg .type = val->type->members[i]->type, 1290b8e80941Smrg .name = ralloc_asprintf(b, "field%d", i), 1291b8e80941Smrg .location = -1, 1292b8e80941Smrg .offset = -1, 1293b8e80941Smrg }; 1294b8e80941Smrg } 1295b8e80941Smrg 1296b8e80941Smrg if (b->shader->info.stage == MESA_SHADER_KERNEL) { 1297b8e80941Smrg unsigned offset = 0; 1298b8e80941Smrg for (unsigned i = 0; i < num_fields; i++) { 1299b8e80941Smrg offset = align(offset, glsl_get_cl_alignment(fields[i].type)); 1300b8e80941Smrg fields[i].offset = offset; 1301b8e80941Smrg offset += glsl_get_cl_size(fields[i].type); 1302b8e80941Smrg } 1303b8e80941Smrg } 1304b8e80941Smrg 1305b8e80941Smrg struct member_decoration_ctx ctx = { 1306b8e80941Smrg .num_fields = num_fields, 1307b8e80941Smrg .fields = fields, 1308b8e80941Smrg .type = val->type 1309b8e80941Smrg }; 1310b8e80941Smrg 1311b8e80941Smrg vtn_foreach_decoration(b, val, struct_member_decoration_cb, &ctx); 1312b8e80941Smrg vtn_foreach_decoration(b, val, struct_member_matrix_stride_cb, &ctx); 1313b8e80941Smrg 1314b8e80941Smrg vtn_foreach_decoration(b, val, struct_block_decoration_cb, NULL); 1315b8e80941Smrg 1316b8e80941Smrg const char *name = val->name; 1317b8e80941Smrg 1318b8e80941Smrg if (val->type->block || val->type->buffer_block) { 1319b8e80941Smrg /* Packing will be ignored since types coming from SPIR-V are 1320b8e80941Smrg * explicitly laid out. 1321b8e80941Smrg */ 1322b8e80941Smrg val->type->type = glsl_interface_type(fields, num_fields, 1323b8e80941Smrg /* packing */ 0, false, 1324b8e80941Smrg name ? name : "block"); 1325b8e80941Smrg } else { 1326b8e80941Smrg val->type->type = glsl_struct_type(fields, num_fields, 1327b8e80941Smrg name ? name : "struct", false); 1328b8e80941Smrg } 1329b8e80941Smrg break; 1330b8e80941Smrg } 1331b8e80941Smrg 1332b8e80941Smrg case SpvOpTypeFunction: { 1333b8e80941Smrg val->type->base_type = vtn_base_type_function; 1334b8e80941Smrg val->type->type = NULL; 1335b8e80941Smrg 1336b8e80941Smrg val->type->return_type = vtn_value(b, w[2], vtn_value_type_type)->type; 1337b8e80941Smrg 1338b8e80941Smrg const unsigned num_params = count - 3; 1339b8e80941Smrg val->type->length = num_params; 1340b8e80941Smrg val->type->params = ralloc_array(b, struct vtn_type *, num_params); 1341b8e80941Smrg for (unsigned i = 0; i < count - 3; i++) { 1342b8e80941Smrg val->type->params[i] = 1343b8e80941Smrg vtn_value(b, w[i + 3], vtn_value_type_type)->type; 1344b8e80941Smrg } 1345b8e80941Smrg break; 1346b8e80941Smrg } 1347b8e80941Smrg 1348b8e80941Smrg case SpvOpTypePointer: 1349b8e80941Smrg case SpvOpTypeForwardPointer: { 1350b8e80941Smrg /* We can't blindly push the value because it might be a forward 1351b8e80941Smrg * declaration. 1352b8e80941Smrg */ 1353b8e80941Smrg val = vtn_untyped_value(b, w[1]); 1354b8e80941Smrg 1355b8e80941Smrg SpvStorageClass storage_class = w[2]; 1356b8e80941Smrg 1357b8e80941Smrg if (val->value_type == vtn_value_type_invalid) { 1358b8e80941Smrg val->value_type = vtn_value_type_type; 1359b8e80941Smrg val->type = rzalloc(b, struct vtn_type); 1360b8e80941Smrg val->type->id = w[1]; 1361b8e80941Smrg val->type->base_type = vtn_base_type_pointer; 1362b8e80941Smrg val->type->storage_class = storage_class; 1363b8e80941Smrg 1364b8e80941Smrg /* These can actually be stored to nir_variables and used as SSA 1365b8e80941Smrg * values so they need a real glsl_type. 1366b8e80941Smrg */ 1367b8e80941Smrg switch (storage_class) { 1368b8e80941Smrg case SpvStorageClassUniform: 1369b8e80941Smrg val->type->type = b->options->ubo_ptr_type; 1370b8e80941Smrg break; 1371b8e80941Smrg case SpvStorageClassStorageBuffer: 1372b8e80941Smrg val->type->type = b->options->ssbo_ptr_type; 1373b8e80941Smrg break; 1374b8e80941Smrg case SpvStorageClassPhysicalStorageBufferEXT: 1375b8e80941Smrg val->type->type = b->options->phys_ssbo_ptr_type; 1376b8e80941Smrg break; 1377b8e80941Smrg case SpvStorageClassPushConstant: 1378b8e80941Smrg val->type->type = b->options->push_const_ptr_type; 1379b8e80941Smrg break; 1380b8e80941Smrg case SpvStorageClassWorkgroup: 1381b8e80941Smrg val->type->type = b->options->shared_ptr_type; 1382b8e80941Smrg break; 1383b8e80941Smrg case SpvStorageClassCrossWorkgroup: 1384b8e80941Smrg val->type->type = b->options->global_ptr_type; 1385b8e80941Smrg break; 1386b8e80941Smrg case SpvStorageClassFunction: 1387b8e80941Smrg if (b->physical_ptrs) 1388b8e80941Smrg val->type->type = b->options->temp_ptr_type; 1389b8e80941Smrg break; 1390b8e80941Smrg default: 1391b8e80941Smrg /* In this case, no variable pointers are allowed so all deref 1392b8e80941Smrg * chains are complete back to the variable and it doesn't matter 1393b8e80941Smrg * what type gets used so we leave it NULL. 1394b8e80941Smrg */ 1395b8e80941Smrg break; 1396b8e80941Smrg } 1397b8e80941Smrg } else { 1398b8e80941Smrg vtn_fail_if(val->type->storage_class != storage_class, 1399b8e80941Smrg "The storage classes of an OpTypePointer and any " 1400b8e80941Smrg "OpTypeForwardPointers that provide forward " 1401b8e80941Smrg "declarations of it must match."); 1402b8e80941Smrg } 1403b8e80941Smrg 1404b8e80941Smrg if (opcode == SpvOpTypePointer) { 1405b8e80941Smrg vtn_fail_if(val->type->deref != NULL, 1406b8e80941Smrg "While OpTypeForwardPointer can be used to provide a " 1407b8e80941Smrg "forward declaration of a pointer, OpTypePointer can " 1408b8e80941Smrg "only be used once for a given id."); 1409b8e80941Smrg 1410b8e80941Smrg val->type->deref = vtn_value(b, w[3], vtn_value_type_type)->type; 1411b8e80941Smrg 1412b8e80941Smrg vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL); 1413b8e80941Smrg 1414b8e80941Smrg if (b->physical_ptrs) { 1415b8e80941Smrg switch (storage_class) { 1416b8e80941Smrg case SpvStorageClassFunction: 1417b8e80941Smrg case SpvStorageClassWorkgroup: 1418b8e80941Smrg case SpvStorageClassCrossWorkgroup: 1419b8e80941Smrg val->type->stride = align(glsl_get_cl_size(val->type->deref->type), 1420b8e80941Smrg glsl_get_cl_alignment(val->type->deref->type)); 1421b8e80941Smrg break; 1422b8e80941Smrg default: 1423b8e80941Smrg break; 1424b8e80941Smrg } 1425b8e80941Smrg } else if (storage_class == SpvStorageClassWorkgroup && 1426b8e80941Smrg b->options->lower_workgroup_access_to_offsets) { 1427b8e80941Smrg /* Workgroup is laid out by the implementation. */ 1428b8e80941Smrg uint32_t size, align; 1429b8e80941Smrg val->type->deref = vtn_type_layout_std430(b, val->type->deref, 1430b8e80941Smrg &size, &align); 1431b8e80941Smrg val->type->length = size; 1432b8e80941Smrg val->type->align = align; 1433b8e80941Smrg 1434b8e80941Smrg /* Override any ArrayStride previously set. */ 1435b8e80941Smrg val->type->stride = vtn_align_u32(size, align); 1436b8e80941Smrg } 1437b8e80941Smrg } 1438b8e80941Smrg break; 1439b8e80941Smrg } 1440b8e80941Smrg 1441b8e80941Smrg case SpvOpTypeImage: { 1442b8e80941Smrg val->type->base_type = vtn_base_type_image; 1443b8e80941Smrg 1444b8e80941Smrg const struct vtn_type *sampled_type = 1445b8e80941Smrg vtn_value(b, w[2], vtn_value_type_type)->type; 1446b8e80941Smrg 1447b8e80941Smrg vtn_fail_if(sampled_type->base_type != vtn_base_type_scalar || 1448b8e80941Smrg glsl_get_bit_size(sampled_type->type) != 32, 1449b8e80941Smrg "Sampled type of OpTypeImage must be a 32-bit scalar"); 1450b8e80941Smrg 1451b8e80941Smrg enum glsl_sampler_dim dim; 1452b8e80941Smrg switch ((SpvDim)w[3]) { 1453b8e80941Smrg case SpvDim1D: dim = GLSL_SAMPLER_DIM_1D; break; 1454b8e80941Smrg case SpvDim2D: dim = GLSL_SAMPLER_DIM_2D; break; 1455b8e80941Smrg case SpvDim3D: dim = GLSL_SAMPLER_DIM_3D; break; 1456b8e80941Smrg case SpvDimCube: dim = GLSL_SAMPLER_DIM_CUBE; break; 1457b8e80941Smrg case SpvDimRect: dim = GLSL_SAMPLER_DIM_RECT; break; 1458b8e80941Smrg case SpvDimBuffer: dim = GLSL_SAMPLER_DIM_BUF; break; 1459b8e80941Smrg case SpvDimSubpassData: dim = GLSL_SAMPLER_DIM_SUBPASS; break; 1460b8e80941Smrg default: 1461b8e80941Smrg vtn_fail("Invalid SPIR-V image dimensionality: %s (%u)", 1462b8e80941Smrg spirv_dim_to_string((SpvDim)w[3]), w[3]); 1463b8e80941Smrg } 1464b8e80941Smrg 1465b8e80941Smrg /* w[4]: as per Vulkan spec "Validation Rules within a Module", 1466b8e80941Smrg * The “Depth” operand of OpTypeImage is ignored. 1467b8e80941Smrg */ 1468b8e80941Smrg bool is_array = w[5]; 1469b8e80941Smrg bool multisampled = w[6]; 1470b8e80941Smrg unsigned sampled = w[7]; 1471b8e80941Smrg SpvImageFormat format = w[8]; 1472b8e80941Smrg 1473b8e80941Smrg if (count > 9) 1474b8e80941Smrg val->type->access_qualifier = w[9]; 1475b8e80941Smrg else 1476b8e80941Smrg val->type->access_qualifier = SpvAccessQualifierReadWrite; 1477b8e80941Smrg 1478b8e80941Smrg if (multisampled) { 1479b8e80941Smrg if (dim == GLSL_SAMPLER_DIM_2D) 1480b8e80941Smrg dim = GLSL_SAMPLER_DIM_MS; 1481b8e80941Smrg else if (dim == GLSL_SAMPLER_DIM_SUBPASS) 1482b8e80941Smrg dim = GLSL_SAMPLER_DIM_SUBPASS_MS; 1483b8e80941Smrg else 1484b8e80941Smrg vtn_fail("Unsupported multisampled image type"); 1485b8e80941Smrg } 1486b8e80941Smrg 1487b8e80941Smrg val->type->image_format = translate_image_format(b, format); 1488b8e80941Smrg 1489b8e80941Smrg enum glsl_base_type sampled_base_type = 1490b8e80941Smrg glsl_get_base_type(sampled_type->type); 1491b8e80941Smrg if (sampled == 1) { 1492b8e80941Smrg val->type->sampled = true; 1493b8e80941Smrg val->type->type = glsl_sampler_type(dim, false, is_array, 1494b8e80941Smrg sampled_base_type); 1495b8e80941Smrg } else if (sampled == 2) { 1496b8e80941Smrg val->type->sampled = false; 1497b8e80941Smrg val->type->type = glsl_image_type(dim, is_array, sampled_base_type); 1498b8e80941Smrg } else { 1499b8e80941Smrg vtn_fail("We need to know if the image will be sampled"); 1500b8e80941Smrg } 1501b8e80941Smrg break; 1502b8e80941Smrg } 1503b8e80941Smrg 1504b8e80941Smrg case SpvOpTypeSampledImage: 1505b8e80941Smrg val->type->base_type = vtn_base_type_sampled_image; 1506b8e80941Smrg val->type->image = vtn_value(b, w[2], vtn_value_type_type)->type; 1507b8e80941Smrg val->type->type = val->type->image->type; 1508b8e80941Smrg break; 1509b8e80941Smrg 1510b8e80941Smrg case SpvOpTypeSampler: 1511b8e80941Smrg /* The actual sampler type here doesn't really matter. It gets 1512b8e80941Smrg * thrown away the moment you combine it with an image. What really 1513b8e80941Smrg * matters is that it's a sampler type as opposed to an integer type 1514b8e80941Smrg * so the backend knows what to do. 1515b8e80941Smrg */ 1516b8e80941Smrg val->type->base_type = vtn_base_type_sampler; 1517b8e80941Smrg val->type->type = glsl_bare_sampler_type(); 1518b8e80941Smrg break; 1519b8e80941Smrg 1520b8e80941Smrg case SpvOpTypeOpaque: 1521b8e80941Smrg case SpvOpTypeEvent: 1522b8e80941Smrg case SpvOpTypeDeviceEvent: 1523b8e80941Smrg case SpvOpTypeReserveId: 1524b8e80941Smrg case SpvOpTypeQueue: 1525b8e80941Smrg case SpvOpTypePipe: 1526b8e80941Smrg default: 1527b8e80941Smrg vtn_fail_with_opcode("Unhandled opcode", opcode); 1528b8e80941Smrg } 1529b8e80941Smrg 1530b8e80941Smrg vtn_foreach_decoration(b, val, type_decoration_cb, NULL); 1531b8e80941Smrg 1532b8e80941Smrg if (val->type->base_type == vtn_base_type_struct && 1533b8e80941Smrg (val->type->block || val->type->buffer_block)) { 1534b8e80941Smrg for (unsigned i = 0; i < val->type->length; i++) { 1535b8e80941Smrg vtn_fail_if(vtn_type_contains_block(b, val->type->members[i]), 1536b8e80941Smrg "Block and BufferBlock decorations cannot decorate a " 1537b8e80941Smrg "structure type that is nested at any level inside " 1538b8e80941Smrg "another structure type decorated with Block or " 1539b8e80941Smrg "BufferBlock."); 1540b8e80941Smrg } 1541b8e80941Smrg } 1542b8e80941Smrg} 1543b8e80941Smrg 1544b8e80941Smrgstatic nir_constant * 1545b8e80941Smrgvtn_null_constant(struct vtn_builder *b, const struct glsl_type *type) 1546b8e80941Smrg{ 1547b8e80941Smrg nir_constant *c = rzalloc(b, nir_constant); 1548b8e80941Smrg 1549b8e80941Smrg /* For pointers and other typeless things, we have to return something but 1550b8e80941Smrg * it doesn't matter what. 1551b8e80941Smrg */ 1552b8e80941Smrg if (!type) 1553b8e80941Smrg return c; 1554b8e80941Smrg 1555b8e80941Smrg switch (glsl_get_base_type(type)) { 1556b8e80941Smrg case GLSL_TYPE_INT: 1557b8e80941Smrg case GLSL_TYPE_UINT: 1558b8e80941Smrg case GLSL_TYPE_INT16: 1559b8e80941Smrg case GLSL_TYPE_UINT16: 1560b8e80941Smrg case GLSL_TYPE_UINT8: 1561b8e80941Smrg case GLSL_TYPE_INT8: 1562b8e80941Smrg case GLSL_TYPE_INT64: 1563b8e80941Smrg case GLSL_TYPE_UINT64: 1564b8e80941Smrg case GLSL_TYPE_BOOL: 1565b8e80941Smrg case GLSL_TYPE_FLOAT: 1566b8e80941Smrg case GLSL_TYPE_FLOAT16: 1567b8e80941Smrg case GLSL_TYPE_DOUBLE: 1568b8e80941Smrg /* Nothing to do here. It's already initialized to zero */ 1569b8e80941Smrg break; 1570b8e80941Smrg 1571b8e80941Smrg case GLSL_TYPE_ARRAY: 1572b8e80941Smrg vtn_assert(glsl_get_length(type) > 0); 1573b8e80941Smrg c->num_elements = glsl_get_length(type); 1574b8e80941Smrg c->elements = ralloc_array(b, nir_constant *, c->num_elements); 1575b8e80941Smrg 1576b8e80941Smrg c->elements[0] = vtn_null_constant(b, glsl_get_array_element(type)); 1577b8e80941Smrg for (unsigned i = 1; i < c->num_elements; i++) 1578b8e80941Smrg c->elements[i] = c->elements[0]; 1579b8e80941Smrg break; 1580b8e80941Smrg 1581b8e80941Smrg case GLSL_TYPE_STRUCT: 1582b8e80941Smrg c->num_elements = glsl_get_length(type); 1583b8e80941Smrg c->elements = ralloc_array(b, nir_constant *, c->num_elements); 1584b8e80941Smrg 1585b8e80941Smrg for (unsigned i = 0; i < c->num_elements; i++) { 1586b8e80941Smrg c->elements[i] = vtn_null_constant(b, glsl_get_struct_field(type, i)); 1587b8e80941Smrg } 1588b8e80941Smrg break; 1589b8e80941Smrg 1590b8e80941Smrg default: 1591b8e80941Smrg vtn_fail("Invalid type for null constant"); 1592b8e80941Smrg } 1593b8e80941Smrg 1594b8e80941Smrg return c; 1595b8e80941Smrg} 1596b8e80941Smrg 1597b8e80941Smrgstatic void 1598b8e80941Smrgspec_constant_decoration_cb(struct vtn_builder *b, struct vtn_value *v, 1599b8e80941Smrg int member, const struct vtn_decoration *dec, 1600b8e80941Smrg void *data) 1601b8e80941Smrg{ 1602b8e80941Smrg vtn_assert(member == -1); 1603b8e80941Smrg if (dec->decoration != SpvDecorationSpecId) 1604b8e80941Smrg return; 1605b8e80941Smrg 1606b8e80941Smrg struct spec_constant_value *const_value = data; 1607b8e80941Smrg 1608b8e80941Smrg for (unsigned i = 0; i < b->num_specializations; i++) { 1609b8e80941Smrg if (b->specializations[i].id == dec->operands[0]) { 1610b8e80941Smrg if (const_value->is_double) 1611b8e80941Smrg const_value->data64 = b->specializations[i].data64; 1612b8e80941Smrg else 1613b8e80941Smrg const_value->data32 = b->specializations[i].data32; 1614b8e80941Smrg return; 1615b8e80941Smrg } 1616b8e80941Smrg } 1617b8e80941Smrg} 1618b8e80941Smrg 1619b8e80941Smrgstatic uint32_t 1620b8e80941Smrgget_specialization(struct vtn_builder *b, struct vtn_value *val, 1621b8e80941Smrg uint32_t const_value) 1622b8e80941Smrg{ 1623b8e80941Smrg struct spec_constant_value data; 1624b8e80941Smrg data.is_double = false; 1625b8e80941Smrg data.data32 = const_value; 1626b8e80941Smrg vtn_foreach_decoration(b, val, spec_constant_decoration_cb, &data); 1627b8e80941Smrg return data.data32; 1628b8e80941Smrg} 1629b8e80941Smrg 1630b8e80941Smrgstatic uint64_t 1631b8e80941Smrgget_specialization64(struct vtn_builder *b, struct vtn_value *val, 1632b8e80941Smrg uint64_t const_value) 1633b8e80941Smrg{ 1634b8e80941Smrg struct spec_constant_value data; 1635b8e80941Smrg data.is_double = true; 1636b8e80941Smrg data.data64 = const_value; 1637b8e80941Smrg vtn_foreach_decoration(b, val, spec_constant_decoration_cb, &data); 1638b8e80941Smrg return data.data64; 1639b8e80941Smrg} 1640b8e80941Smrg 1641b8e80941Smrgstatic void 1642b8e80941Smrghandle_workgroup_size_decoration_cb(struct vtn_builder *b, 1643b8e80941Smrg struct vtn_value *val, 1644b8e80941Smrg int member, 1645b8e80941Smrg const struct vtn_decoration *dec, 1646b8e80941Smrg void *data) 1647b8e80941Smrg{ 1648b8e80941Smrg vtn_assert(member == -1); 1649b8e80941Smrg if (dec->decoration != SpvDecorationBuiltIn || 1650b8e80941Smrg dec->operands[0] != SpvBuiltInWorkgroupSize) 1651b8e80941Smrg return; 1652b8e80941Smrg 1653b8e80941Smrg vtn_assert(val->type->type == glsl_vector_type(GLSL_TYPE_UINT, 3)); 1654b8e80941Smrg b->workgroup_size_builtin = val; 1655b8e80941Smrg} 1656b8e80941Smrg 1657b8e80941Smrgstatic void 1658b8e80941Smrgvtn_handle_constant(struct vtn_builder *b, SpvOp opcode, 1659b8e80941Smrg const uint32_t *w, unsigned count) 1660b8e80941Smrg{ 1661b8e80941Smrg struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_constant); 1662b8e80941Smrg val->constant = rzalloc(b, nir_constant); 1663b8e80941Smrg switch (opcode) { 1664b8e80941Smrg case SpvOpConstantTrue: 1665b8e80941Smrg case SpvOpConstantFalse: 1666b8e80941Smrg case SpvOpSpecConstantTrue: 1667b8e80941Smrg case SpvOpSpecConstantFalse: { 1668b8e80941Smrg vtn_fail_if(val->type->type != glsl_bool_type(), 1669b8e80941Smrg "Result type of %s must be OpTypeBool", 1670b8e80941Smrg spirv_op_to_string(opcode)); 1671b8e80941Smrg 1672b8e80941Smrg uint32_t int_val = (opcode == SpvOpConstantTrue || 1673b8e80941Smrg opcode == SpvOpSpecConstantTrue); 1674b8e80941Smrg 1675b8e80941Smrg if (opcode == SpvOpSpecConstantTrue || 1676b8e80941Smrg opcode == SpvOpSpecConstantFalse) 1677b8e80941Smrg int_val = get_specialization(b, val, int_val); 1678b8e80941Smrg 1679b8e80941Smrg val->constant->values[0][0].b = int_val != 0; 1680b8e80941Smrg break; 1681b8e80941Smrg } 1682b8e80941Smrg 1683b8e80941Smrg case SpvOpConstant: { 1684b8e80941Smrg vtn_fail_if(val->type->base_type != vtn_base_type_scalar, 1685b8e80941Smrg "Result type of %s must be a scalar", 1686b8e80941Smrg spirv_op_to_string(opcode)); 1687b8e80941Smrg int bit_size = glsl_get_bit_size(val->type->type); 1688b8e80941Smrg switch (bit_size) { 1689b8e80941Smrg case 64: 1690b8e80941Smrg val->constant->values[0][0].u64 = vtn_u64_literal(&w[3]); 1691b8e80941Smrg break; 1692b8e80941Smrg case 32: 1693b8e80941Smrg val->constant->values[0][0].u32 = w[3]; 1694b8e80941Smrg break; 1695b8e80941Smrg case 16: 1696b8e80941Smrg val->constant->values[0][0].u16 = w[3]; 1697b8e80941Smrg break; 1698b8e80941Smrg case 8: 1699b8e80941Smrg val->constant->values[0][0].u8 = w[3]; 1700b8e80941Smrg break; 1701b8e80941Smrg default: 1702b8e80941Smrg vtn_fail("Unsupported SpvOpConstant bit size: %u", bit_size); 1703b8e80941Smrg } 1704b8e80941Smrg break; 1705b8e80941Smrg } 1706b8e80941Smrg 1707b8e80941Smrg case SpvOpSpecConstant: { 1708b8e80941Smrg vtn_fail_if(val->type->base_type != vtn_base_type_scalar, 1709b8e80941Smrg "Result type of %s must be a scalar", 1710b8e80941Smrg spirv_op_to_string(opcode)); 1711b8e80941Smrg int bit_size = glsl_get_bit_size(val->type->type); 1712b8e80941Smrg switch (bit_size) { 1713b8e80941Smrg case 64: 1714b8e80941Smrg val->constant->values[0][0].u64 = 1715b8e80941Smrg get_specialization64(b, val, vtn_u64_literal(&w[3])); 1716b8e80941Smrg break; 1717b8e80941Smrg case 32: 1718b8e80941Smrg val->constant->values[0][0].u32 = get_specialization(b, val, w[3]); 1719b8e80941Smrg break; 1720b8e80941Smrg case 16: 1721b8e80941Smrg val->constant->values[0][0].u16 = get_specialization(b, val, w[3]); 1722b8e80941Smrg break; 1723b8e80941Smrg case 8: 1724b8e80941Smrg val->constant->values[0][0].u8 = get_specialization(b, val, w[3]); 1725b8e80941Smrg break; 1726b8e80941Smrg default: 1727b8e80941Smrg vtn_fail("Unsupported SpvOpSpecConstant bit size"); 1728b8e80941Smrg } 1729b8e80941Smrg break; 1730b8e80941Smrg } 1731b8e80941Smrg 1732b8e80941Smrg case SpvOpSpecConstantComposite: 1733b8e80941Smrg case SpvOpConstantComposite: { 1734b8e80941Smrg unsigned elem_count = count - 3; 1735b8e80941Smrg vtn_fail_if(elem_count != val->type->length, 1736b8e80941Smrg "%s has %u constituents, expected %u", 1737b8e80941Smrg spirv_op_to_string(opcode), elem_count, val->type->length); 1738b8e80941Smrg 1739b8e80941Smrg nir_constant **elems = ralloc_array(b, nir_constant *, elem_count); 1740b8e80941Smrg for (unsigned i = 0; i < elem_count; i++) { 1741b8e80941Smrg struct vtn_value *val = vtn_untyped_value(b, w[i + 3]); 1742b8e80941Smrg 1743b8e80941Smrg if (val->value_type == vtn_value_type_constant) { 1744b8e80941Smrg elems[i] = val->constant; 1745b8e80941Smrg } else { 1746b8e80941Smrg vtn_fail_if(val->value_type != vtn_value_type_undef, 1747b8e80941Smrg "only constants or undefs allowed for " 1748b8e80941Smrg "SpvOpConstantComposite"); 1749b8e80941Smrg /* to make it easier, just insert a NULL constant for now */ 1750b8e80941Smrg elems[i] = vtn_null_constant(b, val->type->type); 1751b8e80941Smrg } 1752b8e80941Smrg } 1753b8e80941Smrg 1754b8e80941Smrg switch (val->type->base_type) { 1755b8e80941Smrg case vtn_base_type_vector: { 1756b8e80941Smrg assert(glsl_type_is_vector(val->type->type)); 1757b8e80941Smrg for (unsigned i = 0; i < elem_count; i++) 1758b8e80941Smrg val->constant->values[0][i] = elems[i]->values[0][0]; 1759b8e80941Smrg break; 1760b8e80941Smrg } 1761b8e80941Smrg 1762b8e80941Smrg case vtn_base_type_matrix: 1763b8e80941Smrg assert(glsl_type_is_matrix(val->type->type)); 1764b8e80941Smrg for (unsigned i = 0; i < elem_count; i++) { 1765b8e80941Smrg unsigned components = 1766b8e80941Smrg glsl_get_components(glsl_get_column_type(val->type->type)); 1767b8e80941Smrg memcpy(val->constant->values[i], elems[i]->values, 1768b8e80941Smrg sizeof(nir_const_value) * components); 1769b8e80941Smrg } 1770b8e80941Smrg break; 1771b8e80941Smrg 1772b8e80941Smrg case vtn_base_type_struct: 1773b8e80941Smrg case vtn_base_type_array: 1774b8e80941Smrg ralloc_steal(val->constant, elems); 1775b8e80941Smrg val->constant->num_elements = elem_count; 1776b8e80941Smrg val->constant->elements = elems; 1777b8e80941Smrg break; 1778b8e80941Smrg 1779b8e80941Smrg default: 1780b8e80941Smrg vtn_fail("Result type of %s must be a composite type", 1781b8e80941Smrg spirv_op_to_string(opcode)); 1782b8e80941Smrg } 1783b8e80941Smrg break; 1784b8e80941Smrg } 1785b8e80941Smrg 1786b8e80941Smrg case SpvOpSpecConstantOp: { 1787b8e80941Smrg SpvOp opcode = get_specialization(b, val, w[3]); 1788b8e80941Smrg switch (opcode) { 1789b8e80941Smrg case SpvOpVectorShuffle: { 1790b8e80941Smrg struct vtn_value *v0 = &b->values[w[4]]; 1791b8e80941Smrg struct vtn_value *v1 = &b->values[w[5]]; 1792b8e80941Smrg 1793b8e80941Smrg vtn_assert(v0->value_type == vtn_value_type_constant || 1794b8e80941Smrg v0->value_type == vtn_value_type_undef); 1795b8e80941Smrg vtn_assert(v1->value_type == vtn_value_type_constant || 1796b8e80941Smrg v1->value_type == vtn_value_type_undef); 1797b8e80941Smrg 1798b8e80941Smrg unsigned len0 = glsl_get_vector_elements(v0->type->type); 1799b8e80941Smrg unsigned len1 = glsl_get_vector_elements(v1->type->type); 1800b8e80941Smrg 1801b8e80941Smrg vtn_assert(len0 + len1 < 16); 1802b8e80941Smrg 1803b8e80941Smrg unsigned bit_size = glsl_get_bit_size(val->type->type); 1804b8e80941Smrg unsigned bit_size0 = glsl_get_bit_size(v0->type->type); 1805b8e80941Smrg unsigned bit_size1 = glsl_get_bit_size(v1->type->type); 1806b8e80941Smrg 1807b8e80941Smrg vtn_assert(bit_size == bit_size0 && bit_size == bit_size1); 1808b8e80941Smrg (void)bit_size0; (void)bit_size1; 1809b8e80941Smrg 1810b8e80941Smrg if (bit_size == 64) { 1811b8e80941Smrg uint64_t u64[8]; 1812b8e80941Smrg if (v0->value_type == vtn_value_type_constant) { 1813b8e80941Smrg for (unsigned i = 0; i < len0; i++) 1814b8e80941Smrg u64[i] = v0->constant->values[0][i].u64; 1815b8e80941Smrg } 1816b8e80941Smrg if (v1->value_type == vtn_value_type_constant) { 1817b8e80941Smrg for (unsigned i = 0; i < len1; i++) 1818b8e80941Smrg u64[len0 + i] = v1->constant->values[0][i].u64; 1819b8e80941Smrg } 1820b8e80941Smrg 1821b8e80941Smrg for (unsigned i = 0, j = 0; i < count - 6; i++, j++) { 1822b8e80941Smrg uint32_t comp = w[i + 6]; 1823b8e80941Smrg /* If component is not used, set the value to a known constant 1824b8e80941Smrg * to detect if it is wrongly used. 1825b8e80941Smrg */ 1826b8e80941Smrg if (comp == (uint32_t)-1) 1827b8e80941Smrg val->constant->values[0][j].u64 = 0xdeadbeefdeadbeef; 1828b8e80941Smrg else 1829b8e80941Smrg val->constant->values[0][j].u64 = u64[comp]; 1830b8e80941Smrg } 1831b8e80941Smrg } else { 1832b8e80941Smrg /* This is for both 32-bit and 16-bit values */ 1833b8e80941Smrg uint32_t u32[8]; 1834b8e80941Smrg if (v0->value_type == vtn_value_type_constant) { 1835b8e80941Smrg for (unsigned i = 0; i < len0; i++) 1836b8e80941Smrg u32[i] = v0->constant->values[0][i].u32; 1837b8e80941Smrg } 1838b8e80941Smrg if (v1->value_type == vtn_value_type_constant) { 1839b8e80941Smrg for (unsigned i = 0; i < len1; i++) 1840b8e80941Smrg u32[len0 + i] = v1->constant->values[0][i].u32; 1841b8e80941Smrg } 1842b8e80941Smrg 1843b8e80941Smrg for (unsigned i = 0, j = 0; i < count - 6; i++, j++) { 1844b8e80941Smrg uint32_t comp = w[i + 6]; 1845b8e80941Smrg /* If component is not used, set the value to a known constant 1846b8e80941Smrg * to detect if it is wrongly used. 1847b8e80941Smrg */ 1848b8e80941Smrg if (comp == (uint32_t)-1) 1849b8e80941Smrg val->constant->values[0][j].u32 = 0xdeadbeef; 1850b8e80941Smrg else 1851b8e80941Smrg val->constant->values[0][j].u32 = u32[comp]; 1852b8e80941Smrg } 1853b8e80941Smrg } 1854b8e80941Smrg break; 1855b8e80941Smrg } 1856b8e80941Smrg 1857b8e80941Smrg case SpvOpCompositeExtract: 1858b8e80941Smrg case SpvOpCompositeInsert: { 1859b8e80941Smrg struct vtn_value *comp; 1860b8e80941Smrg unsigned deref_start; 1861b8e80941Smrg struct nir_constant **c; 1862b8e80941Smrg if (opcode == SpvOpCompositeExtract) { 1863b8e80941Smrg comp = vtn_value(b, w[4], vtn_value_type_constant); 1864b8e80941Smrg deref_start = 5; 1865b8e80941Smrg c = &comp->constant; 1866b8e80941Smrg } else { 1867b8e80941Smrg comp = vtn_value(b, w[5], vtn_value_type_constant); 1868b8e80941Smrg deref_start = 6; 1869b8e80941Smrg val->constant = nir_constant_clone(comp->constant, 1870b8e80941Smrg (nir_variable *)b); 1871b8e80941Smrg c = &val->constant; 1872b8e80941Smrg } 1873b8e80941Smrg 1874b8e80941Smrg int elem = -1; 1875b8e80941Smrg int col = 0; 1876b8e80941Smrg const struct vtn_type *type = comp->type; 1877b8e80941Smrg for (unsigned i = deref_start; i < count; i++) { 1878b8e80941Smrg vtn_fail_if(w[i] > type->length, 1879b8e80941Smrg "%uth index of %s is %u but the type has only " 1880b8e80941Smrg "%u elements", i - deref_start, 1881b8e80941Smrg spirv_op_to_string(opcode), w[i], type->length); 1882b8e80941Smrg 1883b8e80941Smrg switch (type->base_type) { 1884b8e80941Smrg case vtn_base_type_vector: 1885b8e80941Smrg elem = w[i]; 1886b8e80941Smrg type = type->array_element; 1887b8e80941Smrg break; 1888b8e80941Smrg 1889b8e80941Smrg case vtn_base_type_matrix: 1890b8e80941Smrg assert(col == 0 && elem == -1); 1891b8e80941Smrg col = w[i]; 1892b8e80941Smrg elem = 0; 1893b8e80941Smrg type = type->array_element; 1894b8e80941Smrg break; 1895b8e80941Smrg 1896b8e80941Smrg case vtn_base_type_array: 1897b8e80941Smrg c = &(*c)->elements[w[i]]; 1898b8e80941Smrg type = type->array_element; 1899b8e80941Smrg break; 1900b8e80941Smrg 1901b8e80941Smrg case vtn_base_type_struct: 1902b8e80941Smrg c = &(*c)->elements[w[i]]; 1903b8e80941Smrg type = type->members[w[i]]; 1904b8e80941Smrg break; 1905b8e80941Smrg 1906b8e80941Smrg default: 1907b8e80941Smrg vtn_fail("%s must only index into composite types", 1908b8e80941Smrg spirv_op_to_string(opcode)); 1909b8e80941Smrg } 1910b8e80941Smrg } 1911b8e80941Smrg 1912b8e80941Smrg if (opcode == SpvOpCompositeExtract) { 1913b8e80941Smrg if (elem == -1) { 1914b8e80941Smrg val->constant = *c; 1915b8e80941Smrg } else { 1916b8e80941Smrg unsigned num_components = type->length; 1917b8e80941Smrg for (unsigned i = 0; i < num_components; i++) 1918b8e80941Smrg val->constant->values[0][i] = (*c)->values[col][elem + i]; 1919b8e80941Smrg } 1920b8e80941Smrg } else { 1921b8e80941Smrg struct vtn_value *insert = 1922b8e80941Smrg vtn_value(b, w[4], vtn_value_type_constant); 1923b8e80941Smrg vtn_assert(insert->type == type); 1924b8e80941Smrg if (elem == -1) { 1925b8e80941Smrg *c = insert->constant; 1926b8e80941Smrg } else { 1927b8e80941Smrg unsigned num_components = type->length; 1928b8e80941Smrg for (unsigned i = 0; i < num_components; i++) 1929b8e80941Smrg (*c)->values[col][elem + i] = insert->constant->values[0][i]; 1930b8e80941Smrg } 1931b8e80941Smrg } 1932b8e80941Smrg break; 1933b8e80941Smrg } 1934b8e80941Smrg 1935b8e80941Smrg default: { 1936b8e80941Smrg bool swap; 1937b8e80941Smrg nir_alu_type dst_alu_type = nir_get_nir_type_for_glsl_type(val->type->type); 1938b8e80941Smrg nir_alu_type src_alu_type = dst_alu_type; 1939b8e80941Smrg unsigned num_components = glsl_get_vector_elements(val->type->type); 1940b8e80941Smrg unsigned bit_size; 1941b8e80941Smrg 1942b8e80941Smrg vtn_assert(count <= 7); 1943b8e80941Smrg 1944b8e80941Smrg switch (opcode) { 1945b8e80941Smrg case SpvOpSConvert: 1946b8e80941Smrg case SpvOpFConvert: 1947b8e80941Smrg /* We have a source in a conversion */ 1948b8e80941Smrg src_alu_type = 1949b8e80941Smrg nir_get_nir_type_for_glsl_type( 1950b8e80941Smrg vtn_value(b, w[4], vtn_value_type_constant)->type->type); 1951b8e80941Smrg /* We use the bitsize of the conversion source to evaluate the opcode later */ 1952b8e80941Smrg bit_size = glsl_get_bit_size( 1953b8e80941Smrg vtn_value(b, w[4], vtn_value_type_constant)->type->type); 1954b8e80941Smrg break; 1955b8e80941Smrg default: 1956b8e80941Smrg bit_size = glsl_get_bit_size(val->type->type); 1957b8e80941Smrg }; 1958b8e80941Smrg 1959b8e80941Smrg nir_op op = vtn_nir_alu_op_for_spirv_opcode(b, opcode, &swap, 1960b8e80941Smrg nir_alu_type_get_type_size(src_alu_type), 1961b8e80941Smrg nir_alu_type_get_type_size(dst_alu_type)); 1962b8e80941Smrg nir_const_value src[3][NIR_MAX_VEC_COMPONENTS]; 1963b8e80941Smrg 1964b8e80941Smrg for (unsigned i = 0; i < count - 4; i++) { 1965b8e80941Smrg struct vtn_value *src_val = 1966b8e80941Smrg vtn_value(b, w[4 + i], vtn_value_type_constant); 1967b8e80941Smrg 1968b8e80941Smrg /* If this is an unsized source, pull the bit size from the 1969b8e80941Smrg * source; otherwise, we'll use the bit size from the destination. 1970b8e80941Smrg */ 1971b8e80941Smrg if (!nir_alu_type_get_type_size(nir_op_infos[op].input_types[i])) 1972b8e80941Smrg bit_size = glsl_get_bit_size(src_val->type->type); 1973b8e80941Smrg 1974b8e80941Smrg unsigned j = swap ? 1 - i : i; 1975b8e80941Smrg memcpy(src[j], src_val->constant->values[0], sizeof(src[j])); 1976b8e80941Smrg } 1977b8e80941Smrg 1978b8e80941Smrg /* fix up fixed size sources */ 1979b8e80941Smrg switch (op) { 1980b8e80941Smrg case nir_op_ishl: 1981b8e80941Smrg case nir_op_ishr: 1982b8e80941Smrg case nir_op_ushr: { 1983b8e80941Smrg if (bit_size == 32) 1984b8e80941Smrg break; 1985b8e80941Smrg for (unsigned i = 0; i < num_components; ++i) { 1986b8e80941Smrg switch (bit_size) { 1987b8e80941Smrg case 64: src[1][i].u32 = src[1][i].u64; break; 1988b8e80941Smrg case 16: src[1][i].u32 = src[1][i].u16; break; 1989b8e80941Smrg case 8: src[1][i].u32 = src[1][i].u8; break; 1990b8e80941Smrg } 1991b8e80941Smrg } 1992b8e80941Smrg break; 1993b8e80941Smrg } 1994b8e80941Smrg default: 1995b8e80941Smrg break; 1996b8e80941Smrg } 1997b8e80941Smrg 1998b8e80941Smrg nir_const_value *srcs[3] = { 1999b8e80941Smrg src[0], src[1], src[2], 2000b8e80941Smrg }; 2001b8e80941Smrg nir_eval_const_opcode(op, val->constant->values[0], num_components, bit_size, srcs); 2002b8e80941Smrg break; 2003b8e80941Smrg } /* default */ 2004b8e80941Smrg } 2005b8e80941Smrg break; 2006b8e80941Smrg } 2007b8e80941Smrg 2008b8e80941Smrg case SpvOpConstantNull: 2009b8e80941Smrg val->constant = vtn_null_constant(b, val->type->type); 2010b8e80941Smrg break; 2011b8e80941Smrg 2012b8e80941Smrg case SpvOpConstantSampler: 2013b8e80941Smrg vtn_fail("OpConstantSampler requires Kernel Capability"); 2014b8e80941Smrg break; 2015b8e80941Smrg 2016b8e80941Smrg default: 2017b8e80941Smrg vtn_fail_with_opcode("Unhandled opcode", opcode); 2018b8e80941Smrg } 2019b8e80941Smrg 2020b8e80941Smrg /* Now that we have the value, update the workgroup size if needed */ 2021b8e80941Smrg vtn_foreach_decoration(b, val, handle_workgroup_size_decoration_cb, NULL); 2022b8e80941Smrg} 2023b8e80941Smrg 2024b8e80941Smrgstruct vtn_ssa_value * 2025b8e80941Smrgvtn_create_ssa_value(struct vtn_builder *b, const struct glsl_type *type) 2026b8e80941Smrg{ 2027b8e80941Smrg struct vtn_ssa_value *val = rzalloc(b, struct vtn_ssa_value); 2028b8e80941Smrg val->type = type; 2029b8e80941Smrg 2030b8e80941Smrg if (!glsl_type_is_vector_or_scalar(type)) { 2031b8e80941Smrg unsigned elems = glsl_get_length(type); 2032b8e80941Smrg val->elems = ralloc_array(b, struct vtn_ssa_value *, elems); 2033b8e80941Smrg for (unsigned i = 0; i < elems; i++) { 2034b8e80941Smrg const struct glsl_type *child_type; 2035b8e80941Smrg 2036b8e80941Smrg switch (glsl_get_base_type(type)) { 2037b8e80941Smrg case GLSL_TYPE_INT: 2038b8e80941Smrg case GLSL_TYPE_UINT: 2039b8e80941Smrg case GLSL_TYPE_INT16: 2040b8e80941Smrg case GLSL_TYPE_UINT16: 2041b8e80941Smrg case GLSL_TYPE_UINT8: 2042b8e80941Smrg case GLSL_TYPE_INT8: 2043b8e80941Smrg case GLSL_TYPE_INT64: 2044b8e80941Smrg case GLSL_TYPE_UINT64: 2045b8e80941Smrg case GLSL_TYPE_BOOL: 2046b8e80941Smrg case GLSL_TYPE_FLOAT: 2047b8e80941Smrg case GLSL_TYPE_FLOAT16: 2048b8e80941Smrg case GLSL_TYPE_DOUBLE: 2049b8e80941Smrg child_type = glsl_get_column_type(type); 2050b8e80941Smrg break; 2051b8e80941Smrg case GLSL_TYPE_ARRAY: 2052b8e80941Smrg child_type = glsl_get_array_element(type); 2053b8e80941Smrg break; 2054b8e80941Smrg case GLSL_TYPE_STRUCT: 2055b8e80941Smrg case GLSL_TYPE_INTERFACE: 2056b8e80941Smrg child_type = glsl_get_struct_field(type, i); 2057b8e80941Smrg break; 2058b8e80941Smrg default: 2059b8e80941Smrg vtn_fail("unkown base type"); 2060b8e80941Smrg } 2061b8e80941Smrg 2062b8e80941Smrg val->elems[i] = vtn_create_ssa_value(b, child_type); 2063b8e80941Smrg } 2064b8e80941Smrg } 2065b8e80941Smrg 2066b8e80941Smrg return val; 2067b8e80941Smrg} 2068b8e80941Smrg 2069b8e80941Smrgstatic nir_tex_src 2070b8e80941Smrgvtn_tex_src(struct vtn_builder *b, unsigned index, nir_tex_src_type type) 2071b8e80941Smrg{ 2072b8e80941Smrg nir_tex_src src; 2073b8e80941Smrg src.src = nir_src_for_ssa(vtn_ssa_value(b, index)->def); 2074b8e80941Smrg src.src_type = type; 2075b8e80941Smrg return src; 2076b8e80941Smrg} 2077b8e80941Smrg 2078b8e80941Smrgstatic void 2079b8e80941Smrgvtn_handle_texture(struct vtn_builder *b, SpvOp opcode, 2080b8e80941Smrg const uint32_t *w, unsigned count) 2081b8e80941Smrg{ 2082b8e80941Smrg if (opcode == SpvOpSampledImage) { 2083b8e80941Smrg struct vtn_value *val = 2084b8e80941Smrg vtn_push_value(b, w[2], vtn_value_type_sampled_image); 2085b8e80941Smrg val->sampled_image = ralloc(b, struct vtn_sampled_image); 2086b8e80941Smrg val->sampled_image->type = 2087b8e80941Smrg vtn_value(b, w[1], vtn_value_type_type)->type; 2088b8e80941Smrg val->sampled_image->image = 2089b8e80941Smrg vtn_value(b, w[3], vtn_value_type_pointer)->pointer; 2090b8e80941Smrg val->sampled_image->sampler = 2091b8e80941Smrg vtn_value(b, w[4], vtn_value_type_pointer)->pointer; 2092b8e80941Smrg return; 2093b8e80941Smrg } else if (opcode == SpvOpImage) { 2094b8e80941Smrg struct vtn_value *src_val = vtn_untyped_value(b, w[3]); 2095b8e80941Smrg if (src_val->value_type == vtn_value_type_sampled_image) { 2096b8e80941Smrg vtn_push_value_pointer(b, w[2], src_val->sampled_image->image); 2097b8e80941Smrg } else { 2098b8e80941Smrg vtn_assert(src_val->value_type == vtn_value_type_pointer); 2099b8e80941Smrg vtn_push_value_pointer(b, w[2], src_val->pointer); 2100b8e80941Smrg } 2101b8e80941Smrg return; 2102b8e80941Smrg } 2103b8e80941Smrg 2104b8e80941Smrg struct vtn_type *ret_type = vtn_value(b, w[1], vtn_value_type_type)->type; 2105b8e80941Smrg 2106b8e80941Smrg struct vtn_sampled_image sampled; 2107b8e80941Smrg struct vtn_value *sampled_val = vtn_untyped_value(b, w[3]); 2108b8e80941Smrg if (sampled_val->value_type == vtn_value_type_sampled_image) { 2109b8e80941Smrg sampled = *sampled_val->sampled_image; 2110b8e80941Smrg } else { 2111b8e80941Smrg vtn_assert(sampled_val->value_type == vtn_value_type_pointer); 2112b8e80941Smrg sampled.type = sampled_val->pointer->type; 2113b8e80941Smrg sampled.image = NULL; 2114b8e80941Smrg sampled.sampler = sampled_val->pointer; 2115b8e80941Smrg } 2116b8e80941Smrg 2117b8e80941Smrg const struct glsl_type *image_type = sampled.type->type; 2118b8e80941Smrg const enum glsl_sampler_dim sampler_dim = glsl_get_sampler_dim(image_type); 2119b8e80941Smrg const bool is_array = glsl_sampler_type_is_array(image_type); 2120b8e80941Smrg 2121b8e80941Smrg /* Figure out the base texture operation */ 2122b8e80941Smrg nir_texop texop; 2123b8e80941Smrg switch (opcode) { 2124b8e80941Smrg case SpvOpImageSampleImplicitLod: 2125b8e80941Smrg case SpvOpImageSampleDrefImplicitLod: 2126b8e80941Smrg case SpvOpImageSampleProjImplicitLod: 2127b8e80941Smrg case SpvOpImageSampleProjDrefImplicitLod: 2128b8e80941Smrg texop = nir_texop_tex; 2129b8e80941Smrg break; 2130b8e80941Smrg 2131b8e80941Smrg case SpvOpImageSampleExplicitLod: 2132b8e80941Smrg case SpvOpImageSampleDrefExplicitLod: 2133b8e80941Smrg case SpvOpImageSampleProjExplicitLod: 2134b8e80941Smrg case SpvOpImageSampleProjDrefExplicitLod: 2135b8e80941Smrg texop = nir_texop_txl; 2136b8e80941Smrg break; 2137b8e80941Smrg 2138b8e80941Smrg case SpvOpImageFetch: 2139b8e80941Smrg if (glsl_get_sampler_dim(image_type) == GLSL_SAMPLER_DIM_MS) { 2140b8e80941Smrg texop = nir_texop_txf_ms; 2141b8e80941Smrg } else { 2142b8e80941Smrg texop = nir_texop_txf; 2143b8e80941Smrg } 2144b8e80941Smrg break; 2145b8e80941Smrg 2146b8e80941Smrg case SpvOpImageGather: 2147b8e80941Smrg case SpvOpImageDrefGather: 2148b8e80941Smrg texop = nir_texop_tg4; 2149b8e80941Smrg break; 2150b8e80941Smrg 2151b8e80941Smrg case SpvOpImageQuerySizeLod: 2152b8e80941Smrg case SpvOpImageQuerySize: 2153b8e80941Smrg texop = nir_texop_txs; 2154b8e80941Smrg break; 2155b8e80941Smrg 2156b8e80941Smrg case SpvOpImageQueryLod: 2157b8e80941Smrg texop = nir_texop_lod; 2158b8e80941Smrg break; 2159b8e80941Smrg 2160b8e80941Smrg case SpvOpImageQueryLevels: 2161b8e80941Smrg texop = nir_texop_query_levels; 2162b8e80941Smrg break; 2163b8e80941Smrg 2164b8e80941Smrg case SpvOpImageQuerySamples: 2165b8e80941Smrg texop = nir_texop_texture_samples; 2166b8e80941Smrg break; 2167b8e80941Smrg 2168b8e80941Smrg default: 2169b8e80941Smrg vtn_fail_with_opcode("Unhandled opcode", opcode); 2170b8e80941Smrg } 2171b8e80941Smrg 2172b8e80941Smrg nir_tex_src srcs[10]; /* 10 should be enough */ 2173b8e80941Smrg nir_tex_src *p = srcs; 2174b8e80941Smrg 2175b8e80941Smrg nir_deref_instr *sampler = vtn_pointer_to_deref(b, sampled.sampler); 2176b8e80941Smrg nir_deref_instr *texture = 2177b8e80941Smrg sampled.image ? vtn_pointer_to_deref(b, sampled.image) : sampler; 2178b8e80941Smrg 2179b8e80941Smrg p->src = nir_src_for_ssa(&texture->dest.ssa); 2180b8e80941Smrg p->src_type = nir_tex_src_texture_deref; 2181b8e80941Smrg p++; 2182b8e80941Smrg 2183b8e80941Smrg switch (texop) { 2184b8e80941Smrg case nir_texop_tex: 2185b8e80941Smrg case nir_texop_txb: 2186b8e80941Smrg case nir_texop_txl: 2187b8e80941Smrg case nir_texop_txd: 2188b8e80941Smrg case nir_texop_tg4: 2189b8e80941Smrg case nir_texop_lod: 2190b8e80941Smrg /* These operations require a sampler */ 2191b8e80941Smrg p->src = nir_src_for_ssa(&sampler->dest.ssa); 2192b8e80941Smrg p->src_type = nir_tex_src_sampler_deref; 2193b8e80941Smrg p++; 2194b8e80941Smrg break; 2195b8e80941Smrg case nir_texop_txf: 2196b8e80941Smrg case nir_texop_txf_ms: 2197b8e80941Smrg case nir_texop_txs: 2198b8e80941Smrg case nir_texop_query_levels: 2199b8e80941Smrg case nir_texop_texture_samples: 2200b8e80941Smrg case nir_texop_samples_identical: 2201b8e80941Smrg /* These don't */ 2202b8e80941Smrg break; 2203b8e80941Smrg case nir_texop_txf_ms_fb: 2204b8e80941Smrg vtn_fail("unexpected nir_texop_txf_ms_fb"); 2205b8e80941Smrg break; 2206b8e80941Smrg case nir_texop_txf_ms_mcs: 2207b8e80941Smrg vtn_fail("unexpected nir_texop_txf_ms_mcs"); 2208b8e80941Smrg } 2209b8e80941Smrg 2210b8e80941Smrg unsigned idx = 4; 2211b8e80941Smrg 2212b8e80941Smrg struct nir_ssa_def *coord; 2213b8e80941Smrg unsigned coord_components; 2214b8e80941Smrg switch (opcode) { 2215b8e80941Smrg case SpvOpImageSampleImplicitLod: 2216b8e80941Smrg case SpvOpImageSampleExplicitLod: 2217b8e80941Smrg case SpvOpImageSampleDrefImplicitLod: 2218b8e80941Smrg case SpvOpImageSampleDrefExplicitLod: 2219b8e80941Smrg case SpvOpImageSampleProjImplicitLod: 2220b8e80941Smrg case SpvOpImageSampleProjExplicitLod: 2221b8e80941Smrg case SpvOpImageSampleProjDrefImplicitLod: 2222b8e80941Smrg case SpvOpImageSampleProjDrefExplicitLod: 2223b8e80941Smrg case SpvOpImageFetch: 2224b8e80941Smrg case SpvOpImageGather: 2225b8e80941Smrg case SpvOpImageDrefGather: 2226b8e80941Smrg case SpvOpImageQueryLod: { 2227b8e80941Smrg /* All these types have the coordinate as their first real argument */ 2228b8e80941Smrg switch (sampler_dim) { 2229b8e80941Smrg case GLSL_SAMPLER_DIM_1D: 2230b8e80941Smrg case GLSL_SAMPLER_DIM_BUF: 2231b8e80941Smrg coord_components = 1; 2232b8e80941Smrg break; 2233b8e80941Smrg case GLSL_SAMPLER_DIM_2D: 2234b8e80941Smrg case GLSL_SAMPLER_DIM_RECT: 2235b8e80941Smrg case GLSL_SAMPLER_DIM_MS: 2236b8e80941Smrg coord_components = 2; 2237b8e80941Smrg break; 2238b8e80941Smrg case GLSL_SAMPLER_DIM_3D: 2239b8e80941Smrg case GLSL_SAMPLER_DIM_CUBE: 2240b8e80941Smrg coord_components = 3; 2241b8e80941Smrg break; 2242b8e80941Smrg default: 2243b8e80941Smrg vtn_fail("Invalid sampler type"); 2244b8e80941Smrg } 2245b8e80941Smrg 2246b8e80941Smrg if (is_array && texop != nir_texop_lod) 2247b8e80941Smrg coord_components++; 2248b8e80941Smrg 2249b8e80941Smrg coord = vtn_ssa_value(b, w[idx++])->def; 2250b8e80941Smrg p->src = nir_src_for_ssa(nir_channels(&b->nb, coord, 2251b8e80941Smrg (1 << coord_components) - 1)); 2252b8e80941Smrg p->src_type = nir_tex_src_coord; 2253b8e80941Smrg p++; 2254b8e80941Smrg break; 2255b8e80941Smrg } 2256b8e80941Smrg 2257b8e80941Smrg default: 2258b8e80941Smrg coord = NULL; 2259b8e80941Smrg coord_components = 0; 2260b8e80941Smrg break; 2261b8e80941Smrg } 2262b8e80941Smrg 2263b8e80941Smrg switch (opcode) { 2264b8e80941Smrg case SpvOpImageSampleProjImplicitLod: 2265b8e80941Smrg case SpvOpImageSampleProjExplicitLod: 2266b8e80941Smrg case SpvOpImageSampleProjDrefImplicitLod: 2267b8e80941Smrg case SpvOpImageSampleProjDrefExplicitLod: 2268b8e80941Smrg /* These have the projector as the last coordinate component */ 2269b8e80941Smrg p->src = nir_src_for_ssa(nir_channel(&b->nb, coord, coord_components)); 2270b8e80941Smrg p->src_type = nir_tex_src_projector; 2271b8e80941Smrg p++; 2272b8e80941Smrg break; 2273b8e80941Smrg 2274b8e80941Smrg default: 2275b8e80941Smrg break; 2276b8e80941Smrg } 2277b8e80941Smrg 2278b8e80941Smrg bool is_shadow = false; 2279b8e80941Smrg unsigned gather_component = 0; 2280b8e80941Smrg switch (opcode) { 2281b8e80941Smrg case SpvOpImageSampleDrefImplicitLod: 2282b8e80941Smrg case SpvOpImageSampleDrefExplicitLod: 2283b8e80941Smrg case SpvOpImageSampleProjDrefImplicitLod: 2284b8e80941Smrg case SpvOpImageSampleProjDrefExplicitLod: 2285b8e80941Smrg case SpvOpImageDrefGather: 2286b8e80941Smrg /* These all have an explicit depth value as their next source */ 2287b8e80941Smrg is_shadow = true; 2288b8e80941Smrg (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_comparator); 2289b8e80941Smrg break; 2290b8e80941Smrg 2291b8e80941Smrg case SpvOpImageGather: 2292b8e80941Smrg /* This has a component as its next source */ 2293b8e80941Smrg gather_component = 2294b8e80941Smrg vtn_value(b, w[idx++], vtn_value_type_constant)->constant->values[0][0].u32; 2295b8e80941Smrg break; 2296b8e80941Smrg 2297b8e80941Smrg default: 2298b8e80941Smrg break; 2299b8e80941Smrg } 2300b8e80941Smrg 2301b8e80941Smrg /* For OpImageQuerySizeLod, we always have an LOD */ 2302b8e80941Smrg if (opcode == SpvOpImageQuerySizeLod) 2303b8e80941Smrg (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_lod); 2304b8e80941Smrg 2305b8e80941Smrg /* Now we need to handle some number of optional arguments */ 2306b8e80941Smrg struct vtn_value *gather_offsets = NULL; 2307b8e80941Smrg if (idx < count) { 2308b8e80941Smrg uint32_t operands = w[idx++]; 2309b8e80941Smrg 2310b8e80941Smrg if (operands & SpvImageOperandsBiasMask) { 2311b8e80941Smrg vtn_assert(texop == nir_texop_tex); 2312b8e80941Smrg texop = nir_texop_txb; 2313b8e80941Smrg (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_bias); 2314b8e80941Smrg } 2315b8e80941Smrg 2316b8e80941Smrg if (operands & SpvImageOperandsLodMask) { 2317b8e80941Smrg vtn_assert(texop == nir_texop_txl || texop == nir_texop_txf || 2318b8e80941Smrg texop == nir_texop_txs); 2319b8e80941Smrg (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_lod); 2320b8e80941Smrg } 2321b8e80941Smrg 2322b8e80941Smrg if (operands & SpvImageOperandsGradMask) { 2323b8e80941Smrg vtn_assert(texop == nir_texop_txl); 2324b8e80941Smrg texop = nir_texop_txd; 2325b8e80941Smrg (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ddx); 2326b8e80941Smrg (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ddy); 2327b8e80941Smrg } 2328b8e80941Smrg 2329b8e80941Smrg if (operands & SpvImageOperandsOffsetMask || 2330b8e80941Smrg operands & SpvImageOperandsConstOffsetMask) 2331b8e80941Smrg (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_offset); 2332b8e80941Smrg 2333b8e80941Smrg if (operands & SpvImageOperandsConstOffsetsMask) { 2334b8e80941Smrg vtn_assert(texop == nir_texop_tg4); 2335b8e80941Smrg gather_offsets = vtn_value(b, w[idx++], vtn_value_type_constant); 2336b8e80941Smrg } 2337b8e80941Smrg 2338b8e80941Smrg if (operands & SpvImageOperandsSampleMask) { 2339b8e80941Smrg vtn_assert(texop == nir_texop_txf_ms); 2340b8e80941Smrg texop = nir_texop_txf_ms; 2341b8e80941Smrg (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_ms_index); 2342b8e80941Smrg } 2343b8e80941Smrg 2344b8e80941Smrg if (operands & SpvImageOperandsMinLodMask) { 2345b8e80941Smrg vtn_assert(texop == nir_texop_tex || 2346b8e80941Smrg texop == nir_texop_txb || 2347b8e80941Smrg texop == nir_texop_txd); 2348b8e80941Smrg (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_min_lod); 2349b8e80941Smrg } 2350b8e80941Smrg } 2351b8e80941Smrg /* We should have now consumed exactly all of the arguments */ 2352b8e80941Smrg vtn_assert(idx == count); 2353b8e80941Smrg 2354b8e80941Smrg nir_tex_instr *instr = nir_tex_instr_create(b->shader, p - srcs); 2355b8e80941Smrg instr->op = texop; 2356b8e80941Smrg 2357b8e80941Smrg memcpy(instr->src, srcs, instr->num_srcs * sizeof(*instr->src)); 2358b8e80941Smrg 2359b8e80941Smrg instr->coord_components = coord_components; 2360b8e80941Smrg instr->sampler_dim = sampler_dim; 2361b8e80941Smrg instr->is_array = is_array; 2362b8e80941Smrg instr->is_shadow = is_shadow; 2363b8e80941Smrg instr->is_new_style_shadow = 2364b8e80941Smrg is_shadow && glsl_get_components(ret_type->type) == 1; 2365b8e80941Smrg instr->component = gather_component; 2366b8e80941Smrg 2367b8e80941Smrg if (sampled.image && (sampled.image->access & ACCESS_NON_UNIFORM)) 2368b8e80941Smrg instr->texture_non_uniform = true; 2369b8e80941Smrg 2370b8e80941Smrg if (sampled.sampler && (sampled.sampler->access & ACCESS_NON_UNIFORM)) 2371b8e80941Smrg instr->sampler_non_uniform = true; 2372b8e80941Smrg 2373b8e80941Smrg switch (glsl_get_sampler_result_type(image_type)) { 2374b8e80941Smrg case GLSL_TYPE_FLOAT: instr->dest_type = nir_type_float; break; 2375b8e80941Smrg case GLSL_TYPE_INT: instr->dest_type = nir_type_int; break; 2376b8e80941Smrg case GLSL_TYPE_UINT: instr->dest_type = nir_type_uint; break; 2377b8e80941Smrg case GLSL_TYPE_BOOL: instr->dest_type = nir_type_bool; break; 2378b8e80941Smrg default: 2379b8e80941Smrg vtn_fail("Invalid base type for sampler result"); 2380b8e80941Smrg } 2381b8e80941Smrg 2382b8e80941Smrg nir_ssa_dest_init(&instr->instr, &instr->dest, 2383b8e80941Smrg nir_tex_instr_dest_size(instr), 32, NULL); 2384b8e80941Smrg 2385b8e80941Smrg vtn_assert(glsl_get_vector_elements(ret_type->type) == 2386b8e80941Smrg nir_tex_instr_dest_size(instr)); 2387b8e80941Smrg 2388b8e80941Smrg if (gather_offsets) { 2389b8e80941Smrg vtn_fail_if(gather_offsets->type->base_type != vtn_base_type_array || 2390b8e80941Smrg gather_offsets->type->length != 4, 2391b8e80941Smrg "ConstOffsets must be an array of size four of vectors " 2392b8e80941Smrg "of two integer components"); 2393b8e80941Smrg 2394b8e80941Smrg struct vtn_type *vec_type = gather_offsets->type->array_element; 2395b8e80941Smrg vtn_fail_if(vec_type->base_type != vtn_base_type_vector || 2396b8e80941Smrg vec_type->length != 2 || 2397b8e80941Smrg !glsl_type_is_integer(vec_type->type), 2398b8e80941Smrg "ConstOffsets must be an array of size four of vectors " 2399b8e80941Smrg "of two integer components"); 2400b8e80941Smrg 2401b8e80941Smrg unsigned bit_size = glsl_get_bit_size(vec_type->type); 2402b8e80941Smrg for (uint32_t i = 0; i < 4; i++) { 2403b8e80941Smrg const nir_const_value *cvec = 2404b8e80941Smrg gather_offsets->constant->elements[i]->values[0]; 2405b8e80941Smrg for (uint32_t j = 0; j < 2; j++) { 2406b8e80941Smrg switch (bit_size) { 2407b8e80941Smrg case 8: instr->tg4_offsets[i][j] = cvec[j].i8; break; 2408b8e80941Smrg case 16: instr->tg4_offsets[i][j] = cvec[j].i16; break; 2409b8e80941Smrg case 32: instr->tg4_offsets[i][j] = cvec[j].i32; break; 2410b8e80941Smrg case 64: instr->tg4_offsets[i][j] = cvec[j].i64; break; 2411b8e80941Smrg default: 2412b8e80941Smrg vtn_fail("Unsupported bit size: %u", bit_size); 2413b8e80941Smrg } 2414b8e80941Smrg } 2415b8e80941Smrg } 2416b8e80941Smrg } 2417b8e80941Smrg 2418b8e80941Smrg struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, ret_type->type); 2419b8e80941Smrg ssa->def = &instr->dest.ssa; 2420b8e80941Smrg vtn_push_ssa(b, w[2], ret_type, ssa); 2421b8e80941Smrg 2422b8e80941Smrg nir_builder_instr_insert(&b->nb, &instr->instr); 2423b8e80941Smrg} 2424b8e80941Smrg 2425b8e80941Smrgstatic void 2426b8e80941Smrgfill_common_atomic_sources(struct vtn_builder *b, SpvOp opcode, 2427b8e80941Smrg const uint32_t *w, nir_src *src) 2428b8e80941Smrg{ 2429b8e80941Smrg switch (opcode) { 2430b8e80941Smrg case SpvOpAtomicIIncrement: 2431b8e80941Smrg src[0] = nir_src_for_ssa(nir_imm_int(&b->nb, 1)); 2432b8e80941Smrg break; 2433b8e80941Smrg 2434b8e80941Smrg case SpvOpAtomicIDecrement: 2435b8e80941Smrg src[0] = nir_src_for_ssa(nir_imm_int(&b->nb, -1)); 2436b8e80941Smrg break; 2437b8e80941Smrg 2438b8e80941Smrg case SpvOpAtomicISub: 2439b8e80941Smrg src[0] = 2440b8e80941Smrg nir_src_for_ssa(nir_ineg(&b->nb, vtn_ssa_value(b, w[6])->def)); 2441b8e80941Smrg break; 2442b8e80941Smrg 2443b8e80941Smrg case SpvOpAtomicCompareExchange: 2444b8e80941Smrg case SpvOpAtomicCompareExchangeWeak: 2445b8e80941Smrg src[0] = nir_src_for_ssa(vtn_ssa_value(b, w[8])->def); 2446b8e80941Smrg src[1] = nir_src_for_ssa(vtn_ssa_value(b, w[7])->def); 2447b8e80941Smrg break; 2448b8e80941Smrg 2449b8e80941Smrg case SpvOpAtomicExchange: 2450b8e80941Smrg case SpvOpAtomicIAdd: 2451b8e80941Smrg case SpvOpAtomicSMin: 2452b8e80941Smrg case SpvOpAtomicUMin: 2453b8e80941Smrg case SpvOpAtomicSMax: 2454b8e80941Smrg case SpvOpAtomicUMax: 2455b8e80941Smrg case SpvOpAtomicAnd: 2456b8e80941Smrg case SpvOpAtomicOr: 2457b8e80941Smrg case SpvOpAtomicXor: 2458b8e80941Smrg src[0] = nir_src_for_ssa(vtn_ssa_value(b, w[6])->def); 2459b8e80941Smrg break; 2460b8e80941Smrg 2461b8e80941Smrg default: 2462b8e80941Smrg vtn_fail_with_opcode("Invalid SPIR-V atomic", opcode); 2463b8e80941Smrg } 2464b8e80941Smrg} 2465b8e80941Smrg 2466b8e80941Smrgstatic nir_ssa_def * 2467b8e80941Smrgget_image_coord(struct vtn_builder *b, uint32_t value) 2468b8e80941Smrg{ 2469b8e80941Smrg struct vtn_ssa_value *coord = vtn_ssa_value(b, value); 2470b8e80941Smrg 2471b8e80941Smrg /* The image_load_store intrinsics assume a 4-dim coordinate */ 2472b8e80941Smrg unsigned dim = glsl_get_vector_elements(coord->type); 2473b8e80941Smrg unsigned swizzle[4]; 2474b8e80941Smrg for (unsigned i = 0; i < 4; i++) 2475b8e80941Smrg swizzle[i] = MIN2(i, dim - 1); 2476b8e80941Smrg 2477b8e80941Smrg return nir_swizzle(&b->nb, coord->def, swizzle, 4, false); 2478b8e80941Smrg} 2479b8e80941Smrg 2480b8e80941Smrgstatic nir_ssa_def * 2481b8e80941Smrgexpand_to_vec4(nir_builder *b, nir_ssa_def *value) 2482b8e80941Smrg{ 2483b8e80941Smrg if (value->num_components == 4) 2484b8e80941Smrg return value; 2485b8e80941Smrg 2486b8e80941Smrg unsigned swiz[4]; 2487b8e80941Smrg for (unsigned i = 0; i < 4; i++) 2488b8e80941Smrg swiz[i] = i < value->num_components ? i : 0; 2489b8e80941Smrg return nir_swizzle(b, value, swiz, 4, false); 2490b8e80941Smrg} 2491b8e80941Smrg 2492b8e80941Smrgstatic void 2493b8e80941Smrgvtn_handle_image(struct vtn_builder *b, SpvOp opcode, 2494b8e80941Smrg const uint32_t *w, unsigned count) 2495b8e80941Smrg{ 2496b8e80941Smrg /* Just get this one out of the way */ 2497b8e80941Smrg if (opcode == SpvOpImageTexelPointer) { 2498b8e80941Smrg struct vtn_value *val = 2499b8e80941Smrg vtn_push_value(b, w[2], vtn_value_type_image_pointer); 2500b8e80941Smrg val->image = ralloc(b, struct vtn_image_pointer); 2501b8e80941Smrg 2502b8e80941Smrg val->image->image = vtn_value(b, w[3], vtn_value_type_pointer)->pointer; 2503b8e80941Smrg val->image->coord = get_image_coord(b, w[4]); 2504b8e80941Smrg val->image->sample = vtn_ssa_value(b, w[5])->def; 2505b8e80941Smrg return; 2506b8e80941Smrg } 2507b8e80941Smrg 2508b8e80941Smrg struct vtn_image_pointer image; 2509b8e80941Smrg 2510b8e80941Smrg switch (opcode) { 2511b8e80941Smrg case SpvOpAtomicExchange: 2512b8e80941Smrg case SpvOpAtomicCompareExchange: 2513b8e80941Smrg case SpvOpAtomicCompareExchangeWeak: 2514b8e80941Smrg case SpvOpAtomicIIncrement: 2515b8e80941Smrg case SpvOpAtomicIDecrement: 2516b8e80941Smrg case SpvOpAtomicIAdd: 2517b8e80941Smrg case SpvOpAtomicISub: 2518b8e80941Smrg case SpvOpAtomicLoad: 2519b8e80941Smrg case SpvOpAtomicSMin: 2520b8e80941Smrg case SpvOpAtomicUMin: 2521b8e80941Smrg case SpvOpAtomicSMax: 2522b8e80941Smrg case SpvOpAtomicUMax: 2523b8e80941Smrg case SpvOpAtomicAnd: 2524b8e80941Smrg case SpvOpAtomicOr: 2525b8e80941Smrg case SpvOpAtomicXor: 2526b8e80941Smrg image = *vtn_value(b, w[3], vtn_value_type_image_pointer)->image; 2527b8e80941Smrg break; 2528b8e80941Smrg 2529b8e80941Smrg case SpvOpAtomicStore: 2530b8e80941Smrg image = *vtn_value(b, w[1], vtn_value_type_image_pointer)->image; 2531b8e80941Smrg break; 2532b8e80941Smrg 2533b8e80941Smrg case SpvOpImageQuerySize: 2534b8e80941Smrg image.image = vtn_value(b, w[3], vtn_value_type_pointer)->pointer; 2535b8e80941Smrg image.coord = NULL; 2536b8e80941Smrg image.sample = NULL; 2537b8e80941Smrg break; 2538b8e80941Smrg 2539b8e80941Smrg case SpvOpImageRead: 2540b8e80941Smrg image.image = vtn_value(b, w[3], vtn_value_type_pointer)->pointer; 2541b8e80941Smrg image.coord = get_image_coord(b, w[4]); 2542b8e80941Smrg 2543b8e80941Smrg if (count > 5 && (w[5] & SpvImageOperandsSampleMask)) { 2544b8e80941Smrg vtn_assert(w[5] == SpvImageOperandsSampleMask); 2545b8e80941Smrg image.sample = vtn_ssa_value(b, w[6])->def; 2546b8e80941Smrg } else { 2547b8e80941Smrg image.sample = nir_ssa_undef(&b->nb, 1, 32); 2548b8e80941Smrg } 2549b8e80941Smrg break; 2550b8e80941Smrg 2551b8e80941Smrg case SpvOpImageWrite: 2552b8e80941Smrg image.image = vtn_value(b, w[1], vtn_value_type_pointer)->pointer; 2553b8e80941Smrg image.coord = get_image_coord(b, w[2]); 2554b8e80941Smrg 2555b8e80941Smrg /* texel = w[3] */ 2556b8e80941Smrg 2557b8e80941Smrg if (count > 4 && (w[4] & SpvImageOperandsSampleMask)) { 2558b8e80941Smrg vtn_assert(w[4] == SpvImageOperandsSampleMask); 2559b8e80941Smrg image.sample = vtn_ssa_value(b, w[5])->def; 2560b8e80941Smrg } else { 2561b8e80941Smrg image.sample = nir_ssa_undef(&b->nb, 1, 32); 2562b8e80941Smrg } 2563b8e80941Smrg break; 2564b8e80941Smrg 2565b8e80941Smrg default: 2566b8e80941Smrg vtn_fail_with_opcode("Invalid image opcode", opcode); 2567b8e80941Smrg } 2568b8e80941Smrg 2569b8e80941Smrg nir_intrinsic_op op; 2570b8e80941Smrg switch (opcode) { 2571b8e80941Smrg#define OP(S, N) case SpvOp##S: op = nir_intrinsic_image_deref_##N; break; 2572b8e80941Smrg OP(ImageQuerySize, size) 2573b8e80941Smrg OP(ImageRead, load) 2574b8e80941Smrg OP(ImageWrite, store) 2575b8e80941Smrg OP(AtomicLoad, load) 2576b8e80941Smrg OP(AtomicStore, store) 2577b8e80941Smrg OP(AtomicExchange, atomic_exchange) 2578b8e80941Smrg OP(AtomicCompareExchange, atomic_comp_swap) 2579b8e80941Smrg OP(AtomicCompareExchangeWeak, atomic_comp_swap) 2580b8e80941Smrg OP(AtomicIIncrement, atomic_add) 2581b8e80941Smrg OP(AtomicIDecrement, atomic_add) 2582b8e80941Smrg OP(AtomicIAdd, atomic_add) 2583b8e80941Smrg OP(AtomicISub, atomic_add) 2584b8e80941Smrg OP(AtomicSMin, atomic_min) 2585b8e80941Smrg OP(AtomicUMin, atomic_min) 2586b8e80941Smrg OP(AtomicSMax, atomic_max) 2587b8e80941Smrg OP(AtomicUMax, atomic_max) 2588b8e80941Smrg OP(AtomicAnd, atomic_and) 2589b8e80941Smrg OP(AtomicOr, atomic_or) 2590b8e80941Smrg OP(AtomicXor, atomic_xor) 2591b8e80941Smrg#undef OP 2592b8e80941Smrg default: 2593b8e80941Smrg vtn_fail_with_opcode("Invalid image opcode", opcode); 2594b8e80941Smrg } 2595b8e80941Smrg 2596b8e80941Smrg nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op); 2597b8e80941Smrg 2598b8e80941Smrg nir_deref_instr *image_deref = vtn_pointer_to_deref(b, image.image); 2599b8e80941Smrg intrin->src[0] = nir_src_for_ssa(&image_deref->dest.ssa); 2600b8e80941Smrg 2601b8e80941Smrg /* ImageQuerySize doesn't take any extra parameters */ 2602b8e80941Smrg if (opcode != SpvOpImageQuerySize) { 2603b8e80941Smrg /* The image coordinate is always 4 components but we may not have that 2604b8e80941Smrg * many. Swizzle to compensate. 2605b8e80941Smrg */ 2606b8e80941Smrg intrin->src[1] = nir_src_for_ssa(expand_to_vec4(&b->nb, image.coord)); 2607b8e80941Smrg intrin->src[2] = nir_src_for_ssa(image.sample); 2608b8e80941Smrg } 2609b8e80941Smrg 2610b8e80941Smrg nir_intrinsic_set_access(intrin, image.image->access); 2611b8e80941Smrg 2612b8e80941Smrg switch (opcode) { 2613b8e80941Smrg case SpvOpAtomicLoad: 2614b8e80941Smrg case SpvOpImageQuerySize: 2615b8e80941Smrg case SpvOpImageRead: 2616b8e80941Smrg break; 2617b8e80941Smrg case SpvOpAtomicStore: 2618b8e80941Smrg case SpvOpImageWrite: { 2619b8e80941Smrg const uint32_t value_id = opcode == SpvOpAtomicStore ? w[4] : w[3]; 2620b8e80941Smrg nir_ssa_def *value = vtn_ssa_value(b, value_id)->def; 2621b8e80941Smrg /* nir_intrinsic_image_deref_store always takes a vec4 value */ 2622b8e80941Smrg assert(op == nir_intrinsic_image_deref_store); 2623b8e80941Smrg intrin->num_components = 4; 2624b8e80941Smrg intrin->src[3] = nir_src_for_ssa(expand_to_vec4(&b->nb, value)); 2625b8e80941Smrg break; 2626b8e80941Smrg } 2627b8e80941Smrg 2628b8e80941Smrg case SpvOpAtomicCompareExchange: 2629b8e80941Smrg case SpvOpAtomicCompareExchangeWeak: 2630b8e80941Smrg case SpvOpAtomicIIncrement: 2631b8e80941Smrg case SpvOpAtomicIDecrement: 2632b8e80941Smrg case SpvOpAtomicExchange: 2633b8e80941Smrg case SpvOpAtomicIAdd: 2634b8e80941Smrg case SpvOpAtomicISub: 2635b8e80941Smrg case SpvOpAtomicSMin: 2636b8e80941Smrg case SpvOpAtomicUMin: 2637b8e80941Smrg case SpvOpAtomicSMax: 2638b8e80941Smrg case SpvOpAtomicUMax: 2639b8e80941Smrg case SpvOpAtomicAnd: 2640b8e80941Smrg case SpvOpAtomicOr: 2641b8e80941Smrg case SpvOpAtomicXor: 2642b8e80941Smrg fill_common_atomic_sources(b, opcode, w, &intrin->src[3]); 2643b8e80941Smrg break; 2644b8e80941Smrg 2645b8e80941Smrg default: 2646b8e80941Smrg vtn_fail_with_opcode("Invalid image opcode", opcode); 2647b8e80941Smrg } 2648b8e80941Smrg 2649b8e80941Smrg if (opcode != SpvOpImageWrite && opcode != SpvOpAtomicStore) { 2650b8e80941Smrg struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type; 2651b8e80941Smrg 2652b8e80941Smrg unsigned dest_components = glsl_get_vector_elements(type->type); 2653b8e80941Smrg intrin->num_components = nir_intrinsic_infos[op].dest_components; 2654b8e80941Smrg if (intrin->num_components == 0) 2655b8e80941Smrg intrin->num_components = dest_components; 2656b8e80941Smrg 2657b8e80941Smrg nir_ssa_dest_init(&intrin->instr, &intrin->dest, 2658b8e80941Smrg intrin->num_components, 32, NULL); 2659b8e80941Smrg 2660b8e80941Smrg nir_builder_instr_insert(&b->nb, &intrin->instr); 2661b8e80941Smrg 2662b8e80941Smrg nir_ssa_def *result = &intrin->dest.ssa; 2663b8e80941Smrg if (intrin->num_components != dest_components) 2664b8e80941Smrg result = nir_channels(&b->nb, result, (1 << dest_components) - 1); 2665b8e80941Smrg 2666b8e80941Smrg struct vtn_value *val = 2667b8e80941Smrg vtn_push_ssa(b, w[2], type, vtn_create_ssa_value(b, type->type)); 2668b8e80941Smrg val->ssa->def = result; 2669b8e80941Smrg } else { 2670b8e80941Smrg nir_builder_instr_insert(&b->nb, &intrin->instr); 2671b8e80941Smrg } 2672b8e80941Smrg} 2673b8e80941Smrg 2674b8e80941Smrgstatic nir_intrinsic_op 2675b8e80941Smrgget_ssbo_nir_atomic_op(struct vtn_builder *b, SpvOp opcode) 2676b8e80941Smrg{ 2677b8e80941Smrg switch (opcode) { 2678b8e80941Smrg case SpvOpAtomicLoad: return nir_intrinsic_load_ssbo; 2679b8e80941Smrg case SpvOpAtomicStore: return nir_intrinsic_store_ssbo; 2680b8e80941Smrg#define OP(S, N) case SpvOp##S: return nir_intrinsic_ssbo_##N; 2681b8e80941Smrg OP(AtomicExchange, atomic_exchange) 2682b8e80941Smrg OP(AtomicCompareExchange, atomic_comp_swap) 2683b8e80941Smrg OP(AtomicCompareExchangeWeak, atomic_comp_swap) 2684b8e80941Smrg OP(AtomicIIncrement, atomic_add) 2685b8e80941Smrg OP(AtomicIDecrement, atomic_add) 2686b8e80941Smrg OP(AtomicIAdd, atomic_add) 2687b8e80941Smrg OP(AtomicISub, atomic_add) 2688b8e80941Smrg OP(AtomicSMin, atomic_imin) 2689b8e80941Smrg OP(AtomicUMin, atomic_umin) 2690b8e80941Smrg OP(AtomicSMax, atomic_imax) 2691b8e80941Smrg OP(AtomicUMax, atomic_umax) 2692b8e80941Smrg OP(AtomicAnd, atomic_and) 2693b8e80941Smrg OP(AtomicOr, atomic_or) 2694b8e80941Smrg OP(AtomicXor, atomic_xor) 2695b8e80941Smrg#undef OP 2696b8e80941Smrg default: 2697b8e80941Smrg vtn_fail_with_opcode("Invalid SSBO atomic", opcode); 2698b8e80941Smrg } 2699b8e80941Smrg} 2700b8e80941Smrg 2701b8e80941Smrgstatic nir_intrinsic_op 2702b8e80941Smrgget_uniform_nir_atomic_op(struct vtn_builder *b, SpvOp opcode) 2703b8e80941Smrg{ 2704b8e80941Smrg switch (opcode) { 2705b8e80941Smrg#define OP(S, N) case SpvOp##S: return nir_intrinsic_atomic_counter_ ##N; 2706b8e80941Smrg OP(AtomicLoad, read_deref) 2707b8e80941Smrg OP(AtomicExchange, exchange) 2708b8e80941Smrg OP(AtomicCompareExchange, comp_swap) 2709b8e80941Smrg OP(AtomicCompareExchangeWeak, comp_swap) 2710b8e80941Smrg OP(AtomicIIncrement, inc_deref) 2711b8e80941Smrg OP(AtomicIDecrement, post_dec_deref) 2712b8e80941Smrg OP(AtomicIAdd, add_deref) 2713b8e80941Smrg OP(AtomicISub, add_deref) 2714b8e80941Smrg OP(AtomicUMin, min_deref) 2715b8e80941Smrg OP(AtomicUMax, max_deref) 2716b8e80941Smrg OP(AtomicAnd, and_deref) 2717b8e80941Smrg OP(AtomicOr, or_deref) 2718b8e80941Smrg OP(AtomicXor, xor_deref) 2719b8e80941Smrg#undef OP 2720b8e80941Smrg default: 2721b8e80941Smrg /* We left the following out: AtomicStore, AtomicSMin and 2722b8e80941Smrg * AtomicSmax. Right now there are not nir intrinsics for them. At this 2723b8e80941Smrg * moment Atomic Counter support is needed for ARB_spirv support, so is 2724b8e80941Smrg * only need to support GLSL Atomic Counters that are uints and don't 2725b8e80941Smrg * allow direct storage. 2726b8e80941Smrg */ 2727b8e80941Smrg unreachable("Invalid uniform atomic"); 2728b8e80941Smrg } 2729b8e80941Smrg} 2730b8e80941Smrg 2731b8e80941Smrgstatic nir_intrinsic_op 2732b8e80941Smrgget_shared_nir_atomic_op(struct vtn_builder *b, SpvOp opcode) 2733b8e80941Smrg{ 2734b8e80941Smrg switch (opcode) { 2735b8e80941Smrg case SpvOpAtomicLoad: return nir_intrinsic_load_shared; 2736b8e80941Smrg case SpvOpAtomicStore: return nir_intrinsic_store_shared; 2737b8e80941Smrg#define OP(S, N) case SpvOp##S: return nir_intrinsic_shared_##N; 2738b8e80941Smrg OP(AtomicExchange, atomic_exchange) 2739b8e80941Smrg OP(AtomicCompareExchange, atomic_comp_swap) 2740b8e80941Smrg OP(AtomicCompareExchangeWeak, atomic_comp_swap) 2741b8e80941Smrg OP(AtomicIIncrement, atomic_add) 2742b8e80941Smrg OP(AtomicIDecrement, atomic_add) 2743b8e80941Smrg OP(AtomicIAdd, atomic_add) 2744b8e80941Smrg OP(AtomicISub, atomic_add) 2745b8e80941Smrg OP(AtomicSMin, atomic_imin) 2746b8e80941Smrg OP(AtomicUMin, atomic_umin) 2747b8e80941Smrg OP(AtomicSMax, atomic_imax) 2748b8e80941Smrg OP(AtomicUMax, atomic_umax) 2749b8e80941Smrg OP(AtomicAnd, atomic_and) 2750b8e80941Smrg OP(AtomicOr, atomic_or) 2751b8e80941Smrg OP(AtomicXor, atomic_xor) 2752b8e80941Smrg#undef OP 2753b8e80941Smrg default: 2754b8e80941Smrg vtn_fail_with_opcode("Invalid shared atomic", opcode); 2755b8e80941Smrg } 2756b8e80941Smrg} 2757b8e80941Smrg 2758b8e80941Smrgstatic nir_intrinsic_op 2759b8e80941Smrgget_deref_nir_atomic_op(struct vtn_builder *b, SpvOp opcode) 2760b8e80941Smrg{ 2761b8e80941Smrg switch (opcode) { 2762b8e80941Smrg case SpvOpAtomicLoad: return nir_intrinsic_load_deref; 2763b8e80941Smrg case SpvOpAtomicStore: return nir_intrinsic_store_deref; 2764b8e80941Smrg#define OP(S, N) case SpvOp##S: return nir_intrinsic_deref_##N; 2765b8e80941Smrg OP(AtomicExchange, atomic_exchange) 2766b8e80941Smrg OP(AtomicCompareExchange, atomic_comp_swap) 2767b8e80941Smrg OP(AtomicCompareExchangeWeak, atomic_comp_swap) 2768b8e80941Smrg OP(AtomicIIncrement, atomic_add) 2769b8e80941Smrg OP(AtomicIDecrement, atomic_add) 2770b8e80941Smrg OP(AtomicIAdd, atomic_add) 2771b8e80941Smrg OP(AtomicISub, atomic_add) 2772b8e80941Smrg OP(AtomicSMin, atomic_imin) 2773b8e80941Smrg OP(AtomicUMin, atomic_umin) 2774b8e80941Smrg OP(AtomicSMax, atomic_imax) 2775b8e80941Smrg OP(AtomicUMax, atomic_umax) 2776b8e80941Smrg OP(AtomicAnd, atomic_and) 2777b8e80941Smrg OP(AtomicOr, atomic_or) 2778b8e80941Smrg OP(AtomicXor, atomic_xor) 2779b8e80941Smrg#undef OP 2780b8e80941Smrg default: 2781b8e80941Smrg vtn_fail_with_opcode("Invalid shared atomic", opcode); 2782b8e80941Smrg } 2783b8e80941Smrg} 2784b8e80941Smrg 2785b8e80941Smrg/* 2786b8e80941Smrg * Handles shared atomics, ssbo atomics and atomic counters. 2787b8e80941Smrg */ 2788b8e80941Smrgstatic void 2789b8e80941Smrgvtn_handle_atomics(struct vtn_builder *b, SpvOp opcode, 2790b8e80941Smrg const uint32_t *w, unsigned count) 2791b8e80941Smrg{ 2792b8e80941Smrg struct vtn_pointer *ptr; 2793b8e80941Smrg nir_intrinsic_instr *atomic; 2794b8e80941Smrg 2795b8e80941Smrg switch (opcode) { 2796b8e80941Smrg case SpvOpAtomicLoad: 2797b8e80941Smrg case SpvOpAtomicExchange: 2798b8e80941Smrg case SpvOpAtomicCompareExchange: 2799b8e80941Smrg case SpvOpAtomicCompareExchangeWeak: 2800b8e80941Smrg case SpvOpAtomicIIncrement: 2801b8e80941Smrg case SpvOpAtomicIDecrement: 2802b8e80941Smrg case SpvOpAtomicIAdd: 2803b8e80941Smrg case SpvOpAtomicISub: 2804b8e80941Smrg case SpvOpAtomicSMin: 2805b8e80941Smrg case SpvOpAtomicUMin: 2806b8e80941Smrg case SpvOpAtomicSMax: 2807b8e80941Smrg case SpvOpAtomicUMax: 2808b8e80941Smrg case SpvOpAtomicAnd: 2809b8e80941Smrg case SpvOpAtomicOr: 2810b8e80941Smrg case SpvOpAtomicXor: 2811b8e80941Smrg ptr = vtn_value(b, w[3], vtn_value_type_pointer)->pointer; 2812b8e80941Smrg break; 2813b8e80941Smrg 2814b8e80941Smrg case SpvOpAtomicStore: 2815b8e80941Smrg ptr = vtn_value(b, w[1], vtn_value_type_pointer)->pointer; 2816b8e80941Smrg break; 2817b8e80941Smrg 2818b8e80941Smrg default: 2819b8e80941Smrg vtn_fail_with_opcode("Invalid SPIR-V atomic", opcode); 2820b8e80941Smrg } 2821b8e80941Smrg 2822b8e80941Smrg /* 2823b8e80941Smrg SpvScope scope = w[4]; 2824b8e80941Smrg SpvMemorySemanticsMask semantics = w[5]; 2825b8e80941Smrg */ 2826b8e80941Smrg 2827b8e80941Smrg /* uniform as "atomic counter uniform" */ 2828b8e80941Smrg if (ptr->mode == vtn_variable_mode_uniform) { 2829b8e80941Smrg nir_deref_instr *deref = vtn_pointer_to_deref(b, ptr); 2830b8e80941Smrg const struct glsl_type *deref_type = deref->type; 2831b8e80941Smrg nir_intrinsic_op op = get_uniform_nir_atomic_op(b, opcode); 2832b8e80941Smrg atomic = nir_intrinsic_instr_create(b->nb.shader, op); 2833b8e80941Smrg atomic->src[0] = nir_src_for_ssa(&deref->dest.ssa); 2834b8e80941Smrg 2835b8e80941Smrg /* SSBO needs to initialize index/offset. In this case we don't need to, 2836b8e80941Smrg * as that info is already stored on the ptr->var->var nir_variable (see 2837b8e80941Smrg * vtn_create_variable) 2838b8e80941Smrg */ 2839b8e80941Smrg 2840b8e80941Smrg switch (opcode) { 2841b8e80941Smrg case SpvOpAtomicLoad: 2842b8e80941Smrg atomic->num_components = glsl_get_vector_elements(deref_type); 2843b8e80941Smrg break; 2844b8e80941Smrg 2845b8e80941Smrg case SpvOpAtomicStore: 2846b8e80941Smrg atomic->num_components = glsl_get_vector_elements(deref_type); 2847b8e80941Smrg nir_intrinsic_set_write_mask(atomic, (1 << atomic->num_components) - 1); 2848b8e80941Smrg break; 2849b8e80941Smrg 2850b8e80941Smrg case SpvOpAtomicExchange: 2851b8e80941Smrg case SpvOpAtomicCompareExchange: 2852b8e80941Smrg case SpvOpAtomicCompareExchangeWeak: 2853b8e80941Smrg case SpvOpAtomicIIncrement: 2854b8e80941Smrg case SpvOpAtomicIDecrement: 2855b8e80941Smrg case SpvOpAtomicIAdd: 2856b8e80941Smrg case SpvOpAtomicISub: 2857b8e80941Smrg case SpvOpAtomicSMin: 2858b8e80941Smrg case SpvOpAtomicUMin: 2859b8e80941Smrg case SpvOpAtomicSMax: 2860b8e80941Smrg case SpvOpAtomicUMax: 2861b8e80941Smrg case SpvOpAtomicAnd: 2862b8e80941Smrg case SpvOpAtomicOr: 2863b8e80941Smrg case SpvOpAtomicXor: 2864b8e80941Smrg /* Nothing: we don't need to call fill_common_atomic_sources here, as 2865b8e80941Smrg * atomic counter uniforms doesn't have sources 2866b8e80941Smrg */ 2867b8e80941Smrg break; 2868b8e80941Smrg 2869b8e80941Smrg default: 2870b8e80941Smrg unreachable("Invalid SPIR-V atomic"); 2871b8e80941Smrg 2872b8e80941Smrg } 2873b8e80941Smrg } else if (vtn_pointer_uses_ssa_offset(b, ptr)) { 2874b8e80941Smrg nir_ssa_def *offset, *index; 2875b8e80941Smrg offset = vtn_pointer_to_offset(b, ptr, &index); 2876b8e80941Smrg 2877b8e80941Smrg nir_intrinsic_op op; 2878b8e80941Smrg if (ptr->mode == vtn_variable_mode_ssbo) { 2879b8e80941Smrg op = get_ssbo_nir_atomic_op(b, opcode); 2880b8e80941Smrg } else { 2881b8e80941Smrg vtn_assert(ptr->mode == vtn_variable_mode_workgroup && 2882b8e80941Smrg b->options->lower_workgroup_access_to_offsets); 2883b8e80941Smrg op = get_shared_nir_atomic_op(b, opcode); 2884b8e80941Smrg } 2885b8e80941Smrg 2886b8e80941Smrg atomic = nir_intrinsic_instr_create(b->nb.shader, op); 2887b8e80941Smrg 2888b8e80941Smrg int src = 0; 2889b8e80941Smrg switch (opcode) { 2890b8e80941Smrg case SpvOpAtomicLoad: 2891b8e80941Smrg atomic->num_components = glsl_get_vector_elements(ptr->type->type); 2892b8e80941Smrg nir_intrinsic_set_align(atomic, 4, 0); 2893b8e80941Smrg if (ptr->mode == vtn_variable_mode_ssbo) 2894b8e80941Smrg atomic->src[src++] = nir_src_for_ssa(index); 2895b8e80941Smrg atomic->src[src++] = nir_src_for_ssa(offset); 2896b8e80941Smrg break; 2897b8e80941Smrg 2898b8e80941Smrg case SpvOpAtomicStore: 2899b8e80941Smrg atomic->num_components = glsl_get_vector_elements(ptr->type->type); 2900b8e80941Smrg nir_intrinsic_set_write_mask(atomic, (1 << atomic->num_components) - 1); 2901b8e80941Smrg nir_intrinsic_set_align(atomic, 4, 0); 2902b8e80941Smrg atomic->src[src++] = nir_src_for_ssa(vtn_ssa_value(b, w[4])->def); 2903b8e80941Smrg if (ptr->mode == vtn_variable_mode_ssbo) 2904b8e80941Smrg atomic->src[src++] = nir_src_for_ssa(index); 2905b8e80941Smrg atomic->src[src++] = nir_src_for_ssa(offset); 2906b8e80941Smrg break; 2907b8e80941Smrg 2908b8e80941Smrg case SpvOpAtomicExchange: 2909b8e80941Smrg case SpvOpAtomicCompareExchange: 2910b8e80941Smrg case SpvOpAtomicCompareExchangeWeak: 2911b8e80941Smrg case SpvOpAtomicIIncrement: 2912b8e80941Smrg case SpvOpAtomicIDecrement: 2913b8e80941Smrg case SpvOpAtomicIAdd: 2914b8e80941Smrg case SpvOpAtomicISub: 2915b8e80941Smrg case SpvOpAtomicSMin: 2916b8e80941Smrg case SpvOpAtomicUMin: 2917b8e80941Smrg case SpvOpAtomicSMax: 2918b8e80941Smrg case SpvOpAtomicUMax: 2919b8e80941Smrg case SpvOpAtomicAnd: 2920b8e80941Smrg case SpvOpAtomicOr: 2921b8e80941Smrg case SpvOpAtomicXor: 2922b8e80941Smrg if (ptr->mode == vtn_variable_mode_ssbo) 2923b8e80941Smrg atomic->src[src++] = nir_src_for_ssa(index); 2924b8e80941Smrg atomic->src[src++] = nir_src_for_ssa(offset); 2925b8e80941Smrg fill_common_atomic_sources(b, opcode, w, &atomic->src[src]); 2926b8e80941Smrg break; 2927b8e80941Smrg 2928b8e80941Smrg default: 2929b8e80941Smrg vtn_fail_with_opcode("Invalid SPIR-V atomic", opcode); 2930b8e80941Smrg } 2931b8e80941Smrg } else { 2932b8e80941Smrg nir_deref_instr *deref = vtn_pointer_to_deref(b, ptr); 2933b8e80941Smrg const struct glsl_type *deref_type = deref->type; 2934b8e80941Smrg nir_intrinsic_op op = get_deref_nir_atomic_op(b, opcode); 2935b8e80941Smrg atomic = nir_intrinsic_instr_create(b->nb.shader, op); 2936b8e80941Smrg atomic->src[0] = nir_src_for_ssa(&deref->dest.ssa); 2937b8e80941Smrg 2938b8e80941Smrg switch (opcode) { 2939b8e80941Smrg case SpvOpAtomicLoad: 2940b8e80941Smrg atomic->num_components = glsl_get_vector_elements(deref_type); 2941b8e80941Smrg break; 2942b8e80941Smrg 2943b8e80941Smrg case SpvOpAtomicStore: 2944b8e80941Smrg atomic->num_components = glsl_get_vector_elements(deref_type); 2945b8e80941Smrg nir_intrinsic_set_write_mask(atomic, (1 << atomic->num_components) - 1); 2946b8e80941Smrg atomic->src[1] = nir_src_for_ssa(vtn_ssa_value(b, w[4])->def); 2947b8e80941Smrg break; 2948b8e80941Smrg 2949b8e80941Smrg case SpvOpAtomicExchange: 2950b8e80941Smrg case SpvOpAtomicCompareExchange: 2951b8e80941Smrg case SpvOpAtomicCompareExchangeWeak: 2952b8e80941Smrg case SpvOpAtomicIIncrement: 2953b8e80941Smrg case SpvOpAtomicIDecrement: 2954b8e80941Smrg case SpvOpAtomicIAdd: 2955b8e80941Smrg case SpvOpAtomicISub: 2956b8e80941Smrg case SpvOpAtomicSMin: 2957b8e80941Smrg case SpvOpAtomicUMin: 2958b8e80941Smrg case SpvOpAtomicSMax: 2959b8e80941Smrg case SpvOpAtomicUMax: 2960b8e80941Smrg case SpvOpAtomicAnd: 2961b8e80941Smrg case SpvOpAtomicOr: 2962b8e80941Smrg case SpvOpAtomicXor: 2963b8e80941Smrg fill_common_atomic_sources(b, opcode, w, &atomic->src[1]); 2964b8e80941Smrg break; 2965b8e80941Smrg 2966b8e80941Smrg default: 2967b8e80941Smrg vtn_fail_with_opcode("Invalid SPIR-V atomic", opcode); 2968b8e80941Smrg } 2969b8e80941Smrg } 2970b8e80941Smrg 2971b8e80941Smrg if (opcode != SpvOpAtomicStore) { 2972b8e80941Smrg struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type; 2973b8e80941Smrg 2974b8e80941Smrg nir_ssa_dest_init(&atomic->instr, &atomic->dest, 2975b8e80941Smrg glsl_get_vector_elements(type->type), 2976b8e80941Smrg glsl_get_bit_size(type->type), NULL); 2977b8e80941Smrg 2978b8e80941Smrg struct vtn_ssa_value *ssa = rzalloc(b, struct vtn_ssa_value); 2979b8e80941Smrg ssa->def = &atomic->dest.ssa; 2980b8e80941Smrg ssa->type = type->type; 2981b8e80941Smrg vtn_push_ssa(b, w[2], type, ssa); 2982b8e80941Smrg } 2983b8e80941Smrg 2984b8e80941Smrg nir_builder_instr_insert(&b->nb, &atomic->instr); 2985b8e80941Smrg} 2986b8e80941Smrg 2987b8e80941Smrgstatic nir_alu_instr * 2988b8e80941Smrgcreate_vec(struct vtn_builder *b, unsigned num_components, unsigned bit_size) 2989b8e80941Smrg{ 2990b8e80941Smrg nir_op op = nir_op_vec(num_components); 2991b8e80941Smrg nir_alu_instr *vec = nir_alu_instr_create(b->shader, op); 2992b8e80941Smrg nir_ssa_dest_init(&vec->instr, &vec->dest.dest, num_components, 2993b8e80941Smrg bit_size, NULL); 2994b8e80941Smrg vec->dest.write_mask = (1 << num_components) - 1; 2995b8e80941Smrg 2996b8e80941Smrg return vec; 2997b8e80941Smrg} 2998b8e80941Smrg 2999b8e80941Smrgstruct vtn_ssa_value * 3000b8e80941Smrgvtn_ssa_transpose(struct vtn_builder *b, struct vtn_ssa_value *src) 3001b8e80941Smrg{ 3002b8e80941Smrg if (src->transposed) 3003b8e80941Smrg return src->transposed; 3004b8e80941Smrg 3005b8e80941Smrg struct vtn_ssa_value *dest = 3006b8e80941Smrg vtn_create_ssa_value(b, glsl_transposed_type(src->type)); 3007b8e80941Smrg 3008b8e80941Smrg for (unsigned i = 0; i < glsl_get_matrix_columns(dest->type); i++) { 3009b8e80941Smrg nir_alu_instr *vec = create_vec(b, glsl_get_matrix_columns(src->type), 3010b8e80941Smrg glsl_get_bit_size(src->type)); 3011b8e80941Smrg if (glsl_type_is_vector_or_scalar(src->type)) { 3012b8e80941Smrg vec->src[0].src = nir_src_for_ssa(src->def); 3013b8e80941Smrg vec->src[0].swizzle[0] = i; 3014b8e80941Smrg } else { 3015b8e80941Smrg for (unsigned j = 0; j < glsl_get_matrix_columns(src->type); j++) { 3016b8e80941Smrg vec->src[j].src = nir_src_for_ssa(src->elems[j]->def); 3017b8e80941Smrg vec->src[j].swizzle[0] = i; 3018b8e80941Smrg } 3019b8e80941Smrg } 3020b8e80941Smrg nir_builder_instr_insert(&b->nb, &vec->instr); 3021b8e80941Smrg dest->elems[i]->def = &vec->dest.dest.ssa; 3022b8e80941Smrg } 3023b8e80941Smrg 3024b8e80941Smrg dest->transposed = src; 3025b8e80941Smrg 3026b8e80941Smrg return dest; 3027b8e80941Smrg} 3028b8e80941Smrg 3029b8e80941Smrgnir_ssa_def * 3030b8e80941Smrgvtn_vector_extract(struct vtn_builder *b, nir_ssa_def *src, unsigned index) 3031b8e80941Smrg{ 3032b8e80941Smrg return nir_channel(&b->nb, src, index); 3033b8e80941Smrg} 3034b8e80941Smrg 3035b8e80941Smrgnir_ssa_def * 3036b8e80941Smrgvtn_vector_insert(struct vtn_builder *b, nir_ssa_def *src, nir_ssa_def *insert, 3037b8e80941Smrg unsigned index) 3038b8e80941Smrg{ 3039b8e80941Smrg nir_alu_instr *vec = create_vec(b, src->num_components, 3040b8e80941Smrg src->bit_size); 3041b8e80941Smrg 3042b8e80941Smrg for (unsigned i = 0; i < src->num_components; i++) { 3043b8e80941Smrg if (i == index) { 3044b8e80941Smrg vec->src[i].src = nir_src_for_ssa(insert); 3045b8e80941Smrg } else { 3046b8e80941Smrg vec->src[i].src = nir_src_for_ssa(src); 3047b8e80941Smrg vec->src[i].swizzle[0] = i; 3048b8e80941Smrg } 3049b8e80941Smrg } 3050b8e80941Smrg 3051b8e80941Smrg nir_builder_instr_insert(&b->nb, &vec->instr); 3052b8e80941Smrg 3053b8e80941Smrg return &vec->dest.dest.ssa; 3054b8e80941Smrg} 3055b8e80941Smrg 3056b8e80941Smrgstatic nir_ssa_def * 3057b8e80941Smrgnir_ieq_imm(nir_builder *b, nir_ssa_def *x, uint64_t i) 3058b8e80941Smrg{ 3059b8e80941Smrg return nir_ieq(b, x, nir_imm_intN_t(b, i, x->bit_size)); 3060b8e80941Smrg} 3061b8e80941Smrg 3062b8e80941Smrgnir_ssa_def * 3063b8e80941Smrgvtn_vector_extract_dynamic(struct vtn_builder *b, nir_ssa_def *src, 3064b8e80941Smrg nir_ssa_def *index) 3065b8e80941Smrg{ 3066b8e80941Smrg return nir_vector_extract(&b->nb, src, nir_i2i(&b->nb, index, 32)); 3067b8e80941Smrg} 3068b8e80941Smrg 3069b8e80941Smrgnir_ssa_def * 3070b8e80941Smrgvtn_vector_insert_dynamic(struct vtn_builder *b, nir_ssa_def *src, 3071b8e80941Smrg nir_ssa_def *insert, nir_ssa_def *index) 3072b8e80941Smrg{ 3073b8e80941Smrg nir_ssa_def *dest = vtn_vector_insert(b, src, insert, 0); 3074b8e80941Smrg for (unsigned i = 1; i < src->num_components; i++) 3075b8e80941Smrg dest = nir_bcsel(&b->nb, nir_ieq_imm(&b->nb, index, i), 3076b8e80941Smrg vtn_vector_insert(b, src, insert, i), dest); 3077b8e80941Smrg 3078b8e80941Smrg return dest; 3079b8e80941Smrg} 3080b8e80941Smrg 3081b8e80941Smrgstatic nir_ssa_def * 3082b8e80941Smrgvtn_vector_shuffle(struct vtn_builder *b, unsigned num_components, 3083b8e80941Smrg nir_ssa_def *src0, nir_ssa_def *src1, 3084b8e80941Smrg const uint32_t *indices) 3085b8e80941Smrg{ 3086b8e80941Smrg nir_alu_instr *vec = create_vec(b, num_components, src0->bit_size); 3087b8e80941Smrg 3088b8e80941Smrg for (unsigned i = 0; i < num_components; i++) { 3089b8e80941Smrg uint32_t index = indices[i]; 3090b8e80941Smrg if (index == 0xffffffff) { 3091b8e80941Smrg vec->src[i].src = 3092b8e80941Smrg nir_src_for_ssa(nir_ssa_undef(&b->nb, 1, src0->bit_size)); 3093b8e80941Smrg } else if (index < src0->num_components) { 3094b8e80941Smrg vec->src[i].src = nir_src_for_ssa(src0); 3095b8e80941Smrg vec->src[i].swizzle[0] = index; 3096b8e80941Smrg } else { 3097b8e80941Smrg vec->src[i].src = nir_src_for_ssa(src1); 3098b8e80941Smrg vec->src[i].swizzle[0] = index - src0->num_components; 3099b8e80941Smrg } 3100b8e80941Smrg } 3101b8e80941Smrg 3102b8e80941Smrg nir_builder_instr_insert(&b->nb, &vec->instr); 3103b8e80941Smrg 3104b8e80941Smrg return &vec->dest.dest.ssa; 3105b8e80941Smrg} 3106b8e80941Smrg 3107b8e80941Smrg/* 3108b8e80941Smrg * Concatentates a number of vectors/scalars together to produce a vector 3109b8e80941Smrg */ 3110b8e80941Smrgstatic nir_ssa_def * 3111b8e80941Smrgvtn_vector_construct(struct vtn_builder *b, unsigned num_components, 3112b8e80941Smrg unsigned num_srcs, nir_ssa_def **srcs) 3113b8e80941Smrg{ 3114b8e80941Smrg nir_alu_instr *vec = create_vec(b, num_components, srcs[0]->bit_size); 3115b8e80941Smrg 3116b8e80941Smrg /* From the SPIR-V 1.1 spec for OpCompositeConstruct: 3117b8e80941Smrg * 3118b8e80941Smrg * "When constructing a vector, there must be at least two Constituent 3119b8e80941Smrg * operands." 3120b8e80941Smrg */ 3121b8e80941Smrg vtn_assert(num_srcs >= 2); 3122b8e80941Smrg 3123b8e80941Smrg unsigned dest_idx = 0; 3124b8e80941Smrg for (unsigned i = 0; i < num_srcs; i++) { 3125b8e80941Smrg nir_ssa_def *src = srcs[i]; 3126b8e80941Smrg vtn_assert(dest_idx + src->num_components <= num_components); 3127b8e80941Smrg for (unsigned j = 0; j < src->num_components; j++) { 3128b8e80941Smrg vec->src[dest_idx].src = nir_src_for_ssa(src); 3129b8e80941Smrg vec->src[dest_idx].swizzle[0] = j; 3130b8e80941Smrg dest_idx++; 3131b8e80941Smrg } 3132b8e80941Smrg } 3133b8e80941Smrg 3134b8e80941Smrg /* From the SPIR-V 1.1 spec for OpCompositeConstruct: 3135b8e80941Smrg * 3136b8e80941Smrg * "When constructing a vector, the total number of components in all 3137b8e80941Smrg * the operands must equal the number of components in Result Type." 3138b8e80941Smrg */ 3139b8e80941Smrg vtn_assert(dest_idx == num_components); 3140b8e80941Smrg 3141b8e80941Smrg nir_builder_instr_insert(&b->nb, &vec->instr); 3142b8e80941Smrg 3143b8e80941Smrg return &vec->dest.dest.ssa; 3144b8e80941Smrg} 3145b8e80941Smrg 3146b8e80941Smrgstatic struct vtn_ssa_value * 3147b8e80941Smrgvtn_composite_copy(void *mem_ctx, struct vtn_ssa_value *src) 3148b8e80941Smrg{ 3149b8e80941Smrg struct vtn_ssa_value *dest = rzalloc(mem_ctx, struct vtn_ssa_value); 3150b8e80941Smrg dest->type = src->type; 3151b8e80941Smrg 3152b8e80941Smrg if (glsl_type_is_vector_or_scalar(src->type)) { 3153b8e80941Smrg dest->def = src->def; 3154b8e80941Smrg } else { 3155b8e80941Smrg unsigned elems = glsl_get_length(src->type); 3156b8e80941Smrg 3157b8e80941Smrg dest->elems = ralloc_array(mem_ctx, struct vtn_ssa_value *, elems); 3158b8e80941Smrg for (unsigned i = 0; i < elems; i++) 3159b8e80941Smrg dest->elems[i] = vtn_composite_copy(mem_ctx, src->elems[i]); 3160b8e80941Smrg } 3161b8e80941Smrg 3162b8e80941Smrg return dest; 3163b8e80941Smrg} 3164b8e80941Smrg 3165b8e80941Smrgstatic struct vtn_ssa_value * 3166b8e80941Smrgvtn_composite_insert(struct vtn_builder *b, struct vtn_ssa_value *src, 3167b8e80941Smrg struct vtn_ssa_value *insert, const uint32_t *indices, 3168b8e80941Smrg unsigned num_indices) 3169b8e80941Smrg{ 3170b8e80941Smrg struct vtn_ssa_value *dest = vtn_composite_copy(b, src); 3171b8e80941Smrg 3172b8e80941Smrg struct vtn_ssa_value *cur = dest; 3173b8e80941Smrg unsigned i; 3174b8e80941Smrg for (i = 0; i < num_indices - 1; i++) { 3175b8e80941Smrg cur = cur->elems[indices[i]]; 3176b8e80941Smrg } 3177b8e80941Smrg 3178b8e80941Smrg if (glsl_type_is_vector_or_scalar(cur->type)) { 3179b8e80941Smrg /* According to the SPIR-V spec, OpCompositeInsert may work down to 3180b8e80941Smrg * the component granularity. In that case, the last index will be 3181b8e80941Smrg * the index to insert the scalar into the vector. 3182b8e80941Smrg */ 3183b8e80941Smrg 3184b8e80941Smrg cur->def = vtn_vector_insert(b, cur->def, insert->def, indices[i]); 3185b8e80941Smrg } else { 3186b8e80941Smrg cur->elems[indices[i]] = insert; 3187b8e80941Smrg } 3188b8e80941Smrg 3189b8e80941Smrg return dest; 3190b8e80941Smrg} 3191b8e80941Smrg 3192b8e80941Smrgstatic struct vtn_ssa_value * 3193b8e80941Smrgvtn_composite_extract(struct vtn_builder *b, struct vtn_ssa_value *src, 3194b8e80941Smrg const uint32_t *indices, unsigned num_indices) 3195b8e80941Smrg{ 3196b8e80941Smrg struct vtn_ssa_value *cur = src; 3197b8e80941Smrg for (unsigned i = 0; i < num_indices; i++) { 3198b8e80941Smrg if (glsl_type_is_vector_or_scalar(cur->type)) { 3199b8e80941Smrg vtn_assert(i == num_indices - 1); 3200b8e80941Smrg /* According to the SPIR-V spec, OpCompositeExtract may work down to 3201b8e80941Smrg * the component granularity. The last index will be the index of the 3202b8e80941Smrg * vector to extract. 3203b8e80941Smrg */ 3204b8e80941Smrg 3205b8e80941Smrg struct vtn_ssa_value *ret = rzalloc(b, struct vtn_ssa_value); 3206b8e80941Smrg ret->type = glsl_scalar_type(glsl_get_base_type(cur->type)); 3207b8e80941Smrg ret->def = vtn_vector_extract(b, cur->def, indices[i]); 3208b8e80941Smrg return ret; 3209b8e80941Smrg } else { 3210b8e80941Smrg cur = cur->elems[indices[i]]; 3211b8e80941Smrg } 3212b8e80941Smrg } 3213b8e80941Smrg 3214b8e80941Smrg return cur; 3215b8e80941Smrg} 3216b8e80941Smrg 3217b8e80941Smrgstatic void 3218b8e80941Smrgvtn_handle_composite(struct vtn_builder *b, SpvOp opcode, 3219b8e80941Smrg const uint32_t *w, unsigned count) 3220b8e80941Smrg{ 3221b8e80941Smrg struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type; 3222b8e80941Smrg struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, type->type); 3223b8e80941Smrg 3224b8e80941Smrg switch (opcode) { 3225b8e80941Smrg case SpvOpVectorExtractDynamic: 3226b8e80941Smrg ssa->def = vtn_vector_extract_dynamic(b, vtn_ssa_value(b, w[3])->def, 3227b8e80941Smrg vtn_ssa_value(b, w[4])->def); 3228b8e80941Smrg break; 3229b8e80941Smrg 3230b8e80941Smrg case SpvOpVectorInsertDynamic: 3231b8e80941Smrg ssa->def = vtn_vector_insert_dynamic(b, vtn_ssa_value(b, w[3])->def, 3232b8e80941Smrg vtn_ssa_value(b, w[4])->def, 3233b8e80941Smrg vtn_ssa_value(b, w[5])->def); 3234b8e80941Smrg break; 3235b8e80941Smrg 3236b8e80941Smrg case SpvOpVectorShuffle: 3237b8e80941Smrg ssa->def = vtn_vector_shuffle(b, glsl_get_vector_elements(type->type), 3238b8e80941Smrg vtn_ssa_value(b, w[3])->def, 3239b8e80941Smrg vtn_ssa_value(b, w[4])->def, 3240b8e80941Smrg w + 5); 3241b8e80941Smrg break; 3242b8e80941Smrg 3243b8e80941Smrg case SpvOpCompositeConstruct: { 3244b8e80941Smrg unsigned elems = count - 3; 3245b8e80941Smrg assume(elems >= 1); 3246b8e80941Smrg if (glsl_type_is_vector_or_scalar(type->type)) { 3247b8e80941Smrg nir_ssa_def *srcs[NIR_MAX_VEC_COMPONENTS]; 3248b8e80941Smrg for (unsigned i = 0; i < elems; i++) 3249b8e80941Smrg srcs[i] = vtn_ssa_value(b, w[3 + i])->def; 3250b8e80941Smrg ssa->def = 3251b8e80941Smrg vtn_vector_construct(b, glsl_get_vector_elements(type->type), 3252b8e80941Smrg elems, srcs); 3253b8e80941Smrg } else { 3254b8e80941Smrg ssa->elems = ralloc_array(b, struct vtn_ssa_value *, elems); 3255b8e80941Smrg for (unsigned i = 0; i < elems; i++) 3256b8e80941Smrg ssa->elems[i] = vtn_ssa_value(b, w[3 + i]); 3257b8e80941Smrg } 3258b8e80941Smrg break; 3259b8e80941Smrg } 3260b8e80941Smrg case SpvOpCompositeExtract: 3261b8e80941Smrg ssa = vtn_composite_extract(b, vtn_ssa_value(b, w[3]), 3262b8e80941Smrg w + 4, count - 4); 3263b8e80941Smrg break; 3264b8e80941Smrg 3265b8e80941Smrg case SpvOpCompositeInsert: 3266b8e80941Smrg ssa = vtn_composite_insert(b, vtn_ssa_value(b, w[4]), 3267b8e80941Smrg vtn_ssa_value(b, w[3]), 3268b8e80941Smrg w + 5, count - 5); 3269b8e80941Smrg break; 3270b8e80941Smrg 3271b8e80941Smrg case SpvOpCopyObject: 3272b8e80941Smrg ssa = vtn_composite_copy(b, vtn_ssa_value(b, w[3])); 3273b8e80941Smrg break; 3274b8e80941Smrg 3275b8e80941Smrg default: 3276b8e80941Smrg vtn_fail_with_opcode("unknown composite operation", opcode); 3277b8e80941Smrg } 3278b8e80941Smrg 3279b8e80941Smrg vtn_push_ssa(b, w[2], type, ssa); 3280b8e80941Smrg} 3281b8e80941Smrg 3282b8e80941Smrgstatic void 3283b8e80941Smrgvtn_emit_barrier(struct vtn_builder *b, nir_intrinsic_op op) 3284b8e80941Smrg{ 3285b8e80941Smrg nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op); 3286b8e80941Smrg nir_builder_instr_insert(&b->nb, &intrin->instr); 3287b8e80941Smrg} 3288b8e80941Smrg 3289b8e80941Smrgstatic void 3290b8e80941Smrgvtn_emit_memory_barrier(struct vtn_builder *b, SpvScope scope, 3291b8e80941Smrg SpvMemorySemanticsMask semantics) 3292b8e80941Smrg{ 3293b8e80941Smrg static const SpvMemorySemanticsMask all_memory_semantics = 3294b8e80941Smrg SpvMemorySemanticsUniformMemoryMask | 3295b8e80941Smrg SpvMemorySemanticsWorkgroupMemoryMask | 3296b8e80941Smrg SpvMemorySemanticsAtomicCounterMemoryMask | 3297b8e80941Smrg SpvMemorySemanticsImageMemoryMask; 3298b8e80941Smrg 3299b8e80941Smrg /* If we're not actually doing a memory barrier, bail */ 3300b8e80941Smrg if (!(semantics & all_memory_semantics)) 3301b8e80941Smrg return; 3302b8e80941Smrg 3303b8e80941Smrg /* GL and Vulkan don't have these */ 3304b8e80941Smrg vtn_assert(scope != SpvScopeCrossDevice); 3305b8e80941Smrg 3306b8e80941Smrg if (scope == SpvScopeSubgroup) 3307b8e80941Smrg return; /* Nothing to do here */ 3308b8e80941Smrg 3309b8e80941Smrg if (scope == SpvScopeWorkgroup) { 3310b8e80941Smrg vtn_emit_barrier(b, nir_intrinsic_group_memory_barrier); 3311b8e80941Smrg return; 3312b8e80941Smrg } 3313b8e80941Smrg 3314b8e80941Smrg /* There's only two scopes thing left */ 3315b8e80941Smrg vtn_assert(scope == SpvScopeInvocation || scope == SpvScopeDevice); 3316b8e80941Smrg 3317b8e80941Smrg if ((semantics & all_memory_semantics) == all_memory_semantics) { 3318b8e80941Smrg vtn_emit_barrier(b, nir_intrinsic_memory_barrier); 3319b8e80941Smrg return; 3320b8e80941Smrg } 3321b8e80941Smrg 3322b8e80941Smrg /* Issue a bunch of more specific barriers */ 3323b8e80941Smrg uint32_t bits = semantics; 3324b8e80941Smrg while (bits) { 3325b8e80941Smrg SpvMemorySemanticsMask semantic = 1 << u_bit_scan(&bits); 3326b8e80941Smrg switch (semantic) { 3327b8e80941Smrg case SpvMemorySemanticsUniformMemoryMask: 3328b8e80941Smrg vtn_emit_barrier(b, nir_intrinsic_memory_barrier_buffer); 3329b8e80941Smrg break; 3330b8e80941Smrg case SpvMemorySemanticsWorkgroupMemoryMask: 3331b8e80941Smrg vtn_emit_barrier(b, nir_intrinsic_memory_barrier_shared); 3332b8e80941Smrg break; 3333b8e80941Smrg case SpvMemorySemanticsAtomicCounterMemoryMask: 3334b8e80941Smrg vtn_emit_barrier(b, nir_intrinsic_memory_barrier_atomic_counter); 3335b8e80941Smrg break; 3336b8e80941Smrg case SpvMemorySemanticsImageMemoryMask: 3337b8e80941Smrg vtn_emit_barrier(b, nir_intrinsic_memory_barrier_image); 3338b8e80941Smrg break; 3339b8e80941Smrg default: 3340b8e80941Smrg break;; 3341b8e80941Smrg } 3342b8e80941Smrg } 3343b8e80941Smrg} 3344b8e80941Smrg 3345b8e80941Smrgstatic void 3346b8e80941Smrgvtn_handle_barrier(struct vtn_builder *b, SpvOp opcode, 3347b8e80941Smrg const uint32_t *w, unsigned count) 3348b8e80941Smrg{ 3349b8e80941Smrg switch (opcode) { 3350b8e80941Smrg case SpvOpEmitVertex: 3351b8e80941Smrg case SpvOpEmitStreamVertex: 3352b8e80941Smrg case SpvOpEndPrimitive: 3353b8e80941Smrg case SpvOpEndStreamPrimitive: { 3354b8e80941Smrg nir_intrinsic_op intrinsic_op; 3355b8e80941Smrg switch (opcode) { 3356b8e80941Smrg case SpvOpEmitVertex: 3357b8e80941Smrg case SpvOpEmitStreamVertex: 3358b8e80941Smrg intrinsic_op = nir_intrinsic_emit_vertex; 3359b8e80941Smrg break; 3360b8e80941Smrg case SpvOpEndPrimitive: 3361b8e80941Smrg case SpvOpEndStreamPrimitive: 3362b8e80941Smrg intrinsic_op = nir_intrinsic_end_primitive; 3363b8e80941Smrg break; 3364b8e80941Smrg default: 3365b8e80941Smrg unreachable("Invalid opcode"); 3366b8e80941Smrg } 3367b8e80941Smrg 3368b8e80941Smrg nir_intrinsic_instr *intrin = 3369b8e80941Smrg nir_intrinsic_instr_create(b->shader, intrinsic_op); 3370b8e80941Smrg 3371b8e80941Smrg switch (opcode) { 3372b8e80941Smrg case SpvOpEmitStreamVertex: 3373b8e80941Smrg case SpvOpEndStreamPrimitive: { 3374b8e80941Smrg unsigned stream = vtn_constant_uint(b, w[1]); 3375b8e80941Smrg nir_intrinsic_set_stream_id(intrin, stream); 3376b8e80941Smrg break; 3377b8e80941Smrg } 3378b8e80941Smrg 3379b8e80941Smrg default: 3380b8e80941Smrg break; 3381b8e80941Smrg } 3382b8e80941Smrg 3383b8e80941Smrg nir_builder_instr_insert(&b->nb, &intrin->instr); 3384b8e80941Smrg break; 3385b8e80941Smrg } 3386b8e80941Smrg 3387b8e80941Smrg case SpvOpMemoryBarrier: { 3388b8e80941Smrg SpvScope scope = vtn_constant_uint(b, w[1]); 3389b8e80941Smrg SpvMemorySemanticsMask semantics = vtn_constant_uint(b, w[2]); 3390b8e80941Smrg vtn_emit_memory_barrier(b, scope, semantics); 3391b8e80941Smrg return; 3392b8e80941Smrg } 3393b8e80941Smrg 3394b8e80941Smrg case SpvOpControlBarrier: { 3395b8e80941Smrg SpvScope memory_scope = vtn_constant_uint(b, w[2]); 3396b8e80941Smrg SpvMemorySemanticsMask memory_semantics = vtn_constant_uint(b, w[3]); 3397b8e80941Smrg vtn_emit_memory_barrier(b, memory_scope, memory_semantics); 3398b8e80941Smrg 3399b8e80941Smrg SpvScope execution_scope = vtn_constant_uint(b, w[1]); 3400b8e80941Smrg if (execution_scope == SpvScopeWorkgroup) 3401b8e80941Smrg vtn_emit_barrier(b, nir_intrinsic_barrier); 3402b8e80941Smrg break; 3403b8e80941Smrg } 3404b8e80941Smrg 3405b8e80941Smrg default: 3406b8e80941Smrg unreachable("unknown barrier instruction"); 3407b8e80941Smrg } 3408b8e80941Smrg} 3409b8e80941Smrg 3410b8e80941Smrgstatic unsigned 3411b8e80941Smrggl_primitive_from_spv_execution_mode(struct vtn_builder *b, 3412b8e80941Smrg SpvExecutionMode mode) 3413b8e80941Smrg{ 3414b8e80941Smrg switch (mode) { 3415b8e80941Smrg case SpvExecutionModeInputPoints: 3416b8e80941Smrg case SpvExecutionModeOutputPoints: 3417b8e80941Smrg return 0; /* GL_POINTS */ 3418b8e80941Smrg case SpvExecutionModeInputLines: 3419b8e80941Smrg return 1; /* GL_LINES */ 3420b8e80941Smrg case SpvExecutionModeInputLinesAdjacency: 3421b8e80941Smrg return 0x000A; /* GL_LINE_STRIP_ADJACENCY_ARB */ 3422b8e80941Smrg case SpvExecutionModeTriangles: 3423b8e80941Smrg return 4; /* GL_TRIANGLES */ 3424b8e80941Smrg case SpvExecutionModeInputTrianglesAdjacency: 3425b8e80941Smrg return 0x000C; /* GL_TRIANGLES_ADJACENCY_ARB */ 3426b8e80941Smrg case SpvExecutionModeQuads: 3427b8e80941Smrg return 7; /* GL_QUADS */ 3428b8e80941Smrg case SpvExecutionModeIsolines: 3429b8e80941Smrg return 0x8E7A; /* GL_ISOLINES */ 3430b8e80941Smrg case SpvExecutionModeOutputLineStrip: 3431b8e80941Smrg return 3; /* GL_LINE_STRIP */ 3432b8e80941Smrg case SpvExecutionModeOutputTriangleStrip: 3433b8e80941Smrg return 5; /* GL_TRIANGLE_STRIP */ 3434b8e80941Smrg default: 3435b8e80941Smrg vtn_fail("Invalid primitive type: %s (%u)", 3436b8e80941Smrg spirv_executionmode_to_string(mode), mode); 3437b8e80941Smrg } 3438b8e80941Smrg} 3439b8e80941Smrg 3440b8e80941Smrgstatic unsigned 3441b8e80941Smrgvertices_in_from_spv_execution_mode(struct vtn_builder *b, 3442b8e80941Smrg SpvExecutionMode mode) 3443b8e80941Smrg{ 3444b8e80941Smrg switch (mode) { 3445b8e80941Smrg case SpvExecutionModeInputPoints: 3446b8e80941Smrg return 1; 3447b8e80941Smrg case SpvExecutionModeInputLines: 3448b8e80941Smrg return 2; 3449b8e80941Smrg case SpvExecutionModeInputLinesAdjacency: 3450b8e80941Smrg return 4; 3451b8e80941Smrg case SpvExecutionModeTriangles: 3452b8e80941Smrg return 3; 3453b8e80941Smrg case SpvExecutionModeInputTrianglesAdjacency: 3454b8e80941Smrg return 6; 3455b8e80941Smrg default: 3456b8e80941Smrg vtn_fail("Invalid GS input mode: %s (%u)", 3457b8e80941Smrg spirv_executionmode_to_string(mode), mode); 3458b8e80941Smrg } 3459b8e80941Smrg} 3460b8e80941Smrg 3461b8e80941Smrgstatic gl_shader_stage 3462b8e80941Smrgstage_for_execution_model(struct vtn_builder *b, SpvExecutionModel model) 3463b8e80941Smrg{ 3464b8e80941Smrg switch (model) { 3465b8e80941Smrg case SpvExecutionModelVertex: 3466b8e80941Smrg return MESA_SHADER_VERTEX; 3467b8e80941Smrg case SpvExecutionModelTessellationControl: 3468b8e80941Smrg return MESA_SHADER_TESS_CTRL; 3469b8e80941Smrg case SpvExecutionModelTessellationEvaluation: 3470b8e80941Smrg return MESA_SHADER_TESS_EVAL; 3471b8e80941Smrg case SpvExecutionModelGeometry: 3472b8e80941Smrg return MESA_SHADER_GEOMETRY; 3473b8e80941Smrg case SpvExecutionModelFragment: 3474b8e80941Smrg return MESA_SHADER_FRAGMENT; 3475b8e80941Smrg case SpvExecutionModelGLCompute: 3476b8e80941Smrg return MESA_SHADER_COMPUTE; 3477b8e80941Smrg case SpvExecutionModelKernel: 3478b8e80941Smrg return MESA_SHADER_KERNEL; 3479b8e80941Smrg default: 3480b8e80941Smrg vtn_fail("Unsupported execution model: %s (%u)", 3481b8e80941Smrg spirv_executionmodel_to_string(model), model); 3482b8e80941Smrg } 3483b8e80941Smrg} 3484b8e80941Smrg 3485b8e80941Smrg#define spv_check_supported(name, cap) do { \ 3486b8e80941Smrg if (!(b->options && b->options->caps.name)) \ 3487b8e80941Smrg vtn_warn("Unsupported SPIR-V capability: %s (%u)", \ 3488b8e80941Smrg spirv_capability_to_string(cap), cap); \ 3489b8e80941Smrg } while(0) 3490b8e80941Smrg 3491b8e80941Smrg 3492b8e80941Smrgvoid 3493b8e80941Smrgvtn_handle_entry_point(struct vtn_builder *b, const uint32_t *w, 3494b8e80941Smrg unsigned count) 3495b8e80941Smrg{ 3496b8e80941Smrg struct vtn_value *entry_point = &b->values[w[2]]; 3497b8e80941Smrg /* Let this be a name label regardless */ 3498b8e80941Smrg unsigned name_words; 3499b8e80941Smrg entry_point->name = vtn_string_literal(b, &w[3], count - 3, &name_words); 3500b8e80941Smrg 3501b8e80941Smrg if (strcmp(entry_point->name, b->entry_point_name) != 0 || 3502b8e80941Smrg stage_for_execution_model(b, w[1]) != b->entry_point_stage) 3503b8e80941Smrg return; 3504b8e80941Smrg 3505b8e80941Smrg vtn_assert(b->entry_point == NULL); 3506b8e80941Smrg b->entry_point = entry_point; 3507b8e80941Smrg} 3508b8e80941Smrg 3509b8e80941Smrgstatic bool 3510b8e80941Smrgvtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode, 3511b8e80941Smrg const uint32_t *w, unsigned count) 3512b8e80941Smrg{ 3513b8e80941Smrg switch (opcode) { 3514b8e80941Smrg case SpvOpSource: { 3515b8e80941Smrg const char *lang; 3516b8e80941Smrg switch (w[1]) { 3517b8e80941Smrg default: 3518b8e80941Smrg case SpvSourceLanguageUnknown: lang = "unknown"; break; 3519b8e80941Smrg case SpvSourceLanguageESSL: lang = "ESSL"; break; 3520b8e80941Smrg case SpvSourceLanguageGLSL: lang = "GLSL"; break; 3521b8e80941Smrg case SpvSourceLanguageOpenCL_C: lang = "OpenCL C"; break; 3522b8e80941Smrg case SpvSourceLanguageOpenCL_CPP: lang = "OpenCL C++"; break; 3523b8e80941Smrg case SpvSourceLanguageHLSL: lang = "HLSL"; break; 3524b8e80941Smrg } 3525b8e80941Smrg 3526b8e80941Smrg uint32_t version = w[2]; 3527b8e80941Smrg 3528b8e80941Smrg const char *file = 3529b8e80941Smrg (count > 3) ? vtn_value(b, w[3], vtn_value_type_string)->str : ""; 3530b8e80941Smrg 3531b8e80941Smrg vtn_info("Parsing SPIR-V from %s %u source file %s", lang, version, file); 3532b8e80941Smrg break; 3533b8e80941Smrg } 3534b8e80941Smrg 3535b8e80941Smrg case SpvOpSourceExtension: 3536b8e80941Smrg case SpvOpSourceContinued: 3537b8e80941Smrg case SpvOpExtension: 3538b8e80941Smrg case SpvOpModuleProcessed: 3539b8e80941Smrg /* Unhandled, but these are for debug so that's ok. */ 3540b8e80941Smrg break; 3541b8e80941Smrg 3542b8e80941Smrg case SpvOpCapability: { 3543b8e80941Smrg SpvCapability cap = w[1]; 3544b8e80941Smrg switch (cap) { 3545b8e80941Smrg case SpvCapabilityMatrix: 3546b8e80941Smrg case SpvCapabilityShader: 3547b8e80941Smrg case SpvCapabilityGeometry: 3548b8e80941Smrg case SpvCapabilityGeometryPointSize: 3549b8e80941Smrg case SpvCapabilityUniformBufferArrayDynamicIndexing: 3550b8e80941Smrg case SpvCapabilitySampledImageArrayDynamicIndexing: 3551b8e80941Smrg case SpvCapabilityStorageBufferArrayDynamicIndexing: 3552b8e80941Smrg case SpvCapabilityStorageImageArrayDynamicIndexing: 3553b8e80941Smrg case SpvCapabilityImageRect: 3554b8e80941Smrg case SpvCapabilitySampledRect: 3555b8e80941Smrg case SpvCapabilitySampled1D: 3556b8e80941Smrg case SpvCapabilityImage1D: 3557b8e80941Smrg case SpvCapabilitySampledCubeArray: 3558b8e80941Smrg case SpvCapabilityImageCubeArray: 3559b8e80941Smrg case SpvCapabilitySampledBuffer: 3560b8e80941Smrg case SpvCapabilityImageBuffer: 3561b8e80941Smrg case SpvCapabilityImageQuery: 3562b8e80941Smrg case SpvCapabilityDerivativeControl: 3563b8e80941Smrg case SpvCapabilityInterpolationFunction: 3564b8e80941Smrg case SpvCapabilityMultiViewport: 3565b8e80941Smrg case SpvCapabilitySampleRateShading: 3566b8e80941Smrg case SpvCapabilityClipDistance: 3567b8e80941Smrg case SpvCapabilityCullDistance: 3568b8e80941Smrg case SpvCapabilityInputAttachment: 3569b8e80941Smrg case SpvCapabilityImageGatherExtended: 3570b8e80941Smrg case SpvCapabilityStorageImageExtendedFormats: 3571b8e80941Smrg break; 3572b8e80941Smrg 3573b8e80941Smrg case SpvCapabilityLinkage: 3574b8e80941Smrg case SpvCapabilityVector16: 3575b8e80941Smrg case SpvCapabilityFloat16Buffer: 3576b8e80941Smrg case SpvCapabilitySparseResidency: 3577b8e80941Smrg vtn_warn("Unsupported SPIR-V capability: %s", 3578b8e80941Smrg spirv_capability_to_string(cap)); 3579b8e80941Smrg break; 3580b8e80941Smrg 3581b8e80941Smrg case SpvCapabilityMinLod: 3582b8e80941Smrg spv_check_supported(min_lod, cap); 3583b8e80941Smrg break; 3584b8e80941Smrg 3585b8e80941Smrg case SpvCapabilityAtomicStorage: 3586b8e80941Smrg spv_check_supported(atomic_storage, cap); 3587b8e80941Smrg break; 3588b8e80941Smrg 3589b8e80941Smrg case SpvCapabilityFloat64: 3590b8e80941Smrg spv_check_supported(float64, cap); 3591b8e80941Smrg break; 3592b8e80941Smrg case SpvCapabilityInt64: 3593b8e80941Smrg spv_check_supported(int64, cap); 3594b8e80941Smrg break; 3595b8e80941Smrg case SpvCapabilityInt16: 3596b8e80941Smrg spv_check_supported(int16, cap); 3597b8e80941Smrg break; 3598b8e80941Smrg case SpvCapabilityInt8: 3599b8e80941Smrg spv_check_supported(int8, cap); 3600b8e80941Smrg break; 3601b8e80941Smrg 3602b8e80941Smrg case SpvCapabilityTransformFeedback: 3603b8e80941Smrg spv_check_supported(transform_feedback, cap); 3604b8e80941Smrg break; 3605b8e80941Smrg 3606b8e80941Smrg case SpvCapabilityGeometryStreams: 3607b8e80941Smrg spv_check_supported(geometry_streams, cap); 3608b8e80941Smrg break; 3609b8e80941Smrg 3610b8e80941Smrg case SpvCapabilityInt64Atomics: 3611b8e80941Smrg spv_check_supported(int64_atomics, cap); 3612b8e80941Smrg break; 3613b8e80941Smrg 3614b8e80941Smrg case SpvCapabilityStorageImageMultisample: 3615b8e80941Smrg spv_check_supported(storage_image_ms, cap); 3616b8e80941Smrg break; 3617b8e80941Smrg 3618b8e80941Smrg case SpvCapabilityAddresses: 3619b8e80941Smrg spv_check_supported(address, cap); 3620b8e80941Smrg break; 3621b8e80941Smrg 3622b8e80941Smrg case SpvCapabilityKernel: 3623b8e80941Smrg spv_check_supported(kernel, cap); 3624b8e80941Smrg break; 3625b8e80941Smrg 3626b8e80941Smrg case SpvCapabilityImageBasic: 3627b8e80941Smrg case SpvCapabilityImageReadWrite: 3628b8e80941Smrg case SpvCapabilityImageMipmap: 3629b8e80941Smrg case SpvCapabilityPipes: 3630b8e80941Smrg case SpvCapabilityGroups: 3631b8e80941Smrg case SpvCapabilityDeviceEnqueue: 3632b8e80941Smrg case SpvCapabilityLiteralSampler: 3633b8e80941Smrg case SpvCapabilityGenericPointer: 3634b8e80941Smrg vtn_warn("Unsupported OpenCL-style SPIR-V capability: %s", 3635b8e80941Smrg spirv_capability_to_string(cap)); 3636b8e80941Smrg break; 3637b8e80941Smrg 3638b8e80941Smrg case SpvCapabilityImageMSArray: 3639b8e80941Smrg spv_check_supported(image_ms_array, cap); 3640b8e80941Smrg break; 3641b8e80941Smrg 3642b8e80941Smrg case SpvCapabilityTessellation: 3643b8e80941Smrg case SpvCapabilityTessellationPointSize: 3644b8e80941Smrg spv_check_supported(tessellation, cap); 3645b8e80941Smrg break; 3646b8e80941Smrg 3647b8e80941Smrg case SpvCapabilityDrawParameters: 3648b8e80941Smrg spv_check_supported(draw_parameters, cap); 3649b8e80941Smrg break; 3650b8e80941Smrg 3651b8e80941Smrg case SpvCapabilityStorageImageReadWithoutFormat: 3652b8e80941Smrg spv_check_supported(image_read_without_format, cap); 3653b8e80941Smrg break; 3654b8e80941Smrg 3655b8e80941Smrg case SpvCapabilityStorageImageWriteWithoutFormat: 3656b8e80941Smrg spv_check_supported(image_write_without_format, cap); 3657b8e80941Smrg break; 3658b8e80941Smrg 3659b8e80941Smrg case SpvCapabilityDeviceGroup: 3660b8e80941Smrg spv_check_supported(device_group, cap); 3661b8e80941Smrg break; 3662b8e80941Smrg 3663b8e80941Smrg case SpvCapabilityMultiView: 3664b8e80941Smrg spv_check_supported(multiview, cap); 3665b8e80941Smrg break; 3666b8e80941Smrg 3667b8e80941Smrg case SpvCapabilityGroupNonUniform: 3668b8e80941Smrg spv_check_supported(subgroup_basic, cap); 3669b8e80941Smrg break; 3670b8e80941Smrg 3671b8e80941Smrg case SpvCapabilityGroupNonUniformVote: 3672b8e80941Smrg spv_check_supported(subgroup_vote, cap); 3673b8e80941Smrg break; 3674b8e80941Smrg 3675b8e80941Smrg case SpvCapabilitySubgroupBallotKHR: 3676b8e80941Smrg case SpvCapabilityGroupNonUniformBallot: 3677b8e80941Smrg spv_check_supported(subgroup_ballot, cap); 3678b8e80941Smrg break; 3679b8e80941Smrg 3680b8e80941Smrg case SpvCapabilityGroupNonUniformShuffle: 3681b8e80941Smrg case SpvCapabilityGroupNonUniformShuffleRelative: 3682b8e80941Smrg spv_check_supported(subgroup_shuffle, cap); 3683b8e80941Smrg break; 3684b8e80941Smrg 3685b8e80941Smrg case SpvCapabilityGroupNonUniformQuad: 3686b8e80941Smrg spv_check_supported(subgroup_quad, cap); 3687b8e80941Smrg break; 3688b8e80941Smrg 3689b8e80941Smrg case SpvCapabilityGroupNonUniformArithmetic: 3690b8e80941Smrg case SpvCapabilityGroupNonUniformClustered: 3691b8e80941Smrg spv_check_supported(subgroup_arithmetic, cap); 3692b8e80941Smrg break; 3693b8e80941Smrg 3694b8e80941Smrg case SpvCapabilityVariablePointersStorageBuffer: 3695b8e80941Smrg case SpvCapabilityVariablePointers: 3696b8e80941Smrg spv_check_supported(variable_pointers, cap); 3697b8e80941Smrg b->variable_pointers = true; 3698b8e80941Smrg break; 3699b8e80941Smrg 3700b8e80941Smrg case SpvCapabilityStorageUniformBufferBlock16: 3701b8e80941Smrg case SpvCapabilityStorageUniform16: 3702b8e80941Smrg case SpvCapabilityStoragePushConstant16: 3703b8e80941Smrg case SpvCapabilityStorageInputOutput16: 3704b8e80941Smrg spv_check_supported(storage_16bit, cap); 3705b8e80941Smrg break; 3706b8e80941Smrg 3707b8e80941Smrg case SpvCapabilityShaderViewportIndexLayerEXT: 3708b8e80941Smrg spv_check_supported(shader_viewport_index_layer, cap); 3709b8e80941Smrg break; 3710b8e80941Smrg 3711b8e80941Smrg case SpvCapabilityStorageBuffer8BitAccess: 3712b8e80941Smrg case SpvCapabilityUniformAndStorageBuffer8BitAccess: 3713b8e80941Smrg case SpvCapabilityStoragePushConstant8: 3714b8e80941Smrg spv_check_supported(storage_8bit, cap); 3715b8e80941Smrg break; 3716b8e80941Smrg 3717b8e80941Smrg case SpvCapabilityShaderNonUniformEXT: 3718b8e80941Smrg spv_check_supported(descriptor_indexing, cap); 3719b8e80941Smrg break; 3720b8e80941Smrg 3721b8e80941Smrg case SpvCapabilityInputAttachmentArrayDynamicIndexingEXT: 3722b8e80941Smrg case SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT: 3723b8e80941Smrg case SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT: 3724b8e80941Smrg spv_check_supported(descriptor_array_dynamic_indexing, cap); 3725b8e80941Smrg break; 3726b8e80941Smrg 3727b8e80941Smrg case SpvCapabilityUniformBufferArrayNonUniformIndexingEXT: 3728b8e80941Smrg case SpvCapabilitySampledImageArrayNonUniformIndexingEXT: 3729b8e80941Smrg case SpvCapabilityStorageBufferArrayNonUniformIndexingEXT: 3730b8e80941Smrg case SpvCapabilityStorageImageArrayNonUniformIndexingEXT: 3731b8e80941Smrg case SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT: 3732b8e80941Smrg case SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT: 3733b8e80941Smrg case SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT: 3734b8e80941Smrg spv_check_supported(descriptor_array_non_uniform_indexing, cap); 3735b8e80941Smrg break; 3736b8e80941Smrg 3737b8e80941Smrg case SpvCapabilityRuntimeDescriptorArrayEXT: 3738b8e80941Smrg spv_check_supported(runtime_descriptor_array, cap); 3739b8e80941Smrg break; 3740b8e80941Smrg 3741b8e80941Smrg case SpvCapabilityStencilExportEXT: 3742b8e80941Smrg spv_check_supported(stencil_export, cap); 3743b8e80941Smrg break; 3744b8e80941Smrg 3745b8e80941Smrg case SpvCapabilitySampleMaskPostDepthCoverage: 3746b8e80941Smrg spv_check_supported(post_depth_coverage, cap); 3747b8e80941Smrg break; 3748b8e80941Smrg 3749b8e80941Smrg case SpvCapabilityPhysicalStorageBufferAddressesEXT: 3750b8e80941Smrg spv_check_supported(physical_storage_buffer_address, cap); 3751b8e80941Smrg break; 3752b8e80941Smrg 3753b8e80941Smrg case SpvCapabilityComputeDerivativeGroupQuadsNV: 3754b8e80941Smrg case SpvCapabilityComputeDerivativeGroupLinearNV: 3755b8e80941Smrg spv_check_supported(derivative_group, cap); 3756b8e80941Smrg break; 3757b8e80941Smrg 3758b8e80941Smrg case SpvCapabilityFloat16: 3759b8e80941Smrg spv_check_supported(float16, cap); 3760b8e80941Smrg break; 3761b8e80941Smrg 3762b8e80941Smrg default: 3763b8e80941Smrg vtn_fail("Unhandled capability: %s (%u)", 3764b8e80941Smrg spirv_capability_to_string(cap), cap); 3765b8e80941Smrg } 3766b8e80941Smrg break; 3767b8e80941Smrg } 3768b8e80941Smrg 3769b8e80941Smrg case SpvOpExtInstImport: 3770b8e80941Smrg vtn_handle_extension(b, opcode, w, count); 3771b8e80941Smrg break; 3772b8e80941Smrg 3773b8e80941Smrg case SpvOpMemoryModel: 3774b8e80941Smrg switch (w[1]) { 3775b8e80941Smrg case SpvAddressingModelPhysical32: 3776b8e80941Smrg vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL, 3777b8e80941Smrg "AddressingModelPhysical32 only supported for kernels"); 3778b8e80941Smrg b->shader->info.cs.ptr_size = 32; 3779b8e80941Smrg b->physical_ptrs = true; 3780b8e80941Smrg b->options->shared_ptr_type = glsl_uint_type(); 3781b8e80941Smrg b->options->global_ptr_type = glsl_uint_type(); 3782b8e80941Smrg b->options->temp_ptr_type = glsl_uint_type(); 3783b8e80941Smrg break; 3784b8e80941Smrg case SpvAddressingModelPhysical64: 3785b8e80941Smrg vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL, 3786b8e80941Smrg "AddressingModelPhysical64 only supported for kernels"); 3787b8e80941Smrg b->shader->info.cs.ptr_size = 64; 3788b8e80941Smrg b->physical_ptrs = true; 3789b8e80941Smrg b->options->shared_ptr_type = glsl_uint64_t_type(); 3790b8e80941Smrg b->options->global_ptr_type = glsl_uint64_t_type(); 3791b8e80941Smrg b->options->temp_ptr_type = glsl_uint64_t_type(); 3792b8e80941Smrg break; 3793b8e80941Smrg case SpvAddressingModelLogical: 3794b8e80941Smrg vtn_fail_if(b->shader->info.stage >= MESA_SHADER_STAGES, 3795b8e80941Smrg "AddressingModelLogical only supported for shaders"); 3796b8e80941Smrg b->shader->info.cs.ptr_size = 0; 3797b8e80941Smrg b->physical_ptrs = false; 3798b8e80941Smrg break; 3799b8e80941Smrg case SpvAddressingModelPhysicalStorageBuffer64EXT: 3800b8e80941Smrg vtn_fail_if(!b->options || 3801b8e80941Smrg !b->options->caps.physical_storage_buffer_address, 3802b8e80941Smrg "AddressingModelPhysicalStorageBuffer64EXT not supported"); 3803b8e80941Smrg break; 3804b8e80941Smrg default: 3805b8e80941Smrg vtn_fail("Unknown addressing model: %s (%u)", 3806b8e80941Smrg spirv_addressingmodel_to_string(w[1]), w[1]); 3807b8e80941Smrg break; 3808b8e80941Smrg } 3809b8e80941Smrg 3810b8e80941Smrg vtn_assert(w[2] == SpvMemoryModelSimple || 3811b8e80941Smrg w[2] == SpvMemoryModelGLSL450 || 3812b8e80941Smrg w[2] == SpvMemoryModelOpenCL); 3813b8e80941Smrg break; 3814b8e80941Smrg 3815b8e80941Smrg case SpvOpEntryPoint: 3816b8e80941Smrg vtn_handle_entry_point(b, w, count); 3817b8e80941Smrg break; 3818b8e80941Smrg 3819b8e80941Smrg case SpvOpString: 3820b8e80941Smrg vtn_push_value(b, w[1], vtn_value_type_string)->str = 3821b8e80941Smrg vtn_string_literal(b, &w[2], count - 2, NULL); 3822b8e80941Smrg break; 3823b8e80941Smrg 3824b8e80941Smrg case SpvOpName: 3825b8e80941Smrg b->values[w[1]].name = vtn_string_literal(b, &w[2], count - 2, NULL); 3826b8e80941Smrg break; 3827b8e80941Smrg 3828b8e80941Smrg case SpvOpMemberName: 3829b8e80941Smrg /* TODO */ 3830b8e80941Smrg break; 3831b8e80941Smrg 3832b8e80941Smrg case SpvOpExecutionMode: 3833b8e80941Smrg case SpvOpExecutionModeId: 3834b8e80941Smrg case SpvOpDecorationGroup: 3835b8e80941Smrg case SpvOpDecorate: 3836b8e80941Smrg case SpvOpDecorateId: 3837b8e80941Smrg case SpvOpMemberDecorate: 3838b8e80941Smrg case SpvOpGroupDecorate: 3839b8e80941Smrg case SpvOpGroupMemberDecorate: 3840b8e80941Smrg case SpvOpDecorateStringGOOGLE: 3841b8e80941Smrg case SpvOpMemberDecorateStringGOOGLE: 3842b8e80941Smrg vtn_handle_decoration(b, opcode, w, count); 3843b8e80941Smrg break; 3844b8e80941Smrg 3845b8e80941Smrg default: 3846b8e80941Smrg return false; /* End of preamble */ 3847b8e80941Smrg } 3848b8e80941Smrg 3849b8e80941Smrg return true; 3850b8e80941Smrg} 3851b8e80941Smrg 3852b8e80941Smrgstatic void 3853b8e80941Smrgvtn_handle_execution_mode(struct vtn_builder *b, struct vtn_value *entry_point, 3854b8e80941Smrg const struct vtn_decoration *mode, void *data) 3855b8e80941Smrg{ 3856b8e80941Smrg vtn_assert(b->entry_point == entry_point); 3857b8e80941Smrg 3858b8e80941Smrg switch(mode->exec_mode) { 3859b8e80941Smrg case SpvExecutionModeOriginUpperLeft: 3860b8e80941Smrg case SpvExecutionModeOriginLowerLeft: 3861b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT); 3862b8e80941Smrg b->shader->info.fs.origin_upper_left = 3863b8e80941Smrg (mode->exec_mode == SpvExecutionModeOriginUpperLeft); 3864b8e80941Smrg break; 3865b8e80941Smrg 3866b8e80941Smrg case SpvExecutionModeEarlyFragmentTests: 3867b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT); 3868b8e80941Smrg b->shader->info.fs.early_fragment_tests = true; 3869b8e80941Smrg break; 3870b8e80941Smrg 3871b8e80941Smrg case SpvExecutionModePostDepthCoverage: 3872b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT); 3873b8e80941Smrg b->shader->info.fs.post_depth_coverage = true; 3874b8e80941Smrg break; 3875b8e80941Smrg 3876b8e80941Smrg case SpvExecutionModeInvocations: 3877b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_GEOMETRY); 3878b8e80941Smrg b->shader->info.gs.invocations = MAX2(1, mode->operands[0]); 3879b8e80941Smrg break; 3880b8e80941Smrg 3881b8e80941Smrg case SpvExecutionModeDepthReplacing: 3882b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT); 3883b8e80941Smrg b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_ANY; 3884b8e80941Smrg break; 3885b8e80941Smrg case SpvExecutionModeDepthGreater: 3886b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT); 3887b8e80941Smrg b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_GREATER; 3888b8e80941Smrg break; 3889b8e80941Smrg case SpvExecutionModeDepthLess: 3890b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT); 3891b8e80941Smrg b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_LESS; 3892b8e80941Smrg break; 3893b8e80941Smrg case SpvExecutionModeDepthUnchanged: 3894b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT); 3895b8e80941Smrg b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_UNCHANGED; 3896b8e80941Smrg break; 3897b8e80941Smrg 3898b8e80941Smrg case SpvExecutionModeLocalSize: 3899b8e80941Smrg vtn_assert(gl_shader_stage_is_compute(b->shader->info.stage)); 3900b8e80941Smrg b->shader->info.cs.local_size[0] = mode->operands[0]; 3901b8e80941Smrg b->shader->info.cs.local_size[1] = mode->operands[1]; 3902b8e80941Smrg b->shader->info.cs.local_size[2] = mode->operands[2]; 3903b8e80941Smrg break; 3904b8e80941Smrg 3905b8e80941Smrg case SpvExecutionModeLocalSizeId: 3906b8e80941Smrg b->shader->info.cs.local_size[0] = vtn_constant_uint(b, mode->operands[0]); 3907b8e80941Smrg b->shader->info.cs.local_size[1] = vtn_constant_uint(b, mode->operands[1]); 3908b8e80941Smrg b->shader->info.cs.local_size[2] = vtn_constant_uint(b, mode->operands[2]); 3909b8e80941Smrg break; 3910b8e80941Smrg 3911b8e80941Smrg case SpvExecutionModeLocalSizeHint: 3912b8e80941Smrg case SpvExecutionModeLocalSizeHintId: 3913b8e80941Smrg break; /* Nothing to do with this */ 3914b8e80941Smrg 3915b8e80941Smrg case SpvExecutionModeOutputVertices: 3916b8e80941Smrg if (b->shader->info.stage == MESA_SHADER_TESS_CTRL || 3917b8e80941Smrg b->shader->info.stage == MESA_SHADER_TESS_EVAL) { 3918b8e80941Smrg b->shader->info.tess.tcs_vertices_out = mode->operands[0]; 3919b8e80941Smrg } else { 3920b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_GEOMETRY); 3921b8e80941Smrg b->shader->info.gs.vertices_out = mode->operands[0]; 3922b8e80941Smrg } 3923b8e80941Smrg break; 3924b8e80941Smrg 3925b8e80941Smrg case SpvExecutionModeInputPoints: 3926b8e80941Smrg case SpvExecutionModeInputLines: 3927b8e80941Smrg case SpvExecutionModeInputLinesAdjacency: 3928b8e80941Smrg case SpvExecutionModeTriangles: 3929b8e80941Smrg case SpvExecutionModeInputTrianglesAdjacency: 3930b8e80941Smrg case SpvExecutionModeQuads: 3931b8e80941Smrg case SpvExecutionModeIsolines: 3932b8e80941Smrg if (b->shader->info.stage == MESA_SHADER_TESS_CTRL || 3933b8e80941Smrg b->shader->info.stage == MESA_SHADER_TESS_EVAL) { 3934b8e80941Smrg b->shader->info.tess.primitive_mode = 3935b8e80941Smrg gl_primitive_from_spv_execution_mode(b, mode->exec_mode); 3936b8e80941Smrg } else { 3937b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_GEOMETRY); 3938b8e80941Smrg b->shader->info.gs.vertices_in = 3939b8e80941Smrg vertices_in_from_spv_execution_mode(b, mode->exec_mode); 3940b8e80941Smrg b->shader->info.gs.input_primitive = 3941b8e80941Smrg gl_primitive_from_spv_execution_mode(b, mode->exec_mode); 3942b8e80941Smrg } 3943b8e80941Smrg break; 3944b8e80941Smrg 3945b8e80941Smrg case SpvExecutionModeOutputPoints: 3946b8e80941Smrg case SpvExecutionModeOutputLineStrip: 3947b8e80941Smrg case SpvExecutionModeOutputTriangleStrip: 3948b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_GEOMETRY); 3949b8e80941Smrg b->shader->info.gs.output_primitive = 3950b8e80941Smrg gl_primitive_from_spv_execution_mode(b, mode->exec_mode); 3951b8e80941Smrg break; 3952b8e80941Smrg 3953b8e80941Smrg case SpvExecutionModeSpacingEqual: 3954b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL || 3955b8e80941Smrg b->shader->info.stage == MESA_SHADER_TESS_EVAL); 3956b8e80941Smrg b->shader->info.tess.spacing = TESS_SPACING_EQUAL; 3957b8e80941Smrg break; 3958b8e80941Smrg case SpvExecutionModeSpacingFractionalEven: 3959b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL || 3960b8e80941Smrg b->shader->info.stage == MESA_SHADER_TESS_EVAL); 3961b8e80941Smrg b->shader->info.tess.spacing = TESS_SPACING_FRACTIONAL_EVEN; 3962b8e80941Smrg break; 3963b8e80941Smrg case SpvExecutionModeSpacingFractionalOdd: 3964b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL || 3965b8e80941Smrg b->shader->info.stage == MESA_SHADER_TESS_EVAL); 3966b8e80941Smrg b->shader->info.tess.spacing = TESS_SPACING_FRACTIONAL_ODD; 3967b8e80941Smrg break; 3968b8e80941Smrg case SpvExecutionModeVertexOrderCw: 3969b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL || 3970b8e80941Smrg b->shader->info.stage == MESA_SHADER_TESS_EVAL); 3971b8e80941Smrg b->shader->info.tess.ccw = false; 3972b8e80941Smrg break; 3973b8e80941Smrg case SpvExecutionModeVertexOrderCcw: 3974b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL || 3975b8e80941Smrg b->shader->info.stage == MESA_SHADER_TESS_EVAL); 3976b8e80941Smrg b->shader->info.tess.ccw = true; 3977b8e80941Smrg break; 3978b8e80941Smrg case SpvExecutionModePointMode: 3979b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL || 3980b8e80941Smrg b->shader->info.stage == MESA_SHADER_TESS_EVAL); 3981b8e80941Smrg b->shader->info.tess.point_mode = true; 3982b8e80941Smrg break; 3983b8e80941Smrg 3984b8e80941Smrg case SpvExecutionModePixelCenterInteger: 3985b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT); 3986b8e80941Smrg b->shader->info.fs.pixel_center_integer = true; 3987b8e80941Smrg break; 3988b8e80941Smrg 3989b8e80941Smrg case SpvExecutionModeXfb: 3990b8e80941Smrg b->shader->info.has_transform_feedback_varyings = true; 3991b8e80941Smrg break; 3992b8e80941Smrg 3993b8e80941Smrg case SpvExecutionModeVecTypeHint: 3994b8e80941Smrg break; /* OpenCL */ 3995b8e80941Smrg 3996b8e80941Smrg case SpvExecutionModeContractionOff: 3997b8e80941Smrg if (b->shader->info.stage != MESA_SHADER_KERNEL) 3998b8e80941Smrg vtn_warn("ExectionMode only allowed for CL-style kernels: %s", 3999b8e80941Smrg spirv_executionmode_to_string(mode->exec_mode)); 4000b8e80941Smrg else 4001b8e80941Smrg b->exact = true; 4002b8e80941Smrg break; 4003b8e80941Smrg 4004b8e80941Smrg case SpvExecutionModeStencilRefReplacingEXT: 4005b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_FRAGMENT); 4006b8e80941Smrg break; 4007b8e80941Smrg 4008b8e80941Smrg case SpvExecutionModeDerivativeGroupQuadsNV: 4009b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_COMPUTE); 4010b8e80941Smrg b->shader->info.cs.derivative_group = DERIVATIVE_GROUP_QUADS; 4011b8e80941Smrg break; 4012b8e80941Smrg 4013b8e80941Smrg case SpvExecutionModeDerivativeGroupLinearNV: 4014b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_COMPUTE); 4015b8e80941Smrg b->shader->info.cs.derivative_group = DERIVATIVE_GROUP_LINEAR; 4016b8e80941Smrg break; 4017b8e80941Smrg 4018b8e80941Smrg default: 4019b8e80941Smrg vtn_fail("Unhandled execution mode: %s (%u)", 4020b8e80941Smrg spirv_executionmode_to_string(mode->exec_mode), 4021b8e80941Smrg mode->exec_mode); 4022b8e80941Smrg } 4023b8e80941Smrg} 4024b8e80941Smrg 4025b8e80941Smrgstatic bool 4026b8e80941Smrgvtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode, 4027b8e80941Smrg const uint32_t *w, unsigned count) 4028b8e80941Smrg{ 4029b8e80941Smrg vtn_set_instruction_result_type(b, opcode, w, count); 4030b8e80941Smrg 4031b8e80941Smrg switch (opcode) { 4032b8e80941Smrg case SpvOpSource: 4033b8e80941Smrg case SpvOpSourceContinued: 4034b8e80941Smrg case SpvOpSourceExtension: 4035b8e80941Smrg case SpvOpExtension: 4036b8e80941Smrg case SpvOpCapability: 4037b8e80941Smrg case SpvOpExtInstImport: 4038b8e80941Smrg case SpvOpMemoryModel: 4039b8e80941Smrg case SpvOpEntryPoint: 4040b8e80941Smrg case SpvOpExecutionMode: 4041b8e80941Smrg case SpvOpString: 4042b8e80941Smrg case SpvOpName: 4043b8e80941Smrg case SpvOpMemberName: 4044b8e80941Smrg case SpvOpDecorationGroup: 4045b8e80941Smrg case SpvOpDecorate: 4046b8e80941Smrg case SpvOpDecorateId: 4047b8e80941Smrg case SpvOpMemberDecorate: 4048b8e80941Smrg case SpvOpGroupDecorate: 4049b8e80941Smrg case SpvOpGroupMemberDecorate: 4050b8e80941Smrg case SpvOpDecorateStringGOOGLE: 4051b8e80941Smrg case SpvOpMemberDecorateStringGOOGLE: 4052b8e80941Smrg vtn_fail("Invalid opcode types and variables section"); 4053b8e80941Smrg break; 4054b8e80941Smrg 4055b8e80941Smrg case SpvOpTypeVoid: 4056b8e80941Smrg case SpvOpTypeBool: 4057b8e80941Smrg case SpvOpTypeInt: 4058b8e80941Smrg case SpvOpTypeFloat: 4059b8e80941Smrg case SpvOpTypeVector: 4060b8e80941Smrg case SpvOpTypeMatrix: 4061b8e80941Smrg case SpvOpTypeImage: 4062b8e80941Smrg case SpvOpTypeSampler: 4063b8e80941Smrg case SpvOpTypeSampledImage: 4064b8e80941Smrg case SpvOpTypeArray: 4065b8e80941Smrg case SpvOpTypeRuntimeArray: 4066b8e80941Smrg case SpvOpTypeStruct: 4067b8e80941Smrg case SpvOpTypeOpaque: 4068b8e80941Smrg case SpvOpTypePointer: 4069b8e80941Smrg case SpvOpTypeForwardPointer: 4070b8e80941Smrg case SpvOpTypeFunction: 4071b8e80941Smrg case SpvOpTypeEvent: 4072b8e80941Smrg case SpvOpTypeDeviceEvent: 4073b8e80941Smrg case SpvOpTypeReserveId: 4074b8e80941Smrg case SpvOpTypeQueue: 4075b8e80941Smrg case SpvOpTypePipe: 4076b8e80941Smrg vtn_handle_type(b, opcode, w, count); 4077b8e80941Smrg break; 4078b8e80941Smrg 4079b8e80941Smrg case SpvOpConstantTrue: 4080b8e80941Smrg case SpvOpConstantFalse: 4081b8e80941Smrg case SpvOpConstant: 4082b8e80941Smrg case SpvOpConstantComposite: 4083b8e80941Smrg case SpvOpConstantSampler: 4084b8e80941Smrg case SpvOpConstantNull: 4085b8e80941Smrg case SpvOpSpecConstantTrue: 4086b8e80941Smrg case SpvOpSpecConstantFalse: 4087b8e80941Smrg case SpvOpSpecConstant: 4088b8e80941Smrg case SpvOpSpecConstantComposite: 4089b8e80941Smrg case SpvOpSpecConstantOp: 4090b8e80941Smrg vtn_handle_constant(b, opcode, w, count); 4091b8e80941Smrg break; 4092b8e80941Smrg 4093b8e80941Smrg case SpvOpUndef: 4094b8e80941Smrg case SpvOpVariable: 4095b8e80941Smrg vtn_handle_variables(b, opcode, w, count); 4096b8e80941Smrg break; 4097b8e80941Smrg 4098b8e80941Smrg default: 4099b8e80941Smrg return false; /* End of preamble */ 4100b8e80941Smrg } 4101b8e80941Smrg 4102b8e80941Smrg return true; 4103b8e80941Smrg} 4104b8e80941Smrg 4105b8e80941Smrgstatic bool 4106b8e80941Smrgvtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode, 4107b8e80941Smrg const uint32_t *w, unsigned count) 4108b8e80941Smrg{ 4109b8e80941Smrg switch (opcode) { 4110b8e80941Smrg case SpvOpLabel: 4111b8e80941Smrg break; 4112b8e80941Smrg 4113b8e80941Smrg case SpvOpLoopMerge: 4114b8e80941Smrg case SpvOpSelectionMerge: 4115b8e80941Smrg /* This is handled by cfg pre-pass and walk_blocks */ 4116b8e80941Smrg break; 4117b8e80941Smrg 4118b8e80941Smrg case SpvOpUndef: { 4119b8e80941Smrg struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_undef); 4120b8e80941Smrg val->type = vtn_value(b, w[1], vtn_value_type_type)->type; 4121b8e80941Smrg break; 4122b8e80941Smrg } 4123b8e80941Smrg 4124b8e80941Smrg case SpvOpExtInst: 4125b8e80941Smrg vtn_handle_extension(b, opcode, w, count); 4126b8e80941Smrg break; 4127b8e80941Smrg 4128b8e80941Smrg case SpvOpVariable: 4129b8e80941Smrg case SpvOpLoad: 4130b8e80941Smrg case SpvOpStore: 4131b8e80941Smrg case SpvOpCopyMemory: 4132b8e80941Smrg case SpvOpCopyMemorySized: 4133b8e80941Smrg case SpvOpAccessChain: 4134b8e80941Smrg case SpvOpPtrAccessChain: 4135b8e80941Smrg case SpvOpInBoundsAccessChain: 4136b8e80941Smrg case SpvOpInBoundsPtrAccessChain: 4137b8e80941Smrg case SpvOpArrayLength: 4138b8e80941Smrg case SpvOpConvertPtrToU: 4139b8e80941Smrg case SpvOpConvertUToPtr: 4140b8e80941Smrg vtn_handle_variables(b, opcode, w, count); 4141b8e80941Smrg break; 4142b8e80941Smrg 4143b8e80941Smrg case SpvOpFunctionCall: 4144b8e80941Smrg vtn_handle_function_call(b, opcode, w, count); 4145b8e80941Smrg break; 4146b8e80941Smrg 4147b8e80941Smrg case SpvOpSampledImage: 4148b8e80941Smrg case SpvOpImage: 4149b8e80941Smrg case SpvOpImageSampleImplicitLod: 4150b8e80941Smrg case SpvOpImageSampleExplicitLod: 4151b8e80941Smrg case SpvOpImageSampleDrefImplicitLod: 4152b8e80941Smrg case SpvOpImageSampleDrefExplicitLod: 4153b8e80941Smrg case SpvOpImageSampleProjImplicitLod: 4154b8e80941Smrg case SpvOpImageSampleProjExplicitLod: 4155b8e80941Smrg case SpvOpImageSampleProjDrefImplicitLod: 4156b8e80941Smrg case SpvOpImageSampleProjDrefExplicitLod: 4157b8e80941Smrg case SpvOpImageFetch: 4158b8e80941Smrg case SpvOpImageGather: 4159b8e80941Smrg case SpvOpImageDrefGather: 4160b8e80941Smrg case SpvOpImageQuerySizeLod: 4161b8e80941Smrg case SpvOpImageQueryLod: 4162b8e80941Smrg case SpvOpImageQueryLevels: 4163b8e80941Smrg case SpvOpImageQuerySamples: 4164b8e80941Smrg vtn_handle_texture(b, opcode, w, count); 4165b8e80941Smrg break; 4166b8e80941Smrg 4167b8e80941Smrg case SpvOpImageRead: 4168b8e80941Smrg case SpvOpImageWrite: 4169b8e80941Smrg case SpvOpImageTexelPointer: 4170b8e80941Smrg vtn_handle_image(b, opcode, w, count); 4171b8e80941Smrg break; 4172b8e80941Smrg 4173b8e80941Smrg case SpvOpImageQuerySize: { 4174b8e80941Smrg struct vtn_pointer *image = 4175b8e80941Smrg vtn_value(b, w[3], vtn_value_type_pointer)->pointer; 4176b8e80941Smrg if (glsl_type_is_image(image->type->type)) { 4177b8e80941Smrg vtn_handle_image(b, opcode, w, count); 4178b8e80941Smrg } else { 4179b8e80941Smrg vtn_assert(glsl_type_is_sampler(image->type->type)); 4180b8e80941Smrg vtn_handle_texture(b, opcode, w, count); 4181b8e80941Smrg } 4182b8e80941Smrg break; 4183b8e80941Smrg } 4184b8e80941Smrg 4185b8e80941Smrg case SpvOpAtomicLoad: 4186b8e80941Smrg case SpvOpAtomicExchange: 4187b8e80941Smrg case SpvOpAtomicCompareExchange: 4188b8e80941Smrg case SpvOpAtomicCompareExchangeWeak: 4189b8e80941Smrg case SpvOpAtomicIIncrement: 4190b8e80941Smrg case SpvOpAtomicIDecrement: 4191b8e80941Smrg case SpvOpAtomicIAdd: 4192b8e80941Smrg case SpvOpAtomicISub: 4193b8e80941Smrg case SpvOpAtomicSMin: 4194b8e80941Smrg case SpvOpAtomicUMin: 4195b8e80941Smrg case SpvOpAtomicSMax: 4196b8e80941Smrg case SpvOpAtomicUMax: 4197b8e80941Smrg case SpvOpAtomicAnd: 4198b8e80941Smrg case SpvOpAtomicOr: 4199b8e80941Smrg case SpvOpAtomicXor: { 4200b8e80941Smrg struct vtn_value *pointer = vtn_untyped_value(b, w[3]); 4201b8e80941Smrg if (pointer->value_type == vtn_value_type_image_pointer) { 4202b8e80941Smrg vtn_handle_image(b, opcode, w, count); 4203b8e80941Smrg } else { 4204b8e80941Smrg vtn_assert(pointer->value_type == vtn_value_type_pointer); 4205b8e80941Smrg vtn_handle_atomics(b, opcode, w, count); 4206b8e80941Smrg } 4207b8e80941Smrg break; 4208b8e80941Smrg } 4209b8e80941Smrg 4210b8e80941Smrg case SpvOpAtomicStore: { 4211b8e80941Smrg struct vtn_value *pointer = vtn_untyped_value(b, w[1]); 4212b8e80941Smrg if (pointer->value_type == vtn_value_type_image_pointer) { 4213b8e80941Smrg vtn_handle_image(b, opcode, w, count); 4214b8e80941Smrg } else { 4215b8e80941Smrg vtn_assert(pointer->value_type == vtn_value_type_pointer); 4216b8e80941Smrg vtn_handle_atomics(b, opcode, w, count); 4217b8e80941Smrg } 4218b8e80941Smrg break; 4219b8e80941Smrg } 4220b8e80941Smrg 4221b8e80941Smrg case SpvOpSelect: { 4222b8e80941Smrg /* Handle OpSelect up-front here because it needs to be able to handle 4223b8e80941Smrg * pointers and not just regular vectors and scalars. 4224b8e80941Smrg */ 4225b8e80941Smrg struct vtn_value *res_val = vtn_untyped_value(b, w[2]); 4226b8e80941Smrg struct vtn_value *sel_val = vtn_untyped_value(b, w[3]); 4227b8e80941Smrg struct vtn_value *obj1_val = vtn_untyped_value(b, w[4]); 4228b8e80941Smrg struct vtn_value *obj2_val = vtn_untyped_value(b, w[5]); 4229b8e80941Smrg 4230b8e80941Smrg const struct glsl_type *sel_type; 4231b8e80941Smrg switch (res_val->type->base_type) { 4232b8e80941Smrg case vtn_base_type_scalar: 4233b8e80941Smrg sel_type = glsl_bool_type(); 4234b8e80941Smrg break; 4235b8e80941Smrg case vtn_base_type_vector: 4236b8e80941Smrg sel_type = glsl_vector_type(GLSL_TYPE_BOOL, res_val->type->length); 4237b8e80941Smrg break; 4238b8e80941Smrg case vtn_base_type_pointer: 4239b8e80941Smrg /* We need to have actual storage for pointer types */ 4240b8e80941Smrg vtn_fail_if(res_val->type->type == NULL, 4241b8e80941Smrg "Invalid pointer result type for OpSelect"); 4242b8e80941Smrg sel_type = glsl_bool_type(); 4243b8e80941Smrg break; 4244b8e80941Smrg default: 4245b8e80941Smrg vtn_fail("Result type of OpSelect must be a scalar, vector, or pointer"); 4246b8e80941Smrg } 4247b8e80941Smrg 4248b8e80941Smrg if (unlikely(sel_val->type->type != sel_type)) { 4249b8e80941Smrg if (sel_val->type->type == glsl_bool_type()) { 4250b8e80941Smrg /* This case is illegal but some older versions of GLSLang produce 4251b8e80941Smrg * it. The GLSLang issue was fixed on March 30, 2017: 4252b8e80941Smrg * 4253b8e80941Smrg * https://github.com/KhronosGroup/glslang/issues/809 4254b8e80941Smrg * 4255b8e80941Smrg * Unfortunately, there are applications in the wild which are 4256b8e80941Smrg * shipping with this bug so it isn't nice to fail on them so we 4257b8e80941Smrg * throw a warning instead. It's not actually a problem for us as 4258b8e80941Smrg * nir_builder will just splat the condition out which is most 4259b8e80941Smrg * likely what the client wanted anyway. 4260b8e80941Smrg */ 4261b8e80941Smrg vtn_warn("Condition type of OpSelect must have the same number " 4262b8e80941Smrg "of components as Result Type"); 4263b8e80941Smrg } else { 4264b8e80941Smrg vtn_fail("Condition type of OpSelect must be a scalar or vector " 4265b8e80941Smrg "of Boolean type. It must have the same number of " 4266b8e80941Smrg "components as Result Type"); 4267b8e80941Smrg } 4268b8e80941Smrg } 4269b8e80941Smrg 4270b8e80941Smrg vtn_fail_if(obj1_val->type != res_val->type || 4271b8e80941Smrg obj2_val->type != res_val->type, 4272b8e80941Smrg "Object types must match the result type in OpSelect"); 4273b8e80941Smrg 4274b8e80941Smrg struct vtn_type *res_type = vtn_value(b, w[1], vtn_value_type_type)->type; 4275b8e80941Smrg struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, res_type->type); 4276b8e80941Smrg ssa->def = nir_bcsel(&b->nb, vtn_ssa_value(b, w[3])->def, 4277b8e80941Smrg vtn_ssa_value(b, w[4])->def, 4278b8e80941Smrg vtn_ssa_value(b, w[5])->def); 4279b8e80941Smrg vtn_push_ssa(b, w[2], res_type, ssa); 4280b8e80941Smrg break; 4281b8e80941Smrg } 4282b8e80941Smrg 4283b8e80941Smrg case SpvOpSNegate: 4284b8e80941Smrg case SpvOpFNegate: 4285b8e80941Smrg case SpvOpNot: 4286b8e80941Smrg case SpvOpAny: 4287b8e80941Smrg case SpvOpAll: 4288b8e80941Smrg case SpvOpConvertFToU: 4289b8e80941Smrg case SpvOpConvertFToS: 4290b8e80941Smrg case SpvOpConvertSToF: 4291b8e80941Smrg case SpvOpConvertUToF: 4292b8e80941Smrg case SpvOpUConvert: 4293b8e80941Smrg case SpvOpSConvert: 4294b8e80941Smrg case SpvOpFConvert: 4295b8e80941Smrg case SpvOpQuantizeToF16: 4296b8e80941Smrg case SpvOpPtrCastToGeneric: 4297b8e80941Smrg case SpvOpGenericCastToPtr: 4298b8e80941Smrg case SpvOpIsNan: 4299b8e80941Smrg case SpvOpIsInf: 4300b8e80941Smrg case SpvOpIsFinite: 4301b8e80941Smrg case SpvOpIsNormal: 4302b8e80941Smrg case SpvOpSignBitSet: 4303b8e80941Smrg case SpvOpLessOrGreater: 4304b8e80941Smrg case SpvOpOrdered: 4305b8e80941Smrg case SpvOpUnordered: 4306b8e80941Smrg case SpvOpIAdd: 4307b8e80941Smrg case SpvOpFAdd: 4308b8e80941Smrg case SpvOpISub: 4309b8e80941Smrg case SpvOpFSub: 4310b8e80941Smrg case SpvOpIMul: 4311b8e80941Smrg case SpvOpFMul: 4312b8e80941Smrg case SpvOpUDiv: 4313b8e80941Smrg case SpvOpSDiv: 4314b8e80941Smrg case SpvOpFDiv: 4315b8e80941Smrg case SpvOpUMod: 4316b8e80941Smrg case SpvOpSRem: 4317b8e80941Smrg case SpvOpSMod: 4318b8e80941Smrg case SpvOpFRem: 4319b8e80941Smrg case SpvOpFMod: 4320b8e80941Smrg case SpvOpVectorTimesScalar: 4321b8e80941Smrg case SpvOpDot: 4322b8e80941Smrg case SpvOpIAddCarry: 4323b8e80941Smrg case SpvOpISubBorrow: 4324b8e80941Smrg case SpvOpUMulExtended: 4325b8e80941Smrg case SpvOpSMulExtended: 4326b8e80941Smrg case SpvOpShiftRightLogical: 4327b8e80941Smrg case SpvOpShiftRightArithmetic: 4328b8e80941Smrg case SpvOpShiftLeftLogical: 4329b8e80941Smrg case SpvOpLogicalEqual: 4330b8e80941Smrg case SpvOpLogicalNotEqual: 4331b8e80941Smrg case SpvOpLogicalOr: 4332b8e80941Smrg case SpvOpLogicalAnd: 4333b8e80941Smrg case SpvOpLogicalNot: 4334b8e80941Smrg case SpvOpBitwiseOr: 4335b8e80941Smrg case SpvOpBitwiseXor: 4336b8e80941Smrg case SpvOpBitwiseAnd: 4337b8e80941Smrg case SpvOpIEqual: 4338b8e80941Smrg case SpvOpFOrdEqual: 4339b8e80941Smrg case SpvOpFUnordEqual: 4340b8e80941Smrg case SpvOpINotEqual: 4341b8e80941Smrg case SpvOpFOrdNotEqual: 4342b8e80941Smrg case SpvOpFUnordNotEqual: 4343b8e80941Smrg case SpvOpULessThan: 4344b8e80941Smrg case SpvOpSLessThan: 4345b8e80941Smrg case SpvOpFOrdLessThan: 4346b8e80941Smrg case SpvOpFUnordLessThan: 4347b8e80941Smrg case SpvOpUGreaterThan: 4348b8e80941Smrg case SpvOpSGreaterThan: 4349b8e80941Smrg case SpvOpFOrdGreaterThan: 4350b8e80941Smrg case SpvOpFUnordGreaterThan: 4351b8e80941Smrg case SpvOpULessThanEqual: 4352b8e80941Smrg case SpvOpSLessThanEqual: 4353b8e80941Smrg case SpvOpFOrdLessThanEqual: 4354b8e80941Smrg case SpvOpFUnordLessThanEqual: 4355b8e80941Smrg case SpvOpUGreaterThanEqual: 4356b8e80941Smrg case SpvOpSGreaterThanEqual: 4357b8e80941Smrg case SpvOpFOrdGreaterThanEqual: 4358b8e80941Smrg case SpvOpFUnordGreaterThanEqual: 4359b8e80941Smrg case SpvOpDPdx: 4360b8e80941Smrg case SpvOpDPdy: 4361b8e80941Smrg case SpvOpFwidth: 4362b8e80941Smrg case SpvOpDPdxFine: 4363b8e80941Smrg case SpvOpDPdyFine: 4364b8e80941Smrg case SpvOpFwidthFine: 4365b8e80941Smrg case SpvOpDPdxCoarse: 4366b8e80941Smrg case SpvOpDPdyCoarse: 4367b8e80941Smrg case SpvOpFwidthCoarse: 4368b8e80941Smrg case SpvOpBitFieldInsert: 4369b8e80941Smrg case SpvOpBitFieldSExtract: 4370b8e80941Smrg case SpvOpBitFieldUExtract: 4371b8e80941Smrg case SpvOpBitReverse: 4372b8e80941Smrg case SpvOpBitCount: 4373b8e80941Smrg case SpvOpTranspose: 4374b8e80941Smrg case SpvOpOuterProduct: 4375b8e80941Smrg case SpvOpMatrixTimesScalar: 4376b8e80941Smrg case SpvOpVectorTimesMatrix: 4377b8e80941Smrg case SpvOpMatrixTimesVector: 4378b8e80941Smrg case SpvOpMatrixTimesMatrix: 4379b8e80941Smrg vtn_handle_alu(b, opcode, w, count); 4380b8e80941Smrg break; 4381b8e80941Smrg 4382b8e80941Smrg case SpvOpBitcast: 4383b8e80941Smrg vtn_handle_bitcast(b, w, count); 4384b8e80941Smrg break; 4385b8e80941Smrg 4386b8e80941Smrg case SpvOpVectorExtractDynamic: 4387b8e80941Smrg case SpvOpVectorInsertDynamic: 4388b8e80941Smrg case SpvOpVectorShuffle: 4389b8e80941Smrg case SpvOpCompositeConstruct: 4390b8e80941Smrg case SpvOpCompositeExtract: 4391b8e80941Smrg case SpvOpCompositeInsert: 4392b8e80941Smrg case SpvOpCopyObject: 4393b8e80941Smrg vtn_handle_composite(b, opcode, w, count); 4394b8e80941Smrg break; 4395b8e80941Smrg 4396b8e80941Smrg case SpvOpEmitVertex: 4397b8e80941Smrg case SpvOpEndPrimitive: 4398b8e80941Smrg case SpvOpEmitStreamVertex: 4399b8e80941Smrg case SpvOpEndStreamPrimitive: 4400b8e80941Smrg case SpvOpControlBarrier: 4401b8e80941Smrg case SpvOpMemoryBarrier: 4402b8e80941Smrg vtn_handle_barrier(b, opcode, w, count); 4403b8e80941Smrg break; 4404b8e80941Smrg 4405b8e80941Smrg case SpvOpGroupNonUniformElect: 4406b8e80941Smrg case SpvOpGroupNonUniformAll: 4407b8e80941Smrg case SpvOpGroupNonUniformAny: 4408b8e80941Smrg case SpvOpGroupNonUniformAllEqual: 4409b8e80941Smrg case SpvOpGroupNonUniformBroadcast: 4410b8e80941Smrg case SpvOpGroupNonUniformBroadcastFirst: 4411b8e80941Smrg case SpvOpGroupNonUniformBallot: 4412b8e80941Smrg case SpvOpGroupNonUniformInverseBallot: 4413b8e80941Smrg case SpvOpGroupNonUniformBallotBitExtract: 4414b8e80941Smrg case SpvOpGroupNonUniformBallotBitCount: 4415b8e80941Smrg case SpvOpGroupNonUniformBallotFindLSB: 4416b8e80941Smrg case SpvOpGroupNonUniformBallotFindMSB: 4417b8e80941Smrg case SpvOpGroupNonUniformShuffle: 4418b8e80941Smrg case SpvOpGroupNonUniformShuffleXor: 4419b8e80941Smrg case SpvOpGroupNonUniformShuffleUp: 4420b8e80941Smrg case SpvOpGroupNonUniformShuffleDown: 4421b8e80941Smrg case SpvOpGroupNonUniformIAdd: 4422b8e80941Smrg case SpvOpGroupNonUniformFAdd: 4423b8e80941Smrg case SpvOpGroupNonUniformIMul: 4424b8e80941Smrg case SpvOpGroupNonUniformFMul: 4425b8e80941Smrg case SpvOpGroupNonUniformSMin: 4426b8e80941Smrg case SpvOpGroupNonUniformUMin: 4427b8e80941Smrg case SpvOpGroupNonUniformFMin: 4428b8e80941Smrg case SpvOpGroupNonUniformSMax: 4429b8e80941Smrg case SpvOpGroupNonUniformUMax: 4430b8e80941Smrg case SpvOpGroupNonUniformFMax: 4431b8e80941Smrg case SpvOpGroupNonUniformBitwiseAnd: 4432b8e80941Smrg case SpvOpGroupNonUniformBitwiseOr: 4433b8e80941Smrg case SpvOpGroupNonUniformBitwiseXor: 4434b8e80941Smrg case SpvOpGroupNonUniformLogicalAnd: 4435b8e80941Smrg case SpvOpGroupNonUniformLogicalOr: 4436b8e80941Smrg case SpvOpGroupNonUniformLogicalXor: 4437b8e80941Smrg case SpvOpGroupNonUniformQuadBroadcast: 4438b8e80941Smrg case SpvOpGroupNonUniformQuadSwap: 4439b8e80941Smrg vtn_handle_subgroup(b, opcode, w, count); 4440b8e80941Smrg break; 4441b8e80941Smrg 4442b8e80941Smrg default: 4443b8e80941Smrg vtn_fail_with_opcode("Unhandled opcode", opcode); 4444b8e80941Smrg } 4445b8e80941Smrg 4446b8e80941Smrg return true; 4447b8e80941Smrg} 4448b8e80941Smrg 4449b8e80941Smrgstruct vtn_builder* 4450b8e80941Smrgvtn_create_builder(const uint32_t *words, size_t word_count, 4451b8e80941Smrg gl_shader_stage stage, const char *entry_point_name, 4452b8e80941Smrg const struct spirv_to_nir_options *options) 4453b8e80941Smrg{ 4454b8e80941Smrg /* Initialize the vtn_builder object */ 4455b8e80941Smrg struct vtn_builder *b = rzalloc(NULL, struct vtn_builder); 4456b8e80941Smrg struct spirv_to_nir_options *dup_options = 4457b8e80941Smrg ralloc(b, struct spirv_to_nir_options); 4458b8e80941Smrg *dup_options = *options; 4459b8e80941Smrg 4460b8e80941Smrg b->spirv = words; 4461b8e80941Smrg b->spirv_word_count = word_count; 4462b8e80941Smrg b->file = NULL; 4463b8e80941Smrg b->line = -1; 4464b8e80941Smrg b->col = -1; 4465b8e80941Smrg exec_list_make_empty(&b->functions); 4466b8e80941Smrg b->entry_point_stage = stage; 4467b8e80941Smrg b->entry_point_name = entry_point_name; 4468b8e80941Smrg b->options = dup_options; 4469b8e80941Smrg 4470b8e80941Smrg /* 4471b8e80941Smrg * Handle the SPIR-V header (first 5 dwords). 4472b8e80941Smrg * Can't use vtx_assert() as the setjmp(3) target isn't initialized yet. 4473b8e80941Smrg */ 4474b8e80941Smrg if (word_count <= 5) 4475b8e80941Smrg goto fail; 4476b8e80941Smrg 4477b8e80941Smrg if (words[0] != SpvMagicNumber) { 4478b8e80941Smrg vtn_err("words[0] was 0x%x, want 0x%x", words[0], SpvMagicNumber); 4479b8e80941Smrg goto fail; 4480b8e80941Smrg } 4481b8e80941Smrg if (words[1] < 0x10000) { 4482b8e80941Smrg vtn_err("words[1] was 0x%x, want >= 0x10000", words[1]); 4483b8e80941Smrg goto fail; 4484b8e80941Smrg } 4485b8e80941Smrg 4486b8e80941Smrg uint16_t generator_id = words[2] >> 16; 4487b8e80941Smrg uint16_t generator_version = words[2]; 4488b8e80941Smrg 4489b8e80941Smrg /* The first GLSLang version bump actually 1.5 years after #179 was fixed 4490b8e80941Smrg * but this should at least let us shut the workaround off for modern 4491b8e80941Smrg * versions of GLSLang. 4492b8e80941Smrg */ 4493b8e80941Smrg b->wa_glslang_179 = (generator_id == 8 && generator_version == 1); 4494b8e80941Smrg 4495b8e80941Smrg /* words[2] == generator magic */ 4496b8e80941Smrg unsigned value_id_bound = words[3]; 4497b8e80941Smrg if (words[4] != 0) { 4498b8e80941Smrg vtn_err("words[4] was %u, want 0", words[4]); 4499b8e80941Smrg goto fail; 4500b8e80941Smrg } 4501b8e80941Smrg 4502b8e80941Smrg b->value_id_bound = value_id_bound; 4503b8e80941Smrg b->values = rzalloc_array(b, struct vtn_value, value_id_bound); 4504b8e80941Smrg 4505b8e80941Smrg return b; 4506b8e80941Smrg fail: 4507b8e80941Smrg ralloc_free(b); 4508b8e80941Smrg return NULL; 4509b8e80941Smrg} 4510b8e80941Smrg 4511b8e80941Smrgstatic nir_function * 4512b8e80941Smrgvtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b, 4513b8e80941Smrg nir_function *entry_point) 4514b8e80941Smrg{ 4515b8e80941Smrg vtn_assert(entry_point == b->entry_point->func->impl->function); 4516b8e80941Smrg vtn_fail_if(!entry_point->name, "entry points are required to have a name"); 4517b8e80941Smrg const char *func_name = 4518b8e80941Smrg ralloc_asprintf(b->shader, "__wrapped_%s", entry_point->name); 4519b8e80941Smrg 4520b8e80941Smrg /* we shouldn't have any inputs yet */ 4521b8e80941Smrg vtn_assert(!entry_point->shader->num_inputs); 4522b8e80941Smrg vtn_assert(b->shader->info.stage == MESA_SHADER_KERNEL); 4523b8e80941Smrg 4524b8e80941Smrg nir_function *main_entry_point = nir_function_create(b->shader, func_name); 4525b8e80941Smrg main_entry_point->impl = nir_function_impl_create(main_entry_point); 4526b8e80941Smrg nir_builder_init(&b->nb, main_entry_point->impl); 4527b8e80941Smrg b->nb.cursor = nir_after_cf_list(&main_entry_point->impl->body); 4528b8e80941Smrg b->func_param_idx = 0; 4529b8e80941Smrg 4530b8e80941Smrg nir_call_instr *call = nir_call_instr_create(b->nb.shader, entry_point); 4531b8e80941Smrg 4532b8e80941Smrg for (unsigned i = 0; i < entry_point->num_params; ++i) { 4533b8e80941Smrg struct vtn_type *param_type = b->entry_point->func->type->params[i]; 4534b8e80941Smrg 4535b8e80941Smrg /* consider all pointers to function memory to be parameters passed 4536b8e80941Smrg * by value 4537b8e80941Smrg */ 4538b8e80941Smrg bool is_by_val = param_type->base_type == vtn_base_type_pointer && 4539b8e80941Smrg param_type->storage_class == SpvStorageClassFunction; 4540b8e80941Smrg 4541b8e80941Smrg /* input variable */ 4542b8e80941Smrg nir_variable *in_var = rzalloc(b->nb.shader, nir_variable); 4543b8e80941Smrg in_var->data.mode = nir_var_shader_in; 4544b8e80941Smrg in_var->data.read_only = true; 4545b8e80941Smrg in_var->data.location = i; 4546b8e80941Smrg 4547b8e80941Smrg if (is_by_val) 4548b8e80941Smrg in_var->type = param_type->deref->type; 4549b8e80941Smrg else 4550b8e80941Smrg in_var->type = param_type->type; 4551b8e80941Smrg 4552b8e80941Smrg nir_shader_add_variable(b->nb.shader, in_var); 4553b8e80941Smrg b->nb.shader->num_inputs++; 4554b8e80941Smrg 4555b8e80941Smrg /* we have to copy the entire variable into function memory */ 4556b8e80941Smrg if (is_by_val) { 4557b8e80941Smrg nir_variable *copy_var = 4558b8e80941Smrg nir_local_variable_create(main_entry_point->impl, in_var->type, 4559b8e80941Smrg "copy_in"); 4560b8e80941Smrg nir_copy_var(&b->nb, copy_var, in_var); 4561b8e80941Smrg call->params[i] = 4562b8e80941Smrg nir_src_for_ssa(&nir_build_deref_var(&b->nb, copy_var)->dest.ssa); 4563b8e80941Smrg } else { 4564b8e80941Smrg call->params[i] = nir_src_for_ssa(nir_load_var(&b->nb, in_var)); 4565b8e80941Smrg } 4566b8e80941Smrg } 4567b8e80941Smrg 4568b8e80941Smrg nir_builder_instr_insert(&b->nb, &call->instr); 4569b8e80941Smrg 4570b8e80941Smrg return main_entry_point; 4571b8e80941Smrg} 4572b8e80941Smrg 4573b8e80941Smrgnir_function * 4574b8e80941Smrgspirv_to_nir(const uint32_t *words, size_t word_count, 4575b8e80941Smrg struct nir_spirv_specialization *spec, unsigned num_spec, 4576b8e80941Smrg gl_shader_stage stage, const char *entry_point_name, 4577b8e80941Smrg const struct spirv_to_nir_options *options, 4578b8e80941Smrg const nir_shader_compiler_options *nir_options) 4579b8e80941Smrg 4580b8e80941Smrg{ 4581b8e80941Smrg const uint32_t *word_end = words + word_count; 4582b8e80941Smrg 4583b8e80941Smrg struct vtn_builder *b = vtn_create_builder(words, word_count, 4584b8e80941Smrg stage, entry_point_name, 4585b8e80941Smrg options); 4586b8e80941Smrg 4587b8e80941Smrg if (b == NULL) 4588b8e80941Smrg return NULL; 4589b8e80941Smrg 4590b8e80941Smrg /* See also _vtn_fail() */ 4591b8e80941Smrg if (setjmp(b->fail_jump)) { 4592b8e80941Smrg ralloc_free(b); 4593b8e80941Smrg return NULL; 4594b8e80941Smrg } 4595b8e80941Smrg 4596b8e80941Smrg /* Skip the SPIR-V header, handled at vtn_create_builder */ 4597b8e80941Smrg words+= 5; 4598b8e80941Smrg 4599b8e80941Smrg b->shader = nir_shader_create(b, stage, nir_options, NULL); 4600b8e80941Smrg 4601b8e80941Smrg /* Handle all the preamble instructions */ 4602b8e80941Smrg words = vtn_foreach_instruction(b, words, word_end, 4603b8e80941Smrg vtn_handle_preamble_instruction); 4604b8e80941Smrg 4605b8e80941Smrg if (b->entry_point == NULL) { 4606b8e80941Smrg vtn_fail("Entry point not found"); 4607b8e80941Smrg ralloc_free(b); 4608b8e80941Smrg return NULL; 4609b8e80941Smrg } 4610b8e80941Smrg 4611b8e80941Smrg /* Set shader info defaults */ 4612b8e80941Smrg b->shader->info.gs.invocations = 1; 4613b8e80941Smrg 4614b8e80941Smrg b->specializations = spec; 4615b8e80941Smrg b->num_specializations = num_spec; 4616b8e80941Smrg 4617b8e80941Smrg /* Handle all variable, type, and constant instructions */ 4618b8e80941Smrg words = vtn_foreach_instruction(b, words, word_end, 4619b8e80941Smrg vtn_handle_variable_or_type_instruction); 4620b8e80941Smrg 4621b8e80941Smrg /* Parse execution modes */ 4622b8e80941Smrg vtn_foreach_execution_mode(b, b->entry_point, 4623b8e80941Smrg vtn_handle_execution_mode, NULL); 4624b8e80941Smrg 4625b8e80941Smrg if (b->workgroup_size_builtin) { 4626b8e80941Smrg vtn_assert(b->workgroup_size_builtin->type->type == 4627b8e80941Smrg glsl_vector_type(GLSL_TYPE_UINT, 3)); 4628b8e80941Smrg 4629b8e80941Smrg nir_const_value *const_size = 4630b8e80941Smrg b->workgroup_size_builtin->constant->values[0]; 4631b8e80941Smrg 4632b8e80941Smrg b->shader->info.cs.local_size[0] = const_size[0].u32; 4633b8e80941Smrg b->shader->info.cs.local_size[1] = const_size[1].u32; 4634b8e80941Smrg b->shader->info.cs.local_size[2] = const_size[2].u32; 4635b8e80941Smrg } 4636b8e80941Smrg 4637b8e80941Smrg /* Set types on all vtn_values */ 4638b8e80941Smrg vtn_foreach_instruction(b, words, word_end, vtn_set_instruction_result_type); 4639b8e80941Smrg 4640b8e80941Smrg vtn_build_cfg(b, words, word_end); 4641b8e80941Smrg 4642b8e80941Smrg assert(b->entry_point->value_type == vtn_value_type_function); 4643b8e80941Smrg b->entry_point->func->referenced = true; 4644b8e80941Smrg 4645b8e80941Smrg bool progress; 4646b8e80941Smrg do { 4647b8e80941Smrg progress = false; 4648b8e80941Smrg foreach_list_typed(struct vtn_function, func, node, &b->functions) { 4649b8e80941Smrg if (func->referenced && !func->emitted) { 4650b8e80941Smrg b->const_table = _mesa_pointer_hash_table_create(b); 4651b8e80941Smrg 4652b8e80941Smrg vtn_function_emit(b, func, vtn_handle_body_instruction); 4653b8e80941Smrg progress = true; 4654b8e80941Smrg } 4655b8e80941Smrg } 4656b8e80941Smrg } while (progress); 4657b8e80941Smrg 4658b8e80941Smrg vtn_assert(b->entry_point->value_type == vtn_value_type_function); 4659b8e80941Smrg nir_function *entry_point = b->entry_point->func->impl->function; 4660b8e80941Smrg vtn_assert(entry_point); 4661b8e80941Smrg 4662b8e80941Smrg /* post process entry_points with input params */ 4663b8e80941Smrg if (entry_point->num_params && b->shader->info.stage == MESA_SHADER_KERNEL) 4664b8e80941Smrg entry_point = vtn_emit_kernel_entry_point_wrapper(b, entry_point); 4665b8e80941Smrg 4666b8e80941Smrg entry_point->is_entrypoint = true; 4667b8e80941Smrg 4668b8e80941Smrg /* When multiple shader stages exist in the same SPIR-V module, we 4669b8e80941Smrg * generate input and output variables for every stage, in the same 4670b8e80941Smrg * NIR program. These dead variables can be invalid NIR. For example, 4671b8e80941Smrg * TCS outputs must be per-vertex arrays (or decorated 'patch'), while 4672b8e80941Smrg * VS output variables wouldn't be. 4673b8e80941Smrg * 4674b8e80941Smrg * To ensure we have valid NIR, we eliminate any dead inputs and outputs 4675b8e80941Smrg * right away. In order to do so, we must lower any constant initializers 4676b8e80941Smrg * on outputs so nir_remove_dead_variables sees that they're written to. 4677b8e80941Smrg */ 4678b8e80941Smrg nir_lower_constant_initializers(b->shader, nir_var_shader_out); 4679b8e80941Smrg nir_remove_dead_variables(b->shader, 4680b8e80941Smrg nir_var_shader_in | nir_var_shader_out); 4681b8e80941Smrg 4682b8e80941Smrg /* We sometimes generate bogus derefs that, while never used, give the 4683b8e80941Smrg * validator a bit of heartburn. Run dead code to get rid of them. 4684b8e80941Smrg */ 4685b8e80941Smrg nir_opt_dce(b->shader); 4686b8e80941Smrg 4687b8e80941Smrg /* Unparent the shader from the vtn_builder before we delete the builder */ 4688b8e80941Smrg ralloc_steal(NULL, b->shader); 4689b8e80941Smrg 4690b8e80941Smrg ralloc_free(b); 4691b8e80941Smrg 4692b8e80941Smrg return entry_point; 4693b8e80941Smrg} 4694