1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2019 Red Hat. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "lvp_private.h" 25bf215546Sopenharmony_ci#include "vk_pipeline.h" 26bf215546Sopenharmony_ci#include "vk_render_pass.h" 27bf215546Sopenharmony_ci#include "vk_util.h" 28bf215546Sopenharmony_ci#include "glsl_types.h" 29bf215546Sopenharmony_ci#include "util/os_time.h" 30bf215546Sopenharmony_ci#include "spirv/nir_spirv.h" 31bf215546Sopenharmony_ci#include "nir/nir_builder.h" 32bf215546Sopenharmony_ci#include "lvp_lower_vulkan_resource.h" 33bf215546Sopenharmony_ci#include "pipe/p_state.h" 34bf215546Sopenharmony_ci#include "pipe/p_context.h" 35bf215546Sopenharmony_ci#include "tgsi/tgsi_from_mesa.h" 36bf215546Sopenharmony_ci#include "nir/nir_xfb_info.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#define SPIR_V_MAGIC_NUMBER 0x07230203 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#define LVP_PIPELINE_DUP(dst, src, type, count) do { \ 41bf215546Sopenharmony_ci type *temp = ralloc_array(mem_ctx, type, count); \ 42bf215546Sopenharmony_ci if (!temp) return VK_ERROR_OUT_OF_HOST_MEMORY; \ 43bf215546Sopenharmony_ci memcpy(temp, (src), sizeof(type) * count); \ 44bf215546Sopenharmony_ci dst = temp; \ 45bf215546Sopenharmony_ci } while(0) 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_civoid 48bf215546Sopenharmony_cilvp_pipeline_destroy(struct lvp_device *device, struct lvp_pipeline *pipeline) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci if (pipeline->shader_cso[PIPE_SHADER_VERTEX]) 51bf215546Sopenharmony_ci device->queue.ctx->delete_vs_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_VERTEX]); 52bf215546Sopenharmony_ci if (pipeline->shader_cso[PIPE_SHADER_FRAGMENT]) 53bf215546Sopenharmony_ci device->queue.ctx->delete_fs_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_FRAGMENT]); 54bf215546Sopenharmony_ci if (pipeline->shader_cso[PIPE_SHADER_GEOMETRY]) 55bf215546Sopenharmony_ci device->queue.ctx->delete_gs_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_GEOMETRY]); 56bf215546Sopenharmony_ci if (pipeline->shader_cso[PIPE_SHADER_TESS_CTRL]) 57bf215546Sopenharmony_ci device->queue.ctx->delete_tcs_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_TESS_CTRL]); 58bf215546Sopenharmony_ci if (pipeline->shader_cso[PIPE_SHADER_TESS_EVAL]) 59bf215546Sopenharmony_ci device->queue.ctx->delete_tes_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_TESS_EVAL]); 60bf215546Sopenharmony_ci if (pipeline->shader_cso[PIPE_SHADER_COMPUTE]) 61bf215546Sopenharmony_ci device->queue.ctx->delete_compute_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_COMPUTE]); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) 64bf215546Sopenharmony_ci ralloc_free(pipeline->pipeline_nir[i]); 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci if (pipeline->layout) 67bf215546Sopenharmony_ci vk_pipeline_layout_unref(&device->vk, &pipeline->layout->vk); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci ralloc_free(pipeline->mem_ctx); 70bf215546Sopenharmony_ci vk_free(&device->vk.alloc, pipeline->state_data); 71bf215546Sopenharmony_ci vk_object_base_finish(&pipeline->base); 72bf215546Sopenharmony_ci vk_free(&device->vk.alloc, pipeline); 73bf215546Sopenharmony_ci} 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL lvp_DestroyPipeline( 76bf215546Sopenharmony_ci VkDevice _device, 77bf215546Sopenharmony_ci VkPipeline _pipeline, 78bf215546Sopenharmony_ci const VkAllocationCallbacks* pAllocator) 79bf215546Sopenharmony_ci{ 80bf215546Sopenharmony_ci LVP_FROM_HANDLE(lvp_device, device, _device); 81bf215546Sopenharmony_ci LVP_FROM_HANDLE(lvp_pipeline, pipeline, _pipeline); 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci if (!_pipeline) 84bf215546Sopenharmony_ci return; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci simple_mtx_lock(&device->queue.pipeline_lock); 87bf215546Sopenharmony_ci util_dynarray_append(&device->queue.pipeline_destroys, struct lvp_pipeline*, pipeline); 88bf215546Sopenharmony_ci simple_mtx_unlock(&device->queue.pipeline_lock); 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_cistatic inline unsigned 92bf215546Sopenharmony_cist_shader_stage_to_ptarget(gl_shader_stage stage) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci switch (stage) { 95bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 96bf215546Sopenharmony_ci return PIPE_SHADER_VERTEX; 97bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 98bf215546Sopenharmony_ci return PIPE_SHADER_FRAGMENT; 99bf215546Sopenharmony_ci case MESA_SHADER_GEOMETRY: 100bf215546Sopenharmony_ci return PIPE_SHADER_GEOMETRY; 101bf215546Sopenharmony_ci case MESA_SHADER_TESS_CTRL: 102bf215546Sopenharmony_ci return PIPE_SHADER_TESS_CTRL; 103bf215546Sopenharmony_ci case MESA_SHADER_TESS_EVAL: 104bf215546Sopenharmony_ci return PIPE_SHADER_TESS_EVAL; 105bf215546Sopenharmony_ci case MESA_SHADER_COMPUTE: 106bf215546Sopenharmony_ci return PIPE_SHADER_COMPUTE; 107bf215546Sopenharmony_ci default: 108bf215546Sopenharmony_ci break; 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci assert(!"should not be reached"); 112bf215546Sopenharmony_ci return PIPE_SHADER_VERTEX; 113bf215546Sopenharmony_ci} 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_cistatic void 116bf215546Sopenharmony_cishared_var_info(const struct glsl_type *type, unsigned *size, unsigned *align) 117bf215546Sopenharmony_ci{ 118bf215546Sopenharmony_ci assert(glsl_type_is_vector_or_scalar(type)); 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci uint32_t comp_size = glsl_type_is_boolean(type) 121bf215546Sopenharmony_ci ? 4 : glsl_get_bit_size(type) / 8; 122bf215546Sopenharmony_ci unsigned length = glsl_get_vector_elements(type); 123bf215546Sopenharmony_ci *size = comp_size * length, 124bf215546Sopenharmony_ci *align = comp_size; 125bf215546Sopenharmony_ci} 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_cistatic void 128bf215546Sopenharmony_ciset_image_access(struct lvp_pipeline *pipeline, nir_shader *nir, 129bf215546Sopenharmony_ci nir_intrinsic_instr *instr, 130bf215546Sopenharmony_ci bool reads, bool writes) 131bf215546Sopenharmony_ci{ 132bf215546Sopenharmony_ci nir_variable *var = nir_intrinsic_get_var(instr, 0); 133bf215546Sopenharmony_ci /* calculate the variable's offset in the layout */ 134bf215546Sopenharmony_ci uint64_t value = 0; 135bf215546Sopenharmony_ci const struct lvp_descriptor_set_binding_layout *binding = 136bf215546Sopenharmony_ci get_binding_layout(pipeline->layout, var->data.descriptor_set, var->data.binding); 137bf215546Sopenharmony_ci for (unsigned s = 0; s < var->data.descriptor_set; s++) { 138bf215546Sopenharmony_ci if (pipeline->layout->vk.set_layouts[s]) 139bf215546Sopenharmony_ci value += get_set_layout(pipeline->layout, s)->stage[nir->info.stage].image_count; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci value += binding->stage[nir->info.stage].image_index; 142bf215546Sopenharmony_ci const unsigned size = glsl_type_is_array(var->type) ? glsl_get_aoa_size(var->type) : 1; 143bf215546Sopenharmony_ci uint64_t mask = BITFIELD64_MASK(MAX2(size, 1)) << value; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci if (reads) 146bf215546Sopenharmony_ci pipeline->access[nir->info.stage].images_read |= mask; 147bf215546Sopenharmony_ci if (writes) 148bf215546Sopenharmony_ci pipeline->access[nir->info.stage].images_written |= mask; 149bf215546Sopenharmony_ci} 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_cistatic void 152bf215546Sopenharmony_ciset_buffer_access(struct lvp_pipeline *pipeline, nir_shader *nir, 153bf215546Sopenharmony_ci nir_intrinsic_instr *instr) 154bf215546Sopenharmony_ci{ 155bf215546Sopenharmony_ci nir_variable *var = nir_intrinsic_get_var(instr, 0); 156bf215546Sopenharmony_ci if (!var) { 157bf215546Sopenharmony_ci nir_deref_instr *deref = nir_instr_as_deref(instr->src[0].ssa->parent_instr); 158bf215546Sopenharmony_ci if (deref->modes != nir_var_mem_ssbo) 159bf215546Sopenharmony_ci return; 160bf215546Sopenharmony_ci nir_binding b = nir_chase_binding(instr->src[0]); 161bf215546Sopenharmony_ci var = nir_get_binding_variable(nir, b); 162bf215546Sopenharmony_ci if (!var) 163bf215546Sopenharmony_ci return; 164bf215546Sopenharmony_ci } 165bf215546Sopenharmony_ci if (var->data.mode != nir_var_mem_ssbo) 166bf215546Sopenharmony_ci return; 167bf215546Sopenharmony_ci /* calculate the variable's offset in the layout */ 168bf215546Sopenharmony_ci uint64_t value = 0; 169bf215546Sopenharmony_ci const struct lvp_descriptor_set_binding_layout *binding = 170bf215546Sopenharmony_ci get_binding_layout(pipeline->layout, var->data.descriptor_set, var->data.binding); 171bf215546Sopenharmony_ci for (unsigned s = 0; s < var->data.descriptor_set; s++) { 172bf215546Sopenharmony_ci if (pipeline->layout->vk.set_layouts[s]) 173bf215546Sopenharmony_ci value += get_set_layout(pipeline->layout, s)->stage[nir->info.stage].shader_buffer_count; 174bf215546Sopenharmony_ci } 175bf215546Sopenharmony_ci value += binding->stage[nir->info.stage].shader_buffer_index; 176bf215546Sopenharmony_ci /* Structs have been lowered already, so get_aoa_size is sufficient. */ 177bf215546Sopenharmony_ci const unsigned size = glsl_type_is_array(var->type) ? glsl_get_aoa_size(var->type) : 1; 178bf215546Sopenharmony_ci uint64_t mask = BITFIELD64_MASK(MAX2(size, 1)) << value; 179bf215546Sopenharmony_ci pipeline->access[nir->info.stage].buffers_written |= mask; 180bf215546Sopenharmony_ci} 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_cistatic void 183bf215546Sopenharmony_ciscan_intrinsic(struct lvp_pipeline *pipeline, nir_shader *nir, nir_intrinsic_instr *instr) 184bf215546Sopenharmony_ci{ 185bf215546Sopenharmony_ci switch (instr->intrinsic) { 186bf215546Sopenharmony_ci case nir_intrinsic_image_deref_sparse_load: 187bf215546Sopenharmony_ci case nir_intrinsic_image_deref_load: 188bf215546Sopenharmony_ci case nir_intrinsic_image_deref_size: 189bf215546Sopenharmony_ci case nir_intrinsic_image_deref_samples: 190bf215546Sopenharmony_ci set_image_access(pipeline, nir, instr, true, false); 191bf215546Sopenharmony_ci break; 192bf215546Sopenharmony_ci case nir_intrinsic_image_deref_store: 193bf215546Sopenharmony_ci set_image_access(pipeline, nir, instr, false, true); 194bf215546Sopenharmony_ci break; 195bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_add: 196bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_imin: 197bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_umin: 198bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_imax: 199bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_umax: 200bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_and: 201bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_or: 202bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_xor: 203bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_exchange: 204bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_comp_swap: 205bf215546Sopenharmony_ci case nir_intrinsic_image_deref_atomic_fadd: 206bf215546Sopenharmony_ci set_image_access(pipeline, nir, instr, true, true); 207bf215546Sopenharmony_ci break; 208bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_add: 209bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_and: 210bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_comp_swap: 211bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_exchange: 212bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_fadd: 213bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_fcomp_swap: 214bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_fmax: 215bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_fmin: 216bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_imax: 217bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_imin: 218bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_or: 219bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_umax: 220bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_umin: 221bf215546Sopenharmony_ci case nir_intrinsic_deref_atomic_xor: 222bf215546Sopenharmony_ci case nir_intrinsic_store_deref: 223bf215546Sopenharmony_ci set_buffer_access(pipeline, nir, instr); 224bf215546Sopenharmony_ci break; 225bf215546Sopenharmony_ci default: break; 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci} 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_cistatic void 230bf215546Sopenharmony_ciscan_pipeline_info(struct lvp_pipeline *pipeline, nir_shader *nir) 231bf215546Sopenharmony_ci{ 232bf215546Sopenharmony_ci nir_foreach_function(function, nir) { 233bf215546Sopenharmony_ci if (function->impl) 234bf215546Sopenharmony_ci nir_foreach_block(block, function->impl) { 235bf215546Sopenharmony_ci nir_foreach_instr(instr, block) { 236bf215546Sopenharmony_ci if (instr->type == nir_instr_type_intrinsic) 237bf215546Sopenharmony_ci scan_intrinsic(pipeline, nir, nir_instr_as_intrinsic(instr)); 238bf215546Sopenharmony_ci } 239bf215546Sopenharmony_ci } 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_cistatic bool 245bf215546Sopenharmony_ciremove_scoped_barriers_impl(nir_builder *b, nir_instr *instr, void *data) 246bf215546Sopenharmony_ci{ 247bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 248bf215546Sopenharmony_ci return false; 249bf215546Sopenharmony_ci nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); 250bf215546Sopenharmony_ci if (intr->intrinsic != nir_intrinsic_scoped_barrier) 251bf215546Sopenharmony_ci return false; 252bf215546Sopenharmony_ci if (data) { 253bf215546Sopenharmony_ci if (nir_intrinsic_memory_scope(intr) == NIR_SCOPE_WORKGROUP || 254bf215546Sopenharmony_ci nir_intrinsic_memory_scope(intr) == NIR_SCOPE_DEVICE) 255bf215546Sopenharmony_ci return false; 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci nir_instr_remove(instr); 258bf215546Sopenharmony_ci return true; 259bf215546Sopenharmony_ci} 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_cistatic bool 262bf215546Sopenharmony_ciremove_scoped_barriers(nir_shader *nir, bool is_compute) 263bf215546Sopenharmony_ci{ 264bf215546Sopenharmony_ci return nir_shader_instructions_pass(nir, remove_scoped_barriers_impl, nir_metadata_dominance, (void*)is_compute); 265bf215546Sopenharmony_ci} 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_cistatic bool 268bf215546Sopenharmony_cilower_demote_impl(nir_builder *b, nir_instr *instr, void *data) 269bf215546Sopenharmony_ci{ 270bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 271bf215546Sopenharmony_ci return false; 272bf215546Sopenharmony_ci nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); 273bf215546Sopenharmony_ci if (intr->intrinsic == nir_intrinsic_demote || intr->intrinsic == nir_intrinsic_terminate) { 274bf215546Sopenharmony_ci intr->intrinsic = nir_intrinsic_discard; 275bf215546Sopenharmony_ci return true; 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci if (intr->intrinsic == nir_intrinsic_demote_if || intr->intrinsic == nir_intrinsic_terminate_if) { 278bf215546Sopenharmony_ci intr->intrinsic = nir_intrinsic_discard_if; 279bf215546Sopenharmony_ci return true; 280bf215546Sopenharmony_ci } 281bf215546Sopenharmony_ci return false; 282bf215546Sopenharmony_ci} 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_cistatic bool 285bf215546Sopenharmony_cilower_demote(nir_shader *nir) 286bf215546Sopenharmony_ci{ 287bf215546Sopenharmony_ci return nir_shader_instructions_pass(nir, lower_demote_impl, nir_metadata_dominance, NULL); 288bf215546Sopenharmony_ci} 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_cistatic bool 291bf215546Sopenharmony_cifind_tex(const nir_instr *instr, const void *data_cb) 292bf215546Sopenharmony_ci{ 293bf215546Sopenharmony_ci if (instr->type == nir_instr_type_tex) 294bf215546Sopenharmony_ci return true; 295bf215546Sopenharmony_ci return false; 296bf215546Sopenharmony_ci} 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_cistatic nir_ssa_def * 299bf215546Sopenharmony_cifixup_tex_instr(struct nir_builder *b, nir_instr *instr, void *data_cb) 300bf215546Sopenharmony_ci{ 301bf215546Sopenharmony_ci nir_tex_instr *tex_instr = nir_instr_as_tex(instr); 302bf215546Sopenharmony_ci unsigned offset = 0; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci int idx = nir_tex_instr_src_index(tex_instr, nir_tex_src_texture_offset); 305bf215546Sopenharmony_ci if (idx == -1) 306bf215546Sopenharmony_ci return NULL; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (!nir_src_is_const(tex_instr->src[idx].src)) 309bf215546Sopenharmony_ci return NULL; 310bf215546Sopenharmony_ci offset = nir_src_comp_as_uint(tex_instr->src[idx].src, 0); 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci nir_tex_instr_remove_src(tex_instr, idx); 313bf215546Sopenharmony_ci tex_instr->texture_index += offset; 314bf215546Sopenharmony_ci return NIR_LOWER_INSTR_PROGRESS; 315bf215546Sopenharmony_ci} 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_cistatic bool 318bf215546Sopenharmony_cilvp_nir_fixup_indirect_tex(nir_shader *shader) 319bf215546Sopenharmony_ci{ 320bf215546Sopenharmony_ci return nir_shader_lower_instructions(shader, find_tex, fixup_tex_instr, NULL); 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_cistatic void 324bf215546Sopenharmony_cioptimize(nir_shader *nir) 325bf215546Sopenharmony_ci{ 326bf215546Sopenharmony_ci bool progress = false; 327bf215546Sopenharmony_ci do { 328bf215546Sopenharmony_ci progress = false; 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_lower_flrp, 32|64, true); 331bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_split_array_vars, nir_var_function_temp); 332bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_shrink_vec_array_vars, nir_var_function_temp); 333bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_deref); 334bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_lower_vars_to_ssa); 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_copy_prop_vars); 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_copy_prop); 339bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_dce); 340bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_peephole_select, 8, true, true); 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_algebraic); 343bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_constant_folding); 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_remove_phis); 346bf215546Sopenharmony_ci bool trivial_continues = false; 347bf215546Sopenharmony_ci NIR_PASS(trivial_continues, nir, nir_opt_trivial_continues); 348bf215546Sopenharmony_ci progress |= trivial_continues; 349bf215546Sopenharmony_ci if (trivial_continues) { 350bf215546Sopenharmony_ci /* If nir_opt_trivial_continues makes progress, then we need to clean 351bf215546Sopenharmony_ci * things up if we want any hope of nir_opt_if or nir_opt_loop_unroll 352bf215546Sopenharmony_ci * to make progress. 353bf215546Sopenharmony_ci */ 354bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_copy_prop); 355bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_dce); 356bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_remove_phis); 357bf215546Sopenharmony_ci } 358bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_if, nir_opt_if_aggressive_last_continue | nir_opt_if_optimize_phi_true_false); 359bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_dead_cf); 360bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_conditional_discard); 361bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_remove_phis); 362bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_cse); 363bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_undef); 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_deref); 366bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_lower_alu_to_scalar, NULL, NULL); 367bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_opt_loop_unroll); 368bf215546Sopenharmony_ci NIR_PASS(progress, nir, lvp_nir_fixup_indirect_tex); 369bf215546Sopenharmony_ci } while (progress); 370bf215546Sopenharmony_ci} 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_civoid 373bf215546Sopenharmony_cilvp_shader_optimize(nir_shader *nir) 374bf215546Sopenharmony_ci{ 375bf215546Sopenharmony_ci optimize(nir); 376bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_var_copies); 377bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL); 378bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_opt_dce); 379bf215546Sopenharmony_ci nir_sweep(nir); 380bf215546Sopenharmony_ci} 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_cistatic VkResult 383bf215546Sopenharmony_cilvp_shader_compile_to_ir(struct lvp_pipeline *pipeline, 384bf215546Sopenharmony_ci const VkPipelineShaderStageCreateInfo *sinfo) 385bf215546Sopenharmony_ci{ 386bf215546Sopenharmony_ci struct lvp_device *pdevice = pipeline->device; 387bf215546Sopenharmony_ci gl_shader_stage stage = vk_to_mesa_shader_stage(sinfo->stage); 388bf215546Sopenharmony_ci const nir_shader_compiler_options *drv_options = pdevice->pscreen->get_compiler_options(pipeline->device->pscreen, PIPE_SHADER_IR_NIR, st_shader_stage_to_ptarget(stage)); 389bf215546Sopenharmony_ci VkResult result; 390bf215546Sopenharmony_ci nir_shader *nir; 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci const struct spirv_to_nir_options spirv_options = { 393bf215546Sopenharmony_ci .environment = NIR_SPIRV_VULKAN, 394bf215546Sopenharmony_ci .caps = { 395bf215546Sopenharmony_ci .float64 = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DOUBLES) == 1), 396bf215546Sopenharmony_ci .int16 = true, 397bf215546Sopenharmony_ci .int64 = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_INT64) == 1), 398bf215546Sopenharmony_ci .tessellation = true, 399bf215546Sopenharmony_ci .float_controls = true, 400bf215546Sopenharmony_ci .image_ms_array = true, 401bf215546Sopenharmony_ci .image_read_without_format = true, 402bf215546Sopenharmony_ci .image_write_without_format = true, 403bf215546Sopenharmony_ci .storage_image_ms = true, 404bf215546Sopenharmony_ci .geometry_streams = true, 405bf215546Sopenharmony_ci .storage_8bit = true, 406bf215546Sopenharmony_ci .storage_16bit = true, 407bf215546Sopenharmony_ci .variable_pointers = true, 408bf215546Sopenharmony_ci .stencil_export = true, 409bf215546Sopenharmony_ci .post_depth_coverage = true, 410bf215546Sopenharmony_ci .transform_feedback = true, 411bf215546Sopenharmony_ci .device_group = true, 412bf215546Sopenharmony_ci .draw_parameters = true, 413bf215546Sopenharmony_ci .shader_viewport_index_layer = true, 414bf215546Sopenharmony_ci .multiview = true, 415bf215546Sopenharmony_ci .physical_storage_buffer_address = true, 416bf215546Sopenharmony_ci .int64_atomics = true, 417bf215546Sopenharmony_ci .subgroup_arithmetic = true, 418bf215546Sopenharmony_ci .subgroup_basic = true, 419bf215546Sopenharmony_ci .subgroup_ballot = true, 420bf215546Sopenharmony_ci .subgroup_quad = true, 421bf215546Sopenharmony_ci#if LLVM_VERSION_MAJOR >= 10 422bf215546Sopenharmony_ci .subgroup_shuffle = true, 423bf215546Sopenharmony_ci#endif 424bf215546Sopenharmony_ci .subgroup_vote = true, 425bf215546Sopenharmony_ci .vk_memory_model = true, 426bf215546Sopenharmony_ci .vk_memory_model_device_scope = true, 427bf215546Sopenharmony_ci .int8 = true, 428bf215546Sopenharmony_ci .float16 = true, 429bf215546Sopenharmony_ci .demote_to_helper_invocation = true, 430bf215546Sopenharmony_ci }, 431bf215546Sopenharmony_ci .ubo_addr_format = nir_address_format_32bit_index_offset, 432bf215546Sopenharmony_ci .ssbo_addr_format = nir_address_format_32bit_index_offset, 433bf215546Sopenharmony_ci .phys_ssbo_addr_format = nir_address_format_64bit_global, 434bf215546Sopenharmony_ci .push_const_addr_format = nir_address_format_logical, 435bf215546Sopenharmony_ci .shared_addr_format = nir_address_format_32bit_offset, 436bf215546Sopenharmony_ci }; 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci result = vk_pipeline_shader_stage_to_nir(&pdevice->vk, sinfo, 439bf215546Sopenharmony_ci &spirv_options, drv_options, 440bf215546Sopenharmony_ci NULL, &nir); 441bf215546Sopenharmony_ci if (result != VK_SUCCESS) 442bf215546Sopenharmony_ci return result; 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci if (nir->info.stage != MESA_SHADER_TESS_CTRL) 445bf215546Sopenharmony_ci NIR_PASS_V(nir, remove_scoped_barriers, nir->info.stage == MESA_SHADER_COMPUTE); 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci const struct nir_lower_sysvals_to_varyings_options sysvals_to_varyings = { 448bf215546Sopenharmony_ci .frag_coord = true, 449bf215546Sopenharmony_ci .point_coord = true, 450bf215546Sopenharmony_ci }; 451bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_sysvals_to_varyings, &sysvals_to_varyings); 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci struct nir_lower_subgroups_options subgroup_opts = {0}; 454bf215546Sopenharmony_ci subgroup_opts.lower_quad = true; 455bf215546Sopenharmony_ci subgroup_opts.ballot_components = 1; 456bf215546Sopenharmony_ci subgroup_opts.ballot_bit_size = 32; 457bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_subgroups, &subgroup_opts); 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci if (stage == MESA_SHADER_FRAGMENT) 460bf215546Sopenharmony_ci lvp_lower_input_attachments(nir, false); 461bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_is_helper_invocation); 462bf215546Sopenharmony_ci NIR_PASS_V(nir, lower_demote); 463bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_system_values); 464bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_compute_system_values, NULL); 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_remove_dead_variables, 467bf215546Sopenharmony_ci nir_var_uniform | nir_var_image, NULL); 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci scan_pipeline_info(pipeline, nir); 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci optimize(nir); 472bf215546Sopenharmony_ci lvp_lower_pipeline_layout(pipeline->device, pipeline->layout, nir); 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(nir), true, true); 475bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_split_var_copies); 476bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_global_vars_to_local); 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_push_const, 479bf215546Sopenharmony_ci nir_address_format_32bit_offset); 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_explicit_io, 482bf215546Sopenharmony_ci nir_var_mem_ubo | nir_var_mem_ssbo, 483bf215546Sopenharmony_ci nir_address_format_32bit_index_offset); 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_explicit_io, 486bf215546Sopenharmony_ci nir_var_mem_global, 487bf215546Sopenharmony_ci nir_address_format_64bit_global); 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_COMPUTE) { 490bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_vars_to_explicit_types, nir_var_mem_shared, shared_var_info); 491bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_shared, nir_address_format_32bit_offset); 492bf215546Sopenharmony_ci } 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL); 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX || 497bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_GEOMETRY) { 498bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, false); 499bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_FRAGMENT) { 500bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, true); 501bf215546Sopenharmony_ci } 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ci // TODO: also optimize the tex srcs. see radeonSI for reference */ 504bf215546Sopenharmony_ci /* Skip if there are potentially conflicting rounding modes */ 505bf215546Sopenharmony_ci struct nir_fold_16bit_tex_image_options fold_16bit_options = { 506bf215546Sopenharmony_ci .rounding_mode = nir_rounding_mode_undef, 507bf215546Sopenharmony_ci .fold_tex_dest = true, 508bf215546Sopenharmony_ci }; 509bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_fold_16bit_tex_image, &fold_16bit_options); 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci lvp_shader_optimize(nir); 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir)); 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci if (nir->info.stage != MESA_SHADER_VERTEX) 516bf215546Sopenharmony_ci nir_assign_io_var_locations(nir, nir_var_shader_in, &nir->num_inputs, nir->info.stage); 517bf215546Sopenharmony_ci else { 518bf215546Sopenharmony_ci nir->num_inputs = util_last_bit64(nir->info.inputs_read); 519bf215546Sopenharmony_ci nir_foreach_shader_in_variable(var, nir) { 520bf215546Sopenharmony_ci var->data.driver_location = var->data.location - VERT_ATTRIB_GENERIC0; 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci } 523bf215546Sopenharmony_ci nir_assign_io_var_locations(nir, nir_var_shader_out, &nir->num_outputs, 524bf215546Sopenharmony_ci nir->info.stage); 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci nir_function_impl *impl = nir_shader_get_entrypoint(nir); 527bf215546Sopenharmony_ci if (impl->ssa_alloc > 100) //skip for small shaders 528bf215546Sopenharmony_ci pipeline->inlines[stage].must_inline = lvp_find_inlinable_uniforms(pipeline, nir); 529bf215546Sopenharmony_ci pipeline->pipeline_nir[stage] = nir; 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci return VK_SUCCESS; 532bf215546Sopenharmony_ci} 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_cistatic void 535bf215546Sopenharmony_cimerge_tess_info(struct shader_info *tes_info, 536bf215546Sopenharmony_ci const struct shader_info *tcs_info) 537bf215546Sopenharmony_ci{ 538bf215546Sopenharmony_ci /* The Vulkan 1.0.38 spec, section 21.1 Tessellator says: 539bf215546Sopenharmony_ci * 540bf215546Sopenharmony_ci * "PointMode. Controls generation of points rather than triangles 541bf215546Sopenharmony_ci * or lines. This functionality defaults to disabled, and is 542bf215546Sopenharmony_ci * enabled if either shader stage includes the execution mode. 543bf215546Sopenharmony_ci * 544bf215546Sopenharmony_ci * and about Triangles, Quads, IsoLines, VertexOrderCw, VertexOrderCcw, 545bf215546Sopenharmony_ci * PointMode, SpacingEqual, SpacingFractionalEven, SpacingFractionalOdd, 546bf215546Sopenharmony_ci * and OutputVertices, it says: 547bf215546Sopenharmony_ci * 548bf215546Sopenharmony_ci * "One mode must be set in at least one of the tessellation 549bf215546Sopenharmony_ci * shader stages." 550bf215546Sopenharmony_ci * 551bf215546Sopenharmony_ci * So, the fields can be set in either the TCS or TES, but they must 552bf215546Sopenharmony_ci * agree if set in both. Our backend looks at TES, so bitwise-or in 553bf215546Sopenharmony_ci * the values from the TCS. 554bf215546Sopenharmony_ci */ 555bf215546Sopenharmony_ci assert(tcs_info->tess.tcs_vertices_out == 0 || 556bf215546Sopenharmony_ci tes_info->tess.tcs_vertices_out == 0 || 557bf215546Sopenharmony_ci tcs_info->tess.tcs_vertices_out == tes_info->tess.tcs_vertices_out); 558bf215546Sopenharmony_ci tes_info->tess.tcs_vertices_out |= tcs_info->tess.tcs_vertices_out; 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci assert(tcs_info->tess.spacing == TESS_SPACING_UNSPECIFIED || 561bf215546Sopenharmony_ci tes_info->tess.spacing == TESS_SPACING_UNSPECIFIED || 562bf215546Sopenharmony_ci tcs_info->tess.spacing == tes_info->tess.spacing); 563bf215546Sopenharmony_ci tes_info->tess.spacing |= tcs_info->tess.spacing; 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_ci assert(tcs_info->tess._primitive_mode == 0 || 566bf215546Sopenharmony_ci tes_info->tess._primitive_mode == 0 || 567bf215546Sopenharmony_ci tcs_info->tess._primitive_mode == tes_info->tess._primitive_mode); 568bf215546Sopenharmony_ci tes_info->tess._primitive_mode |= tcs_info->tess._primitive_mode; 569bf215546Sopenharmony_ci tes_info->tess.ccw |= tcs_info->tess.ccw; 570bf215546Sopenharmony_ci tes_info->tess.point_mode |= tcs_info->tess.point_mode; 571bf215546Sopenharmony_ci} 572bf215546Sopenharmony_ci 573bf215546Sopenharmony_cistatic void 574bf215546Sopenharmony_cilvp_pipeline_xfb_init(struct lvp_pipeline *pipeline) 575bf215546Sopenharmony_ci{ 576bf215546Sopenharmony_ci gl_shader_stage stage = MESA_SHADER_VERTEX; 577bf215546Sopenharmony_ci if (pipeline->pipeline_nir[MESA_SHADER_GEOMETRY]) 578bf215546Sopenharmony_ci stage = MESA_SHADER_GEOMETRY; 579bf215546Sopenharmony_ci else if (pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]) 580bf215546Sopenharmony_ci stage = MESA_SHADER_TESS_EVAL; 581bf215546Sopenharmony_ci pipeline->last_vertex = stage; 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_ci nir_xfb_info *xfb_info = pipeline->pipeline_nir[stage]->xfb_info; 584bf215546Sopenharmony_ci if (xfb_info) { 585bf215546Sopenharmony_ci uint8_t output_mapping[VARYING_SLOT_TESS_MAX]; 586bf215546Sopenharmony_ci memset(output_mapping, 0, sizeof(output_mapping)); 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_ci nir_foreach_shader_out_variable(var, pipeline->pipeline_nir[stage]) { 589bf215546Sopenharmony_ci unsigned slots = var->data.compact ? DIV_ROUND_UP(glsl_get_length(var->type), 4) 590bf215546Sopenharmony_ci : glsl_count_attribute_slots(var->type, false); 591bf215546Sopenharmony_ci for (unsigned i = 0; i < slots; i++) 592bf215546Sopenharmony_ci output_mapping[var->data.location + i] = var->data.driver_location + i; 593bf215546Sopenharmony_ci } 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci pipeline->stream_output.num_outputs = xfb_info->output_count; 596bf215546Sopenharmony_ci for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; i++) { 597bf215546Sopenharmony_ci if (xfb_info->buffers_written & (1 << i)) { 598bf215546Sopenharmony_ci pipeline->stream_output.stride[i] = xfb_info->buffers[i].stride / 4; 599bf215546Sopenharmony_ci } 600bf215546Sopenharmony_ci } 601bf215546Sopenharmony_ci for (unsigned i = 0; i < xfb_info->output_count; i++) { 602bf215546Sopenharmony_ci pipeline->stream_output.output[i].output_buffer = xfb_info->outputs[i].buffer; 603bf215546Sopenharmony_ci pipeline->stream_output.output[i].dst_offset = xfb_info->outputs[i].offset / 4; 604bf215546Sopenharmony_ci pipeline->stream_output.output[i].register_index = output_mapping[xfb_info->outputs[i].location]; 605bf215546Sopenharmony_ci pipeline->stream_output.output[i].num_components = util_bitcount(xfb_info->outputs[i].component_mask); 606bf215546Sopenharmony_ci pipeline->stream_output.output[i].start_component = ffs(xfb_info->outputs[i].component_mask) - 1; 607bf215546Sopenharmony_ci pipeline->stream_output.output[i].stream = xfb_info->buffer_to_stream[xfb_info->outputs[i].buffer]; 608bf215546Sopenharmony_ci } 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_ci } 611bf215546Sopenharmony_ci} 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_civoid * 614bf215546Sopenharmony_cilvp_pipeline_compile_stage(struct lvp_pipeline *pipeline, nir_shader *nir) 615bf215546Sopenharmony_ci{ 616bf215546Sopenharmony_ci struct lvp_device *device = pipeline->device; 617bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_COMPUTE) { 618bf215546Sopenharmony_ci struct pipe_compute_state shstate = {0}; 619bf215546Sopenharmony_ci shstate.prog = nir; 620bf215546Sopenharmony_ci shstate.ir_type = PIPE_SHADER_IR_NIR; 621bf215546Sopenharmony_ci shstate.req_local_mem = nir->info.shared_size; 622bf215546Sopenharmony_ci return device->queue.ctx->create_compute_state(device->queue.ctx, &shstate); 623bf215546Sopenharmony_ci } else { 624bf215546Sopenharmony_ci struct pipe_shader_state shstate = {0}; 625bf215546Sopenharmony_ci shstate.type = PIPE_SHADER_IR_NIR; 626bf215546Sopenharmony_ci shstate.ir.nir = nir; 627bf215546Sopenharmony_ci if (nir->info.stage == pipeline->last_vertex) 628bf215546Sopenharmony_ci memcpy(&shstate.stream_output, &pipeline->stream_output, sizeof(shstate.stream_output)); 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci switch (nir->info.stage) { 631bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 632bf215546Sopenharmony_ci return device->queue.ctx->create_fs_state(device->queue.ctx, &shstate); 633bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 634bf215546Sopenharmony_ci return device->queue.ctx->create_vs_state(device->queue.ctx, &shstate); 635bf215546Sopenharmony_ci case MESA_SHADER_GEOMETRY: 636bf215546Sopenharmony_ci return device->queue.ctx->create_gs_state(device->queue.ctx, &shstate); 637bf215546Sopenharmony_ci case MESA_SHADER_TESS_CTRL: 638bf215546Sopenharmony_ci return device->queue.ctx->create_tcs_state(device->queue.ctx, &shstate); 639bf215546Sopenharmony_ci case MESA_SHADER_TESS_EVAL: 640bf215546Sopenharmony_ci return device->queue.ctx->create_tes_state(device->queue.ctx, &shstate); 641bf215546Sopenharmony_ci default: 642bf215546Sopenharmony_ci unreachable("illegal shader"); 643bf215546Sopenharmony_ci break; 644bf215546Sopenharmony_ci } 645bf215546Sopenharmony_ci } 646bf215546Sopenharmony_ci return NULL; 647bf215546Sopenharmony_ci} 648bf215546Sopenharmony_ci 649bf215546Sopenharmony_civoid * 650bf215546Sopenharmony_cilvp_pipeline_compile(struct lvp_pipeline *pipeline, nir_shader *nir) 651bf215546Sopenharmony_ci{ 652bf215546Sopenharmony_ci struct lvp_device *device = pipeline->device; 653bf215546Sopenharmony_ci device->physical_device->pscreen->finalize_nir(device->physical_device->pscreen, nir); 654bf215546Sopenharmony_ci return lvp_pipeline_compile_stage(pipeline, nir); 655bf215546Sopenharmony_ci} 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci#ifndef NDEBUG 658bf215546Sopenharmony_cistatic bool 659bf215546Sopenharmony_cilayouts_equal(const struct lvp_descriptor_set_layout *a, const struct lvp_descriptor_set_layout *b) 660bf215546Sopenharmony_ci{ 661bf215546Sopenharmony_ci const uint8_t *pa = (const uint8_t*)a, *pb = (const uint8_t*)b; 662bf215546Sopenharmony_ci uint32_t hash_start_offset = sizeof(struct vk_descriptor_set_layout); 663bf215546Sopenharmony_ci uint32_t binding_offset = offsetof(struct lvp_descriptor_set_layout, binding); 664bf215546Sopenharmony_ci /* base equal */ 665bf215546Sopenharmony_ci if (memcmp(pa + hash_start_offset, pb + hash_start_offset, binding_offset - hash_start_offset)) 666bf215546Sopenharmony_ci return false; 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci /* bindings equal */ 669bf215546Sopenharmony_ci if (a->binding_count != b->binding_count) 670bf215546Sopenharmony_ci return false; 671bf215546Sopenharmony_ci size_t binding_size = a->binding_count * sizeof(struct lvp_descriptor_set_binding_layout); 672bf215546Sopenharmony_ci const struct lvp_descriptor_set_binding_layout *la = a->binding; 673bf215546Sopenharmony_ci const struct lvp_descriptor_set_binding_layout *lb = b->binding; 674bf215546Sopenharmony_ci if (memcmp(la, lb, binding_size)) { 675bf215546Sopenharmony_ci for (unsigned i = 0; i < a->binding_count; i++) { 676bf215546Sopenharmony_ci if (memcmp(&la[i], &lb[i], offsetof(struct lvp_descriptor_set_binding_layout, immutable_samplers))) 677bf215546Sopenharmony_ci return false; 678bf215546Sopenharmony_ci } 679bf215546Sopenharmony_ci } 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_ci /* immutable sampler equal */ 682bf215546Sopenharmony_ci if (a->immutable_sampler_count != b->immutable_sampler_count) 683bf215546Sopenharmony_ci return false; 684bf215546Sopenharmony_ci if (a->immutable_sampler_count) { 685bf215546Sopenharmony_ci size_t sampler_size = a->immutable_sampler_count * sizeof(struct lvp_sampler *); 686bf215546Sopenharmony_ci if (memcmp(pa + binding_offset + binding_size, pb + binding_offset + binding_size, sampler_size)) { 687bf215546Sopenharmony_ci struct lvp_sampler **sa = (struct lvp_sampler **)(pa + binding_offset); 688bf215546Sopenharmony_ci struct lvp_sampler **sb = (struct lvp_sampler **)(pb + binding_offset); 689bf215546Sopenharmony_ci for (unsigned i = 0; i < a->immutable_sampler_count; i++) { 690bf215546Sopenharmony_ci if (memcmp(sa[i], sb[i], sizeof(struct lvp_sampler))) 691bf215546Sopenharmony_ci return false; 692bf215546Sopenharmony_ci } 693bf215546Sopenharmony_ci } 694bf215546Sopenharmony_ci } 695bf215546Sopenharmony_ci return true; 696bf215546Sopenharmony_ci} 697bf215546Sopenharmony_ci#endif 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_cistatic void 700bf215546Sopenharmony_cimerge_layouts(struct lvp_pipeline *dst, struct lvp_pipeline_layout *src) 701bf215546Sopenharmony_ci{ 702bf215546Sopenharmony_ci if (!src) 703bf215546Sopenharmony_ci return; 704bf215546Sopenharmony_ci if (!dst->layout) { 705bf215546Sopenharmony_ci /* no layout created yet: copy onto ralloc ctx allocation for auto-free */ 706bf215546Sopenharmony_ci dst->layout = ralloc(dst->mem_ctx, struct lvp_pipeline_layout); 707bf215546Sopenharmony_ci memcpy(dst->layout, src, sizeof(struct lvp_pipeline_layout)); 708bf215546Sopenharmony_ci return; 709bf215546Sopenharmony_ci } 710bf215546Sopenharmony_ci#ifndef NDEBUG 711bf215546Sopenharmony_ci /* verify that layouts match */ 712bf215546Sopenharmony_ci const struct lvp_pipeline_layout *smaller = dst->layout->vk.set_count < src->vk.set_count ? dst->layout : src; 713bf215546Sopenharmony_ci const struct lvp_pipeline_layout *bigger = smaller == dst->layout ? src : dst->layout; 714bf215546Sopenharmony_ci for (unsigned i = 0; i < smaller->vk.set_count; i++) { 715bf215546Sopenharmony_ci if (!smaller->vk.set_layouts[i] || !bigger->vk.set_layouts[i] || 716bf215546Sopenharmony_ci smaller->vk.set_layouts[i] == bigger->vk.set_layouts[i]) 717bf215546Sopenharmony_ci continue; 718bf215546Sopenharmony_ci 719bf215546Sopenharmony_ci const struct lvp_descriptor_set_layout *smaller_set_layout = 720bf215546Sopenharmony_ci vk_to_lvp_descriptor_set_layout(smaller->vk.set_layouts[i]); 721bf215546Sopenharmony_ci const struct lvp_descriptor_set_layout *bigger_set_layout = 722bf215546Sopenharmony_ci vk_to_lvp_descriptor_set_layout(bigger->vk.set_layouts[i]); 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_ci assert(!smaller_set_layout->binding_count || 725bf215546Sopenharmony_ci !bigger_set_layout->binding_count || 726bf215546Sopenharmony_ci layouts_equal(smaller_set_layout, bigger_set_layout)); 727bf215546Sopenharmony_ci } 728bf215546Sopenharmony_ci#endif 729bf215546Sopenharmony_ci for (unsigned i = 0; i < src->vk.set_count; i++) { 730bf215546Sopenharmony_ci if (!dst->layout->vk.set_layouts[i]) 731bf215546Sopenharmony_ci dst->layout->vk.set_layouts[i] = src->vk.set_layouts[i]; 732bf215546Sopenharmony_ci } 733bf215546Sopenharmony_ci dst->layout->vk.set_count = MAX2(dst->layout->vk.set_count, 734bf215546Sopenharmony_ci src->vk.set_count); 735bf215546Sopenharmony_ci dst->layout->push_constant_size += src->push_constant_size; 736bf215546Sopenharmony_ci dst->layout->push_constant_stages |= src->push_constant_stages; 737bf215546Sopenharmony_ci} 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_cistatic VkResult 740bf215546Sopenharmony_cilvp_graphics_pipeline_init(struct lvp_pipeline *pipeline, 741bf215546Sopenharmony_ci struct lvp_device *device, 742bf215546Sopenharmony_ci struct lvp_pipeline_cache *cache, 743bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *pCreateInfo) 744bf215546Sopenharmony_ci{ 745bf215546Sopenharmony_ci VkResult result; 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_ci const VkGraphicsPipelineLibraryCreateInfoEXT *libinfo = vk_find_struct_const(pCreateInfo, 748bf215546Sopenharmony_ci GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT); 749bf215546Sopenharmony_ci const VkPipelineLibraryCreateInfoKHR *libstate = vk_find_struct_const(pCreateInfo, 750bf215546Sopenharmony_ci PIPELINE_LIBRARY_CREATE_INFO_KHR); 751bf215546Sopenharmony_ci const VkGraphicsPipelineLibraryFlagsEXT layout_stages = VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT | 752bf215546Sopenharmony_ci VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT; 753bf215546Sopenharmony_ci if (libinfo) 754bf215546Sopenharmony_ci pipeline->stages = libinfo->flags; 755bf215546Sopenharmony_ci else if (!libstate) 756bf215546Sopenharmony_ci pipeline->stages = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT | 757bf215546Sopenharmony_ci VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT | 758bf215546Sopenharmony_ci VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT | 759bf215546Sopenharmony_ci VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT; 760bf215546Sopenharmony_ci pipeline->mem_ctx = ralloc_context(NULL); 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci if (pCreateInfo->flags & VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) 763bf215546Sopenharmony_ci pipeline->library = true; 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci struct lvp_pipeline_layout *layout = lvp_pipeline_layout_from_handle(pCreateInfo->layout); 766bf215546Sopenharmony_ci if (layout) 767bf215546Sopenharmony_ci vk_pipeline_layout_ref(&layout->vk); 768bf215546Sopenharmony_ci 769bf215546Sopenharmony_ci if (!layout || !(layout->vk.create_flags & VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT)) 770bf215546Sopenharmony_ci /* this is a regular pipeline with no partials: directly reuse */ 771bf215546Sopenharmony_ci pipeline->layout = layout; 772bf215546Sopenharmony_ci else if (pipeline->stages & layout_stages) { 773bf215546Sopenharmony_ci if ((pipeline->stages & layout_stages) == layout_stages) 774bf215546Sopenharmony_ci /* this has all the layout stages: directly reuse */ 775bf215546Sopenharmony_ci pipeline->layout = layout; 776bf215546Sopenharmony_ci else { 777bf215546Sopenharmony_ci /* this is a partial: copy for later merging to avoid modifying another layout */ 778bf215546Sopenharmony_ci merge_layouts(pipeline, layout); 779bf215546Sopenharmony_ci } 780bf215546Sopenharmony_ci } 781bf215546Sopenharmony_ci 782bf215546Sopenharmony_ci if (libstate) { 783bf215546Sopenharmony_ci for (unsigned i = 0; i < libstate->libraryCount; i++) { 784bf215546Sopenharmony_ci LVP_FROM_HANDLE(lvp_pipeline, p, libstate->pLibraries[i]); 785bf215546Sopenharmony_ci vk_graphics_pipeline_state_merge(&pipeline->graphics_state, 786bf215546Sopenharmony_ci &p->graphics_state); 787bf215546Sopenharmony_ci if (p->stages & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) { 788bf215546Sopenharmony_ci pipeline->line_smooth = p->line_smooth; 789bf215546Sopenharmony_ci pipeline->disable_multisample = p->disable_multisample; 790bf215546Sopenharmony_ci pipeline->line_rectangular = p->line_rectangular; 791bf215546Sopenharmony_ci pipeline->last_vertex = p->last_vertex; 792bf215546Sopenharmony_ci memcpy(&pipeline->stream_output, &p->stream_output, sizeof(p->stream_output)); 793bf215546Sopenharmony_ci memcpy(&pipeline->access, &p->access, sizeof(p->access)); 794bf215546Sopenharmony_ci } 795bf215546Sopenharmony_ci if (p->stages & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) 796bf215546Sopenharmony_ci pipeline->force_min_sample = p->force_min_sample; 797bf215546Sopenharmony_ci if (p->stages & layout_stages) { 798bf215546Sopenharmony_ci if (!layout || (layout->vk.create_flags & VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT)) 799bf215546Sopenharmony_ci merge_layouts(pipeline, p->layout); 800bf215546Sopenharmony_ci } 801bf215546Sopenharmony_ci pipeline->stages |= p->stages; 802bf215546Sopenharmony_ci } 803bf215546Sopenharmony_ci } 804bf215546Sopenharmony_ci 805bf215546Sopenharmony_ci result = vk_graphics_pipeline_state_fill(&device->vk, 806bf215546Sopenharmony_ci &pipeline->graphics_state, 807bf215546Sopenharmony_ci pCreateInfo, NULL, NULL, NULL, 808bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, 809bf215546Sopenharmony_ci &pipeline->state_data); 810bf215546Sopenharmony_ci if (result != VK_SUCCESS) 811bf215546Sopenharmony_ci return result; 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci assert(pipeline->library || pipeline->stages == (VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT | 814bf215546Sopenharmony_ci VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT | 815bf215546Sopenharmony_ci VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT | 816bf215546Sopenharmony_ci VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT)); 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_ci pipeline->device = device; 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 821bf215546Sopenharmony_ci const VkPipelineShaderStageCreateInfo *sinfo = &pCreateInfo->pStages[i]; 822bf215546Sopenharmony_ci gl_shader_stage stage = vk_to_mesa_shader_stage(sinfo->stage); 823bf215546Sopenharmony_ci if (stage == MESA_SHADER_FRAGMENT) { 824bf215546Sopenharmony_ci if (!(pipeline->stages & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT)) 825bf215546Sopenharmony_ci continue; 826bf215546Sopenharmony_ci } else { 827bf215546Sopenharmony_ci if (!(pipeline->stages & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT)) 828bf215546Sopenharmony_ci continue; 829bf215546Sopenharmony_ci } 830bf215546Sopenharmony_ci result = lvp_shader_compile_to_ir(pipeline, sinfo); 831bf215546Sopenharmony_ci if (result != VK_SUCCESS) 832bf215546Sopenharmony_ci goto fail; 833bf215546Sopenharmony_ci 834bf215546Sopenharmony_ci switch (stage) { 835bf215546Sopenharmony_ci case MESA_SHADER_GEOMETRY: 836bf215546Sopenharmony_ci pipeline->gs_output_lines = pipeline->pipeline_nir[MESA_SHADER_GEOMETRY] && 837bf215546Sopenharmony_ci pipeline->pipeline_nir[MESA_SHADER_GEOMETRY]->info.gs.output_primitive == SHADER_PRIM_LINES; 838bf215546Sopenharmony_ci break; 839bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 840bf215546Sopenharmony_ci if (pipeline->pipeline_nir[MESA_SHADER_FRAGMENT]->info.fs.uses_sample_shading) 841bf215546Sopenharmony_ci pipeline->force_min_sample = true; 842bf215546Sopenharmony_ci break; 843bf215546Sopenharmony_ci default: break; 844bf215546Sopenharmony_ci } 845bf215546Sopenharmony_ci } 846bf215546Sopenharmony_ci if (pCreateInfo->stageCount && pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]) { 847bf215546Sopenharmony_ci nir_lower_patch_vertices(pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL], pipeline->pipeline_nir[MESA_SHADER_TESS_CTRL]->info.tess.tcs_vertices_out, NULL); 848bf215546Sopenharmony_ci merge_tess_info(&pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]->info, &pipeline->pipeline_nir[MESA_SHADER_TESS_CTRL]->info); 849bf215546Sopenharmony_ci if (pipeline->graphics_state.ts->domain_origin == VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT) 850bf215546Sopenharmony_ci pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]->info.tess.ccw = !pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]->info.tess.ccw; 851bf215546Sopenharmony_ci } 852bf215546Sopenharmony_ci if (libstate) { 853bf215546Sopenharmony_ci for (unsigned i = 0; i < libstate->libraryCount; i++) { 854bf215546Sopenharmony_ci LVP_FROM_HANDLE(lvp_pipeline, p, libstate->pLibraries[i]); 855bf215546Sopenharmony_ci if (p->stages & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) { 856bf215546Sopenharmony_ci if (p->pipeline_nir[MESA_SHADER_FRAGMENT]) 857bf215546Sopenharmony_ci pipeline->pipeline_nir[MESA_SHADER_FRAGMENT] = nir_shader_clone(pipeline->mem_ctx, p->pipeline_nir[MESA_SHADER_FRAGMENT]); 858bf215546Sopenharmony_ci } 859bf215546Sopenharmony_ci if (p->stages & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) { 860bf215546Sopenharmony_ci for (unsigned j = MESA_SHADER_VERTEX; j < MESA_SHADER_FRAGMENT; j++) { 861bf215546Sopenharmony_ci if (p->pipeline_nir[j]) 862bf215546Sopenharmony_ci pipeline->pipeline_nir[j] = nir_shader_clone(pipeline->mem_ctx, p->pipeline_nir[j]); 863bf215546Sopenharmony_ci } 864bf215546Sopenharmony_ci } 865bf215546Sopenharmony_ci } 866bf215546Sopenharmony_ci } else if (pipeline->stages & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) { 867bf215546Sopenharmony_ci const struct vk_rasterization_state *rs = pipeline->graphics_state.rs; 868bf215546Sopenharmony_ci if (rs) { 869bf215546Sopenharmony_ci /* always draw bresenham if !smooth */ 870bf215546Sopenharmony_ci pipeline->line_smooth = rs->line.mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT; 871bf215546Sopenharmony_ci pipeline->disable_multisample = rs->line.mode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT || 872bf215546Sopenharmony_ci rs->line.mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT; 873bf215546Sopenharmony_ci pipeline->line_rectangular = rs->line.mode != VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT; 874bf215546Sopenharmony_ci } else 875bf215546Sopenharmony_ci pipeline->line_rectangular = true; 876bf215546Sopenharmony_ci lvp_pipeline_xfb_init(pipeline); 877bf215546Sopenharmony_ci } 878bf215546Sopenharmony_ci 879bf215546Sopenharmony_ci if (!pipeline->library) { 880bf215546Sopenharmony_ci bool has_fragment_shader = false; 881bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->pipeline_nir); i++) { 882bf215546Sopenharmony_ci if (!pipeline->pipeline_nir[i]) 883bf215546Sopenharmony_ci continue; 884bf215546Sopenharmony_ci 885bf215546Sopenharmony_ci gl_shader_stage stage = i; 886bf215546Sopenharmony_ci assert(stage == pipeline->pipeline_nir[i]->info.stage); 887bf215546Sopenharmony_ci enum pipe_shader_type pstage = pipe_shader_type_from_mesa(stage); 888bf215546Sopenharmony_ci if (!pipeline->inlines[stage].can_inline) 889bf215546Sopenharmony_ci pipeline->shader_cso[pstage] = lvp_pipeline_compile(pipeline, 890bf215546Sopenharmony_ci nir_shader_clone(NULL, pipeline->pipeline_nir[stage])); 891bf215546Sopenharmony_ci if (stage == MESA_SHADER_FRAGMENT) 892bf215546Sopenharmony_ci has_fragment_shader = true; 893bf215546Sopenharmony_ci } 894bf215546Sopenharmony_ci 895bf215546Sopenharmony_ci if (has_fragment_shader == false) { 896bf215546Sopenharmony_ci /* create a dummy fragment shader for this pipeline. */ 897bf215546Sopenharmony_ci nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, NULL, 898bf215546Sopenharmony_ci "dummy_frag"); 899bf215546Sopenharmony_ci 900bf215546Sopenharmony_ci pipeline->pipeline_nir[MESA_SHADER_FRAGMENT] = b.shader; 901bf215546Sopenharmony_ci struct pipe_shader_state shstate = {0}; 902bf215546Sopenharmony_ci shstate.type = PIPE_SHADER_IR_NIR; 903bf215546Sopenharmony_ci shstate.ir.nir = nir_shader_clone(NULL, pipeline->pipeline_nir[MESA_SHADER_FRAGMENT]); 904bf215546Sopenharmony_ci pipeline->shader_cso[PIPE_SHADER_FRAGMENT] = device->queue.ctx->create_fs_state(device->queue.ctx, &shstate); 905bf215546Sopenharmony_ci } 906bf215546Sopenharmony_ci } 907bf215546Sopenharmony_ci return VK_SUCCESS; 908bf215546Sopenharmony_ci 909bf215546Sopenharmony_cifail: 910bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(pipeline->pipeline_nir); i++) { 911bf215546Sopenharmony_ci if (pipeline->pipeline_nir[i]) 912bf215546Sopenharmony_ci ralloc_free(pipeline->pipeline_nir[i]); 913bf215546Sopenharmony_ci } 914bf215546Sopenharmony_ci vk_free(&device->vk.alloc, pipeline->state_data); 915bf215546Sopenharmony_ci 916bf215546Sopenharmony_ci return result; 917bf215546Sopenharmony_ci} 918bf215546Sopenharmony_ci 919bf215546Sopenharmony_cistatic VkResult 920bf215546Sopenharmony_cilvp_graphics_pipeline_create( 921bf215546Sopenharmony_ci VkDevice _device, 922bf215546Sopenharmony_ci VkPipelineCache _cache, 923bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *pCreateInfo, 924bf215546Sopenharmony_ci VkPipeline *pPipeline) 925bf215546Sopenharmony_ci{ 926bf215546Sopenharmony_ci LVP_FROM_HANDLE(lvp_device, device, _device); 927bf215546Sopenharmony_ci LVP_FROM_HANDLE(lvp_pipeline_cache, cache, _cache); 928bf215546Sopenharmony_ci struct lvp_pipeline *pipeline; 929bf215546Sopenharmony_ci VkResult result; 930bf215546Sopenharmony_ci 931bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO); 932bf215546Sopenharmony_ci 933bf215546Sopenharmony_ci pipeline = vk_zalloc(&device->vk.alloc, sizeof(*pipeline), 8, 934bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 935bf215546Sopenharmony_ci if (pipeline == NULL) 936bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 937bf215546Sopenharmony_ci 938bf215546Sopenharmony_ci vk_object_base_init(&device->vk, &pipeline->base, 939bf215546Sopenharmony_ci VK_OBJECT_TYPE_PIPELINE); 940bf215546Sopenharmony_ci uint64_t t0 = os_time_get_nano(); 941bf215546Sopenharmony_ci result = lvp_graphics_pipeline_init(pipeline, device, cache, pCreateInfo); 942bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 943bf215546Sopenharmony_ci vk_free(&device->vk.alloc, pipeline); 944bf215546Sopenharmony_ci return result; 945bf215546Sopenharmony_ci } 946bf215546Sopenharmony_ci 947bf215546Sopenharmony_ci VkPipelineCreationFeedbackCreateInfo *feedback = (void*)vk_find_struct_const(pCreateInfo->pNext, PIPELINE_CREATION_FEEDBACK_CREATE_INFO); 948bf215546Sopenharmony_ci if (feedback) { 949bf215546Sopenharmony_ci feedback->pPipelineCreationFeedback->duration = os_time_get_nano() - t0; 950bf215546Sopenharmony_ci feedback->pPipelineCreationFeedback->flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT; 951bf215546Sopenharmony_ci memset(feedback->pPipelineStageCreationFeedbacks, 0, sizeof(VkPipelineCreationFeedback) * feedback->pipelineStageCreationFeedbackCount); 952bf215546Sopenharmony_ci } 953bf215546Sopenharmony_ci 954bf215546Sopenharmony_ci *pPipeline = lvp_pipeline_to_handle(pipeline); 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_ci return VK_SUCCESS; 957bf215546Sopenharmony_ci} 958bf215546Sopenharmony_ci 959bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateGraphicsPipelines( 960bf215546Sopenharmony_ci VkDevice _device, 961bf215546Sopenharmony_ci VkPipelineCache pipelineCache, 962bf215546Sopenharmony_ci uint32_t count, 963bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo* pCreateInfos, 964bf215546Sopenharmony_ci const VkAllocationCallbacks* pAllocator, 965bf215546Sopenharmony_ci VkPipeline* pPipelines) 966bf215546Sopenharmony_ci{ 967bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 968bf215546Sopenharmony_ci unsigned i = 0; 969bf215546Sopenharmony_ci 970bf215546Sopenharmony_ci for (; i < count; i++) { 971bf215546Sopenharmony_ci VkResult r = VK_PIPELINE_COMPILE_REQUIRED; 972bf215546Sopenharmony_ci if (!(pCreateInfos[i].flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT)) 973bf215546Sopenharmony_ci r = lvp_graphics_pipeline_create(_device, 974bf215546Sopenharmony_ci pipelineCache, 975bf215546Sopenharmony_ci &pCreateInfos[i], 976bf215546Sopenharmony_ci &pPipelines[i]); 977bf215546Sopenharmony_ci if (r != VK_SUCCESS) { 978bf215546Sopenharmony_ci result = r; 979bf215546Sopenharmony_ci pPipelines[i] = VK_NULL_HANDLE; 980bf215546Sopenharmony_ci if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT) 981bf215546Sopenharmony_ci break; 982bf215546Sopenharmony_ci } 983bf215546Sopenharmony_ci } 984bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 985bf215546Sopenharmony_ci for (; i < count; i++) 986bf215546Sopenharmony_ci pPipelines[i] = VK_NULL_HANDLE; 987bf215546Sopenharmony_ci } 988bf215546Sopenharmony_ci 989bf215546Sopenharmony_ci return result; 990bf215546Sopenharmony_ci} 991bf215546Sopenharmony_ci 992bf215546Sopenharmony_cistatic VkResult 993bf215546Sopenharmony_cilvp_compute_pipeline_init(struct lvp_pipeline *pipeline, 994bf215546Sopenharmony_ci struct lvp_device *device, 995bf215546Sopenharmony_ci struct lvp_pipeline_cache *cache, 996bf215546Sopenharmony_ci const VkComputePipelineCreateInfo *pCreateInfo) 997bf215546Sopenharmony_ci{ 998bf215546Sopenharmony_ci pipeline->device = device; 999bf215546Sopenharmony_ci pipeline->layout = lvp_pipeline_layout_from_handle(pCreateInfo->layout); 1000bf215546Sopenharmony_ci vk_pipeline_layout_ref(&pipeline->layout->vk); 1001bf215546Sopenharmony_ci pipeline->force_min_sample = false; 1002bf215546Sopenharmony_ci 1003bf215546Sopenharmony_ci pipeline->mem_ctx = ralloc_context(NULL); 1004bf215546Sopenharmony_ci pipeline->is_compute_pipeline = true; 1005bf215546Sopenharmony_ci 1006bf215546Sopenharmony_ci VkResult result = lvp_shader_compile_to_ir(pipeline, &pCreateInfo->stage); 1007bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1008bf215546Sopenharmony_ci return result; 1009bf215546Sopenharmony_ci 1010bf215546Sopenharmony_ci if (!pipeline->inlines[MESA_SHADER_COMPUTE].can_inline) 1011bf215546Sopenharmony_ci pipeline->shader_cso[PIPE_SHADER_COMPUTE] = lvp_pipeline_compile(pipeline, nir_shader_clone(NULL, pipeline->pipeline_nir[MESA_SHADER_COMPUTE])); 1012bf215546Sopenharmony_ci return VK_SUCCESS; 1013bf215546Sopenharmony_ci} 1014bf215546Sopenharmony_ci 1015bf215546Sopenharmony_cistatic VkResult 1016bf215546Sopenharmony_cilvp_compute_pipeline_create( 1017bf215546Sopenharmony_ci VkDevice _device, 1018bf215546Sopenharmony_ci VkPipelineCache _cache, 1019bf215546Sopenharmony_ci const VkComputePipelineCreateInfo *pCreateInfo, 1020bf215546Sopenharmony_ci VkPipeline *pPipeline) 1021bf215546Sopenharmony_ci{ 1022bf215546Sopenharmony_ci LVP_FROM_HANDLE(lvp_device, device, _device); 1023bf215546Sopenharmony_ci LVP_FROM_HANDLE(lvp_pipeline_cache, cache, _cache); 1024bf215546Sopenharmony_ci struct lvp_pipeline *pipeline; 1025bf215546Sopenharmony_ci VkResult result; 1026bf215546Sopenharmony_ci 1027bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO); 1028bf215546Sopenharmony_ci 1029bf215546Sopenharmony_ci pipeline = vk_zalloc(&device->vk.alloc, sizeof(*pipeline), 8, 1030bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1031bf215546Sopenharmony_ci if (pipeline == NULL) 1032bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1033bf215546Sopenharmony_ci 1034bf215546Sopenharmony_ci vk_object_base_init(&device->vk, &pipeline->base, 1035bf215546Sopenharmony_ci VK_OBJECT_TYPE_PIPELINE); 1036bf215546Sopenharmony_ci uint64_t t0 = os_time_get_nano(); 1037bf215546Sopenharmony_ci result = lvp_compute_pipeline_init(pipeline, device, cache, pCreateInfo); 1038bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1039bf215546Sopenharmony_ci vk_free(&device->vk.alloc, pipeline); 1040bf215546Sopenharmony_ci return result; 1041bf215546Sopenharmony_ci } 1042bf215546Sopenharmony_ci 1043bf215546Sopenharmony_ci const VkPipelineCreationFeedbackCreateInfo *feedback = (void*)vk_find_struct_const(pCreateInfo->pNext, PIPELINE_CREATION_FEEDBACK_CREATE_INFO); 1044bf215546Sopenharmony_ci if (feedback) { 1045bf215546Sopenharmony_ci feedback->pPipelineCreationFeedback->duration = os_time_get_nano() - t0; 1046bf215546Sopenharmony_ci feedback->pPipelineCreationFeedback->flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT; 1047bf215546Sopenharmony_ci memset(feedback->pPipelineStageCreationFeedbacks, 0, sizeof(VkPipelineCreationFeedback) * feedback->pipelineStageCreationFeedbackCount); 1048bf215546Sopenharmony_ci } 1049bf215546Sopenharmony_ci 1050bf215546Sopenharmony_ci *pPipeline = lvp_pipeline_to_handle(pipeline); 1051bf215546Sopenharmony_ci 1052bf215546Sopenharmony_ci return VK_SUCCESS; 1053bf215546Sopenharmony_ci} 1054bf215546Sopenharmony_ci 1055bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateComputePipelines( 1056bf215546Sopenharmony_ci VkDevice _device, 1057bf215546Sopenharmony_ci VkPipelineCache pipelineCache, 1058bf215546Sopenharmony_ci uint32_t count, 1059bf215546Sopenharmony_ci const VkComputePipelineCreateInfo* pCreateInfos, 1060bf215546Sopenharmony_ci const VkAllocationCallbacks* pAllocator, 1061bf215546Sopenharmony_ci VkPipeline* pPipelines) 1062bf215546Sopenharmony_ci{ 1063bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 1064bf215546Sopenharmony_ci unsigned i = 0; 1065bf215546Sopenharmony_ci 1066bf215546Sopenharmony_ci for (; i < count; i++) { 1067bf215546Sopenharmony_ci VkResult r = VK_PIPELINE_COMPILE_REQUIRED; 1068bf215546Sopenharmony_ci if (!(pCreateInfos[i].flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT)) 1069bf215546Sopenharmony_ci r = lvp_compute_pipeline_create(_device, 1070bf215546Sopenharmony_ci pipelineCache, 1071bf215546Sopenharmony_ci &pCreateInfos[i], 1072bf215546Sopenharmony_ci &pPipelines[i]); 1073bf215546Sopenharmony_ci if (r != VK_SUCCESS) { 1074bf215546Sopenharmony_ci result = r; 1075bf215546Sopenharmony_ci pPipelines[i] = VK_NULL_HANDLE; 1076bf215546Sopenharmony_ci if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT) 1077bf215546Sopenharmony_ci break; 1078bf215546Sopenharmony_ci } 1079bf215546Sopenharmony_ci } 1080bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1081bf215546Sopenharmony_ci for (; i < count; i++) 1082bf215546Sopenharmony_ci pPipelines[i] = VK_NULL_HANDLE; 1083bf215546Sopenharmony_ci } 1084bf215546Sopenharmony_ci 1085bf215546Sopenharmony_ci 1086bf215546Sopenharmony_ci return result; 1087bf215546Sopenharmony_ci} 1088