1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "dzn_private.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "spirv/nir_spirv.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "dxil_nir.h" 29bf215546Sopenharmony_ci#include "nir_to_dxil.h" 30bf215546Sopenharmony_ci#include "dxil_spirv_nir.h" 31bf215546Sopenharmony_ci#include "spirv_to_dxil.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "dxil_validator.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include "vk_alloc.h" 36bf215546Sopenharmony_ci#include "vk_util.h" 37bf215546Sopenharmony_ci#include "vk_format.h" 38bf215546Sopenharmony_ci#include "vk_pipeline.h" 39bf215546Sopenharmony_ci#include "vk_pipeline_cache.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "util/u_debug.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci#define d3d12_pipeline_state_stream_new_desc(__stream, __maxstreamsz, __id, __type, __desc) \ 44bf215546Sopenharmony_ci __type *__desc; \ 45bf215546Sopenharmony_ci do { \ 46bf215546Sopenharmony_ci struct { \ 47bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_SUBOBJECT_TYPE type; \ 48bf215546Sopenharmony_ci __type desc; \ 49bf215546Sopenharmony_ci } *__wrapper; \ 50bf215546Sopenharmony_ci (__stream)->SizeInBytes = ALIGN_POT((__stream)->SizeInBytes, alignof(void *)); \ 51bf215546Sopenharmony_ci __wrapper = (void *)((uint8_t *)(__stream)->pPipelineStateSubobjectStream + (__stream)->SizeInBytes); \ 52bf215546Sopenharmony_ci (__stream)->SizeInBytes += sizeof(*__wrapper); \ 53bf215546Sopenharmony_ci assert((__stream)->SizeInBytes <= __maxstreamsz); \ 54bf215546Sopenharmony_ci __wrapper->type = D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ ## __id; \ 55bf215546Sopenharmony_ci __desc = &__wrapper->desc; \ 56bf215546Sopenharmony_ci memset(__desc, 0, sizeof(*__desc)); \ 57bf215546Sopenharmony_ci } while (0) 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci#define d3d12_gfx_pipeline_state_stream_new_desc(__stream, __id, __type, __desc) \ 60bf215546Sopenharmony_ci d3d12_pipeline_state_stream_new_desc(__stream, MAX_GFX_PIPELINE_STATE_STREAM_SIZE, __id, __type, __desc) 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci#define d3d12_compute_pipeline_state_stream_new_desc(__stream, __id, __type, __desc) \ 63bf215546Sopenharmony_ci d3d12_pipeline_state_stream_new_desc(__stream, MAX_COMPUTE_PIPELINE_STATE_STREAM_SIZE, __id, __type, __desc) 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_cistatic bool 66bf215546Sopenharmony_cigfx_pipeline_variant_key_equal(const void *a, const void *b) 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci return !memcmp(a, b, sizeof(struct dzn_graphics_pipeline_variant_key)); 69bf215546Sopenharmony_ci} 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_cistatic uint32_t 72bf215546Sopenharmony_cigfx_pipeline_variant_key_hash(const void *key) 73bf215546Sopenharmony_ci{ 74bf215546Sopenharmony_ci return _mesa_hash_data(key, sizeof(struct dzn_graphics_pipeline_variant_key)); 75bf215546Sopenharmony_ci} 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_cistruct dzn_cached_blob { 78bf215546Sopenharmony_ci struct vk_pipeline_cache_object base; 79bf215546Sopenharmony_ci uint8_t hash[SHA1_DIGEST_LENGTH]; 80bf215546Sopenharmony_ci const void *data; 81bf215546Sopenharmony_ci size_t size; 82bf215546Sopenharmony_ci}; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_cistatic bool 85bf215546Sopenharmony_cidzn_cached_blob_serialize(struct vk_pipeline_cache_object *object, 86bf215546Sopenharmony_ci struct blob *blob) 87bf215546Sopenharmony_ci{ 88bf215546Sopenharmony_ci struct dzn_cached_blob *cached_blob = 89bf215546Sopenharmony_ci container_of(object, struct dzn_cached_blob, base); 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci blob_write_bytes(blob, cached_blob->data, cached_blob->size); 92bf215546Sopenharmony_ci return true; 93bf215546Sopenharmony_ci} 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_cistatic void 96bf215546Sopenharmony_cidzn_cached_blob_destroy(struct vk_pipeline_cache_object *object) 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci struct dzn_cached_blob *shader = 99bf215546Sopenharmony_ci container_of(object, struct dzn_cached_blob, base); 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci vk_free(&shader->base.device->alloc, shader); 102bf215546Sopenharmony_ci} 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_cistatic struct vk_pipeline_cache_object * 105bf215546Sopenharmony_cidzn_cached_blob_create(struct vk_device *device, 106bf215546Sopenharmony_ci const void *hash, 107bf215546Sopenharmony_ci const void *data, 108bf215546Sopenharmony_ci size_t data_size); 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_cistatic struct vk_pipeline_cache_object * 111bf215546Sopenharmony_cidzn_cached_blob_deserialize(struct vk_device *device, 112bf215546Sopenharmony_ci const void *key_data, 113bf215546Sopenharmony_ci size_t key_size, 114bf215546Sopenharmony_ci struct blob_reader *blob) 115bf215546Sopenharmony_ci{ 116bf215546Sopenharmony_ci size_t data_size = blob->end - blob->current; 117bf215546Sopenharmony_ci assert(key_size == SHA1_DIGEST_LENGTH); 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci return dzn_cached_blob_create(device, key_data, 120bf215546Sopenharmony_ci blob_read_bytes(blob, data_size), 121bf215546Sopenharmony_ci data_size); 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ciconst struct vk_pipeline_cache_object_ops dzn_cached_blob_ops = { 125bf215546Sopenharmony_ci .serialize = dzn_cached_blob_serialize, 126bf215546Sopenharmony_ci .deserialize = dzn_cached_blob_deserialize, 127bf215546Sopenharmony_ci .destroy = dzn_cached_blob_destroy, 128bf215546Sopenharmony_ci}; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_cistatic struct vk_pipeline_cache_object * 132bf215546Sopenharmony_cidzn_cached_blob_create(struct vk_device *device, 133bf215546Sopenharmony_ci const void *hash, 134bf215546Sopenharmony_ci const void *data, 135bf215546Sopenharmony_ci size_t data_size) 136bf215546Sopenharmony_ci{ 137bf215546Sopenharmony_ci VK_MULTIALLOC(ma); 138bf215546Sopenharmony_ci VK_MULTIALLOC_DECL(&ma, struct dzn_cached_blob, blob, 1); 139bf215546Sopenharmony_ci VK_MULTIALLOC_DECL(&ma, uint8_t, copy, data_size); 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci if (!vk_multialloc_alloc(&ma, &device->alloc, 142bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE)) 143bf215546Sopenharmony_ci return NULL; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci memcpy(blob->hash, hash, sizeof(blob->hash)); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci vk_pipeline_cache_object_init(device, &blob->base, 148bf215546Sopenharmony_ci &dzn_cached_blob_ops, 149bf215546Sopenharmony_ci blob->hash, sizeof(blob->hash)); 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci if (data) 152bf215546Sopenharmony_ci memcpy(copy, data, data_size); 153bf215546Sopenharmony_ci blob->data = copy; 154bf215546Sopenharmony_ci blob->size = data_size; 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci return &blob->base; 157bf215546Sopenharmony_ci} 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_cistatic VkResult 160bf215546Sopenharmony_cidzn_graphics_pipeline_prepare_for_variants(struct dzn_device *device, 161bf215546Sopenharmony_ci struct dzn_graphics_pipeline *pipeline) 162bf215546Sopenharmony_ci{ 163bf215546Sopenharmony_ci if (pipeline->variants) 164bf215546Sopenharmony_ci return VK_SUCCESS; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci pipeline->variants = 167bf215546Sopenharmony_ci _mesa_hash_table_create(NULL, 168bf215546Sopenharmony_ci gfx_pipeline_variant_key_hash, 169bf215546Sopenharmony_ci gfx_pipeline_variant_key_equal); 170bf215546Sopenharmony_ci if (!pipeline->variants) 171bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci return VK_SUCCESS; 174bf215546Sopenharmony_ci} 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_cistatic dxil_spirv_shader_stage 177bf215546Sopenharmony_cito_dxil_shader_stage(VkShaderStageFlagBits in) 178bf215546Sopenharmony_ci{ 179bf215546Sopenharmony_ci switch (in) { 180bf215546Sopenharmony_ci case VK_SHADER_STAGE_VERTEX_BIT: return DXIL_SPIRV_SHADER_VERTEX; 181bf215546Sopenharmony_ci case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return DXIL_SPIRV_SHADER_TESS_CTRL; 182bf215546Sopenharmony_ci case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return DXIL_SPIRV_SHADER_TESS_EVAL; 183bf215546Sopenharmony_ci case VK_SHADER_STAGE_GEOMETRY_BIT: return DXIL_SPIRV_SHADER_GEOMETRY; 184bf215546Sopenharmony_ci case VK_SHADER_STAGE_FRAGMENT_BIT: return DXIL_SPIRV_SHADER_FRAGMENT; 185bf215546Sopenharmony_ci case VK_SHADER_STAGE_COMPUTE_BIT: return DXIL_SPIRV_SHADER_COMPUTE; 186bf215546Sopenharmony_ci default: unreachable("Unsupported stage"); 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_cistatic VkResult 191bf215546Sopenharmony_cidzn_pipeline_get_nir_shader(struct dzn_device *device, 192bf215546Sopenharmony_ci const struct dzn_pipeline_layout *layout, 193bf215546Sopenharmony_ci struct vk_pipeline_cache *cache, 194bf215546Sopenharmony_ci const uint8_t *hash, 195bf215546Sopenharmony_ci const VkPipelineShaderStageCreateInfo *stage_info, 196bf215546Sopenharmony_ci gl_shader_stage stage, 197bf215546Sopenharmony_ci enum dxil_spirv_yz_flip_mode yz_flip_mode, 198bf215546Sopenharmony_ci uint16_t y_flip_mask, uint16_t z_flip_mask, 199bf215546Sopenharmony_ci bool force_sample_rate_shading, 200bf215546Sopenharmony_ci enum pipe_format *vi_conversions, 201bf215546Sopenharmony_ci const nir_shader_compiler_options *nir_opts, 202bf215546Sopenharmony_ci nir_shader **nir) 203bf215546Sopenharmony_ci{ 204bf215546Sopenharmony_ci if (cache) { 205bf215546Sopenharmony_ci *nir = vk_pipeline_cache_lookup_nir(cache, hash, SHA1_DIGEST_LENGTH, 206bf215546Sopenharmony_ci nir_opts, NULL, NULL); 207bf215546Sopenharmony_ci if (*nir) 208bf215546Sopenharmony_ci return VK_SUCCESS; 209bf215546Sopenharmony_ci } 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_shader_module, module, stage_info->module); 212bf215546Sopenharmony_ci struct spirv_to_nir_options spirv_opts = { 213bf215546Sopenharmony_ci .caps = { 214bf215546Sopenharmony_ci .draw_parameters = true, 215bf215546Sopenharmony_ci }, 216bf215546Sopenharmony_ci .ubo_addr_format = nir_address_format_32bit_index_offset, 217bf215546Sopenharmony_ci .ssbo_addr_format = nir_address_format_32bit_index_offset, 218bf215546Sopenharmony_ci .shared_addr_format = nir_address_format_32bit_offset_as_64bit, 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci /* use_deref_buffer_array_length + nir_lower_explicit_io force 221bf215546Sopenharmony_ci * get_ssbo_size to take in the return from load_vulkan_descriptor 222bf215546Sopenharmony_ci * instead of vulkan_resource_index. This makes it much easier to 223bf215546Sopenharmony_ci * get the DXIL handle for the SSBO. 224bf215546Sopenharmony_ci */ 225bf215546Sopenharmony_ci .use_deref_buffer_array_length = true 226bf215546Sopenharmony_ci }; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci VkResult result = 229bf215546Sopenharmony_ci vk_shader_module_to_nir(&device->vk, module, stage, 230bf215546Sopenharmony_ci stage_info->pName, stage_info->pSpecializationInfo, 231bf215546Sopenharmony_ci &spirv_opts, nir_opts, NULL, nir); 232bf215546Sopenharmony_ci if (result != VK_SUCCESS) 233bf215546Sopenharmony_ci return result; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci struct dxil_spirv_runtime_conf conf = { 236bf215546Sopenharmony_ci .runtime_data_cbv = { 237bf215546Sopenharmony_ci .register_space = DZN_REGISTER_SPACE_SYSVALS, 238bf215546Sopenharmony_ci .base_shader_register = 0, 239bf215546Sopenharmony_ci }, 240bf215546Sopenharmony_ci .push_constant_cbv = { 241bf215546Sopenharmony_ci .register_space = DZN_REGISTER_SPACE_PUSH_CONSTANT, 242bf215546Sopenharmony_ci .base_shader_register = 0, 243bf215546Sopenharmony_ci }, 244bf215546Sopenharmony_ci .zero_based_vertex_instance_id = false, 245bf215546Sopenharmony_ci .yz_flip = { 246bf215546Sopenharmony_ci .mode = yz_flip_mode, 247bf215546Sopenharmony_ci .y_mask = y_flip_mask, 248bf215546Sopenharmony_ci .z_mask = z_flip_mask, 249bf215546Sopenharmony_ci }, 250bf215546Sopenharmony_ci .read_only_images_as_srvs = true, 251bf215546Sopenharmony_ci .force_sample_rate_shading = force_sample_rate_shading, 252bf215546Sopenharmony_ci }; 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci bool requires_runtime_data; 255bf215546Sopenharmony_ci dxil_spirv_nir_passes(*nir, &conf, &requires_runtime_data); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci if (stage == MESA_SHADER_VERTEX) { 258bf215546Sopenharmony_ci bool needs_conv = false; 259bf215546Sopenharmony_ci for (uint32_t i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) { 260bf215546Sopenharmony_ci if (vi_conversions[i] != PIPE_FORMAT_NONE) 261bf215546Sopenharmony_ci needs_conv = true; 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci if (needs_conv) 265bf215546Sopenharmony_ci NIR_PASS_V(*nir, dxil_nir_lower_vs_vertex_conversion, vi_conversions); 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci if (cache) 269bf215546Sopenharmony_ci vk_pipeline_cache_add_nir(cache, hash, SHA1_DIGEST_LENGTH, *nir); 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci return VK_SUCCESS; 272bf215546Sopenharmony_ci} 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_cistatic bool 275bf215546Sopenharmony_ciadjust_resource_index_binding(struct nir_builder *builder, nir_instr *instr, 276bf215546Sopenharmony_ci void *cb_data) 277bf215546Sopenharmony_ci{ 278bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 279bf215546Sopenharmony_ci return false; 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci if (intrin->intrinsic != nir_intrinsic_vulkan_resource_index) 284bf215546Sopenharmony_ci return false; 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci const struct dzn_pipeline_layout *layout = cb_data; 287bf215546Sopenharmony_ci unsigned set = nir_intrinsic_desc_set(intrin); 288bf215546Sopenharmony_ci unsigned binding = nir_intrinsic_binding(intrin); 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci if (set >= layout->set_count || 291bf215546Sopenharmony_ci binding >= layout->binding_translation[set].binding_count) 292bf215546Sopenharmony_ci return false; 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci binding = layout->binding_translation[set].base_reg[binding]; 295bf215546Sopenharmony_ci nir_intrinsic_set_binding(intrin, binding); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci return true; 298bf215546Sopenharmony_ci} 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_cistatic bool 301bf215546Sopenharmony_ciadjust_var_bindings(nir_shader *shader, 302bf215546Sopenharmony_ci const struct dzn_pipeline_layout *layout, 303bf215546Sopenharmony_ci uint8_t *bindings_hash) 304bf215546Sopenharmony_ci{ 305bf215546Sopenharmony_ci uint32_t modes = nir_var_image | nir_var_uniform | nir_var_mem_ubo | nir_var_mem_ssbo; 306bf215546Sopenharmony_ci struct mesa_sha1 bindings_hash_ctx; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (bindings_hash) 309bf215546Sopenharmony_ci _mesa_sha1_init(&bindings_hash_ctx); 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci nir_foreach_variable_with_modes(var, shader, modes) { 312bf215546Sopenharmony_ci if (var->data.mode == nir_var_uniform) { 313bf215546Sopenharmony_ci const struct glsl_type *type = glsl_without_array(var->type); 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci if (!glsl_type_is_sampler(type) && !glsl_type_is_texture(type)) 316bf215546Sopenharmony_ci continue; 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci unsigned s = var->data.descriptor_set, b = var->data.binding; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci if (s >= layout->set_count) 322bf215546Sopenharmony_ci continue; 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci assert(b < layout->binding_translation[s].binding_count); 325bf215546Sopenharmony_ci var->data.binding = layout->binding_translation[s].base_reg[b]; 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci if (bindings_hash) { 328bf215546Sopenharmony_ci _mesa_sha1_update(&bindings_hash_ctx, &s, sizeof(s)); 329bf215546Sopenharmony_ci _mesa_sha1_update(&bindings_hash_ctx, &b, sizeof(b)); 330bf215546Sopenharmony_ci _mesa_sha1_update(&bindings_hash_ctx, &var->data.binding, sizeof(var->data.binding)); 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci if (bindings_hash) 335bf215546Sopenharmony_ci _mesa_sha1_final(&bindings_hash_ctx, bindings_hash); 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci return nir_shader_instructions_pass(shader, adjust_resource_index_binding, 338bf215546Sopenharmony_ci nir_metadata_all, (void *)layout); 339bf215546Sopenharmony_ci} 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_cistatic VkResult 342bf215546Sopenharmony_cidzn_pipeline_compile_shader(struct dzn_device *device, 343bf215546Sopenharmony_ci nir_shader *nir, 344bf215546Sopenharmony_ci D3D12_SHADER_BYTECODE *slot) 345bf215546Sopenharmony_ci{ 346bf215546Sopenharmony_ci struct dzn_instance *instance = 347bf215546Sopenharmony_ci container_of(device->vk.physical->instance, struct dzn_instance, vk); 348bf215546Sopenharmony_ci struct nir_to_dxil_options opts = { 349bf215546Sopenharmony_ci .environment = DXIL_ENVIRONMENT_VULKAN, 350bf215546Sopenharmony_ci .shader_model_max = SHADER_MODEL_6_2, 351bf215546Sopenharmony_ci#ifdef _WIN32 352bf215546Sopenharmony_ci .validator_version_max = dxil_get_validator_version(instance->dxil_validator), 353bf215546Sopenharmony_ci#endif 354bf215546Sopenharmony_ci }; 355bf215546Sopenharmony_ci struct blob dxil_blob; 356bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci if (instance->debug_flags & DZN_DEBUG_NIR) 359bf215546Sopenharmony_ci nir_print_shader(nir, stderr); 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci if (nir_to_dxil(nir, &opts, &dxil_blob)) { 362bf215546Sopenharmony_ci blob_finish_get_buffer(&dxil_blob, (void **)&slot->pShaderBytecode, 363bf215546Sopenharmony_ci (size_t *)&slot->BytecodeLength); 364bf215546Sopenharmony_ci } else { 365bf215546Sopenharmony_ci result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci if (dxil_blob.allocated) 369bf215546Sopenharmony_ci blob_finish(&dxil_blob); 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (result != VK_SUCCESS) 372bf215546Sopenharmony_ci return result; 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci#ifdef _WIN32 375bf215546Sopenharmony_ci char *err; 376bf215546Sopenharmony_ci bool res = dxil_validate_module(instance->dxil_validator, 377bf215546Sopenharmony_ci (void *)slot->pShaderBytecode, 378bf215546Sopenharmony_ci slot->BytecodeLength, &err); 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci if (instance->debug_flags & DZN_DEBUG_DXIL) { 381bf215546Sopenharmony_ci char *disasm = dxil_disasm_module(instance->dxil_validator, 382bf215546Sopenharmony_ci (void *)slot->pShaderBytecode, 383bf215546Sopenharmony_ci slot->BytecodeLength); 384bf215546Sopenharmony_ci if (disasm) { 385bf215546Sopenharmony_ci fprintf(stderr, 386bf215546Sopenharmony_ci "== BEGIN SHADER ============================================\n" 387bf215546Sopenharmony_ci "%s\n" 388bf215546Sopenharmony_ci "== END SHADER ==============================================\n", 389bf215546Sopenharmony_ci disasm); 390bf215546Sopenharmony_ci ralloc_free(disasm); 391bf215546Sopenharmony_ci } 392bf215546Sopenharmony_ci } 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci if (!res) { 395bf215546Sopenharmony_ci if (err) { 396bf215546Sopenharmony_ci fprintf(stderr, 397bf215546Sopenharmony_ci "== VALIDATION ERROR =============================================\n" 398bf215546Sopenharmony_ci "%s\n" 399bf215546Sopenharmony_ci "== END ==========================================================\n", 400bf215546Sopenharmony_ci err); 401bf215546Sopenharmony_ci ralloc_free(err); 402bf215546Sopenharmony_ci } 403bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci#endif 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci return VK_SUCCESS; 408bf215546Sopenharmony_ci} 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_cistatic D3D12_SHADER_BYTECODE * 411bf215546Sopenharmony_cidzn_pipeline_get_gfx_shader_slot(D3D12_PIPELINE_STATE_STREAM_DESC *stream, 412bf215546Sopenharmony_ci gl_shader_stage in) 413bf215546Sopenharmony_ci{ 414bf215546Sopenharmony_ci switch (in) { 415bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: { 416bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(stream, VS, D3D12_SHADER_BYTECODE, desc); 417bf215546Sopenharmony_ci return desc; 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci case MESA_SHADER_TESS_CTRL: { 420bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(stream, DS, D3D12_SHADER_BYTECODE, desc); 421bf215546Sopenharmony_ci return desc; 422bf215546Sopenharmony_ci } 423bf215546Sopenharmony_ci case MESA_SHADER_TESS_EVAL: { 424bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(stream, HS, D3D12_SHADER_BYTECODE, desc); 425bf215546Sopenharmony_ci return desc; 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci case MESA_SHADER_GEOMETRY: { 428bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(stream, GS, D3D12_SHADER_BYTECODE, desc); 429bf215546Sopenharmony_ci return desc; 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: { 432bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(stream, PS, D3D12_SHADER_BYTECODE, desc); 433bf215546Sopenharmony_ci return desc; 434bf215546Sopenharmony_ci } 435bf215546Sopenharmony_ci default: unreachable("Unsupported stage"); 436bf215546Sopenharmony_ci } 437bf215546Sopenharmony_ci} 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_cistruct dzn_cached_dxil_shader_header { 440bf215546Sopenharmony_ci gl_shader_stage stage; 441bf215546Sopenharmony_ci size_t size; 442bf215546Sopenharmony_ci uint8_t data[0]; 443bf215546Sopenharmony_ci}; 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_cistatic VkResult 446bf215546Sopenharmony_cidzn_pipeline_cache_lookup_dxil_shader(struct vk_pipeline_cache *cache, 447bf215546Sopenharmony_ci const uint8_t *dxil_hash, 448bf215546Sopenharmony_ci gl_shader_stage *stage, 449bf215546Sopenharmony_ci D3D12_SHADER_BYTECODE *bc) 450bf215546Sopenharmony_ci{ 451bf215546Sopenharmony_ci *stage = MESA_SHADER_NONE; 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci if (!cache) 454bf215546Sopenharmony_ci return VK_SUCCESS; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci struct vk_pipeline_cache_object *cache_obj = NULL; 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci cache_obj = 459bf215546Sopenharmony_ci vk_pipeline_cache_lookup_object(cache, dxil_hash, SHA1_DIGEST_LENGTH, 460bf215546Sopenharmony_ci &dzn_cached_blob_ops, 461bf215546Sopenharmony_ci NULL); 462bf215546Sopenharmony_ci if (!cache_obj) 463bf215546Sopenharmony_ci return VK_SUCCESS; 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci struct dzn_cached_blob *cached_blob = 466bf215546Sopenharmony_ci container_of(cache_obj, struct dzn_cached_blob, base); 467bf215546Sopenharmony_ci VkResult ret = VK_SUCCESS; 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci assert(sizeof(struct dzn_cached_dxil_shader_header) <= cached_blob->size); 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci const struct dzn_cached_dxil_shader_header *info = 472bf215546Sopenharmony_ci (struct dzn_cached_dxil_shader_header *)(cached_blob->data); 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci assert(sizeof(struct dzn_cached_dxil_shader_header) + info->size <= cached_blob->size); 475bf215546Sopenharmony_ci assert(info->stage > MESA_SHADER_NONE && info->stage < MESA_VULKAN_SHADER_STAGES); 476bf215546Sopenharmony_ci assert(info->size > 0); 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci void *code = malloc(info->size); 479bf215546Sopenharmony_ci if (!code) { 480bf215546Sopenharmony_ci ret = vk_error(cache->base.device, VK_ERROR_OUT_OF_HOST_MEMORY); 481bf215546Sopenharmony_ci goto out; 482bf215546Sopenharmony_ci } 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci memcpy(code, info->data, info->size); 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci bc->pShaderBytecode = code; 487bf215546Sopenharmony_ci bc->BytecodeLength = info->size; 488bf215546Sopenharmony_ci *stage = info->stage; 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ciout: 491bf215546Sopenharmony_ci vk_pipeline_cache_object_unref(cache_obj); 492bf215546Sopenharmony_ci return ret; 493bf215546Sopenharmony_ci} 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_cistatic void 496bf215546Sopenharmony_cidzn_pipeline_cache_add_dxil_shader(struct vk_pipeline_cache *cache, 497bf215546Sopenharmony_ci const uint8_t *dxil_hash, 498bf215546Sopenharmony_ci gl_shader_stage stage, 499bf215546Sopenharmony_ci const D3D12_SHADER_BYTECODE *bc) 500bf215546Sopenharmony_ci{ 501bf215546Sopenharmony_ci size_t size = sizeof(struct dzn_cached_dxil_shader_header) + 502bf215546Sopenharmony_ci bc->BytecodeLength; 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci struct vk_pipeline_cache_object *cache_obj = 505bf215546Sopenharmony_ci dzn_cached_blob_create(cache->base.device, dxil_hash, NULL, size); 506bf215546Sopenharmony_ci if (!cache_obj) 507bf215546Sopenharmony_ci return; 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci struct dzn_cached_blob *cached_blob = 510bf215546Sopenharmony_ci container_of(cache_obj, struct dzn_cached_blob, base); 511bf215546Sopenharmony_ci struct dzn_cached_dxil_shader_header *info = 512bf215546Sopenharmony_ci (struct dzn_cached_dxil_shader_header *)(cached_blob->data); 513bf215546Sopenharmony_ci info->stage = stage; 514bf215546Sopenharmony_ci info->size = bc->BytecodeLength; 515bf215546Sopenharmony_ci memcpy(info->data, bc->pShaderBytecode, bc->BytecodeLength); 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci cache_obj = vk_pipeline_cache_add_object(cache, cache_obj); 518bf215546Sopenharmony_ci vk_pipeline_cache_object_unref(cache_obj); 519bf215546Sopenharmony_ci} 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_cistruct dzn_cached_gfx_pipeline_header { 522bf215546Sopenharmony_ci uint32_t stages; 523bf215546Sopenharmony_ci uint32_t input_count; 524bf215546Sopenharmony_ci}; 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_cistatic VkResult 527bf215546Sopenharmony_cidzn_pipeline_cache_lookup_gfx_pipeline(struct dzn_graphics_pipeline *pipeline, 528bf215546Sopenharmony_ci struct vk_pipeline_cache *cache, 529bf215546Sopenharmony_ci const uint8_t *pipeline_hash, 530bf215546Sopenharmony_ci bool *cache_hit) 531bf215546Sopenharmony_ci{ 532bf215546Sopenharmony_ci *cache_hit = false; 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci if (!cache) 535bf215546Sopenharmony_ci return VK_SUCCESS; 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci struct vk_pipeline_cache_object *cache_obj = NULL; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci cache_obj = 540bf215546Sopenharmony_ci vk_pipeline_cache_lookup_object(cache, pipeline_hash, SHA1_DIGEST_LENGTH, 541bf215546Sopenharmony_ci &dzn_cached_blob_ops, 542bf215546Sopenharmony_ci NULL); 543bf215546Sopenharmony_ci if (!cache_obj) 544bf215546Sopenharmony_ci return VK_SUCCESS; 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci struct dzn_cached_blob *cached_blob = 547bf215546Sopenharmony_ci container_of(cache_obj, struct dzn_cached_blob, base); 548bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc = 549bf215546Sopenharmony_ci &pipeline->templates.stream_desc; 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci const struct dzn_cached_gfx_pipeline_header *info = 552bf215546Sopenharmony_ci (const struct dzn_cached_gfx_pipeline_header *)(cached_blob->data); 553bf215546Sopenharmony_ci size_t offset = sizeof(*info); 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci assert(cached_blob->size >= sizeof(*info)); 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_ci if (info->input_count > 0) { 558bf215546Sopenharmony_ci offset = ALIGN_POT(offset, alignof(D3D12_INPUT_LAYOUT_DESC)); 559bf215546Sopenharmony_ci const D3D12_INPUT_ELEMENT_DESC *inputs = 560bf215546Sopenharmony_ci (const D3D12_INPUT_ELEMENT_DESC *)((uint8_t *)cached_blob->data + offset); 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_ci assert(cached_blob->size >= offset + sizeof(*inputs) * info->input_count); 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci memcpy(pipeline->templates.inputs, inputs, 565bf215546Sopenharmony_ci sizeof(*inputs) * info->input_count); 566bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, INPUT_LAYOUT, D3D12_INPUT_LAYOUT_DESC, desc); 567bf215546Sopenharmony_ci desc->pInputElementDescs = pipeline->templates.inputs; 568bf215546Sopenharmony_ci desc->NumElements = info->input_count; 569bf215546Sopenharmony_ci offset += sizeof(*inputs) * info->input_count; 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci assert(cached_blob->size == offset + util_bitcount(info->stages) * SHA1_DIGEST_LENGTH); 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci u_foreach_bit(s, info->stages) { 575bf215546Sopenharmony_ci uint8_t *dxil_hash = (uint8_t *)cached_blob->data + offset; 576bf215546Sopenharmony_ci gl_shader_stage stage; 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci D3D12_SHADER_BYTECODE *slot = 579bf215546Sopenharmony_ci dzn_pipeline_get_gfx_shader_slot(stream_desc, s); 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_ci VkResult ret = 582bf215546Sopenharmony_ci dzn_pipeline_cache_lookup_dxil_shader(cache, dxil_hash, &stage, slot); 583bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 584bf215546Sopenharmony_ci return ret; 585bf215546Sopenharmony_ci 586bf215546Sopenharmony_ci assert(stage == s); 587bf215546Sopenharmony_ci offset += SHA1_DIGEST_LENGTH; 588bf215546Sopenharmony_ci } 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_ci *cache_hit = true; 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci vk_pipeline_cache_object_unref(cache_obj); 593bf215546Sopenharmony_ci return VK_SUCCESS; 594bf215546Sopenharmony_ci} 595bf215546Sopenharmony_ci 596bf215546Sopenharmony_cistatic void 597bf215546Sopenharmony_cidzn_pipeline_cache_add_gfx_pipeline(struct dzn_graphics_pipeline *pipeline, 598bf215546Sopenharmony_ci struct vk_pipeline_cache *cache, 599bf215546Sopenharmony_ci uint32_t vertex_input_count, 600bf215546Sopenharmony_ci const uint8_t *pipeline_hash, 601bf215546Sopenharmony_ci const uint8_t *const *dxil_hashes) 602bf215546Sopenharmony_ci{ 603bf215546Sopenharmony_ci size_t offset = 604bf215546Sopenharmony_ci ALIGN_POT(sizeof(struct dzn_cached_gfx_pipeline_header), alignof(D3D12_INPUT_ELEMENT_DESC)) + 605bf215546Sopenharmony_ci (sizeof(D3D12_INPUT_ELEMENT_DESC) * vertex_input_count); 606bf215546Sopenharmony_ci uint32_t stages = 0; 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_ci for (uint32_t i = 0; i < MESA_VULKAN_SHADER_STAGES; i++) { 609bf215546Sopenharmony_ci if (pipeline->templates.shaders[i].bc) { 610bf215546Sopenharmony_ci stages |= BITFIELD_BIT(i); 611bf215546Sopenharmony_ci offset += SHA1_DIGEST_LENGTH; 612bf215546Sopenharmony_ci } 613bf215546Sopenharmony_ci } 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci struct vk_pipeline_cache_object *cache_obj = 616bf215546Sopenharmony_ci dzn_cached_blob_create(cache->base.device, pipeline_hash, NULL, offset); 617bf215546Sopenharmony_ci if (!cache_obj) 618bf215546Sopenharmony_ci return; 619bf215546Sopenharmony_ci 620bf215546Sopenharmony_ci struct dzn_cached_blob *cached_blob = 621bf215546Sopenharmony_ci container_of(cache_obj, struct dzn_cached_blob, base); 622bf215546Sopenharmony_ci 623bf215546Sopenharmony_ci offset = 0; 624bf215546Sopenharmony_ci struct dzn_cached_gfx_pipeline_header *info = 625bf215546Sopenharmony_ci (struct dzn_cached_gfx_pipeline_header *)(cached_blob->data); 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci info->input_count = vertex_input_count; 628bf215546Sopenharmony_ci info->stages = stages; 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci offset = ALIGN_POT(offset + sizeof(*info), alignof(D3D12_INPUT_ELEMENT_DESC)); 631bf215546Sopenharmony_ci 632bf215546Sopenharmony_ci D3D12_INPUT_ELEMENT_DESC *inputs = 633bf215546Sopenharmony_ci (D3D12_INPUT_ELEMENT_DESC *)((uint8_t *)cached_blob->data + offset); 634bf215546Sopenharmony_ci memcpy(inputs, pipeline->templates.inputs, 635bf215546Sopenharmony_ci sizeof(*inputs) * vertex_input_count); 636bf215546Sopenharmony_ci offset += sizeof(*inputs) * vertex_input_count; 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci u_foreach_bit(s, stages) { 639bf215546Sopenharmony_ci uint8_t *dxil_hash = (uint8_t *)cached_blob->data + offset; 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_ci memcpy(dxil_hash, dxil_hashes[s], SHA1_DIGEST_LENGTH); 642bf215546Sopenharmony_ci offset += SHA1_DIGEST_LENGTH; 643bf215546Sopenharmony_ci } 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_ci cache_obj = vk_pipeline_cache_add_object(cache, cache_obj); 646bf215546Sopenharmony_ci vk_pipeline_cache_object_unref(cache_obj); 647bf215546Sopenharmony_ci} 648bf215546Sopenharmony_ci 649bf215546Sopenharmony_cistatic void 650bf215546Sopenharmony_cidzn_graphics_pipeline_hash_attribs(D3D12_INPUT_ELEMENT_DESC *attribs, 651bf215546Sopenharmony_ci enum pipe_format *vi_conversions, 652bf215546Sopenharmony_ci uint8_t *result) 653bf215546Sopenharmony_ci{ 654bf215546Sopenharmony_ci struct mesa_sha1 ctx; 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_ci _mesa_sha1_init(&ctx); 657bf215546Sopenharmony_ci _mesa_sha1_update(&ctx, attribs, sizeof(*attribs) * MAX_VERTEX_GENERIC_ATTRIBS); 658bf215546Sopenharmony_ci _mesa_sha1_update(&ctx, vi_conversions, sizeof(*vi_conversions) * MAX_VERTEX_GENERIC_ATTRIBS); 659bf215546Sopenharmony_ci _mesa_sha1_final(&ctx, result); 660bf215546Sopenharmony_ci} 661bf215546Sopenharmony_ci 662bf215546Sopenharmony_cistatic VkResult 663bf215546Sopenharmony_cidzn_graphics_pipeline_compile_shaders(struct dzn_device *device, 664bf215546Sopenharmony_ci struct dzn_graphics_pipeline *pipeline, 665bf215546Sopenharmony_ci struct vk_pipeline_cache *cache, 666bf215546Sopenharmony_ci const struct dzn_pipeline_layout *layout, 667bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *out, 668bf215546Sopenharmony_ci D3D12_INPUT_ELEMENT_DESC *attribs, 669bf215546Sopenharmony_ci enum pipe_format *vi_conversions, 670bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *info) 671bf215546Sopenharmony_ci{ 672bf215546Sopenharmony_ci const VkPipelineViewportStateCreateInfo *vp_info = 673bf215546Sopenharmony_ci info->pRasterizationState->rasterizerDiscardEnable ? 674bf215546Sopenharmony_ci NULL : info->pViewportState; 675bf215546Sopenharmony_ci struct { 676bf215546Sopenharmony_ci const VkPipelineShaderStageCreateInfo *info; 677bf215546Sopenharmony_ci uint8_t spirv_hash[SHA1_DIGEST_LENGTH]; 678bf215546Sopenharmony_ci uint8_t dxil_hash[SHA1_DIGEST_LENGTH]; 679bf215546Sopenharmony_ci } stages[MESA_VULKAN_SHADER_STAGES] = { 0 }; 680bf215546Sopenharmony_ci const uint8_t *dxil_hashes[MESA_VULKAN_SHADER_STAGES] = { 0 }; 681bf215546Sopenharmony_ci uint8_t attribs_hash[SHA1_DIGEST_LENGTH]; 682bf215546Sopenharmony_ci uint8_t pipeline_hash[SHA1_DIGEST_LENGTH]; 683bf215546Sopenharmony_ci gl_shader_stage yz_flip_stage = MESA_SHADER_NONE; 684bf215546Sopenharmony_ci uint32_t active_stage_mask = 0; 685bf215546Sopenharmony_ci VkResult ret; 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci /* First step: collect stage info in a table indexed by gl_shader_stage 688bf215546Sopenharmony_ci * so we can iterate over stages in pipeline order or reverse pipeline 689bf215546Sopenharmony_ci * order. 690bf215546Sopenharmony_ci */ 691bf215546Sopenharmony_ci for (uint32_t i = 0; i < info->stageCount; i++) { 692bf215546Sopenharmony_ci gl_shader_stage stage = 693bf215546Sopenharmony_ci vk_to_mesa_shader_stage(info->pStages[i].stage); 694bf215546Sopenharmony_ci 695bf215546Sopenharmony_ci assert(stage <= MESA_SHADER_FRAGMENT); 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_ci if ((stage == MESA_SHADER_VERTEX || 698bf215546Sopenharmony_ci stage == MESA_SHADER_TESS_EVAL || 699bf215546Sopenharmony_ci stage == MESA_SHADER_GEOMETRY) && 700bf215546Sopenharmony_ci yz_flip_stage < stage) 701bf215546Sopenharmony_ci yz_flip_stage = stage; 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci if (stage == MESA_SHADER_FRAGMENT && 704bf215546Sopenharmony_ci info->pRasterizationState && 705bf215546Sopenharmony_ci (info->pRasterizationState->rasterizerDiscardEnable || 706bf215546Sopenharmony_ci info->pRasterizationState->cullMode == VK_CULL_MODE_FRONT_AND_BACK)) { 707bf215546Sopenharmony_ci /* Disable rasterization (AKA leave fragment shader NULL) when 708bf215546Sopenharmony_ci * front+back culling or discard is set. 709bf215546Sopenharmony_ci */ 710bf215546Sopenharmony_ci continue; 711bf215546Sopenharmony_ci } 712bf215546Sopenharmony_ci 713bf215546Sopenharmony_ci stages[stage].info = &info->pStages[i]; 714bf215546Sopenharmony_ci active_stage_mask |= BITFIELD_BIT(stage); 715bf215546Sopenharmony_ci } 716bf215546Sopenharmony_ci 717bf215546Sopenharmony_ci enum dxil_spirv_yz_flip_mode yz_flip_mode = DXIL_SPIRV_YZ_FLIP_NONE; 718bf215546Sopenharmony_ci uint16_t y_flip_mask = 0, z_flip_mask = 0; 719bf215546Sopenharmony_ci 720bf215546Sopenharmony_ci if (pipeline->vp.dynamic) { 721bf215546Sopenharmony_ci yz_flip_mode = DXIL_SPIRV_YZ_FLIP_CONDITIONAL; 722bf215546Sopenharmony_ci } else if (vp_info) { 723bf215546Sopenharmony_ci for (uint32_t i = 0; vp_info->pViewports && i < vp_info->viewportCount; i++) { 724bf215546Sopenharmony_ci if (vp_info->pViewports[i].height > 0) 725bf215546Sopenharmony_ci y_flip_mask |= BITFIELD_BIT(i); 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci if (vp_info->pViewports[i].minDepth > vp_info->pViewports[i].maxDepth) 728bf215546Sopenharmony_ci z_flip_mask |= BITFIELD_BIT(i); 729bf215546Sopenharmony_ci } 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_ci if (y_flip_mask && z_flip_mask) 732bf215546Sopenharmony_ci yz_flip_mode = DXIL_SPIRV_YZ_FLIP_UNCONDITIONAL; 733bf215546Sopenharmony_ci else if (z_flip_mask) 734bf215546Sopenharmony_ci yz_flip_mode = DXIL_SPIRV_Z_FLIP_UNCONDITIONAL; 735bf215546Sopenharmony_ci else if (y_flip_mask) 736bf215546Sopenharmony_ci yz_flip_mode = DXIL_SPIRV_Y_FLIP_UNCONDITIONAL; 737bf215546Sopenharmony_ci } 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_ci bool force_sample_rate_shading = 740bf215546Sopenharmony_ci info->pMultisampleState && 741bf215546Sopenharmony_ci info->pMultisampleState->sampleShadingEnable; 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci if (cache) { 744bf215546Sopenharmony_ci dzn_graphics_pipeline_hash_attribs(attribs, vi_conversions, attribs_hash); 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci struct mesa_sha1 pipeline_hash_ctx; 747bf215546Sopenharmony_ci 748bf215546Sopenharmony_ci _mesa_sha1_init(&pipeline_hash_ctx); 749bf215546Sopenharmony_ci _mesa_sha1_update(&pipeline_hash_ctx, attribs_hash, sizeof(attribs_hash)); 750bf215546Sopenharmony_ci _mesa_sha1_update(&pipeline_hash_ctx, &yz_flip_mode, sizeof(yz_flip_mode)); 751bf215546Sopenharmony_ci _mesa_sha1_update(&pipeline_hash_ctx, &y_flip_mask, sizeof(y_flip_mask)); 752bf215546Sopenharmony_ci _mesa_sha1_update(&pipeline_hash_ctx, &z_flip_mask, sizeof(z_flip_mask)); 753bf215546Sopenharmony_ci _mesa_sha1_update(&pipeline_hash_ctx, &force_sample_rate_shading, sizeof(force_sample_rate_shading)); 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci u_foreach_bit(stage, active_stage_mask) { 756bf215546Sopenharmony_ci vk_pipeline_hash_shader_stage(stages[stage].info, stages[stage].spirv_hash); 757bf215546Sopenharmony_ci _mesa_sha1_update(&pipeline_hash_ctx, stages[stage].spirv_hash, sizeof(stages[stage].spirv_hash)); 758bf215546Sopenharmony_ci _mesa_sha1_update(&pipeline_hash_ctx, layout->stages[stage].hash, sizeof(layout->stages[stage].hash)); 759bf215546Sopenharmony_ci } 760bf215546Sopenharmony_ci _mesa_sha1_final(&pipeline_hash_ctx, pipeline_hash); 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci bool cache_hit; 763bf215546Sopenharmony_ci ret = dzn_pipeline_cache_lookup_gfx_pipeline(pipeline, cache, pipeline_hash, 764bf215546Sopenharmony_ci &cache_hit); 765bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 766bf215546Sopenharmony_ci return ret; 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci if (cache_hit) 769bf215546Sopenharmony_ci return VK_SUCCESS; 770bf215546Sopenharmony_ci } 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci /* Second step: get NIR shaders for all stages. */ 773bf215546Sopenharmony_ci nir_shader_compiler_options nir_opts = *dxil_get_nir_compiler_options(); 774bf215546Sopenharmony_ci nir_opts.lower_base_vertex = true; 775bf215546Sopenharmony_ci u_foreach_bit(stage, active_stage_mask) { 776bf215546Sopenharmony_ci struct mesa_sha1 nir_hash_ctx; 777bf215546Sopenharmony_ci uint8_t nir_hash[SHA1_DIGEST_LENGTH]; 778bf215546Sopenharmony_ci 779bf215546Sopenharmony_ci if (cache) { 780bf215546Sopenharmony_ci _mesa_sha1_init(&nir_hash_ctx); 781bf215546Sopenharmony_ci if (stage == MESA_SHADER_VERTEX) 782bf215546Sopenharmony_ci _mesa_sha1_update(&nir_hash_ctx, attribs_hash, sizeof(attribs_hash)); 783bf215546Sopenharmony_ci if (stage == yz_flip_stage) { 784bf215546Sopenharmony_ci _mesa_sha1_update(&nir_hash_ctx, &yz_flip_mode, sizeof(yz_flip_mode)); 785bf215546Sopenharmony_ci _mesa_sha1_update(&nir_hash_ctx, &y_flip_mask, sizeof(y_flip_mask)); 786bf215546Sopenharmony_ci _mesa_sha1_update(&nir_hash_ctx, &z_flip_mask, sizeof(z_flip_mask)); 787bf215546Sopenharmony_ci } 788bf215546Sopenharmony_ci _mesa_sha1_update(&nir_hash_ctx, stages[stage].spirv_hash, sizeof(stages[stage].spirv_hash)); 789bf215546Sopenharmony_ci _mesa_sha1_final(&nir_hash_ctx, nir_hash); 790bf215546Sopenharmony_ci } 791bf215546Sopenharmony_ci 792bf215546Sopenharmony_ci ret = dzn_pipeline_get_nir_shader(device, layout, 793bf215546Sopenharmony_ci cache, nir_hash, 794bf215546Sopenharmony_ci stages[stage].info, stage, 795bf215546Sopenharmony_ci stage == yz_flip_stage ? yz_flip_mode : DXIL_SPIRV_YZ_FLIP_NONE, 796bf215546Sopenharmony_ci y_flip_mask, z_flip_mask, 797bf215546Sopenharmony_ci stage == MESA_SHADER_FRAGMENT ? force_sample_rate_shading : false, 798bf215546Sopenharmony_ci vi_conversions, 799bf215546Sopenharmony_ci &nir_opts, &pipeline->templates.shaders[stage].nir); 800bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 801bf215546Sopenharmony_ci return ret; 802bf215546Sopenharmony_ci } 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci /* Third step: link those NIR shaders. We iterate in reverse order 805bf215546Sopenharmony_ci * so we can eliminate outputs that are never read by the next stage. 806bf215546Sopenharmony_ci */ 807bf215546Sopenharmony_ci uint32_t link_mask = active_stage_mask; 808bf215546Sopenharmony_ci while (link_mask != 0) { 809bf215546Sopenharmony_ci gl_shader_stage stage = util_last_bit(link_mask) - 1; 810bf215546Sopenharmony_ci link_mask &= ~BITFIELD_BIT(stage); 811bf215546Sopenharmony_ci gl_shader_stage prev_stage = util_last_bit(link_mask) - 1; 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci assert(pipeline->templates.shaders[stage].nir); 814bf215546Sopenharmony_ci dxil_spirv_nir_link(pipeline->templates.shaders[stage].nir, 815bf215546Sopenharmony_ci prev_stage != MESA_SHADER_NONE ? 816bf215546Sopenharmony_ci pipeline->templates.shaders[prev_stage].nir : NULL); 817bf215546Sopenharmony_ci } 818bf215546Sopenharmony_ci 819bf215546Sopenharmony_ci u_foreach_bit(stage, active_stage_mask) { 820bf215546Sopenharmony_ci uint8_t bindings_hash[SHA1_DIGEST_LENGTH]; 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci NIR_PASS_V(pipeline->templates.shaders[stage].nir, adjust_var_bindings, layout, 823bf215546Sopenharmony_ci cache ? bindings_hash : NULL); 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci if (cache) { 826bf215546Sopenharmony_ci struct mesa_sha1 dxil_hash_ctx; 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci _mesa_sha1_init(&dxil_hash_ctx); 829bf215546Sopenharmony_ci 830bf215546Sopenharmony_ci if (stage == MESA_SHADER_VERTEX) 831bf215546Sopenharmony_ci _mesa_sha1_update(&dxil_hash_ctx, attribs_hash, sizeof(attribs_hash)); 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_ci if (stage == yz_flip_stage) { 834bf215546Sopenharmony_ci _mesa_sha1_update(&dxil_hash_ctx, &yz_flip_mode, sizeof(yz_flip_mode)); 835bf215546Sopenharmony_ci _mesa_sha1_update(&dxil_hash_ctx, &y_flip_mask, sizeof(y_flip_mask)); 836bf215546Sopenharmony_ci _mesa_sha1_update(&dxil_hash_ctx, &z_flip_mask, sizeof(z_flip_mask)); 837bf215546Sopenharmony_ci } 838bf215546Sopenharmony_ci 839bf215546Sopenharmony_ci if (stage == MESA_SHADER_FRAGMENT) 840bf215546Sopenharmony_ci _mesa_sha1_update(&dxil_hash_ctx, &force_sample_rate_shading, sizeof(force_sample_rate_shading)); 841bf215546Sopenharmony_ci 842bf215546Sopenharmony_ci _mesa_sha1_update(&dxil_hash_ctx, stages[stage].spirv_hash, sizeof(stages[stage].spirv_hash)); 843bf215546Sopenharmony_ci _mesa_sha1_update(&dxil_hash_ctx, bindings_hash, sizeof(bindings_hash)); 844bf215546Sopenharmony_ci _mesa_sha1_final(&dxil_hash_ctx, stages[stage].dxil_hash); 845bf215546Sopenharmony_ci dxil_hashes[stage] = stages[stage].dxil_hash; 846bf215546Sopenharmony_ci 847bf215546Sopenharmony_ci gl_shader_stage cached_stage; 848bf215546Sopenharmony_ci D3D12_SHADER_BYTECODE bc; 849bf215546Sopenharmony_ci ret = dzn_pipeline_cache_lookup_dxil_shader(cache, stages[stage].dxil_hash, &cached_stage, &bc); 850bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 851bf215546Sopenharmony_ci return ret; 852bf215546Sopenharmony_ci 853bf215546Sopenharmony_ci if (cached_stage != MESA_SHADER_NONE) { 854bf215546Sopenharmony_ci assert(cached_stage == stage); 855bf215546Sopenharmony_ci D3D12_SHADER_BYTECODE *slot = 856bf215546Sopenharmony_ci dzn_pipeline_get_gfx_shader_slot(out, stage); 857bf215546Sopenharmony_ci *slot = bc; 858bf215546Sopenharmony_ci pipeline->templates.shaders[stage].bc = slot; 859bf215546Sopenharmony_ci } 860bf215546Sopenharmony_ci } 861bf215546Sopenharmony_ci } 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci uint32_t vert_input_count = 0; 864bf215546Sopenharmony_ci if (pipeline->templates.shaders[MESA_SHADER_VERTEX].nir) { 865bf215546Sopenharmony_ci /* Now, declare one D3D12_INPUT_ELEMENT_DESC per VS input variable, so 866bf215546Sopenharmony_ci * we can handle location overlaps properly. 867bf215546Sopenharmony_ci */ 868bf215546Sopenharmony_ci nir_foreach_shader_in_variable(var, pipeline->templates.shaders[MESA_SHADER_VERTEX].nir) { 869bf215546Sopenharmony_ci assert(var->data.location >= VERT_ATTRIB_GENERIC0); 870bf215546Sopenharmony_ci unsigned loc = var->data.location - VERT_ATTRIB_GENERIC0; 871bf215546Sopenharmony_ci assert(vert_input_count < D3D12_VS_INPUT_REGISTER_COUNT); 872bf215546Sopenharmony_ci assert(loc < MAX_VERTEX_GENERIC_ATTRIBS); 873bf215546Sopenharmony_ci 874bf215546Sopenharmony_ci pipeline->templates.inputs[vert_input_count] = attribs[loc]; 875bf215546Sopenharmony_ci pipeline->templates.inputs[vert_input_count].SemanticIndex = vert_input_count; 876bf215546Sopenharmony_ci var->data.driver_location = vert_input_count++; 877bf215546Sopenharmony_ci } 878bf215546Sopenharmony_ci 879bf215546Sopenharmony_ci if (vert_input_count > 0) { 880bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(out, INPUT_LAYOUT, D3D12_INPUT_LAYOUT_DESC, desc); 881bf215546Sopenharmony_ci desc->pInputElementDescs = pipeline->templates.inputs; 882bf215546Sopenharmony_ci desc->NumElements = vert_input_count; 883bf215546Sopenharmony_ci } 884bf215546Sopenharmony_ci } 885bf215546Sopenharmony_ci 886bf215546Sopenharmony_ci /* Last step: translate NIR shaders into DXIL modules */ 887bf215546Sopenharmony_ci u_foreach_bit(stage, active_stage_mask) { 888bf215546Sopenharmony_ci /* Cache hit, we can skip the compilation. */ 889bf215546Sopenharmony_ci if (pipeline->templates.shaders[stage].bc) 890bf215546Sopenharmony_ci continue; 891bf215546Sopenharmony_ci 892bf215546Sopenharmony_ci if (stage == MESA_SHADER_FRAGMENT) { 893bf215546Sopenharmony_ci gl_shader_stage prev_stage = 894bf215546Sopenharmony_ci util_last_bit(active_stage_mask & BITFIELD_MASK(MESA_SHADER_FRAGMENT)) - 1; 895bf215546Sopenharmony_ci /* Disable rasterization if the last geometry stage doesn't 896bf215546Sopenharmony_ci * write the position. 897bf215546Sopenharmony_ci */ 898bf215546Sopenharmony_ci if (prev_stage == MESA_SHADER_NONE || 899bf215546Sopenharmony_ci !(pipeline->templates.shaders[prev_stage].nir->info.outputs_written & VARYING_BIT_POS)) 900bf215546Sopenharmony_ci continue; 901bf215546Sopenharmony_ci } 902bf215546Sopenharmony_ci 903bf215546Sopenharmony_ci D3D12_SHADER_BYTECODE *slot = 904bf215546Sopenharmony_ci dzn_pipeline_get_gfx_shader_slot(out, stage); 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ci ret = dzn_pipeline_compile_shader(device, pipeline->templates.shaders[stage].nir, slot); 907bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 908bf215546Sopenharmony_ci return ret; 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci pipeline->templates.shaders[stage].bc = slot; 911bf215546Sopenharmony_ci 912bf215546Sopenharmony_ci if (cache) 913bf215546Sopenharmony_ci dzn_pipeline_cache_add_dxil_shader(cache, stages[stage].dxil_hash, stage, slot); 914bf215546Sopenharmony_ci } 915bf215546Sopenharmony_ci 916bf215546Sopenharmony_ci if (cache) 917bf215546Sopenharmony_ci dzn_pipeline_cache_add_gfx_pipeline(pipeline, cache, vert_input_count, pipeline_hash, 918bf215546Sopenharmony_ci dxil_hashes); 919bf215546Sopenharmony_ci 920bf215546Sopenharmony_ci return VK_SUCCESS; 921bf215546Sopenharmony_ci} 922bf215546Sopenharmony_ci 923bf215546Sopenharmony_ciVkFormat 924bf215546Sopenharmony_cidzn_graphics_pipeline_patch_vi_format(VkFormat format) 925bf215546Sopenharmony_ci{ 926bf215546Sopenharmony_ci switch (format) { 927bf215546Sopenharmony_ci case VK_FORMAT_A2R10G10B10_SNORM_PACK32: 928bf215546Sopenharmony_ci case VK_FORMAT_A2R10G10B10_UNORM_PACK32: 929bf215546Sopenharmony_ci case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: 930bf215546Sopenharmony_ci case VK_FORMAT_A2R10G10B10_USCALED_PACK32: 931bf215546Sopenharmony_ci case VK_FORMAT_A2B10G10R10_SNORM_PACK32: 932bf215546Sopenharmony_ci case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: 933bf215546Sopenharmony_ci case VK_FORMAT_A2B10G10R10_USCALED_PACK32: 934bf215546Sopenharmony_ci return VK_FORMAT_R32_UINT; 935bf215546Sopenharmony_ci case VK_FORMAT_R8G8B8A8_SSCALED: 936bf215546Sopenharmony_ci return VK_FORMAT_R8G8B8A8_SINT; 937bf215546Sopenharmony_ci case VK_FORMAT_R8G8B8A8_USCALED: 938bf215546Sopenharmony_ci return VK_FORMAT_R8G8B8A8_UINT; 939bf215546Sopenharmony_ci case VK_FORMAT_R16G16B16A16_USCALED: 940bf215546Sopenharmony_ci return VK_FORMAT_R16G16B16A16_UINT; 941bf215546Sopenharmony_ci case VK_FORMAT_R16G16B16A16_SSCALED: 942bf215546Sopenharmony_ci return VK_FORMAT_R16G16B16A16_SINT; 943bf215546Sopenharmony_ci default: 944bf215546Sopenharmony_ci return format; 945bf215546Sopenharmony_ci } 946bf215546Sopenharmony_ci} 947bf215546Sopenharmony_ci 948bf215546Sopenharmony_cistatic VkResult 949bf215546Sopenharmony_cidzn_graphics_pipeline_translate_vi(struct dzn_graphics_pipeline *pipeline, 950bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *in, 951bf215546Sopenharmony_ci D3D12_INPUT_ELEMENT_DESC *inputs, 952bf215546Sopenharmony_ci enum pipe_format *vi_conversions) 953bf215546Sopenharmony_ci{ 954bf215546Sopenharmony_ci const VkPipelineVertexInputStateCreateInfo *in_vi = 955bf215546Sopenharmony_ci in->pVertexInputState; 956bf215546Sopenharmony_ci const VkPipelineVertexInputDivisorStateCreateInfoEXT *divisors = 957bf215546Sopenharmony_ci (const VkPipelineVertexInputDivisorStateCreateInfoEXT *) 958bf215546Sopenharmony_ci vk_find_struct_const(in_vi, PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT); 959bf215546Sopenharmony_ci 960bf215546Sopenharmony_ci if (!in_vi->vertexAttributeDescriptionCount) 961bf215546Sopenharmony_ci return VK_SUCCESS; 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_ci D3D12_INPUT_CLASSIFICATION slot_class[MAX_VBS]; 964bf215546Sopenharmony_ci 965bf215546Sopenharmony_ci pipeline->vb.count = 0; 966bf215546Sopenharmony_ci for (uint32_t i = 0; i < in_vi->vertexBindingDescriptionCount; i++) { 967bf215546Sopenharmony_ci const struct VkVertexInputBindingDescription *bdesc = 968bf215546Sopenharmony_ci &in_vi->pVertexBindingDescriptions[i]; 969bf215546Sopenharmony_ci 970bf215546Sopenharmony_ci pipeline->vb.count = MAX2(pipeline->vb.count, bdesc->binding + 1); 971bf215546Sopenharmony_ci pipeline->vb.strides[bdesc->binding] = bdesc->stride; 972bf215546Sopenharmony_ci if (bdesc->inputRate == VK_VERTEX_INPUT_RATE_INSTANCE) { 973bf215546Sopenharmony_ci slot_class[bdesc->binding] = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA; 974bf215546Sopenharmony_ci } else { 975bf215546Sopenharmony_ci assert(bdesc->inputRate == VK_VERTEX_INPUT_RATE_VERTEX); 976bf215546Sopenharmony_ci slot_class[bdesc->binding] = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; 977bf215546Sopenharmony_ci } 978bf215546Sopenharmony_ci } 979bf215546Sopenharmony_ci 980bf215546Sopenharmony_ci for (uint32_t i = 0; i < in_vi->vertexAttributeDescriptionCount; i++) { 981bf215546Sopenharmony_ci const VkVertexInputAttributeDescription *attr = 982bf215546Sopenharmony_ci &in_vi->pVertexAttributeDescriptions[i]; 983bf215546Sopenharmony_ci const VkVertexInputBindingDivisorDescriptionEXT *divisor = NULL; 984bf215546Sopenharmony_ci 985bf215546Sopenharmony_ci if (slot_class[attr->binding] == D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA && 986bf215546Sopenharmony_ci divisors) { 987bf215546Sopenharmony_ci for (uint32_t d = 0; d < divisors->vertexBindingDivisorCount; d++) { 988bf215546Sopenharmony_ci if (attr->binding == divisors->pVertexBindingDivisors[d].binding) { 989bf215546Sopenharmony_ci divisor = &divisors->pVertexBindingDivisors[d]; 990bf215546Sopenharmony_ci break; 991bf215546Sopenharmony_ci } 992bf215546Sopenharmony_ci } 993bf215546Sopenharmony_ci } 994bf215546Sopenharmony_ci 995bf215546Sopenharmony_ci VkFormat patched_format = dzn_graphics_pipeline_patch_vi_format(attr->format); 996bf215546Sopenharmony_ci if (patched_format != attr->format) 997bf215546Sopenharmony_ci vi_conversions[attr->location] = vk_format_to_pipe_format(attr->format); 998bf215546Sopenharmony_ci 999bf215546Sopenharmony_ci /* nir_to_dxil() name all vertex inputs as TEXCOORDx */ 1000bf215546Sopenharmony_ci inputs[attr->location] = (D3D12_INPUT_ELEMENT_DESC) { 1001bf215546Sopenharmony_ci .SemanticName = "TEXCOORD", 1002bf215546Sopenharmony_ci .Format = dzn_buffer_get_dxgi_format(patched_format), 1003bf215546Sopenharmony_ci .InputSlot = attr->binding, 1004bf215546Sopenharmony_ci .InputSlotClass = slot_class[attr->binding], 1005bf215546Sopenharmony_ci .InstanceDataStepRate = 1006bf215546Sopenharmony_ci divisor ? divisor->divisor : 1007bf215546Sopenharmony_ci slot_class[attr->binding] == D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA ? 1 : 0, 1008bf215546Sopenharmony_ci .AlignedByteOffset = attr->offset, 1009bf215546Sopenharmony_ci }; 1010bf215546Sopenharmony_ci } 1011bf215546Sopenharmony_ci 1012bf215546Sopenharmony_ci return VK_SUCCESS; 1013bf215546Sopenharmony_ci} 1014bf215546Sopenharmony_ci 1015bf215546Sopenharmony_cistatic D3D12_PRIMITIVE_TOPOLOGY_TYPE 1016bf215546Sopenharmony_cito_prim_topology_type(VkPrimitiveTopology in) 1017bf215546Sopenharmony_ci{ 1018bf215546Sopenharmony_ci switch (in) { 1019bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: 1020bf215546Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; 1021bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 1022bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 1023bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 1024bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: 1025bf215546Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; 1026bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 1027bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 1028bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 1029bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 1030bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: 1031bf215546Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; 1032bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: 1033bf215546Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; 1034bf215546Sopenharmony_ci default: unreachable("Invalid primitive topology"); 1035bf215546Sopenharmony_ci } 1036bf215546Sopenharmony_ci} 1037bf215546Sopenharmony_ci 1038bf215546Sopenharmony_cistatic D3D12_PRIMITIVE_TOPOLOGY 1039bf215546Sopenharmony_cito_prim_topology(VkPrimitiveTopology in, unsigned patch_control_points) 1040bf215546Sopenharmony_ci{ 1041bf215546Sopenharmony_ci switch (in) { 1042bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return D3D_PRIMITIVE_TOPOLOGY_POINTLIST; 1043bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return D3D_PRIMITIVE_TOPOLOGY_LINELIST; 1044bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; 1045bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ; 1046bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ; 1047bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; 1048bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; 1049bf215546Sopenharmony_ci /* Triangle fans are emulated using an intermediate index buffer. */ 1050bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; 1051bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ; 1052bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ; 1053bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: 1054bf215546Sopenharmony_ci assert(patch_control_points); 1055bf215546Sopenharmony_ci return (D3D12_PRIMITIVE_TOPOLOGY)(D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + patch_control_points - 1); 1056bf215546Sopenharmony_ci default: unreachable("Invalid primitive topology"); 1057bf215546Sopenharmony_ci } 1058bf215546Sopenharmony_ci} 1059bf215546Sopenharmony_ci 1060bf215546Sopenharmony_cistatic VkResult 1061bf215546Sopenharmony_cidzn_graphics_pipeline_translate_ia(struct dzn_device *device, 1062bf215546Sopenharmony_ci struct dzn_graphics_pipeline *pipeline, 1063bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *out, 1064bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *in) 1065bf215546Sopenharmony_ci{ 1066bf215546Sopenharmony_ci const VkPipelineInputAssemblyStateCreateInfo *in_ia = 1067bf215546Sopenharmony_ci in->pInputAssemblyState; 1068bf215546Sopenharmony_ci bool has_tes = false; 1069bf215546Sopenharmony_ci for (uint32_t i = 0; i < in->stageCount; i++) { 1070bf215546Sopenharmony_ci if (in->pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || 1071bf215546Sopenharmony_ci in->pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) { 1072bf215546Sopenharmony_ci has_tes = true; 1073bf215546Sopenharmony_ci break; 1074bf215546Sopenharmony_ci } 1075bf215546Sopenharmony_ci } 1076bf215546Sopenharmony_ci const VkPipelineTessellationStateCreateInfo *in_tes = 1077bf215546Sopenharmony_ci has_tes ? in->pTessellationState : NULL; 1078bf215546Sopenharmony_ci VkResult ret = VK_SUCCESS; 1079bf215546Sopenharmony_ci 1080bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(out, PRIMITIVE_TOPOLOGY, D3D12_PRIMITIVE_TOPOLOGY_TYPE, prim_top_type); 1081bf215546Sopenharmony_ci *prim_top_type = to_prim_topology_type(in_ia->topology); 1082bf215546Sopenharmony_ci pipeline->ia.triangle_fan = in_ia->topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; 1083bf215546Sopenharmony_ci pipeline->ia.topology = 1084bf215546Sopenharmony_ci to_prim_topology(in_ia->topology, in_tes ? in_tes->patchControlPoints : 0); 1085bf215546Sopenharmony_ci 1086bf215546Sopenharmony_ci if (in_ia->primitiveRestartEnable) { 1087bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(out, IB_STRIP_CUT_VALUE, D3D12_INDEX_BUFFER_STRIP_CUT_VALUE, ib_strip_cut); 1088bf215546Sopenharmony_ci pipeline->templates.desc_offsets.ib_strip_cut = 1089bf215546Sopenharmony_ci (uintptr_t)ib_strip_cut - (uintptr_t)out->pPipelineStateSubobjectStream; 1090bf215546Sopenharmony_ci *ib_strip_cut = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; 1091bf215546Sopenharmony_ci ret = dzn_graphics_pipeline_prepare_for_variants(device, pipeline); 1092bf215546Sopenharmony_ci } 1093bf215546Sopenharmony_ci 1094bf215546Sopenharmony_ci return ret; 1095bf215546Sopenharmony_ci} 1096bf215546Sopenharmony_ci 1097bf215546Sopenharmony_cistatic D3D12_FILL_MODE 1098bf215546Sopenharmony_citranslate_polygon_mode(VkPolygonMode in) 1099bf215546Sopenharmony_ci{ 1100bf215546Sopenharmony_ci switch (in) { 1101bf215546Sopenharmony_ci case VK_POLYGON_MODE_FILL: return D3D12_FILL_MODE_SOLID; 1102bf215546Sopenharmony_ci case VK_POLYGON_MODE_LINE: return D3D12_FILL_MODE_WIREFRAME; 1103bf215546Sopenharmony_ci default: unreachable("Unsupported polygon mode"); 1104bf215546Sopenharmony_ci } 1105bf215546Sopenharmony_ci} 1106bf215546Sopenharmony_ci 1107bf215546Sopenharmony_cistatic D3D12_CULL_MODE 1108bf215546Sopenharmony_citranslate_cull_mode(VkCullModeFlags in) 1109bf215546Sopenharmony_ci{ 1110bf215546Sopenharmony_ci switch (in) { 1111bf215546Sopenharmony_ci case VK_CULL_MODE_NONE: return D3D12_CULL_MODE_NONE; 1112bf215546Sopenharmony_ci case VK_CULL_MODE_FRONT_BIT: return D3D12_CULL_MODE_FRONT; 1113bf215546Sopenharmony_ci case VK_CULL_MODE_BACK_BIT: return D3D12_CULL_MODE_BACK; 1114bf215546Sopenharmony_ci /* Front+back face culling is equivalent to 'rasterization disabled' */ 1115bf215546Sopenharmony_ci case VK_CULL_MODE_FRONT_AND_BACK: return D3D12_CULL_MODE_NONE; 1116bf215546Sopenharmony_ci default: unreachable("Unsupported cull mode"); 1117bf215546Sopenharmony_ci } 1118bf215546Sopenharmony_ci} 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_cistatic int32_t 1121bf215546Sopenharmony_citranslate_depth_bias(double depth_bias) 1122bf215546Sopenharmony_ci{ 1123bf215546Sopenharmony_ci if (depth_bias > INT32_MAX) 1124bf215546Sopenharmony_ci return INT32_MAX; 1125bf215546Sopenharmony_ci else if (depth_bias < INT32_MIN) 1126bf215546Sopenharmony_ci return INT32_MIN; 1127bf215546Sopenharmony_ci 1128bf215546Sopenharmony_ci return depth_bias; 1129bf215546Sopenharmony_ci} 1130bf215546Sopenharmony_ci 1131bf215546Sopenharmony_cistatic void 1132bf215546Sopenharmony_cidzn_graphics_pipeline_translate_rast(struct dzn_graphics_pipeline *pipeline, 1133bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *out, 1134bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *in) 1135bf215546Sopenharmony_ci{ 1136bf215546Sopenharmony_ci const VkPipelineRasterizationStateCreateInfo *in_rast = 1137bf215546Sopenharmony_ci in->pRasterizationState; 1138bf215546Sopenharmony_ci const VkPipelineViewportStateCreateInfo *in_vp = 1139bf215546Sopenharmony_ci in_rast->rasterizerDiscardEnable ? NULL : in->pViewportState; 1140bf215546Sopenharmony_ci 1141bf215546Sopenharmony_ci if (in_vp) { 1142bf215546Sopenharmony_ci pipeline->vp.count = in_vp->viewportCount; 1143bf215546Sopenharmony_ci if (in_vp->pViewports) { 1144bf215546Sopenharmony_ci for (uint32_t i = 0; in_vp->pViewports && i < in_vp->viewportCount; i++) 1145bf215546Sopenharmony_ci dzn_translate_viewport(&pipeline->vp.desc[i], &in_vp->pViewports[i]); 1146bf215546Sopenharmony_ci } 1147bf215546Sopenharmony_ci 1148bf215546Sopenharmony_ci pipeline->scissor.count = in_vp->scissorCount; 1149bf215546Sopenharmony_ci if (in_vp->pScissors) { 1150bf215546Sopenharmony_ci for (uint32_t i = 0; i < in_vp->scissorCount; i++) 1151bf215546Sopenharmony_ci dzn_translate_rect(&pipeline->scissor.desc[i], &in_vp->pScissors[i]); 1152bf215546Sopenharmony_ci } 1153bf215546Sopenharmony_ci } 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(out, RASTERIZER, D3D12_RASTERIZER_DESC, desc); 1156bf215546Sopenharmony_ci pipeline->templates.desc_offsets.rast = 1157bf215546Sopenharmony_ci (uintptr_t)desc - (uintptr_t)out->pPipelineStateSubobjectStream; 1158bf215546Sopenharmony_ci desc->DepthClipEnable = !in_rast->depthClampEnable; 1159bf215546Sopenharmony_ci desc->FillMode = translate_polygon_mode(in_rast->polygonMode); 1160bf215546Sopenharmony_ci desc->CullMode = translate_cull_mode(in_rast->cullMode); 1161bf215546Sopenharmony_ci desc->FrontCounterClockwise = 1162bf215546Sopenharmony_ci in_rast->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE; 1163bf215546Sopenharmony_ci if (in_rast->depthBiasEnable) { 1164bf215546Sopenharmony_ci desc->DepthBias = translate_depth_bias(in_rast->depthBiasConstantFactor); 1165bf215546Sopenharmony_ci desc->SlopeScaledDepthBias = in_rast->depthBiasSlopeFactor; 1166bf215546Sopenharmony_ci desc->DepthBiasClamp = in_rast->depthBiasClamp; 1167bf215546Sopenharmony_ci } 1168bf215546Sopenharmony_ci 1169bf215546Sopenharmony_ci assert(in_rast->lineWidth == 1.0f); 1170bf215546Sopenharmony_ci} 1171bf215546Sopenharmony_ci 1172bf215546Sopenharmony_cistatic void 1173bf215546Sopenharmony_cidzn_graphics_pipeline_translate_ms(struct dzn_graphics_pipeline *pipeline, 1174bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *out, 1175bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *in) 1176bf215546Sopenharmony_ci{ 1177bf215546Sopenharmony_ci const VkPipelineRasterizationStateCreateInfo *in_rast = 1178bf215546Sopenharmony_ci in->pRasterizationState; 1179bf215546Sopenharmony_ci const VkPipelineMultisampleStateCreateInfo *in_ms = 1180bf215546Sopenharmony_ci in_rast->rasterizerDiscardEnable ? NULL : in->pMultisampleState; 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_ci if (!in_ms) 1183bf215546Sopenharmony_ci return; 1184bf215546Sopenharmony_ci 1185bf215546Sopenharmony_ci /* TODO: minSampleShading (use VRS), alphaToOneEnable */ 1186bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(out, SAMPLE_DESC, DXGI_SAMPLE_DESC, desc); 1187bf215546Sopenharmony_ci desc->Count = in_ms ? in_ms->rasterizationSamples : 1; 1188bf215546Sopenharmony_ci desc->Quality = 0; 1189bf215546Sopenharmony_ci 1190bf215546Sopenharmony_ci if (!in_ms->pSampleMask) 1191bf215546Sopenharmony_ci return; 1192bf215546Sopenharmony_ci 1193bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(out, SAMPLE_MASK, UINT, mask); 1194bf215546Sopenharmony_ci *mask = *in_ms->pSampleMask; 1195bf215546Sopenharmony_ci} 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_cistatic D3D12_STENCIL_OP 1198bf215546Sopenharmony_citranslate_stencil_op(VkStencilOp in) 1199bf215546Sopenharmony_ci{ 1200bf215546Sopenharmony_ci switch (in) { 1201bf215546Sopenharmony_ci case VK_STENCIL_OP_KEEP: return D3D12_STENCIL_OP_KEEP; 1202bf215546Sopenharmony_ci case VK_STENCIL_OP_ZERO: return D3D12_STENCIL_OP_ZERO; 1203bf215546Sopenharmony_ci case VK_STENCIL_OP_REPLACE: return D3D12_STENCIL_OP_REPLACE; 1204bf215546Sopenharmony_ci case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return D3D12_STENCIL_OP_INCR_SAT; 1205bf215546Sopenharmony_ci case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return D3D12_STENCIL_OP_DECR_SAT; 1206bf215546Sopenharmony_ci case VK_STENCIL_OP_INCREMENT_AND_WRAP: return D3D12_STENCIL_OP_INCR; 1207bf215546Sopenharmony_ci case VK_STENCIL_OP_DECREMENT_AND_WRAP: return D3D12_STENCIL_OP_DECR; 1208bf215546Sopenharmony_ci case VK_STENCIL_OP_INVERT: return D3D12_STENCIL_OP_INVERT; 1209bf215546Sopenharmony_ci default: unreachable("Invalid stencil op"); 1210bf215546Sopenharmony_ci } 1211bf215546Sopenharmony_ci} 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_cistatic void 1214bf215546Sopenharmony_citranslate_stencil_test(struct dzn_graphics_pipeline *pipeline, 1215bf215546Sopenharmony_ci D3D12_DEPTH_STENCIL_DESC1 *out, 1216bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *in) 1217bf215546Sopenharmony_ci{ 1218bf215546Sopenharmony_ci const VkPipelineDepthStencilStateCreateInfo *in_zsa = 1219bf215546Sopenharmony_ci in->pDepthStencilState; 1220bf215546Sopenharmony_ci 1221bf215546Sopenharmony_ci bool front_test_uses_ref = 1222bf215546Sopenharmony_ci !(in->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT) && 1223bf215546Sopenharmony_ci in_zsa->front.compareOp != VK_COMPARE_OP_NEVER && 1224bf215546Sopenharmony_ci in_zsa->front.compareOp != VK_COMPARE_OP_ALWAYS && 1225bf215546Sopenharmony_ci (pipeline->zsa.stencil_test.dynamic_compare_mask || 1226bf215546Sopenharmony_ci in_zsa->front.compareMask != 0); 1227bf215546Sopenharmony_ci bool back_test_uses_ref = 1228bf215546Sopenharmony_ci !(in->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT) && 1229bf215546Sopenharmony_ci in_zsa->back.compareOp != VK_COMPARE_OP_NEVER && 1230bf215546Sopenharmony_ci in_zsa->back.compareOp != VK_COMPARE_OP_ALWAYS && 1231bf215546Sopenharmony_ci (pipeline->zsa.stencil_test.dynamic_compare_mask || 1232bf215546Sopenharmony_ci in_zsa->back.compareMask != 0); 1233bf215546Sopenharmony_ci 1234bf215546Sopenharmony_ci if (front_test_uses_ref && pipeline->zsa.stencil_test.dynamic_compare_mask) 1235bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.compare_mask = UINT32_MAX; 1236bf215546Sopenharmony_ci else if (front_test_uses_ref) 1237bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.compare_mask = in_zsa->front.compareMask; 1238bf215546Sopenharmony_ci else 1239bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.compare_mask = 0; 1240bf215546Sopenharmony_ci 1241bf215546Sopenharmony_ci if (back_test_uses_ref && pipeline->zsa.stencil_test.dynamic_compare_mask) 1242bf215546Sopenharmony_ci pipeline->zsa.stencil_test.back.compare_mask = UINT32_MAX; 1243bf215546Sopenharmony_ci else if (back_test_uses_ref) 1244bf215546Sopenharmony_ci pipeline->zsa.stencil_test.back.compare_mask = in_zsa->back.compareMask; 1245bf215546Sopenharmony_ci else 1246bf215546Sopenharmony_ci pipeline->zsa.stencil_test.back.compare_mask = 0; 1247bf215546Sopenharmony_ci 1248bf215546Sopenharmony_ci bool diff_wr_mask = 1249bf215546Sopenharmony_ci in->pRasterizationState->cullMode == VK_CULL_MODE_NONE && 1250bf215546Sopenharmony_ci (pipeline->zsa.stencil_test.dynamic_write_mask || 1251bf215546Sopenharmony_ci in_zsa->back.writeMask != in_zsa->front.writeMask); 1252bf215546Sopenharmony_ci bool diff_ref = 1253bf215546Sopenharmony_ci in->pRasterizationState->cullMode == VK_CULL_MODE_NONE && 1254bf215546Sopenharmony_ci (pipeline->zsa.stencil_test.dynamic_ref || 1255bf215546Sopenharmony_ci in_zsa->back.reference != in_zsa->front.reference); 1256bf215546Sopenharmony_ci bool diff_cmp_mask = 1257bf215546Sopenharmony_ci back_test_uses_ref && front_test_uses_ref && 1258bf215546Sopenharmony_ci (pipeline->zsa.stencil_test.dynamic_compare_mask || 1259bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.compare_mask != pipeline->zsa.stencil_test.back.compare_mask); 1260bf215546Sopenharmony_ci 1261bf215546Sopenharmony_ci if (diff_cmp_mask || diff_wr_mask) 1262bf215546Sopenharmony_ci pipeline->zsa.stencil_test.independent_front_back = true; 1263bf215546Sopenharmony_ci 1264bf215546Sopenharmony_ci bool back_wr_uses_ref = 1265bf215546Sopenharmony_ci !(in->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT) && 1266bf215546Sopenharmony_ci ((in_zsa->back.compareOp != VK_COMPARE_OP_ALWAYS && 1267bf215546Sopenharmony_ci in_zsa->back.failOp == VK_STENCIL_OP_REPLACE) || 1268bf215546Sopenharmony_ci (in_zsa->back.compareOp != VK_COMPARE_OP_NEVER && 1269bf215546Sopenharmony_ci (!in_zsa->depthTestEnable || in_zsa->depthCompareOp != VK_COMPARE_OP_NEVER) && 1270bf215546Sopenharmony_ci in_zsa->back.passOp == VK_STENCIL_OP_REPLACE) || 1271bf215546Sopenharmony_ci (in_zsa->depthTestEnable && 1272bf215546Sopenharmony_ci in_zsa->depthCompareOp != VK_COMPARE_OP_ALWAYS && 1273bf215546Sopenharmony_ci in_zsa->back.depthFailOp == VK_STENCIL_OP_REPLACE)); 1274bf215546Sopenharmony_ci bool front_wr_uses_ref = 1275bf215546Sopenharmony_ci !(in->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT) && 1276bf215546Sopenharmony_ci ((in_zsa->front.compareOp != VK_COMPARE_OP_ALWAYS && 1277bf215546Sopenharmony_ci in_zsa->front.failOp == VK_STENCIL_OP_REPLACE) || 1278bf215546Sopenharmony_ci (in_zsa->front.compareOp != VK_COMPARE_OP_NEVER && 1279bf215546Sopenharmony_ci (!in_zsa->depthTestEnable || in_zsa->depthCompareOp != VK_COMPARE_OP_NEVER) && 1280bf215546Sopenharmony_ci in_zsa->front.passOp == VK_STENCIL_OP_REPLACE) || 1281bf215546Sopenharmony_ci (in_zsa->depthTestEnable && 1282bf215546Sopenharmony_ci in_zsa->depthCompareOp != VK_COMPARE_OP_ALWAYS && 1283bf215546Sopenharmony_ci in_zsa->front.depthFailOp == VK_STENCIL_OP_REPLACE)); 1284bf215546Sopenharmony_ci 1285bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.write_mask = 1286bf215546Sopenharmony_ci (pipeline->zsa.stencil_test.dynamic_write_mask || 1287bf215546Sopenharmony_ci (in->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT)) ? 1288bf215546Sopenharmony_ci 0 : in_zsa->front.writeMask; 1289bf215546Sopenharmony_ci pipeline->zsa.stencil_test.back.write_mask = 1290bf215546Sopenharmony_ci (pipeline->zsa.stencil_test.dynamic_write_mask || 1291bf215546Sopenharmony_ci (in->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT)) ? 1292bf215546Sopenharmony_ci 0 : in_zsa->back.writeMask; 1293bf215546Sopenharmony_ci 1294bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.uses_ref = front_test_uses_ref || front_wr_uses_ref; 1295bf215546Sopenharmony_ci pipeline->zsa.stencil_test.back.uses_ref = back_test_uses_ref || back_wr_uses_ref; 1296bf215546Sopenharmony_ci 1297bf215546Sopenharmony_ci if (diff_ref && 1298bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.uses_ref && 1299bf215546Sopenharmony_ci pipeline->zsa.stencil_test.back.uses_ref) 1300bf215546Sopenharmony_ci pipeline->zsa.stencil_test.independent_front_back = true; 1301bf215546Sopenharmony_ci 1302bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.ref = 1303bf215546Sopenharmony_ci pipeline->zsa.stencil_test.dynamic_ref ? 0 : in_zsa->front.reference; 1304bf215546Sopenharmony_ci pipeline->zsa.stencil_test.back.ref = 1305bf215546Sopenharmony_ci pipeline->zsa.stencil_test.dynamic_ref ? 0 : in_zsa->back.reference; 1306bf215546Sopenharmony_ci 1307bf215546Sopenharmony_ci /* FIXME: We don't support independent {compare,write}_mask and stencil 1308bf215546Sopenharmony_ci * reference. Until we have proper support for independent front/back 1309bf215546Sopenharmony_ci * stencil test, let's prioritize the front setup when both are active. 1310bf215546Sopenharmony_ci */ 1311bf215546Sopenharmony_ci out->StencilReadMask = 1312bf215546Sopenharmony_ci front_test_uses_ref ? 1313bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.compare_mask : 1314bf215546Sopenharmony_ci back_test_uses_ref ? 1315bf215546Sopenharmony_ci pipeline->zsa.stencil_test.back.compare_mask : 0; 1316bf215546Sopenharmony_ci out->StencilWriteMask = 1317bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.write_mask ? 1318bf215546Sopenharmony_ci pipeline->zsa.stencil_test.front.write_mask : 1319bf215546Sopenharmony_ci pipeline->zsa.stencil_test.back.write_mask; 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_ci assert(!pipeline->zsa.stencil_test.independent_front_back); 1322bf215546Sopenharmony_ci} 1323bf215546Sopenharmony_ci 1324bf215546Sopenharmony_cistatic void 1325bf215546Sopenharmony_cidzn_graphics_pipeline_translate_zsa(struct dzn_graphics_pipeline *pipeline, 1326bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *out, 1327bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *in) 1328bf215546Sopenharmony_ci{ 1329bf215546Sopenharmony_ci const VkPipelineRasterizationStateCreateInfo *in_rast = 1330bf215546Sopenharmony_ci in->pRasterizationState; 1331bf215546Sopenharmony_ci const VkPipelineDepthStencilStateCreateInfo *in_zsa = 1332bf215546Sopenharmony_ci in_rast->rasterizerDiscardEnable ? NULL : in->pDepthStencilState; 1333bf215546Sopenharmony_ci 1334bf215546Sopenharmony_ci if (!in_zsa) 1335bf215546Sopenharmony_ci return; 1336bf215546Sopenharmony_ci 1337bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(out, DEPTH_STENCIL1, D3D12_DEPTH_STENCIL_DESC1, desc); 1338bf215546Sopenharmony_ci pipeline->templates.desc_offsets.ds = 1339bf215546Sopenharmony_ci (uintptr_t)desc - (uintptr_t)out->pPipelineStateSubobjectStream; 1340bf215546Sopenharmony_ci 1341bf215546Sopenharmony_ci desc->DepthEnable = 1342bf215546Sopenharmony_ci in_zsa->depthTestEnable || in_zsa->depthBoundsTestEnable; 1343bf215546Sopenharmony_ci desc->DepthWriteMask = 1344bf215546Sopenharmony_ci in_zsa->depthWriteEnable ? 1345bf215546Sopenharmony_ci D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO; 1346bf215546Sopenharmony_ci desc->DepthFunc = 1347bf215546Sopenharmony_ci in_zsa->depthTestEnable ? 1348bf215546Sopenharmony_ci dzn_translate_compare_op(in_zsa->depthCompareOp) : 1349bf215546Sopenharmony_ci D3D12_COMPARISON_FUNC_ALWAYS; 1350bf215546Sopenharmony_ci pipeline->zsa.depth_bounds.enable = in_zsa->depthBoundsTestEnable; 1351bf215546Sopenharmony_ci pipeline->zsa.depth_bounds.min = in_zsa->minDepthBounds; 1352bf215546Sopenharmony_ci pipeline->zsa.depth_bounds.max = in_zsa->maxDepthBounds; 1353bf215546Sopenharmony_ci desc->DepthBoundsTestEnable = in_zsa->depthBoundsTestEnable; 1354bf215546Sopenharmony_ci desc->StencilEnable = in_zsa->stencilTestEnable; 1355bf215546Sopenharmony_ci if (in_zsa->stencilTestEnable) { 1356bf215546Sopenharmony_ci desc->FrontFace.StencilFailOp = 1357bf215546Sopenharmony_ci translate_stencil_op(in_zsa->front.failOp); 1358bf215546Sopenharmony_ci desc->FrontFace.StencilDepthFailOp = 1359bf215546Sopenharmony_ci translate_stencil_op(in_zsa->front.depthFailOp); 1360bf215546Sopenharmony_ci desc->FrontFace.StencilPassOp = 1361bf215546Sopenharmony_ci translate_stencil_op(in_zsa->front.passOp); 1362bf215546Sopenharmony_ci desc->FrontFace.StencilFunc = 1363bf215546Sopenharmony_ci dzn_translate_compare_op(in_zsa->front.compareOp); 1364bf215546Sopenharmony_ci desc->BackFace.StencilFailOp = 1365bf215546Sopenharmony_ci translate_stencil_op(in_zsa->back.failOp); 1366bf215546Sopenharmony_ci desc->BackFace.StencilDepthFailOp = 1367bf215546Sopenharmony_ci translate_stencil_op(in_zsa->back.depthFailOp); 1368bf215546Sopenharmony_ci desc->BackFace.StencilPassOp = 1369bf215546Sopenharmony_ci translate_stencil_op(in_zsa->back.passOp); 1370bf215546Sopenharmony_ci desc->BackFace.StencilFunc = 1371bf215546Sopenharmony_ci dzn_translate_compare_op(in_zsa->back.compareOp); 1372bf215546Sopenharmony_ci 1373bf215546Sopenharmony_ci pipeline->zsa.stencil_test.enable = true; 1374bf215546Sopenharmony_ci 1375bf215546Sopenharmony_ci translate_stencil_test(pipeline, desc, in); 1376bf215546Sopenharmony_ci } 1377bf215546Sopenharmony_ci} 1378bf215546Sopenharmony_ci 1379bf215546Sopenharmony_cistatic D3D12_BLEND 1380bf215546Sopenharmony_citranslate_blend_factor(VkBlendFactor in, bool is_alpha) 1381bf215546Sopenharmony_ci{ 1382bf215546Sopenharmony_ci switch (in) { 1383bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ZERO: return D3D12_BLEND_ZERO; 1384bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE: return D3D12_BLEND_ONE; 1385bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC_COLOR: 1386bf215546Sopenharmony_ci return is_alpha ? D3D12_BLEND_SRC_ALPHA : D3D12_BLEND_SRC_COLOR; 1387bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 1388bf215546Sopenharmony_ci return is_alpha ? D3D12_BLEND_INV_SRC_ALPHA : D3D12_BLEND_INV_SRC_COLOR; 1389bf215546Sopenharmony_ci case VK_BLEND_FACTOR_DST_COLOR: 1390bf215546Sopenharmony_ci return is_alpha ? D3D12_BLEND_DEST_ALPHA : D3D12_BLEND_DEST_COLOR; 1391bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 1392bf215546Sopenharmony_ci return is_alpha ? D3D12_BLEND_INV_DEST_ALPHA : D3D12_BLEND_INV_DEST_COLOR; 1393bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA; 1394bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA; 1395bf215546Sopenharmony_ci case VK_BLEND_FACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA; 1396bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA; 1397bf215546Sopenharmony_ci /* FIXME: no way to isolate the alpla and color constants */ 1398bf215546Sopenharmony_ci case VK_BLEND_FACTOR_CONSTANT_COLOR: 1399bf215546Sopenharmony_ci case VK_BLEND_FACTOR_CONSTANT_ALPHA: 1400bf215546Sopenharmony_ci return D3D12_BLEND_BLEND_FACTOR; 1401bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 1402bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 1403bf215546Sopenharmony_ci return D3D12_BLEND_INV_BLEND_FACTOR; 1404bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC1_COLOR: 1405bf215546Sopenharmony_ci return is_alpha ? D3D12_BLEND_SRC1_ALPHA : D3D12_BLEND_SRC1_COLOR; 1406bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: 1407bf215546Sopenharmony_ci return is_alpha ? D3D12_BLEND_INV_SRC1_ALPHA : D3D12_BLEND_INV_SRC1_COLOR; 1408bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA; 1409bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA; 1410bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT; 1411bf215546Sopenharmony_ci default: unreachable("Invalid blend factor"); 1412bf215546Sopenharmony_ci } 1413bf215546Sopenharmony_ci} 1414bf215546Sopenharmony_ci 1415bf215546Sopenharmony_cistatic D3D12_BLEND_OP 1416bf215546Sopenharmony_citranslate_blend_op(VkBlendOp in) 1417bf215546Sopenharmony_ci{ 1418bf215546Sopenharmony_ci switch (in) { 1419bf215546Sopenharmony_ci case VK_BLEND_OP_ADD: return D3D12_BLEND_OP_ADD; 1420bf215546Sopenharmony_ci case VK_BLEND_OP_SUBTRACT: return D3D12_BLEND_OP_SUBTRACT; 1421bf215546Sopenharmony_ci case VK_BLEND_OP_REVERSE_SUBTRACT: return D3D12_BLEND_OP_REV_SUBTRACT; 1422bf215546Sopenharmony_ci case VK_BLEND_OP_MIN: return D3D12_BLEND_OP_MIN; 1423bf215546Sopenharmony_ci case VK_BLEND_OP_MAX: return D3D12_BLEND_OP_MAX; 1424bf215546Sopenharmony_ci default: unreachable("Invalid blend op"); 1425bf215546Sopenharmony_ci } 1426bf215546Sopenharmony_ci} 1427bf215546Sopenharmony_ci 1428bf215546Sopenharmony_cistatic D3D12_LOGIC_OP 1429bf215546Sopenharmony_citranslate_logic_op(VkLogicOp in) 1430bf215546Sopenharmony_ci{ 1431bf215546Sopenharmony_ci switch (in) { 1432bf215546Sopenharmony_ci case VK_LOGIC_OP_CLEAR: return D3D12_LOGIC_OP_CLEAR; 1433bf215546Sopenharmony_ci case VK_LOGIC_OP_AND: return D3D12_LOGIC_OP_AND; 1434bf215546Sopenharmony_ci case VK_LOGIC_OP_AND_REVERSE: return D3D12_LOGIC_OP_AND_REVERSE; 1435bf215546Sopenharmony_ci case VK_LOGIC_OP_COPY: return D3D12_LOGIC_OP_COPY; 1436bf215546Sopenharmony_ci case VK_LOGIC_OP_AND_INVERTED: return D3D12_LOGIC_OP_AND_INVERTED; 1437bf215546Sopenharmony_ci case VK_LOGIC_OP_NO_OP: return D3D12_LOGIC_OP_NOOP; 1438bf215546Sopenharmony_ci case VK_LOGIC_OP_XOR: return D3D12_LOGIC_OP_XOR; 1439bf215546Sopenharmony_ci case VK_LOGIC_OP_OR: return D3D12_LOGIC_OP_OR; 1440bf215546Sopenharmony_ci case VK_LOGIC_OP_NOR: return D3D12_LOGIC_OP_NOR; 1441bf215546Sopenharmony_ci case VK_LOGIC_OP_EQUIVALENT: return D3D12_LOGIC_OP_EQUIV; 1442bf215546Sopenharmony_ci case VK_LOGIC_OP_INVERT: return D3D12_LOGIC_OP_INVERT; 1443bf215546Sopenharmony_ci case VK_LOGIC_OP_OR_REVERSE: return D3D12_LOGIC_OP_OR_REVERSE; 1444bf215546Sopenharmony_ci case VK_LOGIC_OP_COPY_INVERTED: return D3D12_LOGIC_OP_COPY_INVERTED; 1445bf215546Sopenharmony_ci case VK_LOGIC_OP_OR_INVERTED: return D3D12_LOGIC_OP_OR_INVERTED; 1446bf215546Sopenharmony_ci case VK_LOGIC_OP_NAND: return D3D12_LOGIC_OP_NAND; 1447bf215546Sopenharmony_ci case VK_LOGIC_OP_SET: return D3D12_LOGIC_OP_SET; 1448bf215546Sopenharmony_ci default: unreachable("Invalid logic op"); 1449bf215546Sopenharmony_ci } 1450bf215546Sopenharmony_ci} 1451bf215546Sopenharmony_ci 1452bf215546Sopenharmony_cistatic void 1453bf215546Sopenharmony_cidzn_graphics_pipeline_translate_blend(struct dzn_graphics_pipeline *pipeline, 1454bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *out, 1455bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *in) 1456bf215546Sopenharmony_ci{ 1457bf215546Sopenharmony_ci const VkPipelineRasterizationStateCreateInfo *in_rast = 1458bf215546Sopenharmony_ci in->pRasterizationState; 1459bf215546Sopenharmony_ci const VkPipelineColorBlendStateCreateInfo *in_blend = 1460bf215546Sopenharmony_ci in_rast->rasterizerDiscardEnable ? NULL : in->pColorBlendState; 1461bf215546Sopenharmony_ci const VkPipelineMultisampleStateCreateInfo *in_ms = 1462bf215546Sopenharmony_ci in_rast->rasterizerDiscardEnable ? NULL : in->pMultisampleState; 1463bf215546Sopenharmony_ci 1464bf215546Sopenharmony_ci if (!in_blend || !in_ms) 1465bf215546Sopenharmony_ci return; 1466bf215546Sopenharmony_ci 1467bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(out, BLEND, D3D12_BLEND_DESC, desc); 1468bf215546Sopenharmony_ci D3D12_LOGIC_OP logicop = 1469bf215546Sopenharmony_ci in_blend->logicOpEnable ? 1470bf215546Sopenharmony_ci translate_logic_op(in_blend->logicOp) : D3D12_LOGIC_OP_NOOP; 1471bf215546Sopenharmony_ci desc->AlphaToCoverageEnable = in_ms->alphaToCoverageEnable; 1472bf215546Sopenharmony_ci memcpy(pipeline->blend.constants, in_blend->blendConstants, 1473bf215546Sopenharmony_ci sizeof(pipeline->blend.constants)); 1474bf215546Sopenharmony_ci 1475bf215546Sopenharmony_ci for (uint32_t i = 0; i < in_blend->attachmentCount; i++) { 1476bf215546Sopenharmony_ci if (i > 0 && 1477bf215546Sopenharmony_ci !memcmp(&in_blend->pAttachments[i - 1], &in_blend->pAttachments[i], 1478bf215546Sopenharmony_ci sizeof(*in_blend->pAttachments))) 1479bf215546Sopenharmony_ci desc->IndependentBlendEnable = true; 1480bf215546Sopenharmony_ci 1481bf215546Sopenharmony_ci desc->RenderTarget[i].BlendEnable = 1482bf215546Sopenharmony_ci in_blend->pAttachments[i].blendEnable; 1483bf215546Sopenharmony_ci desc->RenderTarget[i].RenderTargetWriteMask = 1484bf215546Sopenharmony_ci in_blend->pAttachments[i].colorWriteMask; 1485bf215546Sopenharmony_ci 1486bf215546Sopenharmony_ci if (in_blend->logicOpEnable) { 1487bf215546Sopenharmony_ci desc->RenderTarget[i].LogicOpEnable = true; 1488bf215546Sopenharmony_ci desc->RenderTarget[i].LogicOp = logicop; 1489bf215546Sopenharmony_ci } else { 1490bf215546Sopenharmony_ci desc->RenderTarget[i].SrcBlend = 1491bf215546Sopenharmony_ci translate_blend_factor(in_blend->pAttachments[i].srcColorBlendFactor, false); 1492bf215546Sopenharmony_ci desc->RenderTarget[i].DestBlend = 1493bf215546Sopenharmony_ci translate_blend_factor(in_blend->pAttachments[i].dstColorBlendFactor, false); 1494bf215546Sopenharmony_ci desc->RenderTarget[i].BlendOp = 1495bf215546Sopenharmony_ci translate_blend_op(in_blend->pAttachments[i].colorBlendOp); 1496bf215546Sopenharmony_ci desc->RenderTarget[i].SrcBlendAlpha = 1497bf215546Sopenharmony_ci translate_blend_factor(in_blend->pAttachments[i].srcAlphaBlendFactor, true); 1498bf215546Sopenharmony_ci desc->RenderTarget[i].DestBlendAlpha = 1499bf215546Sopenharmony_ci translate_blend_factor(in_blend->pAttachments[i].dstAlphaBlendFactor, true); 1500bf215546Sopenharmony_ci desc->RenderTarget[i].BlendOpAlpha = 1501bf215546Sopenharmony_ci translate_blend_op(in_blend->pAttachments[i].alphaBlendOp); 1502bf215546Sopenharmony_ci } 1503bf215546Sopenharmony_ci } 1504bf215546Sopenharmony_ci} 1505bf215546Sopenharmony_ci 1506bf215546Sopenharmony_ci 1507bf215546Sopenharmony_cistatic void 1508bf215546Sopenharmony_cidzn_pipeline_init(struct dzn_pipeline *pipeline, 1509bf215546Sopenharmony_ci struct dzn_device *device, 1510bf215546Sopenharmony_ci VkPipelineBindPoint type, 1511bf215546Sopenharmony_ci struct dzn_pipeline_layout *layout, 1512bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc) 1513bf215546Sopenharmony_ci{ 1514bf215546Sopenharmony_ci pipeline->type = type; 1515bf215546Sopenharmony_ci pipeline->root.sets_param_count = layout->root.sets_param_count; 1516bf215546Sopenharmony_ci pipeline->root.sysval_cbv_param_idx = layout->root.sysval_cbv_param_idx; 1517bf215546Sopenharmony_ci pipeline->root.push_constant_cbv_param_idx = layout->root.push_constant_cbv_param_idx; 1518bf215546Sopenharmony_ci STATIC_ASSERT(sizeof(pipeline->root.type) == sizeof(layout->root.type)); 1519bf215546Sopenharmony_ci memcpy(pipeline->root.type, layout->root.type, sizeof(pipeline->root.type)); 1520bf215546Sopenharmony_ci pipeline->root.sig = layout->root.sig; 1521bf215546Sopenharmony_ci ID3D12RootSignature_AddRef(pipeline->root.sig); 1522bf215546Sopenharmony_ci 1523bf215546Sopenharmony_ci STATIC_ASSERT(sizeof(layout->desc_count) == sizeof(pipeline->desc_count)); 1524bf215546Sopenharmony_ci memcpy(pipeline->desc_count, layout->desc_count, sizeof(pipeline->desc_count)); 1525bf215546Sopenharmony_ci 1526bf215546Sopenharmony_ci STATIC_ASSERT(sizeof(layout->sets) == sizeof(pipeline->sets)); 1527bf215546Sopenharmony_ci memcpy(pipeline->sets, layout->sets, sizeof(pipeline->sets)); 1528bf215546Sopenharmony_ci vk_object_base_init(&device->vk, &pipeline->base, VK_OBJECT_TYPE_PIPELINE); 1529bf215546Sopenharmony_ci 1530bf215546Sopenharmony_ci ASSERTED uint32_t max_streamsz = 1531bf215546Sopenharmony_ci type == VK_PIPELINE_BIND_POINT_GRAPHICS ? 1532bf215546Sopenharmony_ci MAX_GFX_PIPELINE_STATE_STREAM_SIZE : 1533bf215546Sopenharmony_ci MAX_COMPUTE_PIPELINE_STATE_STREAM_SIZE; 1534bf215546Sopenharmony_ci 1535bf215546Sopenharmony_ci d3d12_pipeline_state_stream_new_desc(stream_desc, max_streamsz, ROOT_SIGNATURE, 1536bf215546Sopenharmony_ci ID3D12RootSignature *, root_sig); 1537bf215546Sopenharmony_ci *root_sig = pipeline->root.sig; 1538bf215546Sopenharmony_ci} 1539bf215546Sopenharmony_ci 1540bf215546Sopenharmony_cistatic void 1541bf215546Sopenharmony_cidzn_pipeline_finish(struct dzn_pipeline *pipeline) 1542bf215546Sopenharmony_ci{ 1543bf215546Sopenharmony_ci if (pipeline->state) 1544bf215546Sopenharmony_ci ID3D12PipelineState_Release(pipeline->state); 1545bf215546Sopenharmony_ci if (pipeline->root.sig) 1546bf215546Sopenharmony_ci ID3D12RootSignature_Release(pipeline->root.sig); 1547bf215546Sopenharmony_ci 1548bf215546Sopenharmony_ci vk_object_base_finish(&pipeline->base); 1549bf215546Sopenharmony_ci} 1550bf215546Sopenharmony_ci 1551bf215546Sopenharmony_cistatic void dzn_graphics_pipeline_delete_variant(struct hash_entry *he) 1552bf215546Sopenharmony_ci{ 1553bf215546Sopenharmony_ci struct dzn_graphics_pipeline_variant *variant = he->data; 1554bf215546Sopenharmony_ci 1555bf215546Sopenharmony_ci if (variant->state) 1556bf215546Sopenharmony_ci ID3D12PipelineState_Release(variant->state); 1557bf215546Sopenharmony_ci} 1558bf215546Sopenharmony_ci 1559bf215546Sopenharmony_cistatic void 1560bf215546Sopenharmony_cidzn_graphics_pipeline_cleanup_nir_shaders(struct dzn_graphics_pipeline *pipeline) 1561bf215546Sopenharmony_ci{ 1562bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->templates.shaders); i++) { 1563bf215546Sopenharmony_ci ralloc_free(pipeline->templates.shaders[i].nir); 1564bf215546Sopenharmony_ci pipeline->templates.shaders[i].nir = NULL; 1565bf215546Sopenharmony_ci } 1566bf215546Sopenharmony_ci} 1567bf215546Sopenharmony_ci 1568bf215546Sopenharmony_cistatic void 1569bf215546Sopenharmony_cidzn_graphics_pipeline_cleanup_dxil_shaders(struct dzn_graphics_pipeline *pipeline) 1570bf215546Sopenharmony_ci{ 1571bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->templates.shaders); i++) { 1572bf215546Sopenharmony_ci if (pipeline->templates.shaders[i].bc) { 1573bf215546Sopenharmony_ci free((void *)pipeline->templates.shaders[i].bc->pShaderBytecode); 1574bf215546Sopenharmony_ci pipeline->templates.shaders[i].bc = NULL; 1575bf215546Sopenharmony_ci } 1576bf215546Sopenharmony_ci } 1577bf215546Sopenharmony_ci} 1578bf215546Sopenharmony_ci 1579bf215546Sopenharmony_cistatic void 1580bf215546Sopenharmony_cidzn_graphics_pipeline_destroy(struct dzn_graphics_pipeline *pipeline, 1581bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 1582bf215546Sopenharmony_ci{ 1583bf215546Sopenharmony_ci if (!pipeline) 1584bf215546Sopenharmony_ci return; 1585bf215546Sopenharmony_ci 1586bf215546Sopenharmony_ci _mesa_hash_table_destroy(pipeline->variants, 1587bf215546Sopenharmony_ci dzn_graphics_pipeline_delete_variant); 1588bf215546Sopenharmony_ci 1589bf215546Sopenharmony_ci dzn_graphics_pipeline_cleanup_nir_shaders(pipeline); 1590bf215546Sopenharmony_ci dzn_graphics_pipeline_cleanup_dxil_shaders(pipeline); 1591bf215546Sopenharmony_ci 1592bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->indirect_cmd_sigs); i++) { 1593bf215546Sopenharmony_ci if (pipeline->indirect_cmd_sigs[i]) 1594bf215546Sopenharmony_ci ID3D12CommandSignature_Release(pipeline->indirect_cmd_sigs[i]); 1595bf215546Sopenharmony_ci } 1596bf215546Sopenharmony_ci 1597bf215546Sopenharmony_ci dzn_pipeline_finish(&pipeline->base); 1598bf215546Sopenharmony_ci vk_free2(&pipeline->base.base.device->alloc, alloc, pipeline); 1599bf215546Sopenharmony_ci} 1600bf215546Sopenharmony_ci 1601bf215546Sopenharmony_cistatic VkResult 1602bf215546Sopenharmony_cidzn_graphics_pipeline_create(struct dzn_device *device, 1603bf215546Sopenharmony_ci VkPipelineCache cache, 1604bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *pCreateInfo, 1605bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 1606bf215546Sopenharmony_ci VkPipeline *out) 1607bf215546Sopenharmony_ci{ 1608bf215546Sopenharmony_ci const VkPipelineRenderingCreateInfo *ri = (const VkPipelineRenderingCreateInfo *) 1609bf215546Sopenharmony_ci vk_find_struct_const(pCreateInfo, PIPELINE_RENDERING_CREATE_INFO); 1610bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_pipeline_cache, pcache, cache); 1611bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_render_pass, pass, pCreateInfo->renderPass); 1612bf215546Sopenharmony_ci VK_FROM_HANDLE(dzn_pipeline_layout, layout, pCreateInfo->layout); 1613bf215546Sopenharmony_ci uint32_t color_count = 0; 1614bf215546Sopenharmony_ci VkFormat color_fmts[MAX_RTS] = { 0 }; 1615bf215546Sopenharmony_ci VkFormat zs_fmt = VK_FORMAT_UNDEFINED; 1616bf215546Sopenharmony_ci VkResult ret; 1617bf215546Sopenharmony_ci HRESULT hres = 0; 1618bf215546Sopenharmony_ci 1619bf215546Sopenharmony_ci struct dzn_graphics_pipeline *pipeline = 1620bf215546Sopenharmony_ci vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8, 1621bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1622bf215546Sopenharmony_ci if (!pipeline) 1623bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1624bf215546Sopenharmony_ci 1625bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc = &pipeline->templates.stream_desc; 1626bf215546Sopenharmony_ci stream_desc->pPipelineStateSubobjectStream = pipeline->templates.stream_buf; 1627bf215546Sopenharmony_ci 1628bf215546Sopenharmony_ci dzn_pipeline_init(&pipeline->base, device, 1629bf215546Sopenharmony_ci VK_PIPELINE_BIND_POINT_GRAPHICS, 1630bf215546Sopenharmony_ci layout, stream_desc); 1631bf215546Sopenharmony_ci D3D12_INPUT_ELEMENT_DESC attribs[MAX_VERTEX_GENERIC_ATTRIBS] = { 0 }; 1632bf215546Sopenharmony_ci enum pipe_format vi_conversions[MAX_VERTEX_GENERIC_ATTRIBS] = { 0 }; 1633bf215546Sopenharmony_ci 1634bf215546Sopenharmony_ci ret = dzn_graphics_pipeline_translate_vi(pipeline, pCreateInfo, 1635bf215546Sopenharmony_ci attribs, vi_conversions); 1636bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 1637bf215546Sopenharmony_ci goto out; 1638bf215546Sopenharmony_ci 1639bf215546Sopenharmony_ci if (pCreateInfo->pDynamicState) { 1640bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->pDynamicState->dynamicStateCount; i++) { 1641bf215546Sopenharmony_ci switch (pCreateInfo->pDynamicState->pDynamicStates[i]) { 1642bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_VIEWPORT: 1643bf215546Sopenharmony_ci pipeline->vp.dynamic = true; 1644bf215546Sopenharmony_ci break; 1645bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_SCISSOR: 1646bf215546Sopenharmony_ci pipeline->scissor.dynamic = true; 1647bf215546Sopenharmony_ci break; 1648bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_STENCIL_REFERENCE: 1649bf215546Sopenharmony_ci pipeline->zsa.stencil_test.dynamic_ref = true; 1650bf215546Sopenharmony_ci break; 1651bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: 1652bf215546Sopenharmony_ci pipeline->zsa.stencil_test.dynamic_compare_mask = true; 1653bf215546Sopenharmony_ci break; 1654bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: 1655bf215546Sopenharmony_ci pipeline->zsa.stencil_test.dynamic_write_mask = true; 1656bf215546Sopenharmony_ci break; 1657bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_BLEND_CONSTANTS: 1658bf215546Sopenharmony_ci pipeline->blend.dynamic_constants = true; 1659bf215546Sopenharmony_ci break; 1660bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_DEPTH_BOUNDS: 1661bf215546Sopenharmony_ci pipeline->zsa.depth_bounds.dynamic = true; 1662bf215546Sopenharmony_ci break; 1663bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_DEPTH_BIAS: 1664bf215546Sopenharmony_ci pipeline->zsa.dynamic_depth_bias = true; 1665bf215546Sopenharmony_ci ret = dzn_graphics_pipeline_prepare_for_variants(device, pipeline); 1666bf215546Sopenharmony_ci if (ret) 1667bf215546Sopenharmony_ci goto out; 1668bf215546Sopenharmony_ci break; 1669bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_LINE_WIDTH: 1670bf215546Sopenharmony_ci /* Nothing to do since we just support lineWidth = 1. */ 1671bf215546Sopenharmony_ci break; 1672bf215546Sopenharmony_ci default: unreachable("Unsupported dynamic state"); 1673bf215546Sopenharmony_ci } 1674bf215546Sopenharmony_ci } 1675bf215546Sopenharmony_ci } 1676bf215546Sopenharmony_ci 1677bf215546Sopenharmony_ci ret = dzn_graphics_pipeline_translate_ia(device, pipeline, stream_desc, pCreateInfo); 1678bf215546Sopenharmony_ci if (ret) 1679bf215546Sopenharmony_ci goto out; 1680bf215546Sopenharmony_ci 1681bf215546Sopenharmony_ci dzn_graphics_pipeline_translate_rast(pipeline, stream_desc, pCreateInfo); 1682bf215546Sopenharmony_ci dzn_graphics_pipeline_translate_ms(pipeline, stream_desc, pCreateInfo); 1683bf215546Sopenharmony_ci dzn_graphics_pipeline_translate_zsa(pipeline, stream_desc, pCreateInfo); 1684bf215546Sopenharmony_ci dzn_graphics_pipeline_translate_blend(pipeline, stream_desc, pCreateInfo); 1685bf215546Sopenharmony_ci 1686bf215546Sopenharmony_ci if (pass) { 1687bf215546Sopenharmony_ci const struct vk_subpass *subpass = &pass->subpasses[pCreateInfo->subpass]; 1688bf215546Sopenharmony_ci color_count = subpass->color_count; 1689bf215546Sopenharmony_ci for (uint32_t i = 0; i < subpass->color_count; i++) { 1690bf215546Sopenharmony_ci uint32_t idx = subpass->color_attachments[i].attachment; 1691bf215546Sopenharmony_ci 1692bf215546Sopenharmony_ci if (idx == VK_ATTACHMENT_UNUSED) continue; 1693bf215546Sopenharmony_ci 1694bf215546Sopenharmony_ci const struct vk_render_pass_attachment *attachment = 1695bf215546Sopenharmony_ci &pass->attachments[idx]; 1696bf215546Sopenharmony_ci 1697bf215546Sopenharmony_ci color_fmts[i] = attachment->format; 1698bf215546Sopenharmony_ci } 1699bf215546Sopenharmony_ci 1700bf215546Sopenharmony_ci if (subpass->depth_stencil_attachment && 1701bf215546Sopenharmony_ci subpass->depth_stencil_attachment->attachment != VK_ATTACHMENT_UNUSED) { 1702bf215546Sopenharmony_ci const struct vk_render_pass_attachment *attachment = 1703bf215546Sopenharmony_ci &pass->attachments[subpass->depth_stencil_attachment->attachment]; 1704bf215546Sopenharmony_ci 1705bf215546Sopenharmony_ci zs_fmt = attachment->format; 1706bf215546Sopenharmony_ci } 1707bf215546Sopenharmony_ci } else if (ri) { 1708bf215546Sopenharmony_ci color_count = ri->colorAttachmentCount; 1709bf215546Sopenharmony_ci memcpy(color_fmts, ri->pColorAttachmentFormats, 1710bf215546Sopenharmony_ci sizeof(color_fmts[0]) * color_count); 1711bf215546Sopenharmony_ci if (ri->depthAttachmentFormat != VK_FORMAT_UNDEFINED) 1712bf215546Sopenharmony_ci zs_fmt = ri->depthAttachmentFormat; 1713bf215546Sopenharmony_ci else if (ri->stencilAttachmentFormat != VK_FORMAT_UNDEFINED) 1714bf215546Sopenharmony_ci zs_fmt = ri->stencilAttachmentFormat; 1715bf215546Sopenharmony_ci } 1716bf215546Sopenharmony_ci 1717bf215546Sopenharmony_ci if (color_count > 0) { 1718bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, RENDER_TARGET_FORMATS, struct D3D12_RT_FORMAT_ARRAY, rts); 1719bf215546Sopenharmony_ci rts->NumRenderTargets = color_count; 1720bf215546Sopenharmony_ci for (uint32_t i = 0; i < color_count; i++) { 1721bf215546Sopenharmony_ci rts->RTFormats[i] = 1722bf215546Sopenharmony_ci dzn_image_get_dxgi_format(color_fmts[i], 1723bf215546Sopenharmony_ci VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1724bf215546Sopenharmony_ci VK_IMAGE_ASPECT_COLOR_BIT); 1725bf215546Sopenharmony_ci } 1726bf215546Sopenharmony_ci } 1727bf215546Sopenharmony_ci 1728bf215546Sopenharmony_ci if (zs_fmt != VK_FORMAT_UNDEFINED) { 1729bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, DEPTH_STENCIL_FORMAT, DXGI_FORMAT, ds_fmt); 1730bf215546Sopenharmony_ci *ds_fmt = 1731bf215546Sopenharmony_ci dzn_image_get_dxgi_format(zs_fmt, 1732bf215546Sopenharmony_ci VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 1733bf215546Sopenharmony_ci VK_IMAGE_ASPECT_DEPTH_BIT | 1734bf215546Sopenharmony_ci VK_IMAGE_ASPECT_STENCIL_BIT); 1735bf215546Sopenharmony_ci } 1736bf215546Sopenharmony_ci 1737bf215546Sopenharmony_ci ret = dzn_graphics_pipeline_compile_shaders(device, pipeline, pcache, 1738bf215546Sopenharmony_ci layout, stream_desc, 1739bf215546Sopenharmony_ci attribs, vi_conversions, 1740bf215546Sopenharmony_ci pCreateInfo); 1741bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 1742bf215546Sopenharmony_ci goto out; 1743bf215546Sopenharmony_ci 1744bf215546Sopenharmony_ci if (!pipeline->variants) { 1745bf215546Sopenharmony_ci hres = ID3D12Device2_CreatePipelineState(device->dev, stream_desc, 1746bf215546Sopenharmony_ci &IID_ID3D12PipelineState, 1747bf215546Sopenharmony_ci (void **)&pipeline->base.state); 1748bf215546Sopenharmony_ci if (FAILED(hres)) { 1749bf215546Sopenharmony_ci ret = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1750bf215546Sopenharmony_ci goto out; 1751bf215546Sopenharmony_ci } 1752bf215546Sopenharmony_ci 1753bf215546Sopenharmony_ci dzn_graphics_pipeline_cleanup_dxil_shaders(pipeline); 1754bf215546Sopenharmony_ci } 1755bf215546Sopenharmony_ci 1756bf215546Sopenharmony_ci dzn_graphics_pipeline_cleanup_nir_shaders(pipeline); 1757bf215546Sopenharmony_ci ret = VK_SUCCESS; 1758bf215546Sopenharmony_ci 1759bf215546Sopenharmony_ciout: 1760bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 1761bf215546Sopenharmony_ci dzn_graphics_pipeline_destroy(pipeline, pAllocator); 1762bf215546Sopenharmony_ci else 1763bf215546Sopenharmony_ci *out = dzn_graphics_pipeline_to_handle(pipeline); 1764bf215546Sopenharmony_ci 1765bf215546Sopenharmony_ci return ret; 1766bf215546Sopenharmony_ci} 1767bf215546Sopenharmony_ci 1768bf215546Sopenharmony_ciID3D12PipelineState * 1769bf215546Sopenharmony_cidzn_graphics_pipeline_get_state(struct dzn_graphics_pipeline *pipeline, 1770bf215546Sopenharmony_ci const struct dzn_graphics_pipeline_variant_key *key) 1771bf215546Sopenharmony_ci{ 1772bf215546Sopenharmony_ci if (!pipeline->variants) 1773bf215546Sopenharmony_ci return pipeline->base.state; 1774bf215546Sopenharmony_ci 1775bf215546Sopenharmony_ci struct dzn_graphics_pipeline_variant_key masked_key = { 0 }; 1776bf215546Sopenharmony_ci 1777bf215546Sopenharmony_ci if (dzn_graphics_pipeline_get_desc_template(pipeline, ib_strip_cut)) 1778bf215546Sopenharmony_ci masked_key.ib_strip_cut = key->ib_strip_cut; 1779bf215546Sopenharmony_ci 1780bf215546Sopenharmony_ci if (dzn_graphics_pipeline_get_desc_template(pipeline, rast) && 1781bf215546Sopenharmony_ci pipeline->zsa.dynamic_depth_bias) 1782bf215546Sopenharmony_ci masked_key.depth_bias = key->depth_bias; 1783bf215546Sopenharmony_ci 1784bf215546Sopenharmony_ci const D3D12_DEPTH_STENCIL_DESC1 *ds_templ = 1785bf215546Sopenharmony_ci dzn_graphics_pipeline_get_desc_template(pipeline, ds); 1786bf215546Sopenharmony_ci if (ds_templ && ds_templ->StencilEnable) { 1787bf215546Sopenharmony_ci if (ds_templ->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER && 1788bf215546Sopenharmony_ci ds_templ->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS) 1789bf215546Sopenharmony_ci masked_key.stencil_test.front.compare_mask = key->stencil_test.front.compare_mask; 1790bf215546Sopenharmony_ci if (ds_templ->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER && 1791bf215546Sopenharmony_ci ds_templ->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS) 1792bf215546Sopenharmony_ci masked_key.stencil_test.back.compare_mask = key->stencil_test.back.compare_mask; 1793bf215546Sopenharmony_ci if (pipeline->zsa.stencil_test.dynamic_write_mask) { 1794bf215546Sopenharmony_ci masked_key.stencil_test.front.write_mask = key->stencil_test.front.write_mask; 1795bf215546Sopenharmony_ci masked_key.stencil_test.back.write_mask = key->stencil_test.back.write_mask; 1796bf215546Sopenharmony_ci } 1797bf215546Sopenharmony_ci } 1798bf215546Sopenharmony_ci 1799bf215546Sopenharmony_ci struct dzn_device *device = 1800bf215546Sopenharmony_ci container_of(pipeline->base.base.device, struct dzn_device, vk); 1801bf215546Sopenharmony_ci struct hash_entry *he = 1802bf215546Sopenharmony_ci _mesa_hash_table_search(pipeline->variants, &masked_key); 1803bf215546Sopenharmony_ci 1804bf215546Sopenharmony_ci struct dzn_graphics_pipeline_variant *variant; 1805bf215546Sopenharmony_ci 1806bf215546Sopenharmony_ci if (!he) { 1807bf215546Sopenharmony_ci variant = rzalloc(pipeline->variants, struct dzn_graphics_pipeline_variant); 1808bf215546Sopenharmony_ci variant->key = masked_key; 1809bf215546Sopenharmony_ci 1810bf215546Sopenharmony_ci uintptr_t stream_buf[MAX_GFX_PIPELINE_STATE_STREAM_SIZE / sizeof(uintptr_t)]; 1811bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC stream_desc = { 1812bf215546Sopenharmony_ci .SizeInBytes = pipeline->templates.stream_desc.SizeInBytes, 1813bf215546Sopenharmony_ci .pPipelineStateSubobjectStream = stream_buf, 1814bf215546Sopenharmony_ci }; 1815bf215546Sopenharmony_ci 1816bf215546Sopenharmony_ci memcpy(stream_buf, pipeline->templates.stream_buf, stream_desc.SizeInBytes); 1817bf215546Sopenharmony_ci 1818bf215546Sopenharmony_ci D3D12_INDEX_BUFFER_STRIP_CUT_VALUE *ib_strip_cut = 1819bf215546Sopenharmony_ci dzn_graphics_pipeline_get_desc(pipeline, stream_buf, ib_strip_cut); 1820bf215546Sopenharmony_ci if (ib_strip_cut) 1821bf215546Sopenharmony_ci *ib_strip_cut = masked_key.ib_strip_cut; 1822bf215546Sopenharmony_ci 1823bf215546Sopenharmony_ci D3D12_RASTERIZER_DESC *rast = 1824bf215546Sopenharmony_ci dzn_graphics_pipeline_get_desc(pipeline, stream_buf, rast); 1825bf215546Sopenharmony_ci if (rast && pipeline->zsa.dynamic_depth_bias) { 1826bf215546Sopenharmony_ci rast->DepthBias = translate_depth_bias(masked_key.depth_bias.constant_factor); 1827bf215546Sopenharmony_ci rast->DepthBiasClamp = masked_key.depth_bias.clamp; 1828bf215546Sopenharmony_ci rast->SlopeScaledDepthBias = masked_key.depth_bias.slope_factor; 1829bf215546Sopenharmony_ci } 1830bf215546Sopenharmony_ci 1831bf215546Sopenharmony_ci D3D12_DEPTH_STENCIL_DESC1 *ds = 1832bf215546Sopenharmony_ci dzn_graphics_pipeline_get_desc(pipeline, stream_buf, ds); 1833bf215546Sopenharmony_ci if (ds && ds->StencilEnable) { 1834bf215546Sopenharmony_ci if (pipeline->zsa.stencil_test.dynamic_compare_mask) { 1835bf215546Sopenharmony_ci if (ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER && 1836bf215546Sopenharmony_ci ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS) { 1837bf215546Sopenharmony_ci ds->StencilReadMask = masked_key.stencil_test.front.compare_mask; 1838bf215546Sopenharmony_ci } 1839bf215546Sopenharmony_ci 1840bf215546Sopenharmony_ci if (ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER && 1841bf215546Sopenharmony_ci ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS) { 1842bf215546Sopenharmony_ci ds->StencilReadMask = masked_key.stencil_test.back.compare_mask; 1843bf215546Sopenharmony_ci } 1844bf215546Sopenharmony_ci 1845bf215546Sopenharmony_ci if (ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER && 1846bf215546Sopenharmony_ci ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS && 1847bf215546Sopenharmony_ci ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER && 1848bf215546Sopenharmony_ci ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS) 1849bf215546Sopenharmony_ci assert(masked_key.stencil_test.front.compare_mask == masked_key.stencil_test.back.compare_mask); 1850bf215546Sopenharmony_ci } 1851bf215546Sopenharmony_ci 1852bf215546Sopenharmony_ci if (pipeline->zsa.stencil_test.dynamic_write_mask) { 1853bf215546Sopenharmony_ci assert(!masked_key.stencil_test.front.write_mask || 1854bf215546Sopenharmony_ci !masked_key.stencil_test.back.write_mask || 1855bf215546Sopenharmony_ci masked_key.stencil_test.front.write_mask == masked_key.stencil_test.back.write_mask); 1856bf215546Sopenharmony_ci ds->StencilWriteMask = 1857bf215546Sopenharmony_ci masked_key.stencil_test.front.write_mask | 1858bf215546Sopenharmony_ci masked_key.stencil_test.back.write_mask; 1859bf215546Sopenharmony_ci } 1860bf215546Sopenharmony_ci } 1861bf215546Sopenharmony_ci 1862bf215546Sopenharmony_ci ASSERTED HRESULT hres = ID3D12Device2_CreatePipelineState(device->dev, &stream_desc, 1863bf215546Sopenharmony_ci &IID_ID3D12PipelineState, 1864bf215546Sopenharmony_ci (void**)(&variant->state)); 1865bf215546Sopenharmony_ci assert(!FAILED(hres)); 1866bf215546Sopenharmony_ci he = _mesa_hash_table_insert(pipeline->variants, &variant->key, variant); 1867bf215546Sopenharmony_ci assert(he); 1868bf215546Sopenharmony_ci } else { 1869bf215546Sopenharmony_ci variant = he->data; 1870bf215546Sopenharmony_ci } 1871bf215546Sopenharmony_ci 1872bf215546Sopenharmony_ci if (variant->state) 1873bf215546Sopenharmony_ci ID3D12PipelineState_AddRef(variant->state); 1874bf215546Sopenharmony_ci 1875bf215546Sopenharmony_ci if (pipeline->base.state) 1876bf215546Sopenharmony_ci ID3D12PipelineState_Release(pipeline->base.state); 1877bf215546Sopenharmony_ci 1878bf215546Sopenharmony_ci pipeline->base.state = variant->state; 1879bf215546Sopenharmony_ci return variant->state; 1880bf215546Sopenharmony_ci} 1881bf215546Sopenharmony_ci 1882bf215546Sopenharmony_ci#define DZN_INDIRECT_CMD_SIG_MAX_ARGS 4 1883bf215546Sopenharmony_ci 1884bf215546Sopenharmony_ciID3D12CommandSignature * 1885bf215546Sopenharmony_cidzn_graphics_pipeline_get_indirect_cmd_sig(struct dzn_graphics_pipeline *pipeline, 1886bf215546Sopenharmony_ci enum dzn_indirect_draw_cmd_sig_type type) 1887bf215546Sopenharmony_ci{ 1888bf215546Sopenharmony_ci assert(type < DZN_NUM_INDIRECT_DRAW_CMD_SIGS); 1889bf215546Sopenharmony_ci 1890bf215546Sopenharmony_ci struct dzn_device *device = 1891bf215546Sopenharmony_ci container_of(pipeline->base.base.device, struct dzn_device, vk); 1892bf215546Sopenharmony_ci ID3D12CommandSignature *cmdsig = pipeline->indirect_cmd_sigs[type]; 1893bf215546Sopenharmony_ci 1894bf215546Sopenharmony_ci if (cmdsig) 1895bf215546Sopenharmony_ci return cmdsig; 1896bf215546Sopenharmony_ci 1897bf215546Sopenharmony_ci bool triangle_fan = type == DZN_INDIRECT_DRAW_TRIANGLE_FAN_CMD_SIG; 1898bf215546Sopenharmony_ci bool indexed = type == DZN_INDIRECT_INDEXED_DRAW_CMD_SIG || triangle_fan; 1899bf215546Sopenharmony_ci 1900bf215546Sopenharmony_ci uint32_t cmd_arg_count = 0; 1901bf215546Sopenharmony_ci D3D12_INDIRECT_ARGUMENT_DESC cmd_args[DZN_INDIRECT_CMD_SIG_MAX_ARGS]; 1902bf215546Sopenharmony_ci 1903bf215546Sopenharmony_ci if (triangle_fan) { 1904bf215546Sopenharmony_ci cmd_args[cmd_arg_count++] = (D3D12_INDIRECT_ARGUMENT_DESC) { 1905bf215546Sopenharmony_ci .Type = D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW, 1906bf215546Sopenharmony_ci }; 1907bf215546Sopenharmony_ci } 1908bf215546Sopenharmony_ci 1909bf215546Sopenharmony_ci cmd_args[cmd_arg_count++] = (D3D12_INDIRECT_ARGUMENT_DESC) { 1910bf215546Sopenharmony_ci .Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT, 1911bf215546Sopenharmony_ci .Constant = { 1912bf215546Sopenharmony_ci .RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx, 1913bf215546Sopenharmony_ci .DestOffsetIn32BitValues = offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex) / 4, 1914bf215546Sopenharmony_ci .Num32BitValuesToSet = 2, 1915bf215546Sopenharmony_ci }, 1916bf215546Sopenharmony_ci }; 1917bf215546Sopenharmony_ci 1918bf215546Sopenharmony_ci cmd_args[cmd_arg_count++] = (D3D12_INDIRECT_ARGUMENT_DESC) { 1919bf215546Sopenharmony_ci .Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT, 1920bf215546Sopenharmony_ci .Constant = { 1921bf215546Sopenharmony_ci .RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx, 1922bf215546Sopenharmony_ci .DestOffsetIn32BitValues = offsetof(struct dxil_spirv_vertex_runtime_data, draw_id) / 4, 1923bf215546Sopenharmony_ci .Num32BitValuesToSet = 1, 1924bf215546Sopenharmony_ci }, 1925bf215546Sopenharmony_ci }; 1926bf215546Sopenharmony_ci 1927bf215546Sopenharmony_ci cmd_args[cmd_arg_count++] = (D3D12_INDIRECT_ARGUMENT_DESC) { 1928bf215546Sopenharmony_ci .Type = indexed ? 1929bf215546Sopenharmony_ci D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED : 1930bf215546Sopenharmony_ci D3D12_INDIRECT_ARGUMENT_TYPE_DRAW, 1931bf215546Sopenharmony_ci }; 1932bf215546Sopenharmony_ci 1933bf215546Sopenharmony_ci assert(cmd_arg_count <= ARRAY_SIZE(cmd_args)); 1934bf215546Sopenharmony_ci assert(offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex) == 0); 1935bf215546Sopenharmony_ci 1936bf215546Sopenharmony_ci D3D12_COMMAND_SIGNATURE_DESC cmd_sig_desc = { 1937bf215546Sopenharmony_ci .ByteStride = 1938bf215546Sopenharmony_ci triangle_fan ? 1939bf215546Sopenharmony_ci sizeof(struct dzn_indirect_triangle_fan_draw_exec_params) : 1940bf215546Sopenharmony_ci sizeof(struct dzn_indirect_draw_exec_params), 1941bf215546Sopenharmony_ci .NumArgumentDescs = cmd_arg_count, 1942bf215546Sopenharmony_ci .pArgumentDescs = cmd_args, 1943bf215546Sopenharmony_ci }; 1944bf215546Sopenharmony_ci HRESULT hres = 1945bf215546Sopenharmony_ci ID3D12Device1_CreateCommandSignature(device->dev, &cmd_sig_desc, 1946bf215546Sopenharmony_ci pipeline->base.root.sig, 1947bf215546Sopenharmony_ci &IID_ID3D12CommandSignature, 1948bf215546Sopenharmony_ci (void **)&cmdsig); 1949bf215546Sopenharmony_ci if (FAILED(hres)) 1950bf215546Sopenharmony_ci return NULL; 1951bf215546Sopenharmony_ci 1952bf215546Sopenharmony_ci pipeline->indirect_cmd_sigs[type] = cmdsig; 1953bf215546Sopenharmony_ci return cmdsig; 1954bf215546Sopenharmony_ci} 1955bf215546Sopenharmony_ci 1956bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 1957bf215546Sopenharmony_cidzn_CreateGraphicsPipelines(VkDevice dev, 1958bf215546Sopenharmony_ci VkPipelineCache pipelineCache, 1959bf215546Sopenharmony_ci uint32_t count, 1960bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *pCreateInfos, 1961bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 1962bf215546Sopenharmony_ci VkPipeline *pPipelines) 1963bf215546Sopenharmony_ci{ 1964bf215546Sopenharmony_ci VK_FROM_HANDLE(dzn_device, device, dev); 1965bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 1966bf215546Sopenharmony_ci 1967bf215546Sopenharmony_ci unsigned i; 1968bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 1969bf215546Sopenharmony_ci result = dzn_graphics_pipeline_create(device, 1970bf215546Sopenharmony_ci pipelineCache, 1971bf215546Sopenharmony_ci &pCreateInfos[i], 1972bf215546Sopenharmony_ci pAllocator, 1973bf215546Sopenharmony_ci &pPipelines[i]); 1974bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1975bf215546Sopenharmony_ci pPipelines[i] = VK_NULL_HANDLE; 1976bf215546Sopenharmony_ci 1977bf215546Sopenharmony_ci /* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED_EX as it 1978bf215546Sopenharmony_ci * is not obvious what error should be report upon 2 different failures. 1979bf215546Sopenharmony_ci */ 1980bf215546Sopenharmony_ci if (result != VK_PIPELINE_COMPILE_REQUIRED) 1981bf215546Sopenharmony_ci break; 1982bf215546Sopenharmony_ci 1983bf215546Sopenharmony_ci if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT) 1984bf215546Sopenharmony_ci break; 1985bf215546Sopenharmony_ci } 1986bf215546Sopenharmony_ci } 1987bf215546Sopenharmony_ci 1988bf215546Sopenharmony_ci for (; i < count; i++) 1989bf215546Sopenharmony_ci pPipelines[i] = VK_NULL_HANDLE; 1990bf215546Sopenharmony_ci 1991bf215546Sopenharmony_ci return result; 1992bf215546Sopenharmony_ci} 1993bf215546Sopenharmony_ci 1994bf215546Sopenharmony_cistatic void 1995bf215546Sopenharmony_cidzn_compute_pipeline_destroy(struct dzn_compute_pipeline *pipeline, 1996bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 1997bf215546Sopenharmony_ci{ 1998bf215546Sopenharmony_ci if (!pipeline) 1999bf215546Sopenharmony_ci return; 2000bf215546Sopenharmony_ci 2001bf215546Sopenharmony_ci if (pipeline->indirect_cmd_sig) 2002bf215546Sopenharmony_ci ID3D12CommandSignature_Release(pipeline->indirect_cmd_sig); 2003bf215546Sopenharmony_ci 2004bf215546Sopenharmony_ci dzn_pipeline_finish(&pipeline->base); 2005bf215546Sopenharmony_ci vk_free2(&pipeline->base.base.device->alloc, alloc, pipeline); 2006bf215546Sopenharmony_ci} 2007bf215546Sopenharmony_ci 2008bf215546Sopenharmony_cistatic VkResult 2009bf215546Sopenharmony_cidzn_pipeline_cache_lookup_compute_pipeline(struct vk_pipeline_cache *cache, 2010bf215546Sopenharmony_ci uint8_t *pipeline_hash, 2011bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc, 2012bf215546Sopenharmony_ci D3D12_SHADER_BYTECODE *dxil, 2013bf215546Sopenharmony_ci bool *cache_hit) 2014bf215546Sopenharmony_ci{ 2015bf215546Sopenharmony_ci *cache_hit = false; 2016bf215546Sopenharmony_ci 2017bf215546Sopenharmony_ci if (!cache) 2018bf215546Sopenharmony_ci return VK_SUCCESS; 2019bf215546Sopenharmony_ci 2020bf215546Sopenharmony_ci struct vk_pipeline_cache_object *cache_obj = NULL; 2021bf215546Sopenharmony_ci 2022bf215546Sopenharmony_ci cache_obj = 2023bf215546Sopenharmony_ci vk_pipeline_cache_lookup_object(cache, pipeline_hash, SHA1_DIGEST_LENGTH, 2024bf215546Sopenharmony_ci &dzn_cached_blob_ops, 2025bf215546Sopenharmony_ci NULL); 2026bf215546Sopenharmony_ci if (!cache_obj) 2027bf215546Sopenharmony_ci return VK_SUCCESS; 2028bf215546Sopenharmony_ci 2029bf215546Sopenharmony_ci struct dzn_cached_blob *cached_blob = 2030bf215546Sopenharmony_ci container_of(cache_obj, struct dzn_cached_blob, base); 2031bf215546Sopenharmony_ci 2032bf215546Sopenharmony_ci assert(cached_blob->size == SHA1_DIGEST_LENGTH); 2033bf215546Sopenharmony_ci 2034bf215546Sopenharmony_ci const uint8_t *dxil_hash = cached_blob->data; 2035bf215546Sopenharmony_ci gl_shader_stage stage; 2036bf215546Sopenharmony_ci 2037bf215546Sopenharmony_ci VkResult ret = 2038bf215546Sopenharmony_ci dzn_pipeline_cache_lookup_dxil_shader(cache, dxil_hash, &stage, dxil); 2039bf215546Sopenharmony_ci 2040bf215546Sopenharmony_ci if (ret != VK_SUCCESS || stage == MESA_SHADER_NONE) 2041bf215546Sopenharmony_ci goto out; 2042bf215546Sopenharmony_ci 2043bf215546Sopenharmony_ci assert(stage == MESA_SHADER_COMPUTE); 2044bf215546Sopenharmony_ci 2045bf215546Sopenharmony_ci d3d12_compute_pipeline_state_stream_new_desc(stream_desc, CS, D3D12_SHADER_BYTECODE, slot); 2046bf215546Sopenharmony_ci *slot = *dxil; 2047bf215546Sopenharmony_ci *cache_hit = true; 2048bf215546Sopenharmony_ci 2049bf215546Sopenharmony_ciout: 2050bf215546Sopenharmony_ci vk_pipeline_cache_object_unref(cache_obj); 2051bf215546Sopenharmony_ci return ret; 2052bf215546Sopenharmony_ci} 2053bf215546Sopenharmony_ci 2054bf215546Sopenharmony_cistatic void 2055bf215546Sopenharmony_cidzn_pipeline_cache_add_compute_pipeline(struct vk_pipeline_cache *cache, 2056bf215546Sopenharmony_ci uint8_t *pipeline_hash, 2057bf215546Sopenharmony_ci uint8_t *dxil_hash) 2058bf215546Sopenharmony_ci{ 2059bf215546Sopenharmony_ci struct vk_pipeline_cache_object *cache_obj = 2060bf215546Sopenharmony_ci dzn_cached_blob_create(cache->base.device, pipeline_hash, NULL, SHA1_DIGEST_LENGTH); 2061bf215546Sopenharmony_ci if (!cache_obj) 2062bf215546Sopenharmony_ci return; 2063bf215546Sopenharmony_ci 2064bf215546Sopenharmony_ci struct dzn_cached_blob *cached_blob = 2065bf215546Sopenharmony_ci container_of(cache_obj, struct dzn_cached_blob, base); 2066bf215546Sopenharmony_ci 2067bf215546Sopenharmony_ci memcpy((void *)cached_blob->data, dxil_hash, SHA1_DIGEST_LENGTH); 2068bf215546Sopenharmony_ci 2069bf215546Sopenharmony_ci cache_obj = vk_pipeline_cache_add_object(cache, cache_obj); 2070bf215546Sopenharmony_ci vk_pipeline_cache_object_unref(cache_obj); 2071bf215546Sopenharmony_ci} 2072bf215546Sopenharmony_ci 2073bf215546Sopenharmony_cistatic VkResult 2074bf215546Sopenharmony_cidzn_compute_pipeline_compile_shader(struct dzn_device *device, 2075bf215546Sopenharmony_ci struct dzn_compute_pipeline *pipeline, 2076bf215546Sopenharmony_ci struct vk_pipeline_cache *cache, 2077bf215546Sopenharmony_ci const struct dzn_pipeline_layout *layout, 2078bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc, 2079bf215546Sopenharmony_ci D3D12_SHADER_BYTECODE *shader, 2080bf215546Sopenharmony_ci const VkComputePipelineCreateInfo *info) 2081bf215546Sopenharmony_ci{ 2082bf215546Sopenharmony_ci uint8_t spirv_hash[SHA1_DIGEST_LENGTH], pipeline_hash[SHA1_DIGEST_LENGTH]; 2083bf215546Sopenharmony_ci VkResult ret = VK_SUCCESS; 2084bf215546Sopenharmony_ci nir_shader *nir = NULL; 2085bf215546Sopenharmony_ci 2086bf215546Sopenharmony_ci if (cache) { 2087bf215546Sopenharmony_ci struct mesa_sha1 pipeline_hash_ctx; 2088bf215546Sopenharmony_ci 2089bf215546Sopenharmony_ci _mesa_sha1_init(&pipeline_hash_ctx); 2090bf215546Sopenharmony_ci vk_pipeline_hash_shader_stage(&info->stage, spirv_hash); 2091bf215546Sopenharmony_ci _mesa_sha1_update(&pipeline_hash_ctx, spirv_hash, sizeof(spirv_hash)); 2092bf215546Sopenharmony_ci _mesa_sha1_update(&pipeline_hash_ctx, layout->stages[MESA_SHADER_COMPUTE].hash, 2093bf215546Sopenharmony_ci sizeof(layout->stages[MESA_SHADER_COMPUTE].hash)); 2094bf215546Sopenharmony_ci _mesa_sha1_final(&pipeline_hash_ctx, pipeline_hash); 2095bf215546Sopenharmony_ci 2096bf215546Sopenharmony_ci bool cache_hit = false; 2097bf215546Sopenharmony_ci ret = dzn_pipeline_cache_lookup_compute_pipeline(cache, pipeline_hash, 2098bf215546Sopenharmony_ci stream_desc, shader, 2099bf215546Sopenharmony_ci &cache_hit); 2100bf215546Sopenharmony_ci if (ret != VK_SUCCESS || cache_hit) 2101bf215546Sopenharmony_ci goto out; 2102bf215546Sopenharmony_ci } 2103bf215546Sopenharmony_ci 2104bf215546Sopenharmony_ci ret = dzn_pipeline_get_nir_shader(device, layout, cache, spirv_hash, 2105bf215546Sopenharmony_ci &info->stage, MESA_SHADER_COMPUTE, 2106bf215546Sopenharmony_ci DXIL_SPIRV_YZ_FLIP_NONE, 0, 0, 2107bf215546Sopenharmony_ci false, NULL, 2108bf215546Sopenharmony_ci dxil_get_nir_compiler_options(), &nir); 2109bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 2110bf215546Sopenharmony_ci return ret; 2111bf215546Sopenharmony_ci 2112bf215546Sopenharmony_ci uint8_t bindings_hash[SHA1_DIGEST_LENGTH], dxil_hash[SHA1_DIGEST_LENGTH]; 2113bf215546Sopenharmony_ci 2114bf215546Sopenharmony_ci NIR_PASS_V(nir, adjust_var_bindings, layout, cache ? bindings_hash : NULL); 2115bf215546Sopenharmony_ci 2116bf215546Sopenharmony_ci if (cache) { 2117bf215546Sopenharmony_ci struct mesa_sha1 dxil_hash_ctx; 2118bf215546Sopenharmony_ci 2119bf215546Sopenharmony_ci _mesa_sha1_init(&dxil_hash_ctx); 2120bf215546Sopenharmony_ci _mesa_sha1_update(&dxil_hash_ctx, spirv_hash, sizeof(spirv_hash)); 2121bf215546Sopenharmony_ci _mesa_sha1_update(&dxil_hash_ctx, bindings_hash, sizeof(bindings_hash)); 2122bf215546Sopenharmony_ci _mesa_sha1_final(&dxil_hash_ctx, dxil_hash); 2123bf215546Sopenharmony_ci 2124bf215546Sopenharmony_ci gl_shader_stage stage; 2125bf215546Sopenharmony_ci 2126bf215546Sopenharmony_ci ret = dzn_pipeline_cache_lookup_dxil_shader(cache, dxil_hash, &stage, shader); 2127bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 2128bf215546Sopenharmony_ci goto out; 2129bf215546Sopenharmony_ci 2130bf215546Sopenharmony_ci if (stage != MESA_SHADER_NONE) { 2131bf215546Sopenharmony_ci assert(stage == MESA_SHADER_COMPUTE); 2132bf215546Sopenharmony_ci d3d12_compute_pipeline_state_stream_new_desc(stream_desc, CS, D3D12_SHADER_BYTECODE, cs); 2133bf215546Sopenharmony_ci *cs = *shader; 2134bf215546Sopenharmony_ci dzn_pipeline_cache_add_compute_pipeline(cache, pipeline_hash, dxil_hash); 2135bf215546Sopenharmony_ci goto out; 2136bf215546Sopenharmony_ci } 2137bf215546Sopenharmony_ci } 2138bf215546Sopenharmony_ci 2139bf215546Sopenharmony_ci ret = dzn_pipeline_compile_shader(device, nir, shader); 2140bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 2141bf215546Sopenharmony_ci goto out; 2142bf215546Sopenharmony_ci 2143bf215546Sopenharmony_ci d3d12_compute_pipeline_state_stream_new_desc(stream_desc, CS, D3D12_SHADER_BYTECODE, cs); 2144bf215546Sopenharmony_ci *cs = *shader; 2145bf215546Sopenharmony_ci 2146bf215546Sopenharmony_ci if (cache) { 2147bf215546Sopenharmony_ci dzn_pipeline_cache_add_dxil_shader(cache, dxil_hash, MESA_SHADER_COMPUTE, shader); 2148bf215546Sopenharmony_ci dzn_pipeline_cache_add_compute_pipeline(cache, pipeline_hash, dxil_hash); 2149bf215546Sopenharmony_ci } 2150bf215546Sopenharmony_ci 2151bf215546Sopenharmony_ciout: 2152bf215546Sopenharmony_ci ralloc_free(nir); 2153bf215546Sopenharmony_ci return ret; 2154bf215546Sopenharmony_ci} 2155bf215546Sopenharmony_ci 2156bf215546Sopenharmony_cistatic VkResult 2157bf215546Sopenharmony_cidzn_compute_pipeline_create(struct dzn_device *device, 2158bf215546Sopenharmony_ci VkPipelineCache cache, 2159bf215546Sopenharmony_ci const VkComputePipelineCreateInfo *pCreateInfo, 2160bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 2161bf215546Sopenharmony_ci VkPipeline *out) 2162bf215546Sopenharmony_ci{ 2163bf215546Sopenharmony_ci VK_FROM_HANDLE(dzn_pipeline_layout, layout, pCreateInfo->layout); 2164bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_pipeline_cache, pcache, cache); 2165bf215546Sopenharmony_ci 2166bf215546Sopenharmony_ci struct dzn_compute_pipeline *pipeline = 2167bf215546Sopenharmony_ci vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8, 2168bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 2169bf215546Sopenharmony_ci if (!pipeline) 2170bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2171bf215546Sopenharmony_ci 2172bf215546Sopenharmony_ci uintptr_t state_buf[MAX_COMPUTE_PIPELINE_STATE_STREAM_SIZE / sizeof(uintptr_t)]; 2173bf215546Sopenharmony_ci D3D12_PIPELINE_STATE_STREAM_DESC stream_desc = { 2174bf215546Sopenharmony_ci .pPipelineStateSubobjectStream = state_buf, 2175bf215546Sopenharmony_ci }; 2176bf215546Sopenharmony_ci 2177bf215546Sopenharmony_ci dzn_pipeline_init(&pipeline->base, device, 2178bf215546Sopenharmony_ci VK_PIPELINE_BIND_POINT_COMPUTE, 2179bf215546Sopenharmony_ci layout, &stream_desc); 2180bf215546Sopenharmony_ci 2181bf215546Sopenharmony_ci D3D12_SHADER_BYTECODE shader = { 0 }; 2182bf215546Sopenharmony_ci VkResult ret = 2183bf215546Sopenharmony_ci dzn_compute_pipeline_compile_shader(device, pipeline, pcache, layout, 2184bf215546Sopenharmony_ci &stream_desc, &shader, pCreateInfo); 2185bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 2186bf215546Sopenharmony_ci goto out; 2187bf215546Sopenharmony_ci 2188bf215546Sopenharmony_ci if (FAILED(ID3D12Device2_CreatePipelineState(device->dev, &stream_desc, 2189bf215546Sopenharmony_ci &IID_ID3D12PipelineState, 2190bf215546Sopenharmony_ci (void **)&pipeline->base.state))) 2191bf215546Sopenharmony_ci ret = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2192bf215546Sopenharmony_ci 2193bf215546Sopenharmony_ciout: 2194bf215546Sopenharmony_ci free((void *)shader.pShaderBytecode); 2195bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 2196bf215546Sopenharmony_ci dzn_compute_pipeline_destroy(pipeline, pAllocator); 2197bf215546Sopenharmony_ci else 2198bf215546Sopenharmony_ci *out = dzn_compute_pipeline_to_handle(pipeline); 2199bf215546Sopenharmony_ci 2200bf215546Sopenharmony_ci return ret; 2201bf215546Sopenharmony_ci} 2202bf215546Sopenharmony_ci 2203bf215546Sopenharmony_ciID3D12CommandSignature * 2204bf215546Sopenharmony_cidzn_compute_pipeline_get_indirect_cmd_sig(struct dzn_compute_pipeline *pipeline) 2205bf215546Sopenharmony_ci{ 2206bf215546Sopenharmony_ci if (pipeline->indirect_cmd_sig) 2207bf215546Sopenharmony_ci return pipeline->indirect_cmd_sig; 2208bf215546Sopenharmony_ci 2209bf215546Sopenharmony_ci struct dzn_device *device = 2210bf215546Sopenharmony_ci container_of(pipeline->base.base.device, struct dzn_device, vk); 2211bf215546Sopenharmony_ci 2212bf215546Sopenharmony_ci D3D12_INDIRECT_ARGUMENT_DESC indirect_dispatch_args[] = { 2213bf215546Sopenharmony_ci { 2214bf215546Sopenharmony_ci .Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT, 2215bf215546Sopenharmony_ci .Constant = { 2216bf215546Sopenharmony_ci .RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx, 2217bf215546Sopenharmony_ci .DestOffsetIn32BitValues = 0, 2218bf215546Sopenharmony_ci .Num32BitValuesToSet = 3, 2219bf215546Sopenharmony_ci }, 2220bf215546Sopenharmony_ci }, 2221bf215546Sopenharmony_ci { 2222bf215546Sopenharmony_ci .Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH, 2223bf215546Sopenharmony_ci }, 2224bf215546Sopenharmony_ci }; 2225bf215546Sopenharmony_ci 2226bf215546Sopenharmony_ci D3D12_COMMAND_SIGNATURE_DESC indirect_dispatch_desc = { 2227bf215546Sopenharmony_ci .ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS) * 2, 2228bf215546Sopenharmony_ci .NumArgumentDescs = ARRAY_SIZE(indirect_dispatch_args), 2229bf215546Sopenharmony_ci .pArgumentDescs = indirect_dispatch_args, 2230bf215546Sopenharmony_ci }; 2231bf215546Sopenharmony_ci 2232bf215546Sopenharmony_ci HRESULT hres = 2233bf215546Sopenharmony_ci ID3D12Device1_CreateCommandSignature(device->dev, &indirect_dispatch_desc, 2234bf215546Sopenharmony_ci pipeline->base.root.sig, 2235bf215546Sopenharmony_ci &IID_ID3D12CommandSignature, 2236bf215546Sopenharmony_ci (void **)&pipeline->indirect_cmd_sig); 2237bf215546Sopenharmony_ci if (FAILED(hres)) 2238bf215546Sopenharmony_ci return NULL; 2239bf215546Sopenharmony_ci 2240bf215546Sopenharmony_ci return pipeline->indirect_cmd_sig; 2241bf215546Sopenharmony_ci} 2242bf215546Sopenharmony_ci 2243bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2244bf215546Sopenharmony_cidzn_CreateComputePipelines(VkDevice dev, 2245bf215546Sopenharmony_ci VkPipelineCache pipelineCache, 2246bf215546Sopenharmony_ci uint32_t count, 2247bf215546Sopenharmony_ci const VkComputePipelineCreateInfo *pCreateInfos, 2248bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 2249bf215546Sopenharmony_ci VkPipeline *pPipelines) 2250bf215546Sopenharmony_ci{ 2251bf215546Sopenharmony_ci VK_FROM_HANDLE(dzn_device, device, dev); 2252bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 2253bf215546Sopenharmony_ci 2254bf215546Sopenharmony_ci unsigned i; 2255bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 2256bf215546Sopenharmony_ci result = dzn_compute_pipeline_create(device, 2257bf215546Sopenharmony_ci pipelineCache, 2258bf215546Sopenharmony_ci &pCreateInfos[i], 2259bf215546Sopenharmony_ci pAllocator, 2260bf215546Sopenharmony_ci &pPipelines[i]); 2261bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 2262bf215546Sopenharmony_ci pPipelines[i] = VK_NULL_HANDLE; 2263bf215546Sopenharmony_ci 2264bf215546Sopenharmony_ci /* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED_EX as it 2265bf215546Sopenharmony_ci * is not obvious what error should be report upon 2 different failures. 2266bf215546Sopenharmony_ci */ 2267bf215546Sopenharmony_ci if (result != VK_PIPELINE_COMPILE_REQUIRED) 2268bf215546Sopenharmony_ci break; 2269bf215546Sopenharmony_ci 2270bf215546Sopenharmony_ci if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT) 2271bf215546Sopenharmony_ci break; 2272bf215546Sopenharmony_ci } 2273bf215546Sopenharmony_ci } 2274bf215546Sopenharmony_ci 2275bf215546Sopenharmony_ci for (; i < count; i++) 2276bf215546Sopenharmony_ci pPipelines[i] = VK_NULL_HANDLE; 2277bf215546Sopenharmony_ci 2278bf215546Sopenharmony_ci return result; 2279bf215546Sopenharmony_ci} 2280bf215546Sopenharmony_ci 2281bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2282bf215546Sopenharmony_cidzn_DestroyPipeline(VkDevice device, 2283bf215546Sopenharmony_ci VkPipeline pipeline, 2284bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 2285bf215546Sopenharmony_ci{ 2286bf215546Sopenharmony_ci VK_FROM_HANDLE(dzn_pipeline, pipe, pipeline); 2287bf215546Sopenharmony_ci 2288bf215546Sopenharmony_ci if (!pipe) 2289bf215546Sopenharmony_ci return; 2290bf215546Sopenharmony_ci 2291bf215546Sopenharmony_ci if (pipe->type == VK_PIPELINE_BIND_POINT_GRAPHICS) { 2292bf215546Sopenharmony_ci struct dzn_graphics_pipeline *gfx = container_of(pipe, struct dzn_graphics_pipeline, base); 2293bf215546Sopenharmony_ci dzn_graphics_pipeline_destroy(gfx, pAllocator); 2294bf215546Sopenharmony_ci } else { 2295bf215546Sopenharmony_ci assert(pipe->type == VK_PIPELINE_BIND_POINT_COMPUTE); 2296bf215546Sopenharmony_ci struct dzn_compute_pipeline *compute = container_of(pipe, struct dzn_compute_pipeline, base); 2297bf215546Sopenharmony_ci dzn_compute_pipeline_destroy(compute, pAllocator); 2298bf215546Sopenharmony_ci } 2299bf215546Sopenharmony_ci} 2300