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 "d3d12_cmd_signature.h" 25bf215546Sopenharmony_ci#include "d3d12_compiler.h" 26bf215546Sopenharmony_ci#include "d3d12_compute_transforms.h" 27bf215546Sopenharmony_ci#include "d3d12_context.h" 28bf215546Sopenharmony_ci#include "d3d12_format.h" 29bf215546Sopenharmony_ci#include "d3d12_query.h" 30bf215546Sopenharmony_ci#include "d3d12_resource.h" 31bf215546Sopenharmony_ci#include "d3d12_root_signature.h" 32bf215546Sopenharmony_ci#include "d3d12_screen.h" 33bf215546Sopenharmony_ci#include "d3d12_surface.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include "util/u_debug.h" 36bf215546Sopenharmony_ci#include "util/u_draw.h" 37bf215546Sopenharmony_ci#include "util/u_helpers.h" 38bf215546Sopenharmony_ci#include "util/u_inlines.h" 39bf215546Sopenharmony_ci#include "util/u_prim.h" 40bf215546Sopenharmony_ci#include "util/u_prim_restart.h" 41bf215546Sopenharmony_ci#include "util/u_math.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ciextern "C" { 44bf215546Sopenharmony_ci#include "indices/u_primconvert.h" 45bf215546Sopenharmony_ci} 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistatic const D3D12_RECT MAX_SCISSOR = { D3D12_VIEWPORT_BOUNDS_MIN, 48bf215546Sopenharmony_ci D3D12_VIEWPORT_BOUNDS_MIN, 49bf215546Sopenharmony_ci D3D12_VIEWPORT_BOUNDS_MAX, 50bf215546Sopenharmony_ci D3D12_VIEWPORT_BOUNDS_MAX }; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_cistatic const D3D12_RECT MAX_SCISSOR_ARRAY[] = { 53bf215546Sopenharmony_ci MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, 54bf215546Sopenharmony_ci MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, 55bf215546Sopenharmony_ci MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, 56bf215546Sopenharmony_ci MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR, MAX_SCISSOR 57bf215546Sopenharmony_ci}; 58bf215546Sopenharmony_cistatic_assert(ARRAY_SIZE(MAX_SCISSOR_ARRAY) == PIPE_MAX_VIEWPORTS, "Wrong scissor count"); 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_cistatic D3D12_GPU_DESCRIPTOR_HANDLE 61bf215546Sopenharmony_cifill_cbv_descriptors(struct d3d12_context *ctx, 62bf215546Sopenharmony_ci struct d3d12_shader *shader, 63bf215546Sopenharmony_ci int stage) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci struct d3d12_batch *batch = d3d12_current_batch(ctx); 66bf215546Sopenharmony_ci struct d3d12_descriptor_handle table_start; 67bf215546Sopenharmony_ci d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci for (unsigned i = 0; i < shader->num_cb_bindings; i++) { 70bf215546Sopenharmony_ci unsigned binding = shader->cb_bindings[i].binding; 71bf215546Sopenharmony_ci struct pipe_constant_buffer *buffer = &ctx->cbufs[stage][binding]; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {}; 74bf215546Sopenharmony_ci if (buffer && buffer->buffer) { 75bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(buffer->buffer); 76bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 77bf215546Sopenharmony_ci cbv_desc.BufferLocation = d3d12_resource_gpu_virtual_address(res) + buffer->buffer_offset; 78bf215546Sopenharmony_ci cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16, 79bf215546Sopenharmony_ci align(buffer->buffer_size, 256)); 80bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, res, false); 81bf215546Sopenharmony_ci } 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci struct d3d12_descriptor_handle handle; 84bf215546Sopenharmony_ci d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle); 85bf215546Sopenharmony_ci d3d12_screen(ctx->base.screen)->dev->CreateConstantBufferView(&cbv_desc, handle.cpu_handle); 86bf215546Sopenharmony_ci } 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci return table_start.gpu_handle; 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_cistatic D3D12_GPU_DESCRIPTOR_HANDLE 92bf215546Sopenharmony_cifill_srv_descriptors(struct d3d12_context *ctx, 93bf215546Sopenharmony_ci struct d3d12_shader *shader, 94bf215546Sopenharmony_ci unsigned stage) 95bf215546Sopenharmony_ci{ 96bf215546Sopenharmony_ci struct d3d12_batch *batch = d3d12_current_batch(ctx); 97bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 98bf215546Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 99bf215546Sopenharmony_ci struct d3d12_descriptor_handle table_start; 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++) 104bf215546Sopenharmony_ci { 105bf215546Sopenharmony_ci struct d3d12_sampler_view *view; 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci if (i == shader->pstipple_binding) { 108bf215546Sopenharmony_ci view = (struct d3d12_sampler_view*)ctx->pstipple.sampler_view; 109bf215546Sopenharmony_ci } else { 110bf215546Sopenharmony_ci view = (struct d3d12_sampler_view*)ctx->sampler_views[stage][i]; 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci unsigned desc_idx = i - shader->begin_srv_binding; 114bf215546Sopenharmony_ci if (view != NULL) { 115bf215546Sopenharmony_ci descs[desc_idx] = view->handle.cpu_handle; 116bf215546Sopenharmony_ci d3d12_batch_reference_sampler_view(batch, view); 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(view->base.texture); 119bf215546Sopenharmony_ci /* If this is a buffer that's been replaced, re-create the descriptor */ 120bf215546Sopenharmony_ci if (view->texture_generation_id != res->generation_id) { 121bf215546Sopenharmony_ci d3d12_init_sampler_view_descriptor(view); 122bf215546Sopenharmony_ci view->texture_generation_id = res->generation_id; 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci D3D12_RESOURCE_STATES state = (stage == PIPE_SHADER_FRAGMENT) ? 126bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE : 127bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; 128bf215546Sopenharmony_ci if (view->base.texture->target == PIPE_BUFFER) { 129bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, d3d12_resource(view->base.texture), 130bf215546Sopenharmony_ci state, 131bf215546Sopenharmony_ci D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 132bf215546Sopenharmony_ci } else { 133bf215546Sopenharmony_ci d3d12_transition_subresources_state(ctx, d3d12_resource(view->base.texture), 134bf215546Sopenharmony_ci view->base.u.tex.first_level, view->mip_levels, 135bf215546Sopenharmony_ci view->base.u.tex.first_layer, view->array_size, 136bf215546Sopenharmony_ci d3d12_get_format_start_plane(view->base.format), 137bf215546Sopenharmony_ci d3d12_get_format_num_planes(view->base.format), 138bf215546Sopenharmony_ci state, 139bf215546Sopenharmony_ci D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci } else { 142bf215546Sopenharmony_ci descs[desc_idx] = screen->null_srvs[shader->srv_bindings[i].dimension].cpu_handle; 143bf215546Sopenharmony_ci } 144bf215546Sopenharmony_ci } 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci d3d12_descriptor_heap_append_handles(batch->view_heap, descs, shader->end_srv_binding - shader->begin_srv_binding); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci return table_start.gpu_handle; 149bf215546Sopenharmony_ci} 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_cistatic D3D12_GPU_DESCRIPTOR_HANDLE 152bf215546Sopenharmony_cifill_ssbo_descriptors(struct d3d12_context *ctx, 153bf215546Sopenharmony_ci const struct d3d12_shader *shader, 154bf215546Sopenharmony_ci int stage) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci struct d3d12_batch *batch = d3d12_current_batch(ctx); 157bf215546Sopenharmony_ci struct d3d12_descriptor_handle table_start; 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci for (unsigned i = 0; i < shader->nir->info.num_ssbos; i++) 162bf215546Sopenharmony_ci { 163bf215546Sopenharmony_ci struct pipe_shader_buffer *view = &ctx->ssbo_views[stage][i]; 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc; 166bf215546Sopenharmony_ci uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; 167bf215546Sopenharmony_ci uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; 168bf215546Sopenharmony_ci uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; 169bf215546Sopenharmony_ci uav_desc.Buffer.StructureByteStride = 0; 170bf215546Sopenharmony_ci uav_desc.Buffer.CounterOffsetInBytes = 0; 171bf215546Sopenharmony_ci ID3D12Resource *d3d12_res = nullptr; 172bf215546Sopenharmony_ci if (view->buffer) { 173bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(view->buffer); 174bf215546Sopenharmony_ci uint64_t res_offset = 0; 175bf215546Sopenharmony_ci d3d12_res = d3d12_resource_underlying(res, &res_offset); 176bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 177bf215546Sopenharmony_ci uav_desc.Buffer.FirstElement = (view->buffer_offset + res_offset) / 4; 178bf215546Sopenharmony_ci uav_desc.Buffer.NumElements = DIV_ROUND_UP(view->buffer_size, 4); 179bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, res, true); 180bf215546Sopenharmony_ci } 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci struct d3d12_descriptor_handle handle; 183bf215546Sopenharmony_ci d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle); 184bf215546Sopenharmony_ci d3d12_screen(ctx->base.screen)->dev->CreateUnorderedAccessView(d3d12_res, nullptr, &uav_desc, handle.cpu_handle); 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci return table_start.gpu_handle; 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_cistatic D3D12_GPU_DESCRIPTOR_HANDLE 191bf215546Sopenharmony_cifill_sampler_descriptors(struct d3d12_context *ctx, 192bf215546Sopenharmony_ci const struct d3d12_shader_selector *shader_sel, 193bf215546Sopenharmony_ci unsigned stage) 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci const struct d3d12_shader *shader = shader_sel->current; 196bf215546Sopenharmony_ci struct d3d12_batch *batch = d3d12_current_batch(ctx); 197bf215546Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 198bf215546Sopenharmony_ci struct d3d12_descriptor_handle table_start; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, &table_start); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++) 203bf215546Sopenharmony_ci { 204bf215546Sopenharmony_ci struct d3d12_sampler_state *sampler; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci if (i == shader->pstipple_binding) { 207bf215546Sopenharmony_ci sampler = ctx->pstipple.sampler_cso; 208bf215546Sopenharmony_ci } else { 209bf215546Sopenharmony_ci sampler = ctx->samplers[stage][i]; 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci unsigned desc_idx = i - shader->begin_srv_binding; 213bf215546Sopenharmony_ci if (sampler != NULL) { 214bf215546Sopenharmony_ci if (sampler->is_shadow_sampler && shader_sel->compare_with_lod_bias_grad) 215bf215546Sopenharmony_ci descs[desc_idx] = sampler->handle_without_shadow.cpu_handle; 216bf215546Sopenharmony_ci else 217bf215546Sopenharmony_ci descs[desc_idx] = sampler->handle.cpu_handle; 218bf215546Sopenharmony_ci } else 219bf215546Sopenharmony_ci descs[desc_idx] = ctx->null_sampler.cpu_handle; 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->end_srv_binding - shader->begin_srv_binding); 223bf215546Sopenharmony_ci return table_start.gpu_handle; 224bf215546Sopenharmony_ci} 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_cistatic D3D12_UAV_DIMENSION 227bf215546Sopenharmony_ciimage_view_dimension(enum pipe_texture_target target) 228bf215546Sopenharmony_ci{ 229bf215546Sopenharmony_ci switch (target) { 230bf215546Sopenharmony_ci case PIPE_BUFFER: return D3D12_UAV_DIMENSION_BUFFER; 231bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: return D3D12_UAV_DIMENSION_TEXTURE1D; 232bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: return D3D12_UAV_DIMENSION_TEXTURE1DARRAY; 233bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 234bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 235bf215546Sopenharmony_ci return D3D12_UAV_DIMENSION_TEXTURE2D; 236bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 237bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 238bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 239bf215546Sopenharmony_ci return D3D12_UAV_DIMENSION_TEXTURE2DARRAY; 240bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: return D3D12_UAV_DIMENSION_TEXTURE3D; 241bf215546Sopenharmony_ci default: 242bf215546Sopenharmony_ci unreachable("unexpected target"); 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci} 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_cistatic D3D12_GPU_DESCRIPTOR_HANDLE 247bf215546Sopenharmony_cifill_image_descriptors(struct d3d12_context *ctx, 248bf215546Sopenharmony_ci const struct d3d12_shader *shader, 249bf215546Sopenharmony_ci int stage) 250bf215546Sopenharmony_ci{ 251bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 252bf215546Sopenharmony_ci struct d3d12_batch *batch = d3d12_current_batch(ctx); 253bf215546Sopenharmony_ci struct d3d12_descriptor_handle table_start; 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci for (unsigned i = 0; i < shader->nir->info.num_images; i++) 258bf215546Sopenharmony_ci { 259bf215546Sopenharmony_ci struct pipe_image_view *view = &ctx->image_views[stage][i]; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci if (view->resource) { 262bf215546Sopenharmony_ci D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc; 263bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(view->resource); 264bf215546Sopenharmony_ci uint64_t offset = 0; 265bf215546Sopenharmony_ci ID3D12Resource *d3d12_res = d3d12_resource_underlying(res, &offset); 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci enum pipe_format view_format = ctx->image_view_emulation_formats[stage][i]; 268bf215546Sopenharmony_ci if (view_format == PIPE_FORMAT_NONE) 269bf215546Sopenharmony_ci view_format = view->format; 270bf215546Sopenharmony_ci uav_desc.Format = d3d12_get_format(view_format); 271bf215546Sopenharmony_ci uav_desc.ViewDimension = image_view_dimension(res->base.b.target); 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci unsigned array_size = view->u.tex.last_layer - view->u.tex.first_layer + 1; 274bf215546Sopenharmony_ci switch (uav_desc.ViewDimension) { 275bf215546Sopenharmony_ci case D3D12_UAV_DIMENSION_TEXTURE1D: 276bf215546Sopenharmony_ci if (view->u.tex.first_layer > 0) 277bf215546Sopenharmony_ci debug_printf("D3D12: can't create 1D UAV from layer %d\n", 278bf215546Sopenharmony_ci view->u.tex.first_layer); 279bf215546Sopenharmony_ci uav_desc.Texture1D.MipSlice = view->u.tex.level; 280bf215546Sopenharmony_ci break; 281bf215546Sopenharmony_ci case D3D12_UAV_DIMENSION_TEXTURE1DARRAY: 282bf215546Sopenharmony_ci uav_desc.Texture1DArray.FirstArraySlice = view->u.tex.first_layer; 283bf215546Sopenharmony_ci uav_desc.Texture1DArray.ArraySize = array_size; 284bf215546Sopenharmony_ci uav_desc.Texture1DArray.MipSlice = view->u.tex.level; 285bf215546Sopenharmony_ci break; 286bf215546Sopenharmony_ci case D3D12_UAV_DIMENSION_TEXTURE2D: 287bf215546Sopenharmony_ci if (view->u.tex.first_layer > 0) 288bf215546Sopenharmony_ci debug_printf("D3D12: can't create 2D UAV from layer %d\n", 289bf215546Sopenharmony_ci view->u.tex.first_layer); 290bf215546Sopenharmony_ci uav_desc.Texture2D.MipSlice = view->u.tex.level; 291bf215546Sopenharmony_ci uav_desc.Texture2D.PlaneSlice = 0; 292bf215546Sopenharmony_ci break; 293bf215546Sopenharmony_ci case D3D12_UAV_DIMENSION_TEXTURE2DARRAY: 294bf215546Sopenharmony_ci uav_desc.Texture2DArray.FirstArraySlice = view->u.tex.first_layer; 295bf215546Sopenharmony_ci uav_desc.Texture2DArray.ArraySize = array_size; 296bf215546Sopenharmony_ci uav_desc.Texture2DArray.MipSlice = view->u.tex.level; 297bf215546Sopenharmony_ci uav_desc.Texture2DArray.PlaneSlice = 0; 298bf215546Sopenharmony_ci break; 299bf215546Sopenharmony_ci case D3D12_UAV_DIMENSION_TEXTURE3D: 300bf215546Sopenharmony_ci uav_desc.Texture3D.MipSlice = view->u.tex.level; 301bf215546Sopenharmony_ci uav_desc.Texture3D.FirstWSlice = view->u.tex.first_layer; 302bf215546Sopenharmony_ci uav_desc.Texture3D.WSize = array_size; 303bf215546Sopenharmony_ci break; 304bf215546Sopenharmony_ci case D3D12_UAV_DIMENSION_BUFFER: { 305bf215546Sopenharmony_ci uav_desc.Format = d3d12_get_format(shader->uav_bindings[i].format); 306bf215546Sopenharmony_ci uint format_size = util_format_get_blocksize(shader->uav_bindings[i].format); 307bf215546Sopenharmony_ci offset += view->u.buf.offset; 308bf215546Sopenharmony_ci uav_desc.Buffer.CounterOffsetInBytes = 0; 309bf215546Sopenharmony_ci uav_desc.Buffer.FirstElement = offset / format_size; 310bf215546Sopenharmony_ci uav_desc.Buffer.NumElements = view->u.buf.size / format_size; 311bf215546Sopenharmony_ci uav_desc.Buffer.StructureByteStride = 0; 312bf215546Sopenharmony_ci uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE; 313bf215546Sopenharmony_ci break; 314bf215546Sopenharmony_ci } 315bf215546Sopenharmony_ci default: 316bf215546Sopenharmony_ci unreachable("Unexpected image view dimension"); 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci if (!batch->pending_memory_barrier) { 320bf215546Sopenharmony_ci if (res->base.b.target == PIPE_BUFFER) { 321bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 322bf215546Sopenharmony_ci } else { 323bf215546Sopenharmony_ci unsigned transition_first_layer = view->u.tex.first_layer; 324bf215546Sopenharmony_ci unsigned transition_array_size = array_size; 325bf215546Sopenharmony_ci if (res->base.b.target == PIPE_TEXTURE_3D) { 326bf215546Sopenharmony_ci transition_first_layer = 0; 327bf215546Sopenharmony_ci transition_array_size = 0; 328bf215546Sopenharmony_ci } 329bf215546Sopenharmony_ci d3d12_transition_subresources_state(ctx, res, 330bf215546Sopenharmony_ci view->u.tex.level, 1, 331bf215546Sopenharmony_ci transition_first_layer, transition_array_size, 332bf215546Sopenharmony_ci 0, 1, 333bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 334bf215546Sopenharmony_ci D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 335bf215546Sopenharmony_ci } 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, res, true); 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci struct d3d12_descriptor_handle handle; 340bf215546Sopenharmony_ci d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle); 341bf215546Sopenharmony_ci d3d12_screen(ctx->base.screen)->dev->CreateUnorderedAccessView(d3d12_res, nullptr, &uav_desc, handle.cpu_handle); 342bf215546Sopenharmony_ci } else { 343bf215546Sopenharmony_ci d3d12_descriptor_heap_append_handles(batch->view_heap, &screen->null_uavs[shader->uav_bindings[i].dimension].cpu_handle, 1); 344bf215546Sopenharmony_ci } 345bf215546Sopenharmony_ci } 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci return table_start.gpu_handle; 348bf215546Sopenharmony_ci} 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_cistatic unsigned 351bf215546Sopenharmony_cifill_graphics_state_vars(struct d3d12_context *ctx, 352bf215546Sopenharmony_ci const struct pipe_draw_info *dinfo, 353bf215546Sopenharmony_ci unsigned drawid, 354bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw, 355bf215546Sopenharmony_ci struct d3d12_shader *shader, 356bf215546Sopenharmony_ci uint32_t *values, 357bf215546Sopenharmony_ci struct d3d12_cmd_signature_key *cmd_sig_key) 358bf215546Sopenharmony_ci{ 359bf215546Sopenharmony_ci unsigned size = 0; 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci for (unsigned j = 0; j < shader->num_state_vars; ++j) { 362bf215546Sopenharmony_ci uint32_t *ptr = values + size; 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci switch (shader->state_vars[j].var) { 365bf215546Sopenharmony_ci case D3D12_STATE_VAR_Y_FLIP: 366bf215546Sopenharmony_ci ptr[0] = fui(ctx->flip_y); 367bf215546Sopenharmony_ci size += 4; 368bf215546Sopenharmony_ci break; 369bf215546Sopenharmony_ci case D3D12_STATE_VAR_PT_SPRITE: 370bf215546Sopenharmony_ci ptr[0] = fui(1.0 / ctx->viewports[0].Width); 371bf215546Sopenharmony_ci ptr[1] = fui(1.0 / ctx->viewports[0].Height); 372bf215546Sopenharmony_ci ptr[2] = fui(ctx->gfx_pipeline_state.rast->base.point_size); 373bf215546Sopenharmony_ci ptr[3] = fui(D3D12_MAX_POINT_SIZE); 374bf215546Sopenharmony_ci size += 4; 375bf215546Sopenharmony_ci break; 376bf215546Sopenharmony_ci case D3D12_STATE_VAR_DRAW_PARAMS: 377bf215546Sopenharmony_ci ptr[0] = dinfo->index_size ? draw->index_bias : draw->start; 378bf215546Sopenharmony_ci ptr[1] = dinfo->start_instance; 379bf215546Sopenharmony_ci ptr[2] = drawid; 380bf215546Sopenharmony_ci ptr[3] = dinfo->index_size ? -1 : 0; 381bf215546Sopenharmony_ci cmd_sig_key->draw_or_dispatch_params = 1; 382bf215546Sopenharmony_ci cmd_sig_key->root_sig = ctx->gfx_pipeline_state.root_signature; 383bf215546Sopenharmony_ci cmd_sig_key->params_root_const_offset = size; 384bf215546Sopenharmony_ci size += 4; 385bf215546Sopenharmony_ci break; 386bf215546Sopenharmony_ci case D3D12_STATE_VAR_DEPTH_TRANSFORM: 387bf215546Sopenharmony_ci ptr[0] = fui(2.0f * ctx->viewport_states[0].scale[2]); 388bf215546Sopenharmony_ci ptr[1] = fui(ctx->viewport_states[0].translate[2] - ctx->viewport_states[0].scale[2]); 389bf215546Sopenharmony_ci size += 4; 390bf215546Sopenharmony_ci break; 391bf215546Sopenharmony_ci case D3D12_STATE_VAR_DEFAULT_INNER_TESS_LEVEL: 392bf215546Sopenharmony_ci memcpy(ptr, ctx->default_inner_tess_factor, sizeof(ctx->default_inner_tess_factor)); 393bf215546Sopenharmony_ci size += 4; 394bf215546Sopenharmony_ci break; 395bf215546Sopenharmony_ci case D3D12_STATE_VAR_DEFAULT_OUTER_TESS_LEVEL: 396bf215546Sopenharmony_ci memcpy(ptr, ctx->default_outer_tess_factor, sizeof(ctx->default_outer_tess_factor)); 397bf215546Sopenharmony_ci size += 4; 398bf215546Sopenharmony_ci break; 399bf215546Sopenharmony_ci case D3D12_STATE_VAR_PATCH_VERTICES_IN: 400bf215546Sopenharmony_ci ptr[0] = ctx->patch_vertices; 401bf215546Sopenharmony_ci size += 4; 402bf215546Sopenharmony_ci break; 403bf215546Sopenharmony_ci default: 404bf215546Sopenharmony_ci unreachable("unknown state variable"); 405bf215546Sopenharmony_ci } 406bf215546Sopenharmony_ci } 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci return size; 409bf215546Sopenharmony_ci} 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_cistatic unsigned 412bf215546Sopenharmony_cifill_compute_state_vars(struct d3d12_context *ctx, 413bf215546Sopenharmony_ci const struct pipe_grid_info *info, 414bf215546Sopenharmony_ci struct d3d12_shader *shader, 415bf215546Sopenharmony_ci uint32_t *values, 416bf215546Sopenharmony_ci struct d3d12_cmd_signature_key *cmd_sig_key) 417bf215546Sopenharmony_ci{ 418bf215546Sopenharmony_ci unsigned size = 0; 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci for (unsigned j = 0; j < shader->num_state_vars; ++j) { 421bf215546Sopenharmony_ci uint32_t *ptr = values + size; 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci switch (shader->state_vars[j].var) { 424bf215546Sopenharmony_ci case D3D12_STATE_VAR_NUM_WORKGROUPS: 425bf215546Sopenharmony_ci ptr[0] = info->grid[0]; 426bf215546Sopenharmony_ci ptr[1] = info->grid[1]; 427bf215546Sopenharmony_ci ptr[2] = info->grid[2]; 428bf215546Sopenharmony_ci cmd_sig_key->draw_or_dispatch_params = 1; 429bf215546Sopenharmony_ci cmd_sig_key->root_sig = ctx->compute_pipeline_state.root_signature; 430bf215546Sopenharmony_ci cmd_sig_key->params_root_const_offset = size; 431bf215546Sopenharmony_ci size += 4; 432bf215546Sopenharmony_ci break; 433bf215546Sopenharmony_ci case D3D12_STATE_VAR_TRANSFORM_GENERIC0: { 434bf215546Sopenharmony_ci unsigned idx = shader->state_vars[j].var - D3D12_STATE_VAR_TRANSFORM_GENERIC0; 435bf215546Sopenharmony_ci ptr[0] = ctx->transform_state_vars[idx * 4]; 436bf215546Sopenharmony_ci ptr[1] = ctx->transform_state_vars[idx * 4 + 1]; 437bf215546Sopenharmony_ci ptr[2] = ctx->transform_state_vars[idx * 4 + 2]; 438bf215546Sopenharmony_ci ptr[3] = ctx->transform_state_vars[idx * 4 + 3]; 439bf215546Sopenharmony_ci size += 4; 440bf215546Sopenharmony_ci break; 441bf215546Sopenharmony_ci } 442bf215546Sopenharmony_ci default: 443bf215546Sopenharmony_ci unreachable("unknown state variable"); 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci } 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci return size; 448bf215546Sopenharmony_ci} 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_cistatic bool 451bf215546Sopenharmony_cicheck_descriptors_left(struct d3d12_context *ctx, bool compute) 452bf215546Sopenharmony_ci{ 453bf215546Sopenharmony_ci struct d3d12_batch *batch = d3d12_current_batch(ctx); 454bf215546Sopenharmony_ci unsigned needed_descs = 0; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci unsigned count = compute ? 1 : D3D12_GFX_SHADER_STAGES; 457bf215546Sopenharmony_ci for (unsigned i = 0; i < count; ++i) { 458bf215546Sopenharmony_ci struct d3d12_shader_selector *shader = compute ? ctx->compute_state : ctx->gfx_stages[i]; 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci if (!shader) 461bf215546Sopenharmony_ci continue; 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci needed_descs += shader->current->num_cb_bindings; 464bf215546Sopenharmony_ci needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding; 465bf215546Sopenharmony_ci needed_descs += shader->current->nir->info.num_ssbos; 466bf215546Sopenharmony_ci needed_descs += shader->current->nir->info.num_images; 467bf215546Sopenharmony_ci } 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs) 470bf215546Sopenharmony_ci return false; 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci needed_descs = 0; 473bf215546Sopenharmony_ci for (unsigned i = 0; i < count; ++i) { 474bf215546Sopenharmony_ci struct d3d12_shader_selector *shader = compute ? ctx->compute_state : ctx->gfx_stages[i]; 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci if (!shader) 477bf215546Sopenharmony_ci continue; 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding; 480bf215546Sopenharmony_ci } 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci if (d3d12_descriptor_heap_get_remaining_handles(batch->sampler_heap) < needed_descs) 483bf215546Sopenharmony_ci return false; 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci return true; 486bf215546Sopenharmony_ci} 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci#define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 4) 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_cistatic void 491bf215546Sopenharmony_ciupdate_shader_stage_root_parameters(struct d3d12_context *ctx, 492bf215546Sopenharmony_ci const struct d3d12_shader_selector *shader_sel, 493bf215546Sopenharmony_ci unsigned &num_params, 494bf215546Sopenharmony_ci unsigned &num_root_descriptors, 495bf215546Sopenharmony_ci D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES], 496bf215546Sopenharmony_ci int root_desc_indices[MAX_DESCRIPTOR_TABLES]) 497bf215546Sopenharmony_ci{ 498bf215546Sopenharmony_ci auto stage = shader_sel->stage; 499bf215546Sopenharmony_ci struct d3d12_shader *shader = shader_sel->current; 500bf215546Sopenharmony_ci uint64_t dirty = ctx->shader_dirty[stage]; 501bf215546Sopenharmony_ci assert(shader); 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ci if (shader->num_cb_bindings > 0) { 504bf215546Sopenharmony_ci if (dirty & D3D12_SHADER_DIRTY_CONSTBUF) { 505bf215546Sopenharmony_ci assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES); 506bf215546Sopenharmony_ci root_desc_tables[num_root_descriptors] = fill_cbv_descriptors(ctx, shader, stage); 507bf215546Sopenharmony_ci root_desc_indices[num_root_descriptors++] = num_params; 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci num_params++; 510bf215546Sopenharmony_ci } 511bf215546Sopenharmony_ci if (shader->end_srv_binding > 0) { 512bf215546Sopenharmony_ci if (dirty & D3D12_SHADER_DIRTY_SAMPLER_VIEWS) { 513bf215546Sopenharmony_ci assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES); 514bf215546Sopenharmony_ci root_desc_tables[num_root_descriptors] = fill_srv_descriptors(ctx, shader, stage); 515bf215546Sopenharmony_ci root_desc_indices[num_root_descriptors++] = num_params; 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci num_params++; 518bf215546Sopenharmony_ci if (dirty & D3D12_SHADER_DIRTY_SAMPLERS) { 519bf215546Sopenharmony_ci assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES); 520bf215546Sopenharmony_ci root_desc_tables[num_root_descriptors] = fill_sampler_descriptors(ctx, shader_sel, stage); 521bf215546Sopenharmony_ci root_desc_indices[num_root_descriptors++] = num_params; 522bf215546Sopenharmony_ci } 523bf215546Sopenharmony_ci num_params++; 524bf215546Sopenharmony_ci } 525bf215546Sopenharmony_ci if (shader->nir->info.num_ssbos > 0) { 526bf215546Sopenharmony_ci if (dirty & D3D12_SHADER_DIRTY_SSBO) { 527bf215546Sopenharmony_ci assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES); 528bf215546Sopenharmony_ci root_desc_tables[num_root_descriptors] = fill_ssbo_descriptors(ctx, shader, stage); 529bf215546Sopenharmony_ci root_desc_indices[num_root_descriptors++] = num_params; 530bf215546Sopenharmony_ci } 531bf215546Sopenharmony_ci num_params++; 532bf215546Sopenharmony_ci } 533bf215546Sopenharmony_ci if (shader->nir->info.num_images > 0) { 534bf215546Sopenharmony_ci if (dirty & D3D12_SHADER_DIRTY_IMAGE) { 535bf215546Sopenharmony_ci assert(num_root_descriptors < MAX_DESCRIPTOR_TABLES); 536bf215546Sopenharmony_ci root_desc_tables[num_root_descriptors] = fill_image_descriptors(ctx, shader, stage); 537bf215546Sopenharmony_ci root_desc_indices[num_root_descriptors++] = num_params; 538bf215546Sopenharmony_ci } 539bf215546Sopenharmony_ci num_params++; 540bf215546Sopenharmony_ci } 541bf215546Sopenharmony_ci} 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_cistatic unsigned 544bf215546Sopenharmony_ciupdate_graphics_root_parameters(struct d3d12_context *ctx, 545bf215546Sopenharmony_ci const struct pipe_draw_info *dinfo, 546bf215546Sopenharmony_ci unsigned drawid, 547bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw, 548bf215546Sopenharmony_ci D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES], 549bf215546Sopenharmony_ci int root_desc_indices[MAX_DESCRIPTOR_TABLES], 550bf215546Sopenharmony_ci struct d3d12_cmd_signature_key *cmd_sig_key) 551bf215546Sopenharmony_ci{ 552bf215546Sopenharmony_ci unsigned num_params = 0; 553bf215546Sopenharmony_ci unsigned num_root_descriptors = 0; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 556bf215546Sopenharmony_ci struct d3d12_shader_selector *shader_sel = ctx->gfx_stages[i]; 557bf215546Sopenharmony_ci if (!shader_sel) 558bf215546Sopenharmony_ci continue; 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci update_shader_stage_root_parameters(ctx, shader_sel, num_params, num_root_descriptors, root_desc_tables, root_desc_indices); 561bf215546Sopenharmony_ci /* TODO Don't always update state vars */ 562bf215546Sopenharmony_ci if (shader_sel->current->num_state_vars > 0) { 563bf215546Sopenharmony_ci uint32_t constants[D3D12_MAX_GRAPHICS_STATE_VARS * 4]; 564bf215546Sopenharmony_ci unsigned size = fill_graphics_state_vars(ctx, dinfo, drawid, draw, shader_sel->current, constants, cmd_sig_key); 565bf215546Sopenharmony_ci if (cmd_sig_key->draw_or_dispatch_params) 566bf215546Sopenharmony_ci cmd_sig_key->params_root_const_param = num_params; 567bf215546Sopenharmony_ci ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0); 568bf215546Sopenharmony_ci num_params++; 569bf215546Sopenharmony_ci } 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci return num_root_descriptors; 572bf215546Sopenharmony_ci} 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_cistatic unsigned 575bf215546Sopenharmony_ciupdate_compute_root_parameters(struct d3d12_context *ctx, 576bf215546Sopenharmony_ci const struct pipe_grid_info *info, 577bf215546Sopenharmony_ci D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES], 578bf215546Sopenharmony_ci int root_desc_indices[MAX_DESCRIPTOR_TABLES], 579bf215546Sopenharmony_ci struct d3d12_cmd_signature_key *cmd_sig_key) 580bf215546Sopenharmony_ci{ 581bf215546Sopenharmony_ci unsigned num_params = 0; 582bf215546Sopenharmony_ci unsigned num_root_descriptors = 0; 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci struct d3d12_shader_selector *shader_sel = ctx->compute_state; 585bf215546Sopenharmony_ci if (shader_sel) { 586bf215546Sopenharmony_ci update_shader_stage_root_parameters(ctx, shader_sel, num_params, num_root_descriptors, root_desc_tables, root_desc_indices); 587bf215546Sopenharmony_ci /* TODO Don't always update state vars */ 588bf215546Sopenharmony_ci if (shader_sel->current->num_state_vars > 0) { 589bf215546Sopenharmony_ci uint32_t constants[D3D12_MAX_COMPUTE_STATE_VARS * 4]; 590bf215546Sopenharmony_ci unsigned size = fill_compute_state_vars(ctx, info, shader_sel->current, constants, cmd_sig_key); 591bf215546Sopenharmony_ci if (cmd_sig_key->draw_or_dispatch_params) 592bf215546Sopenharmony_ci cmd_sig_key->params_root_const_param = num_params; 593bf215546Sopenharmony_ci ctx->cmdlist->SetComputeRoot32BitConstants(num_params, size, constants, 0); 594bf215546Sopenharmony_ci num_params++; 595bf215546Sopenharmony_ci } 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci return num_root_descriptors; 598bf215546Sopenharmony_ci} 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_cistatic bool 601bf215546Sopenharmony_civalidate_stream_output_targets(struct d3d12_context *ctx) 602bf215546Sopenharmony_ci{ 603bf215546Sopenharmony_ci unsigned factor = 0; 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.num_so_targets && 606bf215546Sopenharmony_ci ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]) 607bf215546Sopenharmony_ci factor = ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]->key.gs.stream_output_factor; 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci if (factor > 1) 610bf215546Sopenharmony_ci return d3d12_enable_fake_so_buffers(ctx, factor); 611bf215546Sopenharmony_ci else 612bf215546Sopenharmony_ci return d3d12_disable_fake_so_buffers(ctx); 613bf215546Sopenharmony_ci} 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_cistatic D3D_PRIMITIVE_TOPOLOGY 616bf215546Sopenharmony_citopology(enum pipe_prim_type prim_type, uint8_t patch_vertices) 617bf215546Sopenharmony_ci{ 618bf215546Sopenharmony_ci switch (prim_type) { 619bf215546Sopenharmony_ci case PIPE_PRIM_POINTS: 620bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_POINTLIST; 621bf215546Sopenharmony_ci 622bf215546Sopenharmony_ci case PIPE_PRIM_LINES: 623bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_LINELIST; 624bf215546Sopenharmony_ci 625bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP: 626bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES: 629bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP: 632bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci case PIPE_PRIM_LINES_ADJACENCY: 635bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ; 636bf215546Sopenharmony_ci 637bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP_ADJACENCY: 638bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ; 639bf215546Sopenharmony_ci 640bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES_ADJACENCY: 641bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ; 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 644bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ; 645bf215546Sopenharmony_ci 646bf215546Sopenharmony_ci case PIPE_PRIM_PATCHES: 647bf215546Sopenharmony_ci return (D3D_PRIMITIVE_TOPOLOGY)(D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + patch_vertices - 1); 648bf215546Sopenharmony_ci 649bf215546Sopenharmony_ci case PIPE_PRIM_QUADS: 650bf215546Sopenharmony_ci case PIPE_PRIM_QUAD_STRIP: 651bf215546Sopenharmony_ci return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; /* HACK: this is just wrong! */ 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci default: 654bf215546Sopenharmony_ci debug_printf("pipe_prim_type: %s\n", u_prim_name(prim_type)); 655bf215546Sopenharmony_ci unreachable("unexpected enum pipe_prim_type"); 656bf215546Sopenharmony_ci } 657bf215546Sopenharmony_ci} 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_cistatic DXGI_FORMAT 660bf215546Sopenharmony_ciib_format(unsigned index_size) 661bf215546Sopenharmony_ci{ 662bf215546Sopenharmony_ci switch (index_size) { 663bf215546Sopenharmony_ci case 1: return DXGI_FORMAT_R8_UINT; 664bf215546Sopenharmony_ci case 2: return DXGI_FORMAT_R16_UINT; 665bf215546Sopenharmony_ci case 4: return DXGI_FORMAT_R32_UINT; 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ci default: 668bf215546Sopenharmony_ci unreachable("unexpected index-buffer size"); 669bf215546Sopenharmony_ci } 670bf215546Sopenharmony_ci} 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_cistatic void 673bf215546Sopenharmony_citwoface_emulation(struct d3d12_context *ctx, 674bf215546Sopenharmony_ci struct d3d12_rasterizer_state *rast, 675bf215546Sopenharmony_ci const struct pipe_draw_info *dinfo, 676bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 677bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw) 678bf215546Sopenharmony_ci{ 679bf215546Sopenharmony_ci /* draw backfaces */ 680bf215546Sopenharmony_ci ctx->base.bind_rasterizer_state(&ctx->base, rast->twoface_back); 681bf215546Sopenharmony_ci d3d12_draw_vbo(&ctx->base, dinfo, 0, indirect, draw, 1); 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci /* restore real state */ 684bf215546Sopenharmony_ci ctx->base.bind_rasterizer_state(&ctx->base, rast); 685bf215546Sopenharmony_ci} 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_cistatic void 688bf215546Sopenharmony_citransition_surface_subresources_state(struct d3d12_context *ctx, 689bf215546Sopenharmony_ci struct pipe_surface *psurf, 690bf215546Sopenharmony_ci struct pipe_resource *pres, 691bf215546Sopenharmony_ci D3D12_RESOURCE_STATES state) 692bf215546Sopenharmony_ci{ 693bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(pres); 694bf215546Sopenharmony_ci unsigned start_layer, num_layers; 695bf215546Sopenharmony_ci if (!d3d12_subresource_id_uses_layer(res->base.b.target)) { 696bf215546Sopenharmony_ci start_layer = 0; 697bf215546Sopenharmony_ci num_layers = 1; 698bf215546Sopenharmony_ci } else { 699bf215546Sopenharmony_ci start_layer = psurf->u.tex.first_layer; 700bf215546Sopenharmony_ci num_layers = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1; 701bf215546Sopenharmony_ci } 702bf215546Sopenharmony_ci d3d12_transition_subresources_state(ctx, res, 703bf215546Sopenharmony_ci psurf->u.tex.level, 1, 704bf215546Sopenharmony_ci start_layer, num_layers, 705bf215546Sopenharmony_ci d3d12_get_format_start_plane(psurf->format), 706bf215546Sopenharmony_ci d3d12_get_format_num_planes(psurf->format), 707bf215546Sopenharmony_ci state, 708bf215546Sopenharmony_ci D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 709bf215546Sopenharmony_ci} 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_cistatic bool 712bf215546Sopenharmony_ciprim_supported(enum pipe_prim_type prim_type) 713bf215546Sopenharmony_ci{ 714bf215546Sopenharmony_ci switch (prim_type) { 715bf215546Sopenharmony_ci case PIPE_PRIM_POINTS: 716bf215546Sopenharmony_ci case PIPE_PRIM_LINES: 717bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP: 718bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES: 719bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP: 720bf215546Sopenharmony_ci case PIPE_PRIM_LINES_ADJACENCY: 721bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP_ADJACENCY: 722bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES_ADJACENCY: 723bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 724bf215546Sopenharmony_ci case PIPE_PRIM_PATCHES: 725bf215546Sopenharmony_ci return true; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci default: 728bf215546Sopenharmony_ci return false; 729bf215546Sopenharmony_ci } 730bf215546Sopenharmony_ci} 731bf215546Sopenharmony_ci 732bf215546Sopenharmony_cistatic inline struct d3d12_shader_selector * 733bf215546Sopenharmony_cid3d12_last_vertex_stage(struct d3d12_context *ctx) 734bf215546Sopenharmony_ci{ 735bf215546Sopenharmony_ci struct d3d12_shader_selector *sel = ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; 736bf215546Sopenharmony_ci if (!sel || sel->is_variant) 737bf215546Sopenharmony_ci sel = ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]; 738bf215546Sopenharmony_ci if (!sel) 739bf215546Sopenharmony_ci sel = ctx->gfx_stages[PIPE_SHADER_VERTEX]; 740bf215546Sopenharmony_ci return sel; 741bf215546Sopenharmony_ci} 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_cistatic bool 744bf215546Sopenharmony_ciupdate_draw_indirect_with_sysvals(struct d3d12_context *ctx, 745bf215546Sopenharmony_ci const struct pipe_draw_info *dinfo, 746bf215546Sopenharmony_ci unsigned drawid, 747bf215546Sopenharmony_ci const struct pipe_draw_indirect_info **indirect_inout, 748bf215546Sopenharmony_ci struct pipe_draw_indirect_info *indirect_out) 749bf215546Sopenharmony_ci{ 750bf215546Sopenharmony_ci if (*indirect_inout == nullptr || 751bf215546Sopenharmony_ci ctx->gfx_stages[PIPE_SHADER_VERTEX] == nullptr) 752bf215546Sopenharmony_ci return false; 753bf215546Sopenharmony_ci 754bf215546Sopenharmony_ci unsigned sysvals[] = { 755bf215546Sopenharmony_ci SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, 756bf215546Sopenharmony_ci SYSTEM_VALUE_BASE_VERTEX, 757bf215546Sopenharmony_ci SYSTEM_VALUE_FIRST_VERTEX, 758bf215546Sopenharmony_ci SYSTEM_VALUE_BASE_INSTANCE, 759bf215546Sopenharmony_ci SYSTEM_VALUE_DRAW_ID, 760bf215546Sopenharmony_ci }; 761bf215546Sopenharmony_ci bool any = false; 762bf215546Sopenharmony_ci for (unsigned sysval : sysvals) { 763bf215546Sopenharmony_ci any |= (BITSET_TEST(ctx->gfx_stages[PIPE_SHADER_VERTEX]->initial->info.system_values_read, sysval)); 764bf215546Sopenharmony_ci } 765bf215546Sopenharmony_ci if (!any) 766bf215546Sopenharmony_ci return false; 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci d3d12_compute_transform_save_restore save; 769bf215546Sopenharmony_ci d3d12_save_compute_transform_state(ctx, &save); 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci auto indirect_in = *indirect_inout; 772bf215546Sopenharmony_ci *indirect_inout = indirect_out; 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci d3d12_compute_transform_key key; 775bf215546Sopenharmony_ci memset(&key, 0, sizeof(key)); 776bf215546Sopenharmony_ci key.type = d3d12_compute_transform_type::base_vertex; 777bf215546Sopenharmony_ci key.base_vertex.indexed = dinfo->index_size > 0; 778bf215546Sopenharmony_ci key.base_vertex.dynamic_count = indirect_in->indirect_draw_count != nullptr; 779bf215546Sopenharmony_ci ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key)); 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci ctx->transform_state_vars[0] = indirect_in->stride; 782bf215546Sopenharmony_ci ctx->transform_state_vars[1] = indirect_in->offset; 783bf215546Sopenharmony_ci ctx->transform_state_vars[2] = drawid; 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci if (indirect_in->indirect_draw_count) { 786bf215546Sopenharmony_ci pipe_constant_buffer draw_count_cbuf; 787bf215546Sopenharmony_ci draw_count_cbuf.buffer = indirect_in->indirect_draw_count; 788bf215546Sopenharmony_ci draw_count_cbuf.buffer_offset = indirect_in->indirect_draw_count_offset; 789bf215546Sopenharmony_ci draw_count_cbuf.buffer_size = 4; 790bf215546Sopenharmony_ci draw_count_cbuf.user_buffer = nullptr; 791bf215546Sopenharmony_ci ctx->base.set_constant_buffer(&ctx->base, PIPE_SHADER_COMPUTE, 1, false, &draw_count_cbuf); 792bf215546Sopenharmony_ci } 793bf215546Sopenharmony_ci 794bf215546Sopenharmony_ci pipe_shader_buffer new_cs_ssbos[2]; 795bf215546Sopenharmony_ci new_cs_ssbos[0].buffer = indirect_in->buffer; 796bf215546Sopenharmony_ci new_cs_ssbos[0].buffer_offset = 0; 797bf215546Sopenharmony_ci new_cs_ssbos[0].buffer_size = indirect_in->buffer->width0; 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci /* 4 additional uints for base vertex, base instance, draw ID, and a bool for indexed draw */ 800bf215546Sopenharmony_ci unsigned out_stride = sizeof(uint32_t) * ((key.base_vertex.indexed ? 5 : 4) + 4); 801bf215546Sopenharmony_ci pipe_resource output_buf_templ = {}; 802bf215546Sopenharmony_ci output_buf_templ.target = PIPE_BUFFER; 803bf215546Sopenharmony_ci output_buf_templ.width0 = out_stride * indirect_in->draw_count; 804bf215546Sopenharmony_ci output_buf_templ.height0 = output_buf_templ.depth0 = output_buf_templ.array_size = 805bf215546Sopenharmony_ci output_buf_templ.last_level = 1; 806bf215546Sopenharmony_ci output_buf_templ.usage = PIPE_USAGE_DEFAULT; 807bf215546Sopenharmony_ci 808bf215546Sopenharmony_ci new_cs_ssbos[1].buffer = ctx->base.screen->resource_create(ctx->base.screen, &output_buf_templ); 809bf215546Sopenharmony_ci new_cs_ssbos[1].buffer_offset = 0; 810bf215546Sopenharmony_ci new_cs_ssbos[1].buffer_size = output_buf_templ.width0; 811bf215546Sopenharmony_ci ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 2, new_cs_ssbos, 2); 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci pipe_grid_info grid = {}; 814bf215546Sopenharmony_ci grid.block[0] = grid.block[1] = grid.block[2] = 1; 815bf215546Sopenharmony_ci grid.grid[0] = indirect_in->draw_count; 816bf215546Sopenharmony_ci grid.grid[1] = grid.grid[2] = 1; 817bf215546Sopenharmony_ci ctx->base.launch_grid(&ctx->base, &grid); 818bf215546Sopenharmony_ci 819bf215546Sopenharmony_ci d3d12_restore_compute_transform_state(ctx, &save); 820bf215546Sopenharmony_ci 821bf215546Sopenharmony_ci *indirect_out = *indirect_in; 822bf215546Sopenharmony_ci indirect_out->buffer = new_cs_ssbos[1].buffer; 823bf215546Sopenharmony_ci indirect_out->offset = 0; 824bf215546Sopenharmony_ci indirect_out->stride = out_stride; 825bf215546Sopenharmony_ci return true; 826bf215546Sopenharmony_ci} 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_cistatic bool 829bf215546Sopenharmony_ciupdate_draw_auto(struct d3d12_context *ctx, 830bf215546Sopenharmony_ci const struct pipe_draw_indirect_info **indirect_inout, 831bf215546Sopenharmony_ci struct pipe_draw_indirect_info *indirect_out) 832bf215546Sopenharmony_ci{ 833bf215546Sopenharmony_ci if (*indirect_inout == nullptr || 834bf215546Sopenharmony_ci (*indirect_inout)->count_from_stream_output == nullptr || 835bf215546Sopenharmony_ci ctx->gfx_stages[PIPE_SHADER_VERTEX] == nullptr) 836bf215546Sopenharmony_ci return false; 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_ci d3d12_compute_transform_save_restore save; 839bf215546Sopenharmony_ci d3d12_save_compute_transform_state(ctx, &save); 840bf215546Sopenharmony_ci 841bf215546Sopenharmony_ci auto indirect_in = *indirect_inout; 842bf215546Sopenharmony_ci *indirect_inout = indirect_out; 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_ci d3d12_compute_transform_key key; 845bf215546Sopenharmony_ci memset(&key, 0, sizeof(key)); 846bf215546Sopenharmony_ci key.type = d3d12_compute_transform_type::draw_auto; 847bf215546Sopenharmony_ci ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key)); 848bf215546Sopenharmony_ci 849bf215546Sopenharmony_ci auto so_arg = indirect_in->count_from_stream_output; 850bf215546Sopenharmony_ci d3d12_stream_output_target *target = (d3d12_stream_output_target *)so_arg; 851bf215546Sopenharmony_ci 852bf215546Sopenharmony_ci ctx->transform_state_vars[0] = ctx->vbs[0].stride; 853bf215546Sopenharmony_ci ctx->transform_state_vars[1] = ctx->vbs[0].buffer_offset - so_arg->buffer_offset; 854bf215546Sopenharmony_ci 855bf215546Sopenharmony_ci pipe_shader_buffer new_cs_ssbo; 856bf215546Sopenharmony_ci new_cs_ssbo.buffer = target->fill_buffer; 857bf215546Sopenharmony_ci new_cs_ssbo.buffer_offset = target->fill_buffer_offset; 858bf215546Sopenharmony_ci new_cs_ssbo.buffer_size = target->fill_buffer->width0 - new_cs_ssbo.buffer_offset; 859bf215546Sopenharmony_ci ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 1, &new_cs_ssbo, 1); 860bf215546Sopenharmony_ci 861bf215546Sopenharmony_ci pipe_grid_info grid = {}; 862bf215546Sopenharmony_ci grid.block[0] = grid.block[1] = grid.block[2] = 1; 863bf215546Sopenharmony_ci grid.grid[0] = grid.grid[1] = grid.grid[2] = 1; 864bf215546Sopenharmony_ci ctx->base.launch_grid(&ctx->base, &grid); 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_ci d3d12_restore_compute_transform_state(ctx, &save); 867bf215546Sopenharmony_ci 868bf215546Sopenharmony_ci *indirect_out = *indirect_in; 869bf215546Sopenharmony_ci pipe_resource_reference(&indirect_out->buffer, target->fill_buffer); 870bf215546Sopenharmony_ci indirect_out->offset = target->fill_buffer_offset + 4; 871bf215546Sopenharmony_ci indirect_out->stride = sizeof(D3D12_DRAW_ARGUMENTS); 872bf215546Sopenharmony_ci indirect_out->count_from_stream_output = nullptr; 873bf215546Sopenharmony_ci return true; 874bf215546Sopenharmony_ci} 875bf215546Sopenharmony_ci 876bf215546Sopenharmony_civoid 877bf215546Sopenharmony_cid3d12_draw_vbo(struct pipe_context *pctx, 878bf215546Sopenharmony_ci const struct pipe_draw_info *dinfo, 879bf215546Sopenharmony_ci unsigned drawid_offset, 880bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 881bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 882bf215546Sopenharmony_ci unsigned num_draws) 883bf215546Sopenharmony_ci{ 884bf215546Sopenharmony_ci if (num_draws > 1) { 885bf215546Sopenharmony_ci util_draw_multi(pctx, dinfo, drawid_offset, indirect, draws, num_draws); 886bf215546Sopenharmony_ci return; 887bf215546Sopenharmony_ci } 888bf215546Sopenharmony_ci 889bf215546Sopenharmony_ci if (!indirect && (!draws[0].count || !dinfo->instance_count)) 890bf215546Sopenharmony_ci return; 891bf215546Sopenharmony_ci 892bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 893bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pctx->screen); 894bf215546Sopenharmony_ci struct d3d12_batch *batch; 895bf215546Sopenharmony_ci struct pipe_resource *index_buffer = NULL; 896bf215546Sopenharmony_ci unsigned index_offset = 0; 897bf215546Sopenharmony_ci enum d3d12_surface_conversion_mode conversion_modes[PIPE_MAX_COLOR_BUFS] = {}; 898bf215546Sopenharmony_ci struct pipe_draw_indirect_info patched_indirect = {}; 899bf215546Sopenharmony_ci 900bf215546Sopenharmony_ci if (!prim_supported((enum pipe_prim_type)dinfo->mode) || 901bf215546Sopenharmony_ci dinfo->index_size == 1 || 902bf215546Sopenharmony_ci (dinfo->primitive_restart && dinfo->restart_index != 0xffff && 903bf215546Sopenharmony_ci dinfo->restart_index != 0xffffffff)) { 904bf215546Sopenharmony_ci 905bf215546Sopenharmony_ci if (!dinfo->primitive_restart && 906bf215546Sopenharmony_ci !indirect && 907bf215546Sopenharmony_ci !u_trim_pipe_prim((enum pipe_prim_type)dinfo->mode, (unsigned *)&draws[0].count)) 908bf215546Sopenharmony_ci return; 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci ctx->initial_api_prim = (enum pipe_prim_type)dinfo->mode; 911bf215546Sopenharmony_ci util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->gfx_pipeline_state.rast->base); 912bf215546Sopenharmony_ci util_primconvert_draw_vbo(ctx->primconvert, dinfo, drawid_offset, indirect, draws, num_draws); 913bf215546Sopenharmony_ci return; 914bf215546Sopenharmony_ci } 915bf215546Sopenharmony_ci 916bf215546Sopenharmony_ci bool draw_auto = update_draw_auto(ctx, &indirect, &patched_indirect); 917bf215546Sopenharmony_ci bool indirect_with_sysvals = !draw_auto && update_draw_indirect_with_sysvals(ctx, dinfo, drawid_offset, &indirect, &patched_indirect); 918bf215546Sopenharmony_ci struct d3d12_cmd_signature_key cmd_sig_key; 919bf215546Sopenharmony_ci memset(&cmd_sig_key, 0, sizeof(cmd_sig_key)); 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_ci if (indirect) { 922bf215546Sopenharmony_ci cmd_sig_key.compute = false; 923bf215546Sopenharmony_ci cmd_sig_key.indexed = dinfo->index_size > 0; 924bf215546Sopenharmony_ci if (indirect->draw_count > 1 || 925bf215546Sopenharmony_ci indirect->indirect_draw_count || 926bf215546Sopenharmony_ci indirect_with_sysvals) 927bf215546Sopenharmony_ci cmd_sig_key.multi_draw_stride = indirect->stride; 928bf215546Sopenharmony_ci else if (cmd_sig_key.indexed) 929bf215546Sopenharmony_ci cmd_sig_key.multi_draw_stride = sizeof(D3D12_DRAW_INDEXED_ARGUMENTS); 930bf215546Sopenharmony_ci else 931bf215546Sopenharmony_ci cmd_sig_key.multi_draw_stride = sizeof(D3D12_DRAW_ARGUMENTS); 932bf215546Sopenharmony_ci } 933bf215546Sopenharmony_ci 934bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 935bf215546Sopenharmony_ci if (ctx->fb.cbufs[i]) { 936bf215546Sopenharmony_ci struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]); 937bf215546Sopenharmony_ci conversion_modes[i] = d3d12_surface_update_pre_draw(pctx, surface, d3d12_rtv_format(ctx, i)); 938bf215546Sopenharmony_ci if (conversion_modes[i] != D3D12_SURFACE_CONVERSION_NONE) 939bf215546Sopenharmony_ci ctx->cmdlist_dirty |= D3D12_DIRTY_FRAMEBUFFER; 940bf215546Sopenharmony_ci } 941bf215546Sopenharmony_ci } 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_ci struct d3d12_rasterizer_state *rast = ctx->gfx_pipeline_state.rast; 944bf215546Sopenharmony_ci if (rast->twoface_back) { 945bf215546Sopenharmony_ci enum pipe_prim_type saved_mode = ctx->initial_api_prim; 946bf215546Sopenharmony_ci twoface_emulation(ctx, rast, dinfo, indirect, &draws[0]); 947bf215546Sopenharmony_ci ctx->initial_api_prim = saved_mode; 948bf215546Sopenharmony_ci } 949bf215546Sopenharmony_ci 950bf215546Sopenharmony_ci if (ctx->pstipple.enabled && ctx->gfx_pipeline_state.rast->base.poly_stipple_enable) 951bf215546Sopenharmony_ci ctx->shader_dirty[PIPE_SHADER_FRAGMENT] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS | 952bf215546Sopenharmony_ci D3D12_SHADER_DIRTY_SAMPLERS; 953bf215546Sopenharmony_ci 954bf215546Sopenharmony_ci /* this should *really* be fixed at a higher level than here! */ 955bf215546Sopenharmony_ci enum pipe_prim_type reduced_prim = u_reduced_prim((enum pipe_prim_type)dinfo->mode); 956bf215546Sopenharmony_ci if (reduced_prim == PIPE_PRIM_TRIANGLES && 957bf215546Sopenharmony_ci ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_FRONT_AND_BACK) 958bf215546Sopenharmony_ci return; 959bf215546Sopenharmony_ci 960bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.prim_type != dinfo->mode) { 961bf215546Sopenharmony_ci ctx->gfx_pipeline_state.prim_type = (enum pipe_prim_type)dinfo->mode; 962bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_PRIM_MODE; 963bf215546Sopenharmony_ci } 964bf215546Sopenharmony_ci 965bf215546Sopenharmony_ci d3d12_select_shader_variants(ctx, dinfo); 966bf215546Sopenharmony_ci d3d12_validate_queries(ctx); 967bf215546Sopenharmony_ci for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 968bf215546Sopenharmony_ci struct d3d12_shader *shader = ctx->gfx_stages[i] ? ctx->gfx_stages[i]->current : NULL; 969bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.stages[i] != shader) { 970bf215546Sopenharmony_ci ctx->gfx_pipeline_state.stages[i] = shader; 971bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_SHADER; 972bf215546Sopenharmony_ci } 973bf215546Sopenharmony_ci } 974bf215546Sopenharmony_ci 975bf215546Sopenharmony_ci /* Reset to an invalid value after it's been used */ 976bf215546Sopenharmony_ci ctx->initial_api_prim = PIPE_PRIM_MAX; 977bf215546Sopenharmony_ci 978bf215546Sopenharmony_ci /* Copy the stream output info from the current vertex/geometry shader */ 979bf215546Sopenharmony_ci if (ctx->state_dirty & D3D12_DIRTY_SHADER) { 980bf215546Sopenharmony_ci struct d3d12_shader_selector *sel = d3d12_last_vertex_stage(ctx); 981bf215546Sopenharmony_ci if (sel) { 982bf215546Sopenharmony_ci ctx->gfx_pipeline_state.so_info = sel->so_info; 983bf215546Sopenharmony_ci } else { 984bf215546Sopenharmony_ci memset(&ctx->gfx_pipeline_state.so_info, 0, sizeof(sel->so_info)); 985bf215546Sopenharmony_ci } 986bf215546Sopenharmony_ci } 987bf215546Sopenharmony_ci if (!validate_stream_output_targets(ctx)) { 988bf215546Sopenharmony_ci debug_printf("validate_stream_output_targets() failed\n"); 989bf215546Sopenharmony_ci return; 990bf215546Sopenharmony_ci } 991bf215546Sopenharmony_ci 992bf215546Sopenharmony_ci D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ib_strip_cut_value = 993bf215546Sopenharmony_ci D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; 994bf215546Sopenharmony_ci if (dinfo->index_size > 0) { 995bf215546Sopenharmony_ci assert(dinfo->index_size != 1); 996bf215546Sopenharmony_ci 997bf215546Sopenharmony_ci if (dinfo->has_user_indices) { 998bf215546Sopenharmony_ci if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer, 999bf215546Sopenharmony_ci &index_offset, 4)) { 1000bf215546Sopenharmony_ci debug_printf("util_upload_index_buffer() failed\n"); 1001bf215546Sopenharmony_ci return; 1002bf215546Sopenharmony_ci } 1003bf215546Sopenharmony_ci } else { 1004bf215546Sopenharmony_ci index_buffer = dinfo->index.resource; 1005bf215546Sopenharmony_ci } 1006bf215546Sopenharmony_ci 1007bf215546Sopenharmony_ci if (dinfo->primitive_restart) { 1008bf215546Sopenharmony_ci assert(dinfo->restart_index == 0xffff || 1009bf215546Sopenharmony_ci dinfo->restart_index == 0xffffffff); 1010bf215546Sopenharmony_ci ib_strip_cut_value = dinfo->restart_index == 0xffff ? 1011bf215546Sopenharmony_ci D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF : 1012bf215546Sopenharmony_ci D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF; 1013bf215546Sopenharmony_ci } 1014bf215546Sopenharmony_ci } 1015bf215546Sopenharmony_ci 1016bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.ib_strip_cut_value != ib_strip_cut_value) { 1017bf215546Sopenharmony_ci ctx->gfx_pipeline_state.ib_strip_cut_value = ib_strip_cut_value; 1018bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_STRIP_CUT_VALUE; 1019bf215546Sopenharmony_ci } 1020bf215546Sopenharmony_ci 1021bf215546Sopenharmony_ci if (!ctx->gfx_pipeline_state.root_signature || ctx->state_dirty & D3D12_DIRTY_SHADER) { 1022bf215546Sopenharmony_ci ID3D12RootSignature *root_signature = d3d12_get_root_signature(ctx, false); 1023bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.root_signature != root_signature) { 1024bf215546Sopenharmony_ci ctx->gfx_pipeline_state.root_signature = root_signature; 1025bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_ROOT_SIGNATURE; 1026bf215546Sopenharmony_ci for (int i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) 1027bf215546Sopenharmony_ci ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_ALL; 1028bf215546Sopenharmony_ci } 1029bf215546Sopenharmony_ci } 1030bf215546Sopenharmony_ci 1031bf215546Sopenharmony_ci if (!ctx->current_gfx_pso || ctx->state_dirty & D3D12_DIRTY_GFX_PSO) { 1032bf215546Sopenharmony_ci ctx->current_gfx_pso = d3d12_get_gfx_pipeline_state(ctx); 1033bf215546Sopenharmony_ci assert(ctx->current_gfx_pso); 1034bf215546Sopenharmony_ci } 1035bf215546Sopenharmony_ci 1036bf215546Sopenharmony_ci ctx->cmdlist_dirty |= ctx->state_dirty; 1037bf215546Sopenharmony_ci 1038bf215546Sopenharmony_ci if (!check_descriptors_left(ctx, false)) 1039bf215546Sopenharmony_ci d3d12_flush_cmdlist(ctx); 1040bf215546Sopenharmony_ci batch = d3d12_current_batch(ctx); 1041bf215546Sopenharmony_ci 1042bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_ROOT_SIGNATURE) { 1043bf215546Sopenharmony_ci d3d12_batch_reference_object(batch, ctx->gfx_pipeline_state.root_signature); 1044bf215546Sopenharmony_ci ctx->cmdlist->SetGraphicsRootSignature(ctx->gfx_pipeline_state.root_signature); 1045bf215546Sopenharmony_ci } 1046bf215546Sopenharmony_ci 1047bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_GFX_PSO) { 1048bf215546Sopenharmony_ci assert(ctx->current_gfx_pso); 1049bf215546Sopenharmony_ci d3d12_batch_reference_object(batch, ctx->current_gfx_pso); 1050bf215546Sopenharmony_ci ctx->cmdlist->SetPipelineState(ctx->current_gfx_pso); 1051bf215546Sopenharmony_ci } 1052bf215546Sopenharmony_ci 1053bf215546Sopenharmony_ci D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES]; 1054bf215546Sopenharmony_ci int root_desc_indices[MAX_DESCRIPTOR_TABLES]; 1055bf215546Sopenharmony_ci unsigned num_root_descriptors = update_graphics_root_parameters(ctx, dinfo, drawid_offset, &draws[0], 1056bf215546Sopenharmony_ci root_desc_tables, root_desc_indices, &cmd_sig_key); 1057bf215546Sopenharmony_ci 1058bf215546Sopenharmony_ci bool need_zero_one_depth_range = d3d12_need_zero_one_depth_range(ctx); 1059bf215546Sopenharmony_ci if (need_zero_one_depth_range != ctx->need_zero_one_depth_range) { 1060bf215546Sopenharmony_ci ctx->cmdlist_dirty |= D3D12_DIRTY_VIEWPORT; 1061bf215546Sopenharmony_ci ctx->need_zero_one_depth_range = need_zero_one_depth_range; 1062bf215546Sopenharmony_ci } 1063bf215546Sopenharmony_ci 1064bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_VIEWPORT) { 1065bf215546Sopenharmony_ci D3D12_VIEWPORT viewports[PIPE_MAX_VIEWPORTS]; 1066bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->num_viewports; ++i) { 1067bf215546Sopenharmony_ci viewports[i] = ctx->viewports[i]; 1068bf215546Sopenharmony_ci if (ctx->need_zero_one_depth_range) { 1069bf215546Sopenharmony_ci viewports[i].MinDepth = 0.0f; 1070bf215546Sopenharmony_ci viewports[i].MaxDepth = 1.0f; 1071bf215546Sopenharmony_ci } 1072bf215546Sopenharmony_ci if (ctx->fb.nr_cbufs == 0 && !ctx->fb.zsbuf) { 1073bf215546Sopenharmony_ci viewports[i].TopLeftX = MAX2(0.0f, viewports[i].TopLeftX); 1074bf215546Sopenharmony_ci viewports[i].TopLeftY = MAX2(0.0f, viewports[i].TopLeftY); 1075bf215546Sopenharmony_ci viewports[i].Width = MIN2(ctx->fb.width, viewports[i].Width); 1076bf215546Sopenharmony_ci viewports[i].Height = MIN2(ctx->fb.height, viewports[i].Height); 1077bf215546Sopenharmony_ci } 1078bf215546Sopenharmony_ci } 1079bf215546Sopenharmony_ci ctx->cmdlist->RSSetViewports(ctx->num_viewports, viewports); 1080bf215546Sopenharmony_ci } 1081bf215546Sopenharmony_ci 1082bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_SCISSOR) { 1083bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.rast->base.scissor && ctx->num_viewports > 0) 1084bf215546Sopenharmony_ci ctx->cmdlist->RSSetScissorRects(ctx->num_viewports, ctx->scissors); 1085bf215546Sopenharmony_ci else 1086bf215546Sopenharmony_ci ctx->cmdlist->RSSetScissorRects(PIPE_MAX_VIEWPORTS, MAX_SCISSOR_ARRAY); 1087bf215546Sopenharmony_ci } 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_BLEND_COLOR) { 1090bf215546Sopenharmony_ci unsigned blend_factor_flags = ctx->gfx_pipeline_state.blend->blend_factor_flags; 1091bf215546Sopenharmony_ci if (blend_factor_flags & (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ANY)) { 1092bf215546Sopenharmony_ci ctx->cmdlist->OMSetBlendFactor(ctx->blend_factor); 1093bf215546Sopenharmony_ci } else if (blend_factor_flags & D3D12_BLEND_FACTOR_ALPHA) { 1094bf215546Sopenharmony_ci float alpha_const[4] = { ctx->blend_factor[3], ctx->blend_factor[3], 1095bf215546Sopenharmony_ci ctx->blend_factor[3], ctx->blend_factor[3] }; 1096bf215546Sopenharmony_ci ctx->cmdlist->OMSetBlendFactor(alpha_const); 1097bf215546Sopenharmony_ci } 1098bf215546Sopenharmony_ci } 1099bf215546Sopenharmony_ci 1100bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_STENCIL_REF) 1101bf215546Sopenharmony_ci ctx->cmdlist->OMSetStencilRef(ctx->stencil_ref.ref_value[0]); 1102bf215546Sopenharmony_ci 1103bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_PRIM_MODE) 1104bf215546Sopenharmony_ci ctx->cmdlist->IASetPrimitiveTopology(topology((enum pipe_prim_type)dinfo->mode, ctx->patch_vertices)); 1105bf215546Sopenharmony_ci 1106bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->num_vbs; ++i) { 1107bf215546Sopenharmony_ci if (ctx->vbs[i].buffer.resource) { 1108bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(ctx->vbs[i].buffer.resource); 1109bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 1110bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS) 1111bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, res, false); 1112bf215546Sopenharmony_ci } 1113bf215546Sopenharmony_ci } 1114bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS) 1115bf215546Sopenharmony_ci ctx->cmdlist->IASetVertexBuffers(0, ctx->num_vbs, ctx->vbvs); 1116bf215546Sopenharmony_ci 1117bf215546Sopenharmony_ci if (index_buffer) { 1118bf215546Sopenharmony_ci D3D12_INDEX_BUFFER_VIEW ibv; 1119bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(index_buffer); 1120bf215546Sopenharmony_ci ibv.BufferLocation = d3d12_resource_gpu_virtual_address(res) + index_offset; 1121bf215546Sopenharmony_ci ibv.SizeInBytes = res->base.b.width0 - index_offset; 1122bf215546Sopenharmony_ci ibv.Format = ib_format(dinfo->index_size); 1123bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_INDEX_BUFFER, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 1124bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_INDEX_BUFFER || 1125bf215546Sopenharmony_ci memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) { 1126bf215546Sopenharmony_ci ctx->ibv = ibv; 1127bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, res, false); 1128bf215546Sopenharmony_ci ctx->cmdlist->IASetIndexBuffer(&ibv); 1129bf215546Sopenharmony_ci } 1130bf215546Sopenharmony_ci 1131bf215546Sopenharmony_ci if (dinfo->has_user_indices) 1132bf215546Sopenharmony_ci pipe_resource_reference(&index_buffer, NULL); 1133bf215546Sopenharmony_ci } 1134bf215546Sopenharmony_ci 1135bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_FRAMEBUFFER) { 1136bf215546Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE render_targets[PIPE_MAX_COLOR_BUFS] = {}; 1137bf215546Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE *depth_desc = NULL, tmp_desc; 1138bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 1139bf215546Sopenharmony_ci if (ctx->fb.cbufs[i]) { 1140bf215546Sopenharmony_ci struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]); 1141bf215546Sopenharmony_ci render_targets[i] = d3d12_surface_get_handle(surface, conversion_modes[i]); 1142bf215546Sopenharmony_ci d3d12_batch_reference_surface_texture(batch, surface); 1143bf215546Sopenharmony_ci } else 1144bf215546Sopenharmony_ci render_targets[i] = screen->null_rtv.cpu_handle; 1145bf215546Sopenharmony_ci } 1146bf215546Sopenharmony_ci if (ctx->fb.zsbuf) { 1147bf215546Sopenharmony_ci struct d3d12_surface *surface = d3d12_surface(ctx->fb.zsbuf); 1148bf215546Sopenharmony_ci tmp_desc = surface->desc_handle.cpu_handle; 1149bf215546Sopenharmony_ci d3d12_batch_reference_surface_texture(batch, surface); 1150bf215546Sopenharmony_ci depth_desc = &tmp_desc; 1151bf215546Sopenharmony_ci } 1152bf215546Sopenharmony_ci ctx->cmdlist->OMSetRenderTargets(ctx->fb.nr_cbufs, render_targets, FALSE, depth_desc); 1153bf215546Sopenharmony_ci } 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_ci struct pipe_stream_output_target **so_targets = ctx->fake_so_buffer_factor ? ctx->fake_so_targets 1156bf215546Sopenharmony_ci : ctx->so_targets; 1157bf215546Sopenharmony_ci D3D12_STREAM_OUTPUT_BUFFER_VIEW *so_buffer_views = ctx->fake_so_buffer_factor ? ctx->fake_so_buffer_views 1158bf215546Sopenharmony_ci : ctx->so_buffer_views; 1159bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 1160bf215546Sopenharmony_ci struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)so_targets[i]; 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_ci if (!target) 1163bf215546Sopenharmony_ci continue; 1164bf215546Sopenharmony_ci 1165bf215546Sopenharmony_ci struct d3d12_resource *so_buffer = d3d12_resource(target->base.buffer); 1166bf215546Sopenharmony_ci struct d3d12_resource *fill_buffer = d3d12_resource(target->fill_buffer); 1167bf215546Sopenharmony_ci 1168bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) { 1169bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, so_buffer, true); 1170bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, fill_buffer, true); 1171bf215546Sopenharmony_ci } 1172bf215546Sopenharmony_ci 1173bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 1174bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, fill_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 1175bf215546Sopenharmony_ci } 1176bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) 1177bf215546Sopenharmony_ci ctx->cmdlist->SOSetTargets(0, 4, so_buffer_views); 1178bf215546Sopenharmony_ci 1179bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 1180bf215546Sopenharmony_ci struct pipe_surface *psurf = ctx->fb.cbufs[i]; 1181bf215546Sopenharmony_ci if (!psurf) 1182bf215546Sopenharmony_ci continue; 1183bf215546Sopenharmony_ci 1184bf215546Sopenharmony_ci struct pipe_resource *pres = conversion_modes[i] == D3D12_SURFACE_CONVERSION_BGRA_UINT ? 1185bf215546Sopenharmony_ci d3d12_surface(psurf)->rgba_texture : psurf->texture; 1186bf215546Sopenharmony_ci transition_surface_subresources_state(ctx, psurf, pres, 1187bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_RENDER_TARGET); 1188bf215546Sopenharmony_ci } 1189bf215546Sopenharmony_ci if (ctx->fb.zsbuf) { 1190bf215546Sopenharmony_ci struct pipe_surface *psurf = ctx->fb.zsbuf; 1191bf215546Sopenharmony_ci transition_surface_subresources_state(ctx, psurf, psurf->texture, 1192bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_DEPTH_WRITE); 1193bf215546Sopenharmony_ci } 1194bf215546Sopenharmony_ci 1195bf215546Sopenharmony_ci ID3D12Resource *indirect_arg_buf = nullptr; 1196bf215546Sopenharmony_ci ID3D12Resource *indirect_count_buf = nullptr; 1197bf215546Sopenharmony_ci uint64_t indirect_arg_offset = 0, indirect_count_offset = 0; 1198bf215546Sopenharmony_ci if (indirect) { 1199bf215546Sopenharmony_ci if (indirect->buffer) { 1200bf215546Sopenharmony_ci struct d3d12_resource *indirect_buf = d3d12_resource(indirect->buffer); 1201bf215546Sopenharmony_ci uint64_t buf_offset = 0; 1202bf215546Sopenharmony_ci indirect_arg_buf = d3d12_resource_underlying(indirect_buf, &buf_offset); 1203bf215546Sopenharmony_ci indirect_arg_offset = indirect->offset + buf_offset; 1204bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, indirect_buf, 1205bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 1206bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, indirect_buf, false); 1207bf215546Sopenharmony_ci } 1208bf215546Sopenharmony_ci if (indirect->indirect_draw_count) { 1209bf215546Sopenharmony_ci struct d3d12_resource *count_buf = d3d12_resource(indirect->indirect_draw_count); 1210bf215546Sopenharmony_ci uint64_t count_offset = 0; 1211bf215546Sopenharmony_ci indirect_count_buf = d3d12_resource_underlying(count_buf, &count_offset); 1212bf215546Sopenharmony_ci indirect_count_offset = indirect->indirect_draw_count_offset + count_offset; 1213bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, count_buf, 1214bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 1215bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, count_buf, false); 1216bf215546Sopenharmony_ci } 1217bf215546Sopenharmony_ci assert(!indirect->count_from_stream_output); 1218bf215546Sopenharmony_ci } 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_ci d3d12_apply_resource_states(ctx, false); 1221bf215546Sopenharmony_ci 1222bf215546Sopenharmony_ci for (unsigned i = 0; i < num_root_descriptors; ++i) 1223bf215546Sopenharmony_ci ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]); 1224bf215546Sopenharmony_ci 1225bf215546Sopenharmony_ci if (indirect) { 1226bf215546Sopenharmony_ci unsigned draw_count = draw_auto ? 1 : indirect->draw_count; 1227bf215546Sopenharmony_ci ID3D12CommandSignature *cmd_sig = d3d12_get_cmd_signature(ctx, &cmd_sig_key); 1228bf215546Sopenharmony_ci ctx->cmdlist->ExecuteIndirect(cmd_sig, draw_count, indirect_arg_buf, 1229bf215546Sopenharmony_ci indirect_arg_offset, indirect_count_buf, indirect_count_offset); 1230bf215546Sopenharmony_ci } else { 1231bf215546Sopenharmony_ci if (dinfo->index_size > 0) 1232bf215546Sopenharmony_ci ctx->cmdlist->DrawIndexedInstanced(draws[0].count, dinfo->instance_count, 1233bf215546Sopenharmony_ci draws[0].start, draws[0].index_bias, 1234bf215546Sopenharmony_ci dinfo->start_instance); 1235bf215546Sopenharmony_ci else 1236bf215546Sopenharmony_ci ctx->cmdlist->DrawInstanced(draws[0].count, dinfo->instance_count, 1237bf215546Sopenharmony_ci draws[0].start, dinfo->start_instance); 1238bf215546Sopenharmony_ci } 1239bf215546Sopenharmony_ci 1240bf215546Sopenharmony_ci ctx->state_dirty &= D3D12_DIRTY_COMPUTE_MASK; 1241bf215546Sopenharmony_ci batch->pending_memory_barrier = false; 1242bf215546Sopenharmony_ci 1243bf215546Sopenharmony_ci ctx->cmdlist_dirty &= D3D12_DIRTY_COMPUTE_MASK | 1244bf215546Sopenharmony_ci (index_buffer ? 0 : D3D12_DIRTY_INDEX_BUFFER); 1245bf215546Sopenharmony_ci 1246bf215546Sopenharmony_ci /* The next dispatch needs to reassert the compute PSO */ 1247bf215546Sopenharmony_ci ctx->cmdlist_dirty |= D3D12_DIRTY_COMPUTE_SHADER; 1248bf215546Sopenharmony_ci 1249bf215546Sopenharmony_ci for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) 1250bf215546Sopenharmony_ci ctx->shader_dirty[i] = 0; 1251bf215546Sopenharmony_ci 1252bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 1253bf215546Sopenharmony_ci if (ctx->fb.cbufs[i]) { 1254bf215546Sopenharmony_ci struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]); 1255bf215546Sopenharmony_ci d3d12_surface_update_post_draw(pctx, surface, conversion_modes[i]); 1256bf215546Sopenharmony_ci } 1257bf215546Sopenharmony_ci } 1258bf215546Sopenharmony_ci 1259bf215546Sopenharmony_ci pipe_resource_reference(&patched_indirect.buffer, NULL); 1260bf215546Sopenharmony_ci} 1261bf215546Sopenharmony_ci 1262bf215546Sopenharmony_cistatic bool 1263bf215546Sopenharmony_ciupdate_dispatch_indirect_with_sysvals(struct d3d12_context *ctx, 1264bf215546Sopenharmony_ci struct pipe_resource **indirect_inout, 1265bf215546Sopenharmony_ci unsigned *indirect_offset_inout, 1266bf215546Sopenharmony_ci struct pipe_resource **indirect_out) 1267bf215546Sopenharmony_ci{ 1268bf215546Sopenharmony_ci if (*indirect_inout == nullptr || 1269bf215546Sopenharmony_ci ctx->compute_state == nullptr) 1270bf215546Sopenharmony_ci return false; 1271bf215546Sopenharmony_ci 1272bf215546Sopenharmony_ci if (!BITSET_TEST(ctx->compute_state->current->nir->info.system_values_read, SYSTEM_VALUE_NUM_WORKGROUPS)) 1273bf215546Sopenharmony_ci return false; 1274bf215546Sopenharmony_ci 1275bf215546Sopenharmony_ci if (ctx->current_predication) 1276bf215546Sopenharmony_ci ctx->cmdlist->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); 1277bf215546Sopenharmony_ci 1278bf215546Sopenharmony_ci auto indirect_in = *indirect_inout; 1279bf215546Sopenharmony_ci 1280bf215546Sopenharmony_ci /* 6 uints: 2 copies of the indirect arg buffer */ 1281bf215546Sopenharmony_ci pipe_resource output_buf_templ = {}; 1282bf215546Sopenharmony_ci output_buf_templ.target = PIPE_BUFFER; 1283bf215546Sopenharmony_ci output_buf_templ.width0 = sizeof(uint32_t) * 6; 1284bf215546Sopenharmony_ci output_buf_templ.height0 = output_buf_templ.depth0 = output_buf_templ.array_size = 1285bf215546Sopenharmony_ci output_buf_templ.last_level = 1; 1286bf215546Sopenharmony_ci output_buf_templ.usage = PIPE_USAGE_DEFAULT; 1287bf215546Sopenharmony_ci *indirect_out = ctx->base.screen->resource_create(ctx->base.screen, &output_buf_templ); 1288bf215546Sopenharmony_ci 1289bf215546Sopenharmony_ci struct pipe_box src_box = { (int)*indirect_offset_inout, 0, 0, sizeof(uint32_t) * 3, 1, 1 }; 1290bf215546Sopenharmony_ci ctx->base.resource_copy_region(&ctx->base, *indirect_out, 0, 0, 0, 0, indirect_in, 0, &src_box); 1291bf215546Sopenharmony_ci ctx->base.resource_copy_region(&ctx->base, *indirect_out, 0, src_box.width, 0, 0, indirect_in, 0, &src_box); 1292bf215546Sopenharmony_ci 1293bf215546Sopenharmony_ci if (ctx->current_predication) 1294bf215546Sopenharmony_ci d3d12_enable_predication(ctx); 1295bf215546Sopenharmony_ci 1296bf215546Sopenharmony_ci *indirect_inout = *indirect_out; 1297bf215546Sopenharmony_ci *indirect_offset_inout = 0; 1298bf215546Sopenharmony_ci return true; 1299bf215546Sopenharmony_ci} 1300bf215546Sopenharmony_ci 1301bf215546Sopenharmony_civoid 1302bf215546Sopenharmony_cid3d12_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info) 1303bf215546Sopenharmony_ci{ 1304bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1305bf215546Sopenharmony_ci struct d3d12_batch *batch; 1306bf215546Sopenharmony_ci struct pipe_resource *patched_indirect = nullptr; 1307bf215546Sopenharmony_ci 1308bf215546Sopenharmony_ci struct d3d12_cmd_signature_key cmd_sig_key; 1309bf215546Sopenharmony_ci memset(&cmd_sig_key, 0, sizeof(cmd_sig_key)); 1310bf215546Sopenharmony_ci cmd_sig_key.compute = 1; 1311bf215546Sopenharmony_ci cmd_sig_key.multi_draw_stride = sizeof(D3D12_DISPATCH_ARGUMENTS); 1312bf215546Sopenharmony_ci 1313bf215546Sopenharmony_ci struct pipe_resource *indirect = info->indirect; 1314bf215546Sopenharmony_ci unsigned indirect_offset = info->indirect_offset; 1315bf215546Sopenharmony_ci if (indirect && update_dispatch_indirect_with_sysvals(ctx, &indirect, &indirect_offset, &patched_indirect)) 1316bf215546Sopenharmony_ci cmd_sig_key.multi_draw_stride = sizeof(D3D12_DISPATCH_ARGUMENTS) * 2; 1317bf215546Sopenharmony_ci 1318bf215546Sopenharmony_ci d3d12_select_compute_shader_variants(ctx, info); 1319bf215546Sopenharmony_ci d3d12_validate_queries(ctx); 1320bf215546Sopenharmony_ci struct d3d12_shader *shader = ctx->compute_state ? ctx->compute_state->current : NULL; 1321bf215546Sopenharmony_ci if (ctx->compute_pipeline_state.stage != shader) { 1322bf215546Sopenharmony_ci ctx->compute_pipeline_state.stage = shader; 1323bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_COMPUTE_SHADER; 1324bf215546Sopenharmony_ci } 1325bf215546Sopenharmony_ci 1326bf215546Sopenharmony_ci if (!ctx->compute_pipeline_state.root_signature || ctx->state_dirty & D3D12_DIRTY_COMPUTE_SHADER) { 1327bf215546Sopenharmony_ci ID3D12RootSignature *root_signature = d3d12_get_root_signature(ctx, true); 1328bf215546Sopenharmony_ci if (ctx->compute_pipeline_state.root_signature != root_signature) { 1329bf215546Sopenharmony_ci ctx->compute_pipeline_state.root_signature = root_signature; 1330bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_COMPUTE_ROOT_SIGNATURE; 1331bf215546Sopenharmony_ci ctx->shader_dirty[PIPE_SHADER_COMPUTE] |= D3D12_SHADER_DIRTY_ALL; 1332bf215546Sopenharmony_ci } 1333bf215546Sopenharmony_ci } 1334bf215546Sopenharmony_ci 1335bf215546Sopenharmony_ci if (!ctx->current_compute_pso || ctx->state_dirty & D3D12_DIRTY_COMPUTE_PSO) { 1336bf215546Sopenharmony_ci ctx->current_compute_pso = d3d12_get_compute_pipeline_state(ctx); 1337bf215546Sopenharmony_ci assert(ctx->current_compute_pso); 1338bf215546Sopenharmony_ci } 1339bf215546Sopenharmony_ci 1340bf215546Sopenharmony_ci ctx->cmdlist_dirty |= ctx->state_dirty; 1341bf215546Sopenharmony_ci 1342bf215546Sopenharmony_ci if (!check_descriptors_left(ctx, true)) 1343bf215546Sopenharmony_ci d3d12_flush_cmdlist(ctx); 1344bf215546Sopenharmony_ci batch = d3d12_current_batch(ctx); 1345bf215546Sopenharmony_ci 1346bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_COMPUTE_ROOT_SIGNATURE) { 1347bf215546Sopenharmony_ci d3d12_batch_reference_object(batch, ctx->compute_pipeline_state.root_signature); 1348bf215546Sopenharmony_ci ctx->cmdlist->SetComputeRootSignature(ctx->compute_pipeline_state.root_signature); 1349bf215546Sopenharmony_ci } 1350bf215546Sopenharmony_ci 1351bf215546Sopenharmony_ci if (ctx->cmdlist_dirty & D3D12_DIRTY_COMPUTE_PSO) { 1352bf215546Sopenharmony_ci assert(ctx->current_compute_pso); 1353bf215546Sopenharmony_ci d3d12_batch_reference_object(batch, ctx->current_compute_pso); 1354bf215546Sopenharmony_ci ctx->cmdlist->SetPipelineState(ctx->current_compute_pso); 1355bf215546Sopenharmony_ci } 1356bf215546Sopenharmony_ci 1357bf215546Sopenharmony_ci D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES]; 1358bf215546Sopenharmony_ci int root_desc_indices[MAX_DESCRIPTOR_TABLES]; 1359bf215546Sopenharmony_ci unsigned num_root_descriptors = update_compute_root_parameters(ctx, info, root_desc_tables, root_desc_indices, &cmd_sig_key); 1360bf215546Sopenharmony_ci 1361bf215546Sopenharmony_ci ID3D12Resource *indirect_arg_buf = nullptr; 1362bf215546Sopenharmony_ci uint64_t indirect_arg_offset = 0; 1363bf215546Sopenharmony_ci if (indirect) { 1364bf215546Sopenharmony_ci struct d3d12_resource *indirect_buf = d3d12_resource(indirect); 1365bf215546Sopenharmony_ci uint64_t buf_offset = 0; 1366bf215546Sopenharmony_ci indirect_arg_buf = d3d12_resource_underlying(indirect_buf, &buf_offset); 1367bf215546Sopenharmony_ci indirect_arg_offset = indirect_offset + buf_offset; 1368bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, indirect_buf, 1369bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT, D3D12_TRANSITION_FLAG_ACCUMULATE_STATE); 1370bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, indirect_buf, false); 1371bf215546Sopenharmony_ci } 1372bf215546Sopenharmony_ci 1373bf215546Sopenharmony_ci d3d12_apply_resource_states(ctx, ctx->compute_state->is_variant); 1374bf215546Sopenharmony_ci 1375bf215546Sopenharmony_ci for (unsigned i = 0; i < num_root_descriptors; ++i) 1376bf215546Sopenharmony_ci ctx->cmdlist->SetComputeRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]); 1377bf215546Sopenharmony_ci 1378bf215546Sopenharmony_ci if (indirect) { 1379bf215546Sopenharmony_ci ID3D12CommandSignature *cmd_sig = d3d12_get_cmd_signature(ctx, &cmd_sig_key); 1380bf215546Sopenharmony_ci ctx->cmdlist->ExecuteIndirect(cmd_sig, 1, indirect_arg_buf, indirect_arg_offset, nullptr, 0); 1381bf215546Sopenharmony_ci } else { 1382bf215546Sopenharmony_ci ctx->cmdlist->Dispatch(info->grid[0], info->grid[1], info->grid[2]); 1383bf215546Sopenharmony_ci } 1384bf215546Sopenharmony_ci 1385bf215546Sopenharmony_ci ctx->state_dirty &= D3D12_DIRTY_GFX_MASK; 1386bf215546Sopenharmony_ci ctx->cmdlist_dirty &= D3D12_DIRTY_GFX_MASK; 1387bf215546Sopenharmony_ci 1388bf215546Sopenharmony_ci /* The next draw needs to reassert the graphics PSO */ 1389bf215546Sopenharmony_ci ctx->cmdlist_dirty |= D3D12_DIRTY_SHADER; 1390bf215546Sopenharmony_ci batch->pending_memory_barrier = false; 1391bf215546Sopenharmony_ci 1392bf215546Sopenharmony_ci ctx->shader_dirty[PIPE_SHADER_COMPUTE] = 0; 1393bf215546Sopenharmony_ci pipe_resource_reference(&patched_indirect, nullptr); 1394bf215546Sopenharmony_ci} 1395