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_blit.h" 25bf215546Sopenharmony_ci#include "d3d12_cmd_signature.h" 26bf215546Sopenharmony_ci#include "d3d12_context.h" 27bf215546Sopenharmony_ci#include "d3d12_compiler.h" 28bf215546Sopenharmony_ci#include "d3d12_compute_transforms.h" 29bf215546Sopenharmony_ci#include "d3d12_debug.h" 30bf215546Sopenharmony_ci#include "d3d12_fence.h" 31bf215546Sopenharmony_ci#include "d3d12_format.h" 32bf215546Sopenharmony_ci#include "d3d12_query.h" 33bf215546Sopenharmony_ci#include "d3d12_resource.h" 34bf215546Sopenharmony_ci#include "d3d12_root_signature.h" 35bf215546Sopenharmony_ci#include "d3d12_screen.h" 36bf215546Sopenharmony_ci#include "d3d12_surface.h" 37bf215546Sopenharmony_ci#ifdef HAVE_GALLIUM_D3D12_VIDEO 38bf215546Sopenharmony_ci#include "d3d12_video_dec.h" 39bf215546Sopenharmony_ci#include "d3d12_video_enc.h" 40bf215546Sopenharmony_ci#include "d3d12_video_proc.h" 41bf215546Sopenharmony_ci#include "d3d12_video_buffer.h" 42bf215546Sopenharmony_ci#endif 43bf215546Sopenharmony_ci#include "util/u_atomic.h" 44bf215546Sopenharmony_ci#include "util/u_blitter.h" 45bf215546Sopenharmony_ci#include "util/u_dual_blend.h" 46bf215546Sopenharmony_ci#include "util/u_framebuffer.h" 47bf215546Sopenharmony_ci#include "util/u_helpers.h" 48bf215546Sopenharmony_ci#include "util/u_inlines.h" 49bf215546Sopenharmony_ci#include "util/u_memory.h" 50bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 51bf215546Sopenharmony_ci#include "util/u_pstipple.h" 52bf215546Sopenharmony_ci#include "util/u_dl.h" 53bf215546Sopenharmony_ci#include "nir_to_dxil.h" 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci#include <dxguids/dxguids.h> 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ciextern "C" { 58bf215546Sopenharmony_ci#include "indices/u_primconvert.h" 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci#include <string.h> 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci#ifdef _WIN32 64bf215546Sopenharmony_ci#include "dxil_validator.h" 65bf215546Sopenharmony_ci#endif 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_cistatic void 68bf215546Sopenharmony_cid3d12_context_destroy(struct pipe_context *pctx) 69bf215546Sopenharmony_ci{ 70bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pctx->screen); 73bf215546Sopenharmony_ci mtx_lock(&screen->submit_mutex); 74bf215546Sopenharmony_ci list_del(&ctx->context_list_entry); 75bf215546Sopenharmony_ci mtx_unlock(&screen->submit_mutex); 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci#ifdef _WIN32 78bf215546Sopenharmony_ci if (ctx->dxil_validator) 79bf215546Sopenharmony_ci dxil_destroy_validator(ctx->dxil_validator); 80bf215546Sopenharmony_ci#endif 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci if (ctx->timestamp_query) 83bf215546Sopenharmony_ci pctx->destroy_query(pctx, ctx->timestamp_query); 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci util_unreference_framebuffer_state(&ctx->fb); 86bf215546Sopenharmony_ci util_blitter_destroy(ctx->blitter); 87bf215546Sopenharmony_ci d3d12_end_batch(ctx, d3d12_current_batch(ctx)); 88bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) 89bf215546Sopenharmony_ci d3d12_destroy_batch(ctx, &ctx->batches[i]); 90bf215546Sopenharmony_ci ctx->cmdlist->Release(); 91bf215546Sopenharmony_ci d3d12_descriptor_pool_free(ctx->sampler_pool); 92bf215546Sopenharmony_ci util_primconvert_destroy(ctx->primconvert); 93bf215546Sopenharmony_ci slab_destroy_child(&ctx->transfer_pool); 94bf215546Sopenharmony_ci slab_destroy_child(&ctx->transfer_pool_unsync); 95bf215546Sopenharmony_ci d3d12_gs_variant_cache_destroy(ctx); 96bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_cache_destroy(ctx); 97bf215546Sopenharmony_ci d3d12_compute_pipeline_state_cache_destroy(ctx); 98bf215546Sopenharmony_ci d3d12_root_signature_cache_destroy(ctx); 99bf215546Sopenharmony_ci d3d12_cmd_signature_cache_destroy(ctx); 100bf215546Sopenharmony_ci d3d12_compute_transform_cache_destroy(ctx); 101bf215546Sopenharmony_ci d3d12_context_state_table_destroy(ctx); 102bf215546Sopenharmony_ci pipe_resource_reference(&ctx->pstipple.texture, nullptr); 103bf215546Sopenharmony_ci pipe_sampler_view_reference(&ctx->pstipple.sampler_view, nullptr); 104bf215546Sopenharmony_ci util_dynarray_fini(&ctx->recently_destroyed_bos); 105bf215546Sopenharmony_ci FREE(ctx->pstipple.sampler_cso); 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci u_suballocator_destroy(&ctx->query_allocator); 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci if (pctx->stream_uploader) 110bf215546Sopenharmony_ci u_upload_destroy(pctx->stream_uploader); 111bf215546Sopenharmony_ci if (pctx->const_uploader) 112bf215546Sopenharmony_ci u_upload_destroy(pctx->const_uploader); 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci FREE(ctx); 115bf215546Sopenharmony_ci} 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_cistatic void * 118bf215546Sopenharmony_cid3d12_create_vertex_elements_state(struct pipe_context *pctx, 119bf215546Sopenharmony_ci unsigned num_elements, 120bf215546Sopenharmony_ci const struct pipe_vertex_element *elements) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci struct d3d12_vertex_elements_state *cso = CALLOC_STRUCT(d3d12_vertex_elements_state); 123bf215546Sopenharmony_ci if (!cso) 124bf215546Sopenharmony_ci return NULL; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci for (unsigned i = 0; i < num_elements; ++i) { 127bf215546Sopenharmony_ci cso->elements[i].SemanticName = "TEXCOORD"; 128bf215546Sopenharmony_ci cso->elements[i].SemanticIndex = i; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci enum pipe_format format_helper = 131bf215546Sopenharmony_ci d3d12_emulated_vtx_format((enum pipe_format)elements[i].src_format); 132bf215546Sopenharmony_ci bool needs_emulation = format_helper != elements[i].src_format; 133bf215546Sopenharmony_ci cso->needs_format_emulation |= needs_emulation; 134bf215546Sopenharmony_ci cso->format_conversion[i] = 135bf215546Sopenharmony_ci needs_emulation ? (enum pipe_format)elements[i].src_format : PIPE_FORMAT_NONE; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci cso->elements[i].Format = d3d12_get_format(format_helper); 138bf215546Sopenharmony_ci assert(cso->elements[i].Format != DXGI_FORMAT_UNKNOWN); 139bf215546Sopenharmony_ci cso->elements[i].InputSlot = elements[i].vertex_buffer_index; 140bf215546Sopenharmony_ci cso->elements[i].AlignedByteOffset = elements[i].src_offset; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci if (elements[i].instance_divisor) { 143bf215546Sopenharmony_ci cso->elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA; 144bf215546Sopenharmony_ci cso->elements[i].InstanceDataStepRate = elements[i].instance_divisor; 145bf215546Sopenharmony_ci } else { 146bf215546Sopenharmony_ci cso->elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; 147bf215546Sopenharmony_ci cso->elements[i].InstanceDataStepRate = 0; 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci } 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci cso->num_elements = num_elements; 152bf215546Sopenharmony_ci return cso; 153bf215546Sopenharmony_ci} 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_cistatic void 156bf215546Sopenharmony_cid3d12_bind_vertex_elements_state(struct pipe_context *pctx, 157bf215546Sopenharmony_ci void *ve) 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 160bf215546Sopenharmony_ci ctx->gfx_pipeline_state.ves = (struct d3d12_vertex_elements_state *)ve; 161bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_VERTEX_ELEMENTS; 162bf215546Sopenharmony_ci} 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_cistatic void 165bf215546Sopenharmony_cid3d12_delete_vertex_elements_state(struct pipe_context *pctx, 166bf215546Sopenharmony_ci void *ve) 167bf215546Sopenharmony_ci{ 168bf215546Sopenharmony_ci FREE(ve); 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_cistatic D3D12_BLEND 172bf215546Sopenharmony_ciblend_factor_rgb(enum pipe_blendfactor factor) 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci switch (factor) { 175bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_ZERO: return D3D12_BLEND_ZERO; 176bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_ONE: return D3D12_BLEND_ONE; 177bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC_COLOR: return D3D12_BLEND_SRC_COLOR; 178bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA; 179bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA; 180bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_DST_COLOR: return D3D12_BLEND_DEST_COLOR; 181bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT; 182bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_COLOR: return D3D12_BLEND_BLEND_FACTOR; 183bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC1_COLOR: return D3D12_BLEND_SRC1_COLOR; 184bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA; 185bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC_COLOR: return D3D12_BLEND_INV_SRC_COLOR; 186bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA; 187bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA; 188bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_DST_COLOR: return D3D12_BLEND_INV_DEST_COLOR; 189bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_COLOR: return D3D12_BLEND_INV_BLEND_FACTOR; 190bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return D3D12_BLEND_INV_SRC1_COLOR; 191bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA; 192bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_ALPHA: return D3D12_BLEND_BLEND_FACTOR; /* Doesn't exist in D3D12 */ 193bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return D3D12_BLEND_INV_BLEND_FACTOR; /* Doesn't exist in D3D12 */ 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci unreachable("unexpected blend factor"); 196bf215546Sopenharmony_ci} 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_cistatic D3D12_BLEND 199bf215546Sopenharmony_ciblend_factor_alpha(enum pipe_blendfactor factor) 200bf215546Sopenharmony_ci{ 201bf215546Sopenharmony_ci switch (factor) { 202bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_ZERO: return D3D12_BLEND_ZERO; 203bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_ONE: return D3D12_BLEND_ONE; 204bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC_COLOR: 205bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA; 206bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_DST_COLOR: 207bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA; 208bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT; 209bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_COLOR: 210bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_ALPHA: return D3D12_BLEND_BLEND_FACTOR; 211bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC1_COLOR: 212bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA; 213bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC_COLOR: 214bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA; 215bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_DST_COLOR: 216bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA; 217bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 218bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA; 219bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_COLOR: 220bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return D3D12_BLEND_INV_BLEND_FACTOR; 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci unreachable("unexpected blend factor"); 223bf215546Sopenharmony_ci} 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_cistatic unsigned 226bf215546Sopenharmony_cineed_blend_factor_rgb(enum pipe_blendfactor factor) 227bf215546Sopenharmony_ci{ 228bf215546Sopenharmony_ci switch (factor) { 229bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_COLOR: 230bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_COLOR: 231bf215546Sopenharmony_ci return D3D12_BLEND_FACTOR_COLOR; 232bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_ALPHA: 233bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 234bf215546Sopenharmony_ci return D3D12_BLEND_FACTOR_ALPHA; 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci default: 237bf215546Sopenharmony_ci return D3D12_BLEND_FACTOR_NONE; 238bf215546Sopenharmony_ci } 239bf215546Sopenharmony_ci} 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_cistatic unsigned 242bf215546Sopenharmony_cineed_blend_factor_alpha(enum pipe_blendfactor factor) 243bf215546Sopenharmony_ci{ 244bf215546Sopenharmony_ci switch (factor) { 245bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_COLOR: 246bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_COLOR: 247bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_CONST_ALPHA: 248bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 249bf215546Sopenharmony_ci return D3D12_BLEND_FACTOR_ANY; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci default: 252bf215546Sopenharmony_ci return D3D12_BLEND_FACTOR_NONE; 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci} 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_cistatic D3D12_BLEND_OP 257bf215546Sopenharmony_ciblend_op(enum pipe_blend_func func) 258bf215546Sopenharmony_ci{ 259bf215546Sopenharmony_ci switch (func) { 260bf215546Sopenharmony_ci case PIPE_BLEND_ADD: return D3D12_BLEND_OP_ADD; 261bf215546Sopenharmony_ci case PIPE_BLEND_SUBTRACT: return D3D12_BLEND_OP_SUBTRACT; 262bf215546Sopenharmony_ci case PIPE_BLEND_REVERSE_SUBTRACT: return D3D12_BLEND_OP_REV_SUBTRACT; 263bf215546Sopenharmony_ci case PIPE_BLEND_MIN: return D3D12_BLEND_OP_MIN; 264bf215546Sopenharmony_ci case PIPE_BLEND_MAX: return D3D12_BLEND_OP_MAX; 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci unreachable("unexpected blend function"); 267bf215546Sopenharmony_ci} 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_cistatic D3D12_COMPARISON_FUNC 270bf215546Sopenharmony_cicompare_op(enum pipe_compare_func op) 271bf215546Sopenharmony_ci{ 272bf215546Sopenharmony_ci switch (op) { 273bf215546Sopenharmony_ci case PIPE_FUNC_NEVER: return D3D12_COMPARISON_FUNC_NEVER; 274bf215546Sopenharmony_ci case PIPE_FUNC_LESS: return D3D12_COMPARISON_FUNC_LESS; 275bf215546Sopenharmony_ci case PIPE_FUNC_EQUAL: return D3D12_COMPARISON_FUNC_EQUAL; 276bf215546Sopenharmony_ci case PIPE_FUNC_LEQUAL: return D3D12_COMPARISON_FUNC_LESS_EQUAL; 277bf215546Sopenharmony_ci case PIPE_FUNC_GREATER: return D3D12_COMPARISON_FUNC_GREATER; 278bf215546Sopenharmony_ci case PIPE_FUNC_NOTEQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL; 279bf215546Sopenharmony_ci case PIPE_FUNC_GEQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL; 280bf215546Sopenharmony_ci case PIPE_FUNC_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS; 281bf215546Sopenharmony_ci } 282bf215546Sopenharmony_ci unreachable("unexpected compare"); 283bf215546Sopenharmony_ci} 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_cistatic D3D12_LOGIC_OP 286bf215546Sopenharmony_cilogic_op(enum pipe_logicop func) 287bf215546Sopenharmony_ci{ 288bf215546Sopenharmony_ci switch (func) { 289bf215546Sopenharmony_ci case PIPE_LOGICOP_CLEAR: return D3D12_LOGIC_OP_CLEAR; 290bf215546Sopenharmony_ci case PIPE_LOGICOP_NOR: return D3D12_LOGIC_OP_NOR; 291bf215546Sopenharmony_ci case PIPE_LOGICOP_AND_INVERTED: return D3D12_LOGIC_OP_AND_INVERTED; 292bf215546Sopenharmony_ci case PIPE_LOGICOP_COPY_INVERTED: return D3D12_LOGIC_OP_COPY_INVERTED; 293bf215546Sopenharmony_ci case PIPE_LOGICOP_AND_REVERSE: return D3D12_LOGIC_OP_AND_REVERSE; 294bf215546Sopenharmony_ci case PIPE_LOGICOP_INVERT: return D3D12_LOGIC_OP_INVERT; 295bf215546Sopenharmony_ci case PIPE_LOGICOP_XOR: return D3D12_LOGIC_OP_XOR; 296bf215546Sopenharmony_ci case PIPE_LOGICOP_NAND: return D3D12_LOGIC_OP_NAND; 297bf215546Sopenharmony_ci case PIPE_LOGICOP_AND: return D3D12_LOGIC_OP_AND; 298bf215546Sopenharmony_ci case PIPE_LOGICOP_EQUIV: return D3D12_LOGIC_OP_EQUIV; 299bf215546Sopenharmony_ci case PIPE_LOGICOP_NOOP: return D3D12_LOGIC_OP_NOOP; 300bf215546Sopenharmony_ci case PIPE_LOGICOP_OR_INVERTED: return D3D12_LOGIC_OP_OR_INVERTED; 301bf215546Sopenharmony_ci case PIPE_LOGICOP_COPY: return D3D12_LOGIC_OP_COPY; 302bf215546Sopenharmony_ci case PIPE_LOGICOP_OR_REVERSE: return D3D12_LOGIC_OP_OR_REVERSE; 303bf215546Sopenharmony_ci case PIPE_LOGICOP_OR: return D3D12_LOGIC_OP_OR; 304bf215546Sopenharmony_ci case PIPE_LOGICOP_SET: return D3D12_LOGIC_OP_SET; 305bf215546Sopenharmony_ci } 306bf215546Sopenharmony_ci unreachable("unexpected logicop function"); 307bf215546Sopenharmony_ci} 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_cistatic UINT8 310bf215546Sopenharmony_cicolor_write_mask(unsigned colormask) 311bf215546Sopenharmony_ci{ 312bf215546Sopenharmony_ci UINT8 mask = 0; 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci if (colormask & PIPE_MASK_R) 315bf215546Sopenharmony_ci mask |= D3D12_COLOR_WRITE_ENABLE_RED; 316bf215546Sopenharmony_ci if (colormask & PIPE_MASK_G) 317bf215546Sopenharmony_ci mask |= D3D12_COLOR_WRITE_ENABLE_GREEN; 318bf215546Sopenharmony_ci if (colormask & PIPE_MASK_B) 319bf215546Sopenharmony_ci mask |= D3D12_COLOR_WRITE_ENABLE_BLUE; 320bf215546Sopenharmony_ci if (colormask & PIPE_MASK_A) 321bf215546Sopenharmony_ci mask |= D3D12_COLOR_WRITE_ENABLE_ALPHA; 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci return mask; 324bf215546Sopenharmony_ci} 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_cistatic void * 327bf215546Sopenharmony_cid3d12_create_blend_state(struct pipe_context *pctx, 328bf215546Sopenharmony_ci const struct pipe_blend_state *blend_state) 329bf215546Sopenharmony_ci{ 330bf215546Sopenharmony_ci struct d3d12_blend_state *state = CALLOC_STRUCT(d3d12_blend_state); 331bf215546Sopenharmony_ci if (!state) 332bf215546Sopenharmony_ci return NULL; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci if (blend_state->logicop_enable) { 335bf215546Sopenharmony_ci state->desc.RenderTarget[0].LogicOpEnable = TRUE; 336bf215546Sopenharmony_ci state->desc.RenderTarget[0].LogicOp = logic_op((pipe_logicop) blend_state->logicop_func); 337bf215546Sopenharmony_ci } 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci /* TODO Dithering */ 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci state->desc.AlphaToCoverageEnable = blend_state->alpha_to_coverage; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci int num_targets = 1; 344bf215546Sopenharmony_ci if (blend_state->independent_blend_enable) { 345bf215546Sopenharmony_ci state->desc.IndependentBlendEnable = TRUE; 346bf215546Sopenharmony_ci num_targets = PIPE_MAX_COLOR_BUFS; 347bf215546Sopenharmony_ci } 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci for (int i = 0; i < num_targets; ++i) { 350bf215546Sopenharmony_ci const struct pipe_rt_blend_state *rt = blend_state->rt + i; 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci if (rt->blend_enable) { 353bf215546Sopenharmony_ci state->desc.RenderTarget[i].BlendEnable = TRUE; 354bf215546Sopenharmony_ci state->desc.RenderTarget[i].SrcBlend = blend_factor_rgb((pipe_blendfactor) rt->rgb_src_factor); 355bf215546Sopenharmony_ci state->desc.RenderTarget[i].DestBlend = blend_factor_rgb((pipe_blendfactor) rt->rgb_dst_factor); 356bf215546Sopenharmony_ci state->desc.RenderTarget[i].BlendOp = blend_op((pipe_blend_func) rt->rgb_func); 357bf215546Sopenharmony_ci state->desc.RenderTarget[i].SrcBlendAlpha = blend_factor_alpha((pipe_blendfactor) rt->alpha_src_factor); 358bf215546Sopenharmony_ci state->desc.RenderTarget[i].DestBlendAlpha = blend_factor_alpha((pipe_blendfactor) rt->alpha_dst_factor); 359bf215546Sopenharmony_ci state->desc.RenderTarget[i].BlendOpAlpha = blend_op((pipe_blend_func) rt->alpha_func); 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci state->blend_factor_flags |= need_blend_factor_rgb((pipe_blendfactor) rt->rgb_src_factor); 362bf215546Sopenharmony_ci state->blend_factor_flags |= need_blend_factor_rgb((pipe_blendfactor) rt->rgb_dst_factor); 363bf215546Sopenharmony_ci state->blend_factor_flags |= need_blend_factor_alpha((pipe_blendfactor) rt->alpha_src_factor); 364bf215546Sopenharmony_ci state->blend_factor_flags |= need_blend_factor_alpha((pipe_blendfactor) rt->alpha_dst_factor); 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci if (state->blend_factor_flags == (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ALPHA) && 367bf215546Sopenharmony_ci (d3d12_debug & D3D12_DEBUG_VERBOSE)) { 368bf215546Sopenharmony_ci /* We can't set a blend factor for both constant color and constant alpha */ 369bf215546Sopenharmony_ci debug_printf("D3D12: unsupported blend factors combination (const color and const alpha)\n"); 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci if (util_blend_state_is_dual(blend_state, i)) 373bf215546Sopenharmony_ci state->is_dual_src = true; 374bf215546Sopenharmony_ci } 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci state->desc.RenderTarget[i].RenderTargetWriteMask = color_write_mask(rt->colormask); 377bf215546Sopenharmony_ci } 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci return state; 380bf215546Sopenharmony_ci} 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_cistatic void 383bf215546Sopenharmony_cid3d12_bind_blend_state(struct pipe_context *pctx, void *blend_state) 384bf215546Sopenharmony_ci{ 385bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 386bf215546Sopenharmony_ci struct d3d12_blend_state *new_state = (struct d3d12_blend_state *) blend_state; 387bf215546Sopenharmony_ci struct d3d12_blend_state *old_state = ctx->gfx_pipeline_state.blend; 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci ctx->gfx_pipeline_state.blend = new_state; 390bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_BLEND; 391bf215546Sopenharmony_ci if (new_state == NULL || old_state == NULL || 392bf215546Sopenharmony_ci new_state->blend_factor_flags != old_state->blend_factor_flags) 393bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_BLEND_COLOR; 394bf215546Sopenharmony_ci} 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_cistatic void 397bf215546Sopenharmony_cid3d12_delete_blend_state(struct pipe_context *pctx, void *blend_state) 398bf215546Sopenharmony_ci{ 399bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), blend_state); 400bf215546Sopenharmony_ci FREE(blend_state); 401bf215546Sopenharmony_ci} 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_cistatic D3D12_STENCIL_OP 404bf215546Sopenharmony_cistencil_op(enum pipe_stencil_op op) 405bf215546Sopenharmony_ci{ 406bf215546Sopenharmony_ci switch (op) { 407bf215546Sopenharmony_ci case PIPE_STENCIL_OP_KEEP: return D3D12_STENCIL_OP_KEEP; 408bf215546Sopenharmony_ci case PIPE_STENCIL_OP_ZERO: return D3D12_STENCIL_OP_ZERO; 409bf215546Sopenharmony_ci case PIPE_STENCIL_OP_REPLACE: return D3D12_STENCIL_OP_REPLACE; 410bf215546Sopenharmony_ci case PIPE_STENCIL_OP_INCR: return D3D12_STENCIL_OP_INCR_SAT; 411bf215546Sopenharmony_ci case PIPE_STENCIL_OP_DECR: return D3D12_STENCIL_OP_DECR_SAT; 412bf215546Sopenharmony_ci case PIPE_STENCIL_OP_INCR_WRAP: return D3D12_STENCIL_OP_INCR; 413bf215546Sopenharmony_ci case PIPE_STENCIL_OP_DECR_WRAP: return D3D12_STENCIL_OP_DECR; 414bf215546Sopenharmony_ci case PIPE_STENCIL_OP_INVERT: return D3D12_STENCIL_OP_INVERT; 415bf215546Sopenharmony_ci } 416bf215546Sopenharmony_ci unreachable("unexpected op"); 417bf215546Sopenharmony_ci} 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_cistatic D3D12_DEPTH_STENCILOP_DESC 420bf215546Sopenharmony_cistencil_op_state(const struct pipe_stencil_state *src) 421bf215546Sopenharmony_ci{ 422bf215546Sopenharmony_ci D3D12_DEPTH_STENCILOP_DESC ret; 423bf215546Sopenharmony_ci ret.StencilFailOp = stencil_op((pipe_stencil_op) src->fail_op); 424bf215546Sopenharmony_ci ret.StencilPassOp = stencil_op((pipe_stencil_op) src->zpass_op); 425bf215546Sopenharmony_ci ret.StencilDepthFailOp = stencil_op((pipe_stencil_op) src->zfail_op); 426bf215546Sopenharmony_ci ret.StencilFunc = compare_op((pipe_compare_func) src->func); 427bf215546Sopenharmony_ci return ret; 428bf215546Sopenharmony_ci} 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_cistatic void * 431bf215546Sopenharmony_cid3d12_create_depth_stencil_alpha_state(struct pipe_context *pctx, 432bf215546Sopenharmony_ci const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha) 433bf215546Sopenharmony_ci{ 434bf215546Sopenharmony_ci struct d3d12_depth_stencil_alpha_state *dsa = CALLOC_STRUCT(d3d12_depth_stencil_alpha_state); 435bf215546Sopenharmony_ci if (!dsa) 436bf215546Sopenharmony_ci return NULL; 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci if (depth_stencil_alpha->depth_enabled) { 439bf215546Sopenharmony_ci dsa->desc.DepthEnable = TRUE; 440bf215546Sopenharmony_ci dsa->desc.DepthFunc = compare_op((pipe_compare_func) depth_stencil_alpha->depth_func); 441bf215546Sopenharmony_ci } 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci /* TODO Add support for GL_depth_bound_tests */ 444bf215546Sopenharmony_ci #if 0 445bf215546Sopenharmony_ci if (depth_stencil_alpha->depth.bounds_test) { 446bf215546Sopenharmony_ci dsa->desc.DepthBoundsTestEnable = TRUE; 447bf215546Sopenharmony_ci dsa->min_depth_bounds = depth_stencil_alpha->depth.bounds_min; 448bf215546Sopenharmony_ci dsa->max_depth_bounds = depth_stencil_alpha->depth.bounds_max; 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci #endif 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci if (depth_stencil_alpha->stencil[0].enabled) { 453bf215546Sopenharmony_ci dsa->desc.StencilEnable = TRUE; 454bf215546Sopenharmony_ci dsa->desc.FrontFace = stencil_op_state(depth_stencil_alpha->stencil); 455bf215546Sopenharmony_ci } 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_ci if (depth_stencil_alpha->stencil[1].enabled) 458bf215546Sopenharmony_ci dsa->desc.BackFace = stencil_op_state(depth_stencil_alpha->stencil + 1); 459bf215546Sopenharmony_ci else 460bf215546Sopenharmony_ci dsa->desc.BackFace = dsa->desc.FrontFace; 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci dsa->desc.StencilReadMask = depth_stencil_alpha->stencil[0].valuemask; /* FIXME Back face mask */ 463bf215546Sopenharmony_ci dsa->desc.StencilWriteMask = depth_stencil_alpha->stencil[0].writemask; /* FIXME Back face mask */ 464bf215546Sopenharmony_ci dsa->desc.DepthWriteMask = (D3D12_DEPTH_WRITE_MASK) depth_stencil_alpha->depth_writemask; 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci return dsa; 467bf215546Sopenharmony_ci} 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_cistatic void 470bf215546Sopenharmony_cid3d12_bind_depth_stencil_alpha_state(struct pipe_context *pctx, 471bf215546Sopenharmony_ci void *dsa) 472bf215546Sopenharmony_ci{ 473bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 474bf215546Sopenharmony_ci ctx->gfx_pipeline_state.zsa = (struct d3d12_depth_stencil_alpha_state *) dsa; 475bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_ZSA; 476bf215546Sopenharmony_ci} 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_cistatic void 479bf215546Sopenharmony_cid3d12_delete_depth_stencil_alpha_state(struct pipe_context *pctx, 480bf215546Sopenharmony_ci void *dsa_state) 481bf215546Sopenharmony_ci{ 482bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), dsa_state); 483bf215546Sopenharmony_ci FREE(dsa_state); 484bf215546Sopenharmony_ci} 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_cistatic D3D12_FILL_MODE 487bf215546Sopenharmony_cifill_mode(unsigned mode) 488bf215546Sopenharmony_ci{ 489bf215546Sopenharmony_ci switch (mode) { 490bf215546Sopenharmony_ci case PIPE_POLYGON_MODE_FILL: 491bf215546Sopenharmony_ci return D3D12_FILL_MODE_SOLID; 492bf215546Sopenharmony_ci case PIPE_POLYGON_MODE_LINE: 493bf215546Sopenharmony_ci return D3D12_FILL_MODE_WIREFRAME; 494bf215546Sopenharmony_ci case PIPE_POLYGON_MODE_POINT: 495bf215546Sopenharmony_ci return D3D12_FILL_MODE_SOLID; 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci default: 498bf215546Sopenharmony_ci unreachable("unsupported fill-mode"); 499bf215546Sopenharmony_ci } 500bf215546Sopenharmony_ci} 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_cistatic void * 503bf215546Sopenharmony_cid3d12_create_rasterizer_state(struct pipe_context *pctx, 504bf215546Sopenharmony_ci const struct pipe_rasterizer_state *rs_state) 505bf215546Sopenharmony_ci{ 506bf215546Sopenharmony_ci struct d3d12_rasterizer_state *cso = CALLOC_STRUCT(d3d12_rasterizer_state); 507bf215546Sopenharmony_ci if (!cso) 508bf215546Sopenharmony_ci return NULL; 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci cso->base = *rs_state; 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_ci assert(rs_state->depth_clip_near == rs_state->depth_clip_far); 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci switch (rs_state->cull_face) { 515bf215546Sopenharmony_ci case PIPE_FACE_NONE: 516bf215546Sopenharmony_ci if (rs_state->fill_front != rs_state->fill_back) { 517bf215546Sopenharmony_ci cso->base.cull_face = PIPE_FACE_BACK; 518bf215546Sopenharmony_ci cso->desc.CullMode = D3D12_CULL_MODE_BACK; 519bf215546Sopenharmony_ci cso->desc.FillMode = fill_mode(rs_state->fill_front); 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci /* create a modified CSO for the back-state, so we can draw with 522bf215546Sopenharmony_ci * either. 523bf215546Sopenharmony_ci */ 524bf215546Sopenharmony_ci struct pipe_rasterizer_state templ = *rs_state; 525bf215546Sopenharmony_ci templ.cull_face = PIPE_FACE_FRONT; 526bf215546Sopenharmony_ci templ.fill_front = rs_state->fill_back; 527bf215546Sopenharmony_ci cso->twoface_back = d3d12_create_rasterizer_state(pctx, &templ); 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci if (!cso->twoface_back) { 530bf215546Sopenharmony_ci FREE(cso); 531bf215546Sopenharmony_ci return NULL; 532bf215546Sopenharmony_ci } 533bf215546Sopenharmony_ci } else { 534bf215546Sopenharmony_ci cso->desc.CullMode = D3D12_CULL_MODE_NONE; 535bf215546Sopenharmony_ci cso->desc.FillMode = fill_mode(rs_state->fill_front); 536bf215546Sopenharmony_ci } 537bf215546Sopenharmony_ci break; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci case PIPE_FACE_FRONT: 540bf215546Sopenharmony_ci cso->desc.CullMode = D3D12_CULL_MODE_FRONT; 541bf215546Sopenharmony_ci cso->desc.FillMode = fill_mode(rs_state->fill_back); 542bf215546Sopenharmony_ci break; 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_ci case PIPE_FACE_BACK: 545bf215546Sopenharmony_ci cso->desc.CullMode = D3D12_CULL_MODE_BACK; 546bf215546Sopenharmony_ci cso->desc.FillMode = fill_mode(rs_state->fill_front); 547bf215546Sopenharmony_ci break; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci case PIPE_FACE_FRONT_AND_BACK: 550bf215546Sopenharmony_ci /* this is wrong, and we shouldn't actually have to support this! */ 551bf215546Sopenharmony_ci cso->desc.CullMode = D3D12_CULL_MODE_NONE; 552bf215546Sopenharmony_ci cso->desc.FillMode = D3D12_FILL_MODE_SOLID; 553bf215546Sopenharmony_ci break; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci default: 556bf215546Sopenharmony_ci unreachable("unsupported cull-mode"); 557bf215546Sopenharmony_ci } 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci cso->desc.FrontCounterClockwise = rs_state->front_ccw; 560bf215546Sopenharmony_ci cso->desc.DepthClipEnable = rs_state->depth_clip_near; 561bf215546Sopenharmony_ci cso->desc.MultisampleEnable = rs_state->multisample; 562bf215546Sopenharmony_ci cso->desc.AntialiasedLineEnable = rs_state->line_smooth; 563bf215546Sopenharmony_ci cso->desc.ForcedSampleCount = 0; // TODO 564bf215546Sopenharmony_ci cso->desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; /* Not Implemented */ 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci return cso; 567bf215546Sopenharmony_ci} 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_cistatic void 570bf215546Sopenharmony_cid3d12_bind_rasterizer_state(struct pipe_context *pctx, void *rs_state) 571bf215546Sopenharmony_ci{ 572bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 573bf215546Sopenharmony_ci ctx->gfx_pipeline_state.rast = (struct d3d12_rasterizer_state *)rs_state; 574bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_RASTERIZER | D3D12_DIRTY_SCISSOR; 575bf215546Sopenharmony_ci} 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_cistatic void 578bf215546Sopenharmony_cid3d12_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state) 579bf215546Sopenharmony_ci{ 580bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_cache_invalidate(d3d12_context(pctx), rs_state); 581bf215546Sopenharmony_ci FREE(rs_state); 582bf215546Sopenharmony_ci} 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_cistatic D3D12_TEXTURE_ADDRESS_MODE 585bf215546Sopenharmony_cisampler_address_mode(enum pipe_tex_wrap wrap, enum pipe_tex_filter filter) 586bf215546Sopenharmony_ci{ 587bf215546Sopenharmony_ci switch (wrap) { 588bf215546Sopenharmony_ci case PIPE_TEX_WRAP_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_WRAP; 589bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP: return filter == PIPE_TEX_FILTER_NEAREST ? 590bf215546Sopenharmony_ci D3D12_TEXTURE_ADDRESS_MODE_CLAMP : 591bf215546Sopenharmony_ci D3D12_TEXTURE_ADDRESS_MODE_BORDER; 592bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_CLAMP; 593bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_BORDER; 594bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR; 595bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_CLAMP: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; /* not technically correct, but kinda works */ 596bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; 597bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; /* FIXME: Doesn't exist in D3D12 */ 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci unreachable("unexpected wrap"); 600bf215546Sopenharmony_ci} 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_cistatic D3D12_FILTER 603bf215546Sopenharmony_ciget_filter(const struct pipe_sampler_state *state) 604bf215546Sopenharmony_ci{ 605bf215546Sopenharmony_ci static const D3D12_FILTER lut[16] = { 606bf215546Sopenharmony_ci D3D12_FILTER_MIN_MAG_MIP_POINT, 607bf215546Sopenharmony_ci D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR, 608bf215546Sopenharmony_ci D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, 609bf215546Sopenharmony_ci D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR, 610bf215546Sopenharmony_ci D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT, 611bf215546Sopenharmony_ci D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, 612bf215546Sopenharmony_ci D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, 613bf215546Sopenharmony_ci D3D12_FILTER_MIN_MAG_MIP_LINEAR, 614bf215546Sopenharmony_ci D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT, 615bf215546Sopenharmony_ci D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR, 616bf215546Sopenharmony_ci D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT, 617bf215546Sopenharmony_ci D3D12_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR, 618bf215546Sopenharmony_ci D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT, 619bf215546Sopenharmony_ci D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR, 620bf215546Sopenharmony_ci D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, 621bf215546Sopenharmony_ci D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR, 622bf215546Sopenharmony_ci }; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci static const D3D12_FILTER anisotropic_lut[2] = { 625bf215546Sopenharmony_ci D3D12_FILTER_ANISOTROPIC, 626bf215546Sopenharmony_ci D3D12_FILTER_COMPARISON_ANISOTROPIC, 627bf215546Sopenharmony_ci }; 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci if (state->max_anisotropy > 1) { 630bf215546Sopenharmony_ci return anisotropic_lut[state->compare_mode]; 631bf215546Sopenharmony_ci } else { 632bf215546Sopenharmony_ci int idx = (state->mag_img_filter << 1) | 633bf215546Sopenharmony_ci (state->min_img_filter << 2) | 634bf215546Sopenharmony_ci (state->compare_mode << 3); 635bf215546Sopenharmony_ci if (state->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) 636bf215546Sopenharmony_ci idx |= state->min_mip_filter; 637bf215546Sopenharmony_ci return lut[idx]; 638bf215546Sopenharmony_ci } 639bf215546Sopenharmony_ci} 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_cistatic void * 642bf215546Sopenharmony_cid3d12_create_sampler_state(struct pipe_context *pctx, 643bf215546Sopenharmony_ci const struct pipe_sampler_state *state) 644bf215546Sopenharmony_ci{ 645bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 646bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pctx->screen); 647bf215546Sopenharmony_ci struct d3d12_sampler_state *ss; 648bf215546Sopenharmony_ci D3D12_SAMPLER_DESC desc = {}; 649bf215546Sopenharmony_ci if (!state) 650bf215546Sopenharmony_ci return NULL; 651bf215546Sopenharmony_ci 652bf215546Sopenharmony_ci ss = CALLOC_STRUCT(d3d12_sampler_state); 653bf215546Sopenharmony_ci ss->filter = (pipe_tex_filter)state->min_img_filter; 654bf215546Sopenharmony_ci ss->wrap_r = (pipe_tex_wrap)state->wrap_r; 655bf215546Sopenharmony_ci ss->wrap_s = (pipe_tex_wrap)state->wrap_s; 656bf215546Sopenharmony_ci ss->wrap_t = (pipe_tex_wrap)state->wrap_t; 657bf215546Sopenharmony_ci ss->lod_bias = state->lod_bias; 658bf215546Sopenharmony_ci ss->min_lod = state->min_lod; 659bf215546Sopenharmony_ci ss->max_lod = state->max_lod; 660bf215546Sopenharmony_ci memcpy(ss->border_color, state->border_color.f, sizeof(float) * 4); 661bf215546Sopenharmony_ci ss->compare_func = (pipe_compare_func)state->compare_func; 662bf215546Sopenharmony_ci 663bf215546Sopenharmony_ci if (state->min_mip_filter < PIPE_TEX_MIPFILTER_NONE) { 664bf215546Sopenharmony_ci desc.MinLOD = state->min_lod; 665bf215546Sopenharmony_ci desc.MaxLOD = state->max_lod; 666bf215546Sopenharmony_ci } else if (state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { 667bf215546Sopenharmony_ci desc.MinLOD = 0; 668bf215546Sopenharmony_ci desc.MaxLOD = 0; 669bf215546Sopenharmony_ci } else { 670bf215546Sopenharmony_ci unreachable("unexpected mip filter"); 671bf215546Sopenharmony_ci } 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_ci if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 674bf215546Sopenharmony_ci desc.ComparisonFunc = compare_op((pipe_compare_func) state->compare_func); 675bf215546Sopenharmony_ci } else if (state->compare_mode == PIPE_TEX_COMPARE_NONE) { 676bf215546Sopenharmony_ci desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; 677bf215546Sopenharmony_ci } else 678bf215546Sopenharmony_ci unreachable("unexpected comparison mode"); 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci desc.MaxAnisotropy = state->max_anisotropy; 681bf215546Sopenharmony_ci desc.Filter = get_filter(state); 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci desc.AddressU = sampler_address_mode((pipe_tex_wrap) state->wrap_s, 684bf215546Sopenharmony_ci (pipe_tex_filter) state->min_img_filter); 685bf215546Sopenharmony_ci desc.AddressV = sampler_address_mode((pipe_tex_wrap) state->wrap_t, 686bf215546Sopenharmony_ci (pipe_tex_filter) state->min_img_filter); 687bf215546Sopenharmony_ci desc.AddressW = sampler_address_mode((pipe_tex_wrap) state->wrap_r, 688bf215546Sopenharmony_ci (pipe_tex_filter) state->min_img_filter); 689bf215546Sopenharmony_ci desc.MipLODBias = CLAMP(state->lod_bias, -16.0f, 15.99f); 690bf215546Sopenharmony_ci memcpy(desc.BorderColor, state->border_color.f, sizeof(float) * 4); 691bf215546Sopenharmony_ci 692bf215546Sopenharmony_ci // TODO Normalized Coordinates? 693bf215546Sopenharmony_ci d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ss->handle); 694bf215546Sopenharmony_ci screen->dev->CreateSampler(&desc, ss->handle.cpu_handle); 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 697bf215546Sopenharmony_ci desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; 698bf215546Sopenharmony_ci desc.Filter = D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT; 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, 701bf215546Sopenharmony_ci &ss->handle_without_shadow); 702bf215546Sopenharmony_ci screen->dev->CreateSampler(&desc, 703bf215546Sopenharmony_ci ss->handle_without_shadow.cpu_handle); 704bf215546Sopenharmony_ci ss->is_shadow_sampler = true; 705bf215546Sopenharmony_ci } 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci return ss; 708bf215546Sopenharmony_ci} 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_cistatic void 711bf215546Sopenharmony_cid3d12_bind_sampler_states(struct pipe_context *pctx, 712bf215546Sopenharmony_ci enum pipe_shader_type shader, 713bf215546Sopenharmony_ci unsigned start_slot, 714bf215546Sopenharmony_ci unsigned num_samplers, 715bf215546Sopenharmony_ci void **samplers) 716bf215546Sopenharmony_ci{ 717bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 718bf215546Sopenharmony_ci 719bf215546Sopenharmony_ci#define STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(X) \ 720bf215546Sopenharmony_ci static_assert((enum compare_func)PIPE_FUNC_##X == COMPARE_FUNC_##X, #X " needs switch case"); 721bf215546Sopenharmony_ci 722bf215546Sopenharmony_ci STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(LESS); 723bf215546Sopenharmony_ci STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(GREATER); 724bf215546Sopenharmony_ci STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(LEQUAL); 725bf215546Sopenharmony_ci STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(GEQUAL); 726bf215546Sopenharmony_ci STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(NOTEQUAL); 727bf215546Sopenharmony_ci STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(NEVER); 728bf215546Sopenharmony_ci STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC(ALWAYS); 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci#undef STATIC_ASSERT_PIPE_EQUAL_COMP_FUNC 731bf215546Sopenharmony_ci 732bf215546Sopenharmony_ci for (unsigned i = 0; i < num_samplers; ++i) { 733bf215546Sopenharmony_ci d3d12_sampler_state *sampler = (struct d3d12_sampler_state*) samplers[i]; 734bf215546Sopenharmony_ci ctx->samplers[shader][start_slot + i] = sampler; 735bf215546Sopenharmony_ci dxil_wrap_sampler_state &wrap = ctx->tex_wrap_states[shader][start_slot + i]; 736bf215546Sopenharmony_ci if (sampler) { 737bf215546Sopenharmony_ci wrap.wrap[0] = sampler->wrap_s; 738bf215546Sopenharmony_ci wrap.wrap[1] = sampler->wrap_t; 739bf215546Sopenharmony_ci wrap.wrap[2] = sampler->wrap_r; 740bf215546Sopenharmony_ci wrap.lod_bias = sampler->lod_bias; 741bf215546Sopenharmony_ci wrap.min_lod = sampler->min_lod; 742bf215546Sopenharmony_ci wrap.max_lod = sampler->max_lod; 743bf215546Sopenharmony_ci memcpy(wrap.border_color, sampler->border_color, 4 * sizeof(float)); 744bf215546Sopenharmony_ci ctx->tex_compare_func[shader][start_slot + i] = (enum compare_func)sampler->compare_func; 745bf215546Sopenharmony_ci } else { 746bf215546Sopenharmony_ci memset(&wrap, 0, sizeof (dxil_wrap_sampler_state)); 747bf215546Sopenharmony_ci } 748bf215546Sopenharmony_ci } 749bf215546Sopenharmony_ci 750bf215546Sopenharmony_ci ctx->num_samplers[shader] = start_slot + num_samplers; 751bf215546Sopenharmony_ci ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_SAMPLERS; 752bf215546Sopenharmony_ci} 753bf215546Sopenharmony_ci 754bf215546Sopenharmony_cistatic void 755bf215546Sopenharmony_cid3d12_delete_sampler_state(struct pipe_context *pctx, 756bf215546Sopenharmony_ci void *ss) 757bf215546Sopenharmony_ci{ 758bf215546Sopenharmony_ci struct d3d12_batch *batch = d3d12_current_batch(d3d12_context(pctx)); 759bf215546Sopenharmony_ci struct d3d12_sampler_state *state = (struct d3d12_sampler_state*) ss; 760bf215546Sopenharmony_ci util_dynarray_append(&batch->zombie_samplers, d3d12_descriptor_handle, 761bf215546Sopenharmony_ci state->handle); 762bf215546Sopenharmony_ci if (state->is_shadow_sampler) 763bf215546Sopenharmony_ci util_dynarray_append(&batch->zombie_samplers, d3d12_descriptor_handle, 764bf215546Sopenharmony_ci state->handle_without_shadow); 765bf215546Sopenharmony_ci FREE(ss); 766bf215546Sopenharmony_ci} 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_cistatic D3D12_SRV_DIMENSION 769bf215546Sopenharmony_ciview_dimension(enum pipe_texture_target target, unsigned samples) 770bf215546Sopenharmony_ci{ 771bf215546Sopenharmony_ci switch (target) { 772bf215546Sopenharmony_ci case PIPE_BUFFER: return D3D12_SRV_DIMENSION_BUFFER; 773bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: return D3D12_SRV_DIMENSION_TEXTURE1D; 774bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: return D3D12_SRV_DIMENSION_TEXTURE1DARRAY; 775bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 776bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 777bf215546Sopenharmony_ci return samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMS : 778bf215546Sopenharmony_ci D3D12_SRV_DIMENSION_TEXTURE2D; 779bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 780bf215546Sopenharmony_ci return samples > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY : 781bf215546Sopenharmony_ci D3D12_SRV_DIMENSION_TEXTURE2DARRAY; 782bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: return D3D12_SRV_DIMENSION_TEXTURECUBE; 783bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: return D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; 784bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: return D3D12_SRV_DIMENSION_TEXTURE3D; 785bf215546Sopenharmony_ci default: 786bf215546Sopenharmony_ci unreachable("unexpected target"); 787bf215546Sopenharmony_ci } 788bf215546Sopenharmony_ci} 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_cistatic D3D12_SHADER_COMPONENT_MAPPING 791bf215546Sopenharmony_cicomponent_mapping(enum pipe_swizzle swizzle, D3D12_SHADER_COMPONENT_MAPPING id) 792bf215546Sopenharmony_ci{ 793bf215546Sopenharmony_ci switch (swizzle) { 794bf215546Sopenharmony_ci case PIPE_SWIZZLE_X: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0; 795bf215546Sopenharmony_ci case PIPE_SWIZZLE_Y: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1; 796bf215546Sopenharmony_ci case PIPE_SWIZZLE_Z: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2; 797bf215546Sopenharmony_ci case PIPE_SWIZZLE_W: return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3; 798bf215546Sopenharmony_ci case PIPE_SWIZZLE_0: return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0; 799bf215546Sopenharmony_ci case PIPE_SWIZZLE_1: return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1; 800bf215546Sopenharmony_ci case PIPE_SWIZZLE_NONE: return id; 801bf215546Sopenharmony_ci default: 802bf215546Sopenharmony_ci unreachable("unexpected swizzle"); 803bf215546Sopenharmony_ci } 804bf215546Sopenharmony_ci} 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_civoid 807bf215546Sopenharmony_cid3d12_init_sampler_view_descriptor(struct d3d12_sampler_view *sampler_view) 808bf215546Sopenharmony_ci{ 809bf215546Sopenharmony_ci struct pipe_sampler_view *state = &sampler_view->base; 810bf215546Sopenharmony_ci struct pipe_resource *texture = state->texture; 811bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(texture); 812bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(texture->screen); 813bf215546Sopenharmony_ci 814bf215546Sopenharmony_ci struct d3d12_format_info format_info = d3d12_get_format_info(res->overall_format, state->format, state->target); 815bf215546Sopenharmony_ci D3D12_SHADER_RESOURCE_VIEW_DESC desc = {}; 816bf215546Sopenharmony_ci desc.Format = d3d12_get_resource_srv_format(state->format, state->target); 817bf215546Sopenharmony_ci desc.ViewDimension = view_dimension(state->target, texture->nr_samples); 818bf215546Sopenharmony_ci 819bf215546Sopenharmony_ci /* Integer cube textures are not really supported, because TextureLoad doesn't exist 820bf215546Sopenharmony_ci * for cube maps, and we sampling is not supported for integer textures, so we have to 821bf215546Sopenharmony_ci * handle this SRV as if it were a 2D texture array */ 822bf215546Sopenharmony_ci if ((desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE || 823bf215546Sopenharmony_ci desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) && 824bf215546Sopenharmony_ci util_format_is_pure_integer(state->format)) { 825bf215546Sopenharmony_ci desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; 826bf215546Sopenharmony_ci } 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( 829bf215546Sopenharmony_ci component_mapping((pipe_swizzle)sampler_view->swizzle_override_r, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0), 830bf215546Sopenharmony_ci component_mapping((pipe_swizzle)sampler_view->swizzle_override_g, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1), 831bf215546Sopenharmony_ci component_mapping((pipe_swizzle)sampler_view->swizzle_override_b, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2), 832bf215546Sopenharmony_ci component_mapping((pipe_swizzle)sampler_view->swizzle_override_a, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3) 833bf215546Sopenharmony_ci ); 834bf215546Sopenharmony_ci 835bf215546Sopenharmony_ci uint64_t offset = 0; 836bf215546Sopenharmony_ci ID3D12Resource *d3d12_res = d3d12_resource_underlying(res, &offset); 837bf215546Sopenharmony_ci assert(offset == 0 || res->base.b.target == PIPE_BUFFER); 838bf215546Sopenharmony_ci 839bf215546Sopenharmony_ci unsigned array_size = state->u.tex.last_layer - state->u.tex.first_layer + 1; 840bf215546Sopenharmony_ci switch (desc.ViewDimension) { 841bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_TEXTURE1D: 842bf215546Sopenharmony_ci if (state->u.tex.first_layer > 0) 843bf215546Sopenharmony_ci debug_printf("D3D12: can't create 1D SRV from layer %d\n", 844bf215546Sopenharmony_ci state->u.tex.first_layer); 845bf215546Sopenharmony_ci 846bf215546Sopenharmony_ci desc.Texture1D.MostDetailedMip = state->u.tex.first_level; 847bf215546Sopenharmony_ci desc.Texture1D.MipLevels = sampler_view->mip_levels; 848bf215546Sopenharmony_ci desc.Texture1D.ResourceMinLODClamp = 0.0f; 849bf215546Sopenharmony_ci break; 850bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_TEXTURE1DARRAY: 851bf215546Sopenharmony_ci desc.Texture1DArray.MostDetailedMip = state->u.tex.first_level; 852bf215546Sopenharmony_ci desc.Texture1DArray.MipLevels = sampler_view->mip_levels; 853bf215546Sopenharmony_ci desc.Texture1DArray.ResourceMinLODClamp = 0.0f; 854bf215546Sopenharmony_ci desc.Texture1DArray.FirstArraySlice = state->u.tex.first_layer; 855bf215546Sopenharmony_ci desc.Texture1DArray.ArraySize = array_size; 856bf215546Sopenharmony_ci break; 857bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_TEXTURE2D: 858bf215546Sopenharmony_ci if (state->u.tex.first_layer > 0) 859bf215546Sopenharmony_ci debug_printf("D3D12: can't create 2D SRV from layer %d\n", 860bf215546Sopenharmony_ci state->u.tex.first_layer); 861bf215546Sopenharmony_ci 862bf215546Sopenharmony_ci desc.Texture2D.MostDetailedMip = state->u.tex.first_level; 863bf215546Sopenharmony_ci desc.Texture2D.MipLevels = sampler_view->mip_levels; 864bf215546Sopenharmony_ci desc.Texture2D.PlaneSlice = format_info.plane_slice; 865bf215546Sopenharmony_ci desc.Texture2D.ResourceMinLODClamp = 0.0f; 866bf215546Sopenharmony_ci break; 867bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_TEXTURE2DMS: 868bf215546Sopenharmony_ci if (state->u.tex.first_layer > 0) 869bf215546Sopenharmony_ci debug_printf("D3D12: can't create 2DMS SRV from layer %d\n", 870bf215546Sopenharmony_ci state->u.tex.first_layer); 871bf215546Sopenharmony_ci break; 872bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_TEXTURE2DARRAY: 873bf215546Sopenharmony_ci desc.Texture2DArray.MostDetailedMip = state->u.tex.first_level; 874bf215546Sopenharmony_ci desc.Texture2DArray.MipLevels = sampler_view->mip_levels; 875bf215546Sopenharmony_ci desc.Texture2DArray.ResourceMinLODClamp = 0.0f; 876bf215546Sopenharmony_ci desc.Texture2DArray.FirstArraySlice = state->u.tex.first_layer; 877bf215546Sopenharmony_ci desc.Texture2DArray.PlaneSlice = format_info.plane_slice; 878bf215546Sopenharmony_ci desc.Texture2DArray.ArraySize = array_size; 879bf215546Sopenharmony_ci break; 880bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY: 881bf215546Sopenharmony_ci desc.Texture2DMSArray.FirstArraySlice = state->u.tex.first_layer; 882bf215546Sopenharmony_ci desc.Texture2DMSArray.ArraySize = array_size; 883bf215546Sopenharmony_ci break; 884bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_TEXTURE3D: 885bf215546Sopenharmony_ci if (state->u.tex.first_layer > 0) 886bf215546Sopenharmony_ci debug_printf("D3D12: can't create 3D SRV from layer %d\n", 887bf215546Sopenharmony_ci state->u.tex.first_layer); 888bf215546Sopenharmony_ci 889bf215546Sopenharmony_ci desc.Texture3D.MostDetailedMip = state->u.tex.first_level; 890bf215546Sopenharmony_ci desc.Texture3D.MipLevels = sampler_view->mip_levels; 891bf215546Sopenharmony_ci desc.Texture3D.ResourceMinLODClamp = 0.0f; 892bf215546Sopenharmony_ci break; 893bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_TEXTURECUBE: 894bf215546Sopenharmony_ci if (state->u.tex.first_layer > 0) 895bf215546Sopenharmony_ci debug_printf("D3D12: can't create CUBE SRV from layer %d\n", 896bf215546Sopenharmony_ci state->u.tex.first_layer); 897bf215546Sopenharmony_ci 898bf215546Sopenharmony_ci desc.TextureCube.MostDetailedMip = state->u.tex.first_level; 899bf215546Sopenharmony_ci desc.TextureCube.MipLevels = sampler_view->mip_levels; 900bf215546Sopenharmony_ci desc.TextureCube.ResourceMinLODClamp = 0.0f; 901bf215546Sopenharmony_ci break; 902bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY: 903bf215546Sopenharmony_ci assert(array_size % 6 == 0); 904bf215546Sopenharmony_ci desc.TextureCubeArray.MostDetailedMip = state->u.tex.first_level; 905bf215546Sopenharmony_ci desc.TextureCubeArray.MipLevels = sampler_view->mip_levels; 906bf215546Sopenharmony_ci desc.TextureCubeArray.First2DArrayFace = state->u.tex.first_layer; 907bf215546Sopenharmony_ci desc.TextureCubeArray.NumCubes = array_size / 6; 908bf215546Sopenharmony_ci desc.TextureCubeArray.ResourceMinLODClamp = 0.0f; 909bf215546Sopenharmony_ci break; 910bf215546Sopenharmony_ci case D3D12_SRV_DIMENSION_BUFFER: 911bf215546Sopenharmony_ci desc.Buffer.StructureByteStride = 0; 912bf215546Sopenharmony_ci desc.Buffer.FirstElement = offset / util_format_get_blocksize(state->format); 913bf215546Sopenharmony_ci desc.Buffer.NumElements = texture->width0 / util_format_get_blocksize(state->format); 914bf215546Sopenharmony_ci break; 915bf215546Sopenharmony_ci default: 916bf215546Sopenharmony_ci unreachable("Invalid SRV dimension"); 917bf215546Sopenharmony_ci } 918bf215546Sopenharmony_ci 919bf215546Sopenharmony_ci screen->dev->CreateShaderResourceView(d3d12_res, &desc, 920bf215546Sopenharmony_ci sampler_view->handle.cpu_handle); 921bf215546Sopenharmony_ci} 922bf215546Sopenharmony_ci 923bf215546Sopenharmony_cistatic struct pipe_sampler_view * 924bf215546Sopenharmony_cid3d12_create_sampler_view(struct pipe_context *pctx, 925bf215546Sopenharmony_ci struct pipe_resource *texture, 926bf215546Sopenharmony_ci const struct pipe_sampler_view *state) 927bf215546Sopenharmony_ci{ 928bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pctx->screen); 929bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(texture); 930bf215546Sopenharmony_ci struct d3d12_sampler_view *sampler_view = CALLOC_STRUCT(d3d12_sampler_view); 931bf215546Sopenharmony_ci 932bf215546Sopenharmony_ci sampler_view->base = *state; 933bf215546Sopenharmony_ci sampler_view->base.texture = NULL; 934bf215546Sopenharmony_ci pipe_resource_reference(&sampler_view->base.texture, texture); 935bf215546Sopenharmony_ci sampler_view->base.reference.count = 1; 936bf215546Sopenharmony_ci sampler_view->base.context = pctx; 937bf215546Sopenharmony_ci sampler_view->mip_levels = state->u.tex.last_level - state->u.tex.first_level + 1; 938bf215546Sopenharmony_ci sampler_view->array_size = texture->array_size; 939bf215546Sopenharmony_ci sampler_view->texture_generation_id = p_atomic_read(&res->generation_id); 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci struct d3d12_format_info format_info = d3d12_get_format_info(res->overall_format, state->format, state->target); 942bf215546Sopenharmony_ci pipe_swizzle swizzle[4] = { 943bf215546Sopenharmony_ci format_info.swizzle[sampler_view->base.swizzle_r], 944bf215546Sopenharmony_ci format_info.swizzle[sampler_view->base.swizzle_g], 945bf215546Sopenharmony_ci format_info.swizzle[sampler_view->base.swizzle_b], 946bf215546Sopenharmony_ci format_info.swizzle[sampler_view->base.swizzle_a] 947bf215546Sopenharmony_ci }; 948bf215546Sopenharmony_ci 949bf215546Sopenharmony_ci sampler_view->swizzle_override_r = swizzle[0]; 950bf215546Sopenharmony_ci sampler_view->swizzle_override_g = swizzle[1]; 951bf215546Sopenharmony_ci sampler_view->swizzle_override_b = swizzle[2]; 952bf215546Sopenharmony_ci sampler_view->swizzle_override_a = swizzle[3]; 953bf215546Sopenharmony_ci 954bf215546Sopenharmony_ci mtx_lock(&screen->descriptor_pool_mutex); 955bf215546Sopenharmony_ci d3d12_descriptor_pool_alloc_handle(screen->view_pool, &sampler_view->handle); 956bf215546Sopenharmony_ci mtx_unlock(&screen->descriptor_pool_mutex); 957bf215546Sopenharmony_ci 958bf215546Sopenharmony_ci d3d12_init_sampler_view_descriptor(sampler_view); 959bf215546Sopenharmony_ci 960bf215546Sopenharmony_ci return &sampler_view->base; 961bf215546Sopenharmony_ci} 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_cistatic void 964bf215546Sopenharmony_cid3d12_increment_sampler_view_bind_count(struct pipe_context *ctx, 965bf215546Sopenharmony_ci enum pipe_shader_type shader_type, 966bf215546Sopenharmony_ci struct pipe_sampler_view *view) { 967bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(view->texture); 968bf215546Sopenharmony_ci if (res) 969bf215546Sopenharmony_ci res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]++; 970bf215546Sopenharmony_ci} 971bf215546Sopenharmony_ci 972bf215546Sopenharmony_cistatic void 973bf215546Sopenharmony_cid3d12_decrement_sampler_view_bind_count(struct pipe_context *ctx, 974bf215546Sopenharmony_ci enum pipe_shader_type shader_type, 975bf215546Sopenharmony_ci struct pipe_sampler_view *view) { 976bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(view->texture); 977bf215546Sopenharmony_ci if (res) { 978bf215546Sopenharmony_ci assert(res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0); 979bf215546Sopenharmony_ci res->bind_counts[shader_type][D3D12_RESOURCE_BINDING_TYPE_SRV]--; 980bf215546Sopenharmony_ci } 981bf215546Sopenharmony_ci} 982bf215546Sopenharmony_ci 983bf215546Sopenharmony_cistatic void 984bf215546Sopenharmony_cid3d12_set_sampler_views(struct pipe_context *pctx, 985bf215546Sopenharmony_ci enum pipe_shader_type shader_type, 986bf215546Sopenharmony_ci unsigned start_slot, 987bf215546Sopenharmony_ci unsigned num_views, 988bf215546Sopenharmony_ci unsigned unbind_num_trailing_slots, 989bf215546Sopenharmony_ci bool take_ownership, 990bf215546Sopenharmony_ci struct pipe_sampler_view **views) 991bf215546Sopenharmony_ci{ 992bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 993bf215546Sopenharmony_ci unsigned shader_bit = (1 << shader_type); 994bf215546Sopenharmony_ci ctx->has_int_samplers &= ~shader_bit; 995bf215546Sopenharmony_ci 996bf215546Sopenharmony_ci for (unsigned i = 0; i < num_views; ++i) { 997bf215546Sopenharmony_ci struct pipe_sampler_view *&old_view = ctx->sampler_views[shader_type][start_slot + i]; 998bf215546Sopenharmony_ci if (old_view) 999bf215546Sopenharmony_ci d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view); 1000bf215546Sopenharmony_ci 1001bf215546Sopenharmony_ci struct pipe_sampler_view *new_view = views[i]; 1002bf215546Sopenharmony_ci if (new_view) 1003bf215546Sopenharmony_ci d3d12_increment_sampler_view_bind_count(pctx, shader_type, new_view); 1004bf215546Sopenharmony_ci 1005bf215546Sopenharmony_ci if (take_ownership) { 1006bf215546Sopenharmony_ci pipe_sampler_view_reference(&old_view, NULL); 1007bf215546Sopenharmony_ci old_view = views[i]; 1008bf215546Sopenharmony_ci } else { 1009bf215546Sopenharmony_ci pipe_sampler_view_reference(&old_view, views[i]); 1010bf215546Sopenharmony_ci } 1011bf215546Sopenharmony_ci 1012bf215546Sopenharmony_ci if (views[i]) { 1013bf215546Sopenharmony_ci dxil_wrap_sampler_state &wss = ctx->tex_wrap_states[shader_type][start_slot + i]; 1014bf215546Sopenharmony_ci dxil_texture_swizzle_state &swizzle_state = ctx->tex_swizzle_state[shader_type][i]; 1015bf215546Sopenharmony_ci if (util_format_is_pure_integer(views[i]->format)) { 1016bf215546Sopenharmony_ci ctx->has_int_samplers |= shader_bit; 1017bf215546Sopenharmony_ci wss.is_int_sampler = 1; 1018bf215546Sopenharmony_ci wss.last_level = views[i]->texture->last_level; 1019bf215546Sopenharmony_ci /* When we emulate a integer cube texture (array) by using a texture 2d Array 1020bf215546Sopenharmony_ci * the coordinates are evaluated to always reside withing the acceptable range 1021bf215546Sopenharmony_ci * because the 3d ray for picking the texel is always pointing at one cube face, 1022bf215546Sopenharmony_ci * hence we can skip the boundary condition handling when the texture operations are 1023bf215546Sopenharmony_ci * lowered to texel fetches later. */ 1024bf215546Sopenharmony_ci wss.skip_boundary_conditions = views[i]->target == PIPE_TEXTURE_CUBE || 1025bf215546Sopenharmony_ci views[i]->target == PIPE_TEXTURE_CUBE_ARRAY; 1026bf215546Sopenharmony_ci } else { 1027bf215546Sopenharmony_ci wss.is_int_sampler = 0; 1028bf215546Sopenharmony_ci } 1029bf215546Sopenharmony_ci /* We need the swizzle state for compare texture lowering, because it 1030bf215546Sopenharmony_ci * encode the use of the shadow texture lookup result as either luminosity, 1031bf215546Sopenharmony_ci * intensity, or alpha. and we need the swizzle state for applying the 1032bf215546Sopenharmony_ci * boundary color correctly */ 1033bf215546Sopenharmony_ci struct d3d12_sampler_view *ss = d3d12_sampler_view(views[i]); 1034bf215546Sopenharmony_ci swizzle_state.swizzle_r = ss->swizzle_override_r; 1035bf215546Sopenharmony_ci swizzle_state.swizzle_g = ss->swizzle_override_g; 1036bf215546Sopenharmony_ci swizzle_state.swizzle_b = ss->swizzle_override_b; 1037bf215546Sopenharmony_ci swizzle_state.swizzle_a = ss->swizzle_override_a; 1038bf215546Sopenharmony_ci } 1039bf215546Sopenharmony_ci } 1040bf215546Sopenharmony_ci 1041bf215546Sopenharmony_ci for (unsigned i = 0; i < unbind_num_trailing_slots; i++) { 1042bf215546Sopenharmony_ci struct pipe_sampler_view *&old_view = ctx->sampler_views[shader_type][start_slot + num_views + i]; 1043bf215546Sopenharmony_ci if (old_view) 1044bf215546Sopenharmony_ci d3d12_decrement_sampler_view_bind_count(pctx, shader_type, old_view); 1045bf215546Sopenharmony_ci pipe_sampler_view_reference(&old_view, NULL); 1046bf215546Sopenharmony_ci } 1047bf215546Sopenharmony_ci ctx->num_sampler_views[shader_type] = start_slot + num_views; 1048bf215546Sopenharmony_ci ctx->shader_dirty[shader_type] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS; 1049bf215546Sopenharmony_ci} 1050bf215546Sopenharmony_ci 1051bf215546Sopenharmony_cistatic void 1052bf215546Sopenharmony_cid3d12_destroy_sampler_view(struct pipe_context *pctx, 1053bf215546Sopenharmony_ci struct pipe_sampler_view *pview) 1054bf215546Sopenharmony_ci{ 1055bf215546Sopenharmony_ci struct d3d12_sampler_view *view = d3d12_sampler_view(pview); 1056bf215546Sopenharmony_ci d3d12_descriptor_handle_free(&view->handle); 1057bf215546Sopenharmony_ci pipe_resource_reference(&view->base.texture, NULL); 1058bf215546Sopenharmony_ci FREE(view); 1059bf215546Sopenharmony_ci} 1060bf215546Sopenharmony_ci 1061bf215546Sopenharmony_cistatic void 1062bf215546Sopenharmony_cidelete_shader(struct d3d12_context *ctx, enum pipe_shader_type stage, 1063bf215546Sopenharmony_ci struct d3d12_shader_selector *shader) 1064bf215546Sopenharmony_ci{ 1065bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_cache_invalidate_shader(ctx, stage, shader); 1066bf215546Sopenharmony_ci 1067bf215546Sopenharmony_ci /* Make sure the pipeline state no longer reference the deleted shader */ 1068bf215546Sopenharmony_ci struct d3d12_shader *iter = shader->first; 1069bf215546Sopenharmony_ci while (iter) { 1070bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.stages[stage] == iter) { 1071bf215546Sopenharmony_ci ctx->gfx_pipeline_state.stages[stage] = NULL; 1072bf215546Sopenharmony_ci break; 1073bf215546Sopenharmony_ci } 1074bf215546Sopenharmony_ci iter = iter->next_variant; 1075bf215546Sopenharmony_ci } 1076bf215546Sopenharmony_ci 1077bf215546Sopenharmony_ci d3d12_shader_free(shader); 1078bf215546Sopenharmony_ci} 1079bf215546Sopenharmony_ci 1080bf215546Sopenharmony_cistatic void 1081bf215546Sopenharmony_cibind_stage(struct d3d12_context *ctx, enum pipe_shader_type stage, 1082bf215546Sopenharmony_ci struct d3d12_shader_selector *shader) 1083bf215546Sopenharmony_ci{ 1084bf215546Sopenharmony_ci assert(stage < D3D12_GFX_SHADER_STAGES); 1085bf215546Sopenharmony_ci ctx->gfx_stages[stage] = shader; 1086bf215546Sopenharmony_ci} 1087bf215546Sopenharmony_ci 1088bf215546Sopenharmony_cistatic void * 1089bf215546Sopenharmony_cid3d12_create_vs_state(struct pipe_context *pctx, 1090bf215546Sopenharmony_ci const struct pipe_shader_state *shader) 1091bf215546Sopenharmony_ci{ 1092bf215546Sopenharmony_ci return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX, shader); 1093bf215546Sopenharmony_ci} 1094bf215546Sopenharmony_ci 1095bf215546Sopenharmony_cistatic void 1096bf215546Sopenharmony_cid3d12_bind_vs_state(struct pipe_context *pctx, 1097bf215546Sopenharmony_ci void *vss) 1098bf215546Sopenharmony_ci{ 1099bf215546Sopenharmony_ci bind_stage(d3d12_context(pctx), PIPE_SHADER_VERTEX, 1100bf215546Sopenharmony_ci (struct d3d12_shader_selector *) vss); 1101bf215546Sopenharmony_ci} 1102bf215546Sopenharmony_ci 1103bf215546Sopenharmony_cistatic void 1104bf215546Sopenharmony_cid3d12_delete_vs_state(struct pipe_context *pctx, 1105bf215546Sopenharmony_ci void *vs) 1106bf215546Sopenharmony_ci{ 1107bf215546Sopenharmony_ci delete_shader(d3d12_context(pctx), PIPE_SHADER_VERTEX, 1108bf215546Sopenharmony_ci (struct d3d12_shader_selector *) vs); 1109bf215546Sopenharmony_ci} 1110bf215546Sopenharmony_ci 1111bf215546Sopenharmony_cistatic void * 1112bf215546Sopenharmony_cid3d12_create_fs_state(struct pipe_context *pctx, 1113bf215546Sopenharmony_ci const struct pipe_shader_state *shader) 1114bf215546Sopenharmony_ci{ 1115bf215546Sopenharmony_ci return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, shader); 1116bf215546Sopenharmony_ci} 1117bf215546Sopenharmony_ci 1118bf215546Sopenharmony_cistatic void 1119bf215546Sopenharmony_cid3d12_bind_fs_state(struct pipe_context *pctx, 1120bf215546Sopenharmony_ci void *fss) 1121bf215546Sopenharmony_ci{ 1122bf215546Sopenharmony_ci bind_stage(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, 1123bf215546Sopenharmony_ci (struct d3d12_shader_selector *) fss); 1124bf215546Sopenharmony_ci} 1125bf215546Sopenharmony_ci 1126bf215546Sopenharmony_cistatic void 1127bf215546Sopenharmony_cid3d12_delete_fs_state(struct pipe_context *pctx, 1128bf215546Sopenharmony_ci void *fs) 1129bf215546Sopenharmony_ci{ 1130bf215546Sopenharmony_ci delete_shader(d3d12_context(pctx), PIPE_SHADER_FRAGMENT, 1131bf215546Sopenharmony_ci (struct d3d12_shader_selector *) fs); 1132bf215546Sopenharmony_ci} 1133bf215546Sopenharmony_ci 1134bf215546Sopenharmony_cistatic void * 1135bf215546Sopenharmony_cid3d12_create_gs_state(struct pipe_context *pctx, 1136bf215546Sopenharmony_ci const struct pipe_shader_state *shader) 1137bf215546Sopenharmony_ci{ 1138bf215546Sopenharmony_ci return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, shader); 1139bf215546Sopenharmony_ci} 1140bf215546Sopenharmony_ci 1141bf215546Sopenharmony_cistatic void 1142bf215546Sopenharmony_cid3d12_bind_gs_state(struct pipe_context *pctx, void *gss) 1143bf215546Sopenharmony_ci{ 1144bf215546Sopenharmony_ci bind_stage(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, 1145bf215546Sopenharmony_ci (struct d3d12_shader_selector *) gss); 1146bf215546Sopenharmony_ci} 1147bf215546Sopenharmony_ci 1148bf215546Sopenharmony_cistatic void 1149bf215546Sopenharmony_cid3d12_delete_gs_state(struct pipe_context *pctx, void *gs) 1150bf215546Sopenharmony_ci{ 1151bf215546Sopenharmony_ci delete_shader(d3d12_context(pctx), PIPE_SHADER_GEOMETRY, 1152bf215546Sopenharmony_ci (struct d3d12_shader_selector *) gs); 1153bf215546Sopenharmony_ci} 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_cistatic void * 1156bf215546Sopenharmony_cid3d12_create_tcs_state(struct pipe_context *pctx, 1157bf215546Sopenharmony_ci const struct pipe_shader_state *shader) 1158bf215546Sopenharmony_ci{ 1159bf215546Sopenharmony_ci return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL, shader); 1160bf215546Sopenharmony_ci} 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_cistatic void 1163bf215546Sopenharmony_cid3d12_bind_tcs_state(struct pipe_context *pctx, void *tcss) 1164bf215546Sopenharmony_ci{ 1165bf215546Sopenharmony_ci bind_stage(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL, 1166bf215546Sopenharmony_ci (struct d3d12_shader_selector *)tcss); 1167bf215546Sopenharmony_ci} 1168bf215546Sopenharmony_ci 1169bf215546Sopenharmony_cistatic void 1170bf215546Sopenharmony_cid3d12_delete_tcs_state(struct pipe_context *pctx, void *tcs) 1171bf215546Sopenharmony_ci{ 1172bf215546Sopenharmony_ci delete_shader(d3d12_context(pctx), PIPE_SHADER_TESS_CTRL, 1173bf215546Sopenharmony_ci (struct d3d12_shader_selector *)tcs); 1174bf215546Sopenharmony_ci} 1175bf215546Sopenharmony_ci 1176bf215546Sopenharmony_cistatic void * 1177bf215546Sopenharmony_cid3d12_create_tes_state(struct pipe_context *pctx, 1178bf215546Sopenharmony_ci const struct pipe_shader_state *shader) 1179bf215546Sopenharmony_ci{ 1180bf215546Sopenharmony_ci return d3d12_create_shader(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL, shader); 1181bf215546Sopenharmony_ci} 1182bf215546Sopenharmony_ci 1183bf215546Sopenharmony_cistatic void 1184bf215546Sopenharmony_cid3d12_bind_tes_state(struct pipe_context *pctx, void *tess) 1185bf215546Sopenharmony_ci{ 1186bf215546Sopenharmony_ci bind_stage(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL, 1187bf215546Sopenharmony_ci (struct d3d12_shader_selector *)tess); 1188bf215546Sopenharmony_ci} 1189bf215546Sopenharmony_ci 1190bf215546Sopenharmony_cistatic void 1191bf215546Sopenharmony_cid3d12_delete_tes_state(struct pipe_context *pctx, void *tes) 1192bf215546Sopenharmony_ci{ 1193bf215546Sopenharmony_ci delete_shader(d3d12_context(pctx), PIPE_SHADER_TESS_EVAL, 1194bf215546Sopenharmony_ci (struct d3d12_shader_selector *)tes); 1195bf215546Sopenharmony_ci} 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_cistatic void * 1198bf215546Sopenharmony_cid3d12_create_compute_state(struct pipe_context *pctx, 1199bf215546Sopenharmony_ci const struct pipe_compute_state *shader) 1200bf215546Sopenharmony_ci{ 1201bf215546Sopenharmony_ci return d3d12_create_compute_shader(d3d12_context(pctx), shader); 1202bf215546Sopenharmony_ci} 1203bf215546Sopenharmony_ci 1204bf215546Sopenharmony_cistatic void 1205bf215546Sopenharmony_cid3d12_bind_compute_state(struct pipe_context *pctx, void *css) 1206bf215546Sopenharmony_ci{ 1207bf215546Sopenharmony_ci d3d12_context(pctx)->compute_state = (struct d3d12_shader_selector *)css; 1208bf215546Sopenharmony_ci} 1209bf215546Sopenharmony_ci 1210bf215546Sopenharmony_cistatic void 1211bf215546Sopenharmony_cid3d12_delete_compute_state(struct pipe_context *pctx, void *cs) 1212bf215546Sopenharmony_ci{ 1213bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1214bf215546Sopenharmony_ci struct d3d12_shader_selector *shader = (struct d3d12_shader_selector *)cs; 1215bf215546Sopenharmony_ci d3d12_compute_pipeline_state_cache_invalidate_shader(ctx, shader); 1216bf215546Sopenharmony_ci 1217bf215546Sopenharmony_ci /* Make sure the pipeline state no longer reference the deleted shader */ 1218bf215546Sopenharmony_ci struct d3d12_shader *iter = shader->first; 1219bf215546Sopenharmony_ci while (iter) { 1220bf215546Sopenharmony_ci if (ctx->compute_pipeline_state.stage == iter) { 1221bf215546Sopenharmony_ci ctx->compute_pipeline_state.stage = NULL; 1222bf215546Sopenharmony_ci break; 1223bf215546Sopenharmony_ci } 1224bf215546Sopenharmony_ci iter = iter->next_variant; 1225bf215546Sopenharmony_ci } 1226bf215546Sopenharmony_ci 1227bf215546Sopenharmony_ci d3d12_shader_free(shader); 1228bf215546Sopenharmony_ci} 1229bf215546Sopenharmony_ci 1230bf215546Sopenharmony_cistatic bool 1231bf215546Sopenharmony_cid3d12_init_polygon_stipple(struct pipe_context *pctx) 1232bf215546Sopenharmony_ci{ 1233bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1234bf215546Sopenharmony_ci 1235bf215546Sopenharmony_ci ctx->pstipple.texture = util_pstipple_create_stipple_texture(pctx, NULL); 1236bf215546Sopenharmony_ci if (!ctx->pstipple.texture) 1237bf215546Sopenharmony_ci return false; 1238bf215546Sopenharmony_ci 1239bf215546Sopenharmony_ci ctx->pstipple.sampler_view = util_pstipple_create_sampler_view(pctx, ctx->pstipple.texture); 1240bf215546Sopenharmony_ci if (!ctx->pstipple.sampler_view) 1241bf215546Sopenharmony_ci return false; 1242bf215546Sopenharmony_ci 1243bf215546Sopenharmony_ci ctx->pstipple.sampler_cso = (struct d3d12_sampler_state *)util_pstipple_create_sampler(pctx); 1244bf215546Sopenharmony_ci if (!ctx->pstipple.sampler_cso) 1245bf215546Sopenharmony_ci return false; 1246bf215546Sopenharmony_ci 1247bf215546Sopenharmony_ci return true; 1248bf215546Sopenharmony_ci} 1249bf215546Sopenharmony_ci 1250bf215546Sopenharmony_cistatic void 1251bf215546Sopenharmony_cid3d12_set_polygon_stipple(struct pipe_context *pctx, 1252bf215546Sopenharmony_ci const struct pipe_poly_stipple *ps) 1253bf215546Sopenharmony_ci{ 1254bf215546Sopenharmony_ci static bool initialized = false; 1255bf215546Sopenharmony_ci static const uint32_t zero[32] = {0}; 1256bf215546Sopenharmony_ci static uint32_t undef[32] = {0}; 1257bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1258bf215546Sopenharmony_ci 1259bf215546Sopenharmony_ci if (!initialized) 1260bf215546Sopenharmony_ci memset(undef, UINT32_MAX, sizeof(undef)); 1261bf215546Sopenharmony_ci 1262bf215546Sopenharmony_ci if (!memcmp(ctx->pstipple.pattern, ps->stipple, sizeof(ps->stipple))) 1263bf215546Sopenharmony_ci return; 1264bf215546Sopenharmony_ci 1265bf215546Sopenharmony_ci memcpy(ctx->pstipple.pattern, ps->stipple, sizeof(ps->stipple)); 1266bf215546Sopenharmony_ci ctx->pstipple.enabled = !!memcmp(ps->stipple, undef, sizeof(ps->stipple)) && 1267bf215546Sopenharmony_ci !!memcmp(ps->stipple, zero, sizeof(ps->stipple)); 1268bf215546Sopenharmony_ci if (ctx->pstipple.enabled) 1269bf215546Sopenharmony_ci util_pstipple_update_stipple_texture(pctx, ctx->pstipple.texture, ps->stipple); 1270bf215546Sopenharmony_ci} 1271bf215546Sopenharmony_ci 1272bf215546Sopenharmony_cistatic void 1273bf215546Sopenharmony_cid3d12_set_vertex_buffers(struct pipe_context *pctx, 1274bf215546Sopenharmony_ci unsigned start_slot, 1275bf215546Sopenharmony_ci unsigned num_buffers, 1276bf215546Sopenharmony_ci unsigned unbind_num_trailing_slots, 1277bf215546Sopenharmony_ci bool take_ownership, 1278bf215546Sopenharmony_ci const struct pipe_vertex_buffer *buffers) 1279bf215546Sopenharmony_ci{ 1280bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1281bf215546Sopenharmony_ci util_set_vertex_buffers_count(ctx->vbs, &ctx->num_vbs, 1282bf215546Sopenharmony_ci buffers, start_slot, num_buffers, 1283bf215546Sopenharmony_ci unbind_num_trailing_slots, 1284bf215546Sopenharmony_ci take_ownership); 1285bf215546Sopenharmony_ci 1286bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->num_vbs; ++i) { 1287bf215546Sopenharmony_ci const struct pipe_vertex_buffer* buf = ctx->vbs + i; 1288bf215546Sopenharmony_ci if (!buf->buffer.resource) 1289bf215546Sopenharmony_ci continue; 1290bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(buf->buffer.resource); 1291bf215546Sopenharmony_ci ctx->vbvs[i].BufferLocation = d3d12_resource_gpu_virtual_address(res) + buf->buffer_offset; 1292bf215546Sopenharmony_ci ctx->vbvs[i].StrideInBytes = buf->stride; 1293bf215546Sopenharmony_ci ctx->vbvs[i].SizeInBytes = res->base.b.width0 - buf->buffer_offset; 1294bf215546Sopenharmony_ci } 1295bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS; 1296bf215546Sopenharmony_ci} 1297bf215546Sopenharmony_ci 1298bf215546Sopenharmony_cistatic void 1299bf215546Sopenharmony_cid3d12_set_viewport_states(struct pipe_context *pctx, 1300bf215546Sopenharmony_ci unsigned start_slot, 1301bf215546Sopenharmony_ci unsigned num_viewports, 1302bf215546Sopenharmony_ci const struct pipe_viewport_state *state) 1303bf215546Sopenharmony_ci{ 1304bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1305bf215546Sopenharmony_ci 1306bf215546Sopenharmony_ci for (unsigned i = 0; i < num_viewports; ++i) { 1307bf215546Sopenharmony_ci if (state[i].scale[1] < 0) { 1308bf215546Sopenharmony_ci ctx->flip_y = 1.0f; 1309bf215546Sopenharmony_ci ctx->viewports[start_slot + i].TopLeftY = state[i].translate[1] + state[i].scale[1]; 1310bf215546Sopenharmony_ci ctx->viewports[start_slot + i].Height = -state[i].scale[1] * 2; 1311bf215546Sopenharmony_ci } else { 1312bf215546Sopenharmony_ci ctx->flip_y = -1.0f; 1313bf215546Sopenharmony_ci ctx->viewports[start_slot + i].TopLeftY = state[i].translate[1] - state[i].scale[1]; 1314bf215546Sopenharmony_ci ctx->viewports[start_slot + i].Height = state[i].scale[1] * 2; 1315bf215546Sopenharmony_ci } 1316bf215546Sopenharmony_ci ctx->viewports[start_slot + i].TopLeftX = state[i].translate[0] - state[i].scale[0]; 1317bf215546Sopenharmony_ci ctx->viewports[start_slot + i].Width = state[i].scale[0] * 2; 1318bf215546Sopenharmony_ci 1319bf215546Sopenharmony_ci float near_depth = state[i].translate[2]; 1320bf215546Sopenharmony_ci float far_depth = state[i].translate[2] + state[i].scale[2]; 1321bf215546Sopenharmony_ci 1322bf215546Sopenharmony_ci /* When the rasterizer is configured for "full" depth clipping ([-1, 1]) 1323bf215546Sopenharmony_ci * the viewport that we get is set to cover the positive half of clip space. 1324bf215546Sopenharmony_ci * E.g. a [0, 1] viewport from the GL API will come to the driver as [0.5, 1]. 1325bf215546Sopenharmony_ci * Since we halve clipping space from [-1, 1] to [0, 1], we need to double the 1326bf215546Sopenharmony_ci * viewport, treating translate as the center instead of the near plane. When 1327bf215546Sopenharmony_ci * the rasterizer is configured for "half" depth clipping ([0, 1]), the viewport 1328bf215546Sopenharmony_ci * covers the entire clip range, so no fixup is needed. 1329bf215546Sopenharmony_ci * 1330bf215546Sopenharmony_ci * Note: If halfz mode changes, both the rasterizer and viewport are dirtied, 1331bf215546Sopenharmony_ci * and on the next draw we will get the rasterizer state first, and viewport 1332bf215546Sopenharmony_ci * second, because ST_NEW_RASTERIZER comes before ST_NEW_VIEWPORT. 1333bf215546Sopenharmony_ci */ 1334bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.rast && !ctx->gfx_pipeline_state.rast->base.clip_halfz) { 1335bf215546Sopenharmony_ci near_depth -= state[i].scale[2]; 1336bf215546Sopenharmony_ci } 1337bf215546Sopenharmony_ci 1338bf215546Sopenharmony_ci bool reverse_depth_range = near_depth > far_depth; 1339bf215546Sopenharmony_ci if (reverse_depth_range) { 1340bf215546Sopenharmony_ci float tmp = near_depth; 1341bf215546Sopenharmony_ci near_depth = far_depth; 1342bf215546Sopenharmony_ci far_depth = tmp; 1343bf215546Sopenharmony_ci ctx->reverse_depth_range |= (1 << (start_slot + i)); 1344bf215546Sopenharmony_ci } else 1345bf215546Sopenharmony_ci ctx->reverse_depth_range &= ~(1 << (start_slot + i)); 1346bf215546Sopenharmony_ci ctx->viewports[start_slot + i].MinDepth = near_depth; 1347bf215546Sopenharmony_ci ctx->viewports[start_slot + i].MaxDepth = far_depth; 1348bf215546Sopenharmony_ci ctx->viewport_states[start_slot + i] = state[i]; 1349bf215546Sopenharmony_ci } 1350bf215546Sopenharmony_ci ctx->num_viewports = start_slot + num_viewports; 1351bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_VIEWPORT; 1352bf215546Sopenharmony_ci} 1353bf215546Sopenharmony_ci 1354bf215546Sopenharmony_ci 1355bf215546Sopenharmony_cistatic void 1356bf215546Sopenharmony_cid3d12_set_scissor_states(struct pipe_context *pctx, 1357bf215546Sopenharmony_ci unsigned start_slot, unsigned num_scissors, 1358bf215546Sopenharmony_ci const struct pipe_scissor_state *states) 1359bf215546Sopenharmony_ci{ 1360bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1361bf215546Sopenharmony_ci 1362bf215546Sopenharmony_ci for (unsigned i = 0; i < num_scissors; i++) { 1363bf215546Sopenharmony_ci ctx->scissors[start_slot + i].left = states[i].minx; 1364bf215546Sopenharmony_ci ctx->scissors[start_slot + i].top = states[i].miny; 1365bf215546Sopenharmony_ci ctx->scissors[start_slot + i].right = states[i].maxx; 1366bf215546Sopenharmony_ci ctx->scissors[start_slot + i].bottom = states[i].maxy; 1367bf215546Sopenharmony_ci ctx->scissor_states[start_slot + i] = states[i]; 1368bf215546Sopenharmony_ci } 1369bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_SCISSOR; 1370bf215546Sopenharmony_ci} 1371bf215546Sopenharmony_ci 1372bf215546Sopenharmony_cistatic void 1373bf215546Sopenharmony_cid3d12_decrement_constant_buffer_bind_count(struct d3d12_context *ctx, 1374bf215546Sopenharmony_ci enum pipe_shader_type shader, 1375bf215546Sopenharmony_ci struct d3d12_resource *res) { 1376bf215546Sopenharmony_ci assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0); 1377bf215546Sopenharmony_ci res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV]--; 1378bf215546Sopenharmony_ci} 1379bf215546Sopenharmony_ci 1380bf215546Sopenharmony_cistatic void 1381bf215546Sopenharmony_cid3d12_increment_constant_buffer_bind_count(struct d3d12_context *ctx, 1382bf215546Sopenharmony_ci enum pipe_shader_type shader, 1383bf215546Sopenharmony_ci struct d3d12_resource *res) { 1384bf215546Sopenharmony_ci res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_CBV]++; 1385bf215546Sopenharmony_ci} 1386bf215546Sopenharmony_ci 1387bf215546Sopenharmony_cistatic void 1388bf215546Sopenharmony_cid3d12_set_constant_buffer(struct pipe_context *pctx, 1389bf215546Sopenharmony_ci enum pipe_shader_type shader, uint index, 1390bf215546Sopenharmony_ci bool take_ownership, 1391bf215546Sopenharmony_ci const struct pipe_constant_buffer *buf) 1392bf215546Sopenharmony_ci{ 1393bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1394bf215546Sopenharmony_ci struct d3d12_resource *old_buf = d3d12_resource(ctx->cbufs[shader][index].buffer); 1395bf215546Sopenharmony_ci if (old_buf) 1396bf215546Sopenharmony_ci d3d12_decrement_constant_buffer_bind_count(ctx, shader, old_buf); 1397bf215546Sopenharmony_ci 1398bf215546Sopenharmony_ci if (buf) { 1399bf215546Sopenharmony_ci unsigned offset = buf->buffer_offset; 1400bf215546Sopenharmony_ci if (buf->user_buffer) { 1401bf215546Sopenharmony_ci u_upload_data(pctx->const_uploader, 0, buf->buffer_size, 1402bf215546Sopenharmony_ci D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT, 1403bf215546Sopenharmony_ci buf->user_buffer, &offset, &ctx->cbufs[shader][index].buffer); 1404bf215546Sopenharmony_ci d3d12_increment_constant_buffer_bind_count(ctx, shader, 1405bf215546Sopenharmony_ci d3d12_resource(ctx->cbufs[shader][index].buffer)); 1406bf215546Sopenharmony_ci } else { 1407bf215546Sopenharmony_ci struct pipe_resource *buffer = buf->buffer; 1408bf215546Sopenharmony_ci if (buffer) 1409bf215546Sopenharmony_ci d3d12_increment_constant_buffer_bind_count(ctx, shader, d3d12_resource(buffer)); 1410bf215546Sopenharmony_ci 1411bf215546Sopenharmony_ci if (take_ownership) { 1412bf215546Sopenharmony_ci pipe_resource_reference(&ctx->cbufs[shader][index].buffer, NULL); 1413bf215546Sopenharmony_ci ctx->cbufs[shader][index].buffer = buffer; 1414bf215546Sopenharmony_ci } else { 1415bf215546Sopenharmony_ci pipe_resource_reference(&ctx->cbufs[shader][index].buffer, buffer); 1416bf215546Sopenharmony_ci } 1417bf215546Sopenharmony_ci } 1418bf215546Sopenharmony_ci 1419bf215546Sopenharmony_ci ctx->cbufs[shader][index].buffer_offset = offset; 1420bf215546Sopenharmony_ci ctx->cbufs[shader][index].buffer_size = buf->buffer_size; 1421bf215546Sopenharmony_ci ctx->cbufs[shader][index].user_buffer = NULL; 1422bf215546Sopenharmony_ci 1423bf215546Sopenharmony_ci } else { 1424bf215546Sopenharmony_ci pipe_resource_reference(&ctx->cbufs[shader][index].buffer, NULL); 1425bf215546Sopenharmony_ci ctx->cbufs[shader][index].buffer_offset = 0; 1426bf215546Sopenharmony_ci ctx->cbufs[shader][index].buffer_size = 0; 1427bf215546Sopenharmony_ci ctx->cbufs[shader][index].user_buffer = NULL; 1428bf215546Sopenharmony_ci } 1429bf215546Sopenharmony_ci ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_CONSTBUF; 1430bf215546Sopenharmony_ci} 1431bf215546Sopenharmony_ci 1432bf215546Sopenharmony_cistatic void 1433bf215546Sopenharmony_cid3d12_set_framebuffer_state(struct pipe_context *pctx, 1434bf215546Sopenharmony_ci const struct pipe_framebuffer_state *state) 1435bf215546Sopenharmony_ci{ 1436bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1437bf215546Sopenharmony_ci int samples = -1; 1438bf215546Sopenharmony_ci 1439bf215546Sopenharmony_ci bool prev_cbufs_or_zsbuf = ctx->fb.nr_cbufs || ctx->fb.zsbuf; 1440bf215546Sopenharmony_ci util_copy_framebuffer_state(&d3d12_context(pctx)->fb, state); 1441bf215546Sopenharmony_ci bool new_cbufs_or_zsbuf = ctx->fb.nr_cbufs || ctx->fb.zsbuf; 1442bf215546Sopenharmony_ci 1443bf215546Sopenharmony_ci ctx->gfx_pipeline_state.num_cbufs = state->nr_cbufs; 1444bf215546Sopenharmony_ci ctx->gfx_pipeline_state.has_float_rtv = false; 1445bf215546Sopenharmony_ci for (int i = 0; i < state->nr_cbufs; ++i) { 1446bf215546Sopenharmony_ci if (state->cbufs[i]) { 1447bf215546Sopenharmony_ci if (util_format_is_float(state->cbufs[i]->format)) 1448bf215546Sopenharmony_ci ctx->gfx_pipeline_state.has_float_rtv = true; 1449bf215546Sopenharmony_ci ctx->gfx_pipeline_state.rtv_formats[i] = d3d12_get_format(state->cbufs[i]->format); 1450bf215546Sopenharmony_ci samples = MAX2(samples, (int)state->cbufs[i]->texture->nr_samples); 1451bf215546Sopenharmony_ci } else { 1452bf215546Sopenharmony_ci ctx->gfx_pipeline_state.rtv_formats[i] = DXGI_FORMAT_UNKNOWN; 1453bf215546Sopenharmony_ci } 1454bf215546Sopenharmony_ci } 1455bf215546Sopenharmony_ci 1456bf215546Sopenharmony_ci if (state->zsbuf) { 1457bf215546Sopenharmony_ci ctx->gfx_pipeline_state.dsv_format = d3d12_get_resource_rt_format(state->zsbuf->format); 1458bf215546Sopenharmony_ci samples = MAX2(samples, (int)ctx->fb.zsbuf->texture->nr_samples); 1459bf215546Sopenharmony_ci } else 1460bf215546Sopenharmony_ci ctx->gfx_pipeline_state.dsv_format = DXGI_FORMAT_UNKNOWN; 1461bf215546Sopenharmony_ci 1462bf215546Sopenharmony_ci if (samples < 0) 1463bf215546Sopenharmony_ci samples = state->samples; 1464bf215546Sopenharmony_ci 1465bf215546Sopenharmony_ci ctx->gfx_pipeline_state.samples = MAX2(samples, 1); 1466bf215546Sopenharmony_ci 1467bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_FRAMEBUFFER; 1468bf215546Sopenharmony_ci if (!prev_cbufs_or_zsbuf || !new_cbufs_or_zsbuf) 1469bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_VIEWPORT; 1470bf215546Sopenharmony_ci} 1471bf215546Sopenharmony_ci 1472bf215546Sopenharmony_cistatic void 1473bf215546Sopenharmony_cid3d12_set_blend_color(struct pipe_context *pctx, 1474bf215546Sopenharmony_ci const struct pipe_blend_color *color) 1475bf215546Sopenharmony_ci{ 1476bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1477bf215546Sopenharmony_ci memcpy(ctx->blend_factor, color->color, sizeof(float) * 4); 1478bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_BLEND_COLOR; 1479bf215546Sopenharmony_ci} 1480bf215546Sopenharmony_ci 1481bf215546Sopenharmony_cistatic void 1482bf215546Sopenharmony_cid3d12_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 1483bf215546Sopenharmony_ci{ 1484bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1485bf215546Sopenharmony_ci ctx->gfx_pipeline_state.sample_mask = sample_mask; 1486bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_SAMPLE_MASK; 1487bf215546Sopenharmony_ci} 1488bf215546Sopenharmony_ci 1489bf215546Sopenharmony_cistatic void 1490bf215546Sopenharmony_cid3d12_set_stencil_ref(struct pipe_context *pctx, 1491bf215546Sopenharmony_ci const struct pipe_stencil_ref ref) 1492bf215546Sopenharmony_ci{ 1493bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1494bf215546Sopenharmony_ci if ((ref.ref_value[0] != ref.ref_value[1]) && 1495bf215546Sopenharmony_ci (d3d12_debug & D3D12_DEBUG_VERBOSE)) 1496bf215546Sopenharmony_ci debug_printf("D3D12: Different values for front and back stencil reference are not supported\n"); 1497bf215546Sopenharmony_ci ctx->stencil_ref = ref; 1498bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_STENCIL_REF; 1499bf215546Sopenharmony_ci} 1500bf215546Sopenharmony_ci 1501bf215546Sopenharmony_cistatic void 1502bf215546Sopenharmony_cid3d12_set_clip_state(struct pipe_context *pctx, 1503bf215546Sopenharmony_ci const struct pipe_clip_state *pcs) 1504bf215546Sopenharmony_ci{ 1505bf215546Sopenharmony_ci} 1506bf215546Sopenharmony_ci 1507bf215546Sopenharmony_cistatic struct pipe_stream_output_target * 1508bf215546Sopenharmony_cid3d12_create_stream_output_target(struct pipe_context *pctx, 1509bf215546Sopenharmony_ci struct pipe_resource *pres, 1510bf215546Sopenharmony_ci unsigned buffer_offset, 1511bf215546Sopenharmony_ci unsigned buffer_size) 1512bf215546Sopenharmony_ci{ 1513bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(pres); 1514bf215546Sopenharmony_ci struct d3d12_stream_output_target *cso = CALLOC_STRUCT(d3d12_stream_output_target); 1515bf215546Sopenharmony_ci 1516bf215546Sopenharmony_ci if (!cso) 1517bf215546Sopenharmony_ci return NULL; 1518bf215546Sopenharmony_ci 1519bf215546Sopenharmony_ci pipe_reference_init(&cso->base.reference, 1); 1520bf215546Sopenharmony_ci pipe_resource_reference(&cso->base.buffer, pres); 1521bf215546Sopenharmony_ci cso->base.buffer_offset = buffer_offset; 1522bf215546Sopenharmony_ci cso->base.buffer_size = buffer_size; 1523bf215546Sopenharmony_ci cso->base.context = pctx; 1524bf215546Sopenharmony_ci 1525bf215546Sopenharmony_ci if (res->bo && res->bo->buffer && d3d12_buffer(res->bo->buffer)->map) 1526bf215546Sopenharmony_ci util_range_add(pres, &res->valid_buffer_range, buffer_offset, 1527bf215546Sopenharmony_ci buffer_offset + buffer_size); 1528bf215546Sopenharmony_ci 1529bf215546Sopenharmony_ci return &cso->base; 1530bf215546Sopenharmony_ci} 1531bf215546Sopenharmony_ci 1532bf215546Sopenharmony_cistatic void 1533bf215546Sopenharmony_cid3d12_stream_output_target_destroy(struct pipe_context *ctx, 1534bf215546Sopenharmony_ci struct pipe_stream_output_target *state) 1535bf215546Sopenharmony_ci{ 1536bf215546Sopenharmony_ci pipe_resource_reference(&state->buffer, NULL); 1537bf215546Sopenharmony_ci 1538bf215546Sopenharmony_ci FREE(state); 1539bf215546Sopenharmony_ci} 1540bf215546Sopenharmony_ci 1541bf215546Sopenharmony_cistatic void 1542bf215546Sopenharmony_cifill_stream_output_buffer_view(D3D12_STREAM_OUTPUT_BUFFER_VIEW *view, 1543bf215546Sopenharmony_ci struct d3d12_stream_output_target *target) 1544bf215546Sopenharmony_ci{ 1545bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(target->base.buffer); 1546bf215546Sopenharmony_ci struct d3d12_resource *fill_res = d3d12_resource(target->fill_buffer); 1547bf215546Sopenharmony_ci 1548bf215546Sopenharmony_ci view->SizeInBytes = target->base.buffer_size; 1549bf215546Sopenharmony_ci view->BufferLocation = d3d12_resource_gpu_virtual_address(res) + target->base.buffer_offset; 1550bf215546Sopenharmony_ci view->BufferFilledSizeLocation = d3d12_resource_gpu_virtual_address(fill_res) + target->fill_buffer_offset; 1551bf215546Sopenharmony_ci} 1552bf215546Sopenharmony_ci 1553bf215546Sopenharmony_cistatic void 1554bf215546Sopenharmony_ciupdate_so_fill_buffer_count(struct d3d12_context *ctx, 1555bf215546Sopenharmony_ci struct pipe_resource *fill_buffer, 1556bf215546Sopenharmony_ci unsigned fill_buffer_offset, 1557bf215546Sopenharmony_ci unsigned value) 1558bf215546Sopenharmony_ci{ 1559bf215546Sopenharmony_ci struct pipe_transfer *transfer = NULL; 1560bf215546Sopenharmony_ci uint32_t *ptr = (uint32_t *)pipe_buffer_map_range(&ctx->base, fill_buffer, 1561bf215546Sopenharmony_ci fill_buffer_offset, sizeof(uint32_t), PIPE_MAP_WRITE, &transfer); 1562bf215546Sopenharmony_ci *ptr = value; 1563bf215546Sopenharmony_ci pipe_buffer_unmap(&ctx->base, transfer); 1564bf215546Sopenharmony_ci} 1565bf215546Sopenharmony_ci 1566bf215546Sopenharmony_cistatic void 1567bf215546Sopenharmony_cid3d12_set_stream_output_targets(struct pipe_context *pctx, 1568bf215546Sopenharmony_ci unsigned num_targets, 1569bf215546Sopenharmony_ci struct pipe_stream_output_target **targets, 1570bf215546Sopenharmony_ci const unsigned *offsets) 1571bf215546Sopenharmony_ci{ 1572bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1573bf215546Sopenharmony_ci 1574bf215546Sopenharmony_ci assert(num_targets <= ARRAY_SIZE(ctx->so_targets)); 1575bf215546Sopenharmony_ci 1576bf215546Sopenharmony_ci d3d12_disable_fake_so_buffers(ctx); 1577bf215546Sopenharmony_ci 1578bf215546Sopenharmony_ci for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; i++) { 1579bf215546Sopenharmony_ci struct d3d12_stream_output_target *target = 1580bf215546Sopenharmony_ci i < num_targets ? (struct d3d12_stream_output_target *)targets[i] : NULL; 1581bf215546Sopenharmony_ci 1582bf215546Sopenharmony_ci if (target) { 1583bf215546Sopenharmony_ci /* Sub-allocate a new fill buffer each time to avoid GPU/CPU synchronization */ 1584bf215546Sopenharmony_ci if (offsets[i] != ~0u) { 1585bf215546Sopenharmony_ci u_suballocator_alloc(&ctx->so_allocator, sizeof(uint32_t) * 5, 16, 1586bf215546Sopenharmony_ci &target->fill_buffer_offset, &target->fill_buffer); 1587bf215546Sopenharmony_ci update_so_fill_buffer_count(ctx, target->fill_buffer, target->fill_buffer_offset, offsets[i]); 1588bf215546Sopenharmony_ci } 1589bf215546Sopenharmony_ci fill_stream_output_buffer_view(&ctx->so_buffer_views[i], target); 1590bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->so_targets[i], targets[i]); 1591bf215546Sopenharmony_ci } else { 1592bf215546Sopenharmony_ci ctx->so_buffer_views[i].BufferLocation = 0; 1593bf215546Sopenharmony_ci ctx->so_buffer_views[i].BufferFilledSizeLocation = 0; 1594bf215546Sopenharmony_ci ctx->so_buffer_views[i].SizeInBytes = 0; 1595bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->so_targets[i], NULL); 1596bf215546Sopenharmony_ci } 1597bf215546Sopenharmony_ci } 1598bf215546Sopenharmony_ci 1599bf215546Sopenharmony_ci ctx->gfx_pipeline_state.num_so_targets = num_targets; 1600bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 1601bf215546Sopenharmony_ci} 1602bf215546Sopenharmony_ci 1603bf215546Sopenharmony_cistatic void 1604bf215546Sopenharmony_cid3d12_decrement_ssbo_bind_count(struct d3d12_context *ctx, 1605bf215546Sopenharmony_ci enum pipe_shader_type shader, 1606bf215546Sopenharmony_ci struct d3d12_resource *res) { 1607bf215546Sopenharmony_ci assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_SSBO] > 0); 1608bf215546Sopenharmony_ci res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_SSBO]--; 1609bf215546Sopenharmony_ci} 1610bf215546Sopenharmony_ci 1611bf215546Sopenharmony_cistatic void 1612bf215546Sopenharmony_cid3d12_increment_ssbo_bind_count(struct d3d12_context *ctx, 1613bf215546Sopenharmony_ci enum pipe_shader_type shader, 1614bf215546Sopenharmony_ci struct d3d12_resource *res) { 1615bf215546Sopenharmony_ci res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_SSBO]++; 1616bf215546Sopenharmony_ci} 1617bf215546Sopenharmony_ci 1618bf215546Sopenharmony_cistatic void 1619bf215546Sopenharmony_cid3d12_set_shader_buffers(struct pipe_context *pctx, 1620bf215546Sopenharmony_ci enum pipe_shader_type shader, 1621bf215546Sopenharmony_ci unsigned start_slot, unsigned count, 1622bf215546Sopenharmony_ci const struct pipe_shader_buffer *buffers, 1623bf215546Sopenharmony_ci unsigned writable_bitmask) 1624bf215546Sopenharmony_ci{ 1625bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1626bf215546Sopenharmony_ci for (unsigned i = 0; i < count; ++i) { 1627bf215546Sopenharmony_ci struct pipe_shader_buffer *slot = &ctx->ssbo_views[shader][i + start_slot]; 1628bf215546Sopenharmony_ci if (slot->buffer) { 1629bf215546Sopenharmony_ci d3d12_decrement_ssbo_bind_count(ctx, shader, d3d12_resource(slot->buffer)); 1630bf215546Sopenharmony_ci pipe_resource_reference(&slot->buffer, NULL); 1631bf215546Sopenharmony_ci } 1632bf215546Sopenharmony_ci 1633bf215546Sopenharmony_ci if (buffers && buffers[i].buffer) { 1634bf215546Sopenharmony_ci pipe_resource_reference(&slot->buffer, buffers[i].buffer); 1635bf215546Sopenharmony_ci slot->buffer_offset = buffers[i].buffer_offset; 1636bf215546Sopenharmony_ci slot->buffer_size = buffers[i].buffer_size; 1637bf215546Sopenharmony_ci d3d12_increment_ssbo_bind_count(ctx, shader, d3d12_resource(buffers[i].buffer)); 1638bf215546Sopenharmony_ci } else 1639bf215546Sopenharmony_ci memset(slot, 0, sizeof(*slot)); 1640bf215546Sopenharmony_ci } 1641bf215546Sopenharmony_ci 1642bf215546Sopenharmony_ci if (buffers) { 1643bf215546Sopenharmony_ci ctx->num_ssbo_views[shader] = MAX2(ctx->num_ssbo_views[shader], count + start_slot); 1644bf215546Sopenharmony_ci } else { 1645bf215546Sopenharmony_ci ctx->num_ssbo_views[shader] = 0; 1646bf215546Sopenharmony_ci for (int i = start_slot + count - 1; i >= (int)start_slot; --i) { 1647bf215546Sopenharmony_ci if (ctx->ssbo_views[shader][i].buffer) { 1648bf215546Sopenharmony_ci ctx->num_ssbo_views[shader] = i; 1649bf215546Sopenharmony_ci break; 1650bf215546Sopenharmony_ci } 1651bf215546Sopenharmony_ci } 1652bf215546Sopenharmony_ci } 1653bf215546Sopenharmony_ci ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_SSBO; 1654bf215546Sopenharmony_ci} 1655bf215546Sopenharmony_ci 1656bf215546Sopenharmony_cistatic void 1657bf215546Sopenharmony_cid3d12_decrement_image_bind_count(struct d3d12_context *ctx, 1658bf215546Sopenharmony_ci enum pipe_shader_type shader, 1659bf215546Sopenharmony_ci struct d3d12_resource *res) { 1660bf215546Sopenharmony_ci assert(res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_IMAGE] > 0); 1661bf215546Sopenharmony_ci res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_IMAGE]--; 1662bf215546Sopenharmony_ci} 1663bf215546Sopenharmony_ci 1664bf215546Sopenharmony_cistatic void 1665bf215546Sopenharmony_cid3d12_increment_image_bind_count(struct d3d12_context *ctx, 1666bf215546Sopenharmony_ci enum pipe_shader_type shader, 1667bf215546Sopenharmony_ci struct d3d12_resource *res) { 1668bf215546Sopenharmony_ci res->bind_counts[shader][D3D12_RESOURCE_BINDING_TYPE_IMAGE]++; 1669bf215546Sopenharmony_ci} 1670bf215546Sopenharmony_ci 1671bf215546Sopenharmony_cistatic bool 1672bf215546Sopenharmony_ciis_valid_uav_cast(enum pipe_format resource_format, enum pipe_format view_format) 1673bf215546Sopenharmony_ci{ 1674bf215546Sopenharmony_ci if (view_format != PIPE_FORMAT_R32_UINT && 1675bf215546Sopenharmony_ci view_format != PIPE_FORMAT_R32_SINT && 1676bf215546Sopenharmony_ci view_format != PIPE_FORMAT_R32_FLOAT) 1677bf215546Sopenharmony_ci return false; 1678bf215546Sopenharmony_ci switch (d3d12_get_typeless_format(resource_format)) { 1679bf215546Sopenharmony_ci case DXGI_FORMAT_R8G8B8A8_TYPELESS: 1680bf215546Sopenharmony_ci case DXGI_FORMAT_B8G8R8A8_TYPELESS: 1681bf215546Sopenharmony_ci case DXGI_FORMAT_B8G8R8X8_TYPELESS: 1682bf215546Sopenharmony_ci case DXGI_FORMAT_R16G16_TYPELESS: 1683bf215546Sopenharmony_ci case DXGI_FORMAT_R10G10B10A2_TYPELESS: 1684bf215546Sopenharmony_ci return true; 1685bf215546Sopenharmony_ci default: 1686bf215546Sopenharmony_ci return false; 1687bf215546Sopenharmony_ci } 1688bf215546Sopenharmony_ci} 1689bf215546Sopenharmony_ci 1690bf215546Sopenharmony_cistatic enum pipe_format 1691bf215546Sopenharmony_ciget_shader_image_emulation_format(enum pipe_format resource_format) 1692bf215546Sopenharmony_ci{ 1693bf215546Sopenharmony_ci#define CASE(f) case DXGI_FORMAT_##f##_TYPELESS: return PIPE_FORMAT_##f##_UINT 1694bf215546Sopenharmony_ci switch (d3d12_get_typeless_format(resource_format)) { 1695bf215546Sopenharmony_ci CASE(R8); 1696bf215546Sopenharmony_ci CASE(R8G8); 1697bf215546Sopenharmony_ci CASE(R8G8B8A8); 1698bf215546Sopenharmony_ci CASE(R16); 1699bf215546Sopenharmony_ci CASE(R16G16); 1700bf215546Sopenharmony_ci CASE(R16G16B16A16); 1701bf215546Sopenharmony_ci CASE(R32); 1702bf215546Sopenharmony_ci CASE(R32G32); 1703bf215546Sopenharmony_ci CASE(R32G32B32A32); 1704bf215546Sopenharmony_ci CASE(R10G10B10A2); 1705bf215546Sopenharmony_ci case DXGI_FORMAT_R11G11B10_FLOAT: 1706bf215546Sopenharmony_ci return PIPE_FORMAT_R11G11B10_FLOAT; 1707bf215546Sopenharmony_ci default: 1708bf215546Sopenharmony_ci unreachable("Unexpected shader image resource format"); 1709bf215546Sopenharmony_ci } 1710bf215546Sopenharmony_ci} 1711bf215546Sopenharmony_ci 1712bf215546Sopenharmony_cistatic void 1713bf215546Sopenharmony_cid3d12_set_shader_images(struct pipe_context *pctx, 1714bf215546Sopenharmony_ci enum pipe_shader_type shader, 1715bf215546Sopenharmony_ci unsigned start_slot, unsigned count, 1716bf215546Sopenharmony_ci unsigned unbind_num_trailing_slots, 1717bf215546Sopenharmony_ci const struct pipe_image_view *images) 1718bf215546Sopenharmony_ci{ 1719bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1720bf215546Sopenharmony_ci for (unsigned i = 0; i < count + unbind_num_trailing_slots; ++i) { 1721bf215546Sopenharmony_ci struct pipe_image_view *slot = &ctx->image_views[shader][i + start_slot]; 1722bf215546Sopenharmony_ci if (slot->resource) { 1723bf215546Sopenharmony_ci d3d12_decrement_image_bind_count(ctx, shader, d3d12_resource(slot->resource)); 1724bf215546Sopenharmony_ci pipe_resource_reference(&slot->resource, NULL); 1725bf215546Sopenharmony_ci } 1726bf215546Sopenharmony_ci 1727bf215546Sopenharmony_ci ctx->image_view_emulation_formats[shader][i] = PIPE_FORMAT_NONE; 1728bf215546Sopenharmony_ci if (i < count && images && images[i].resource) { 1729bf215546Sopenharmony_ci pipe_resource_reference(&slot->resource, images[i].resource); 1730bf215546Sopenharmony_ci *slot = images[i]; 1731bf215546Sopenharmony_ci d3d12_increment_image_bind_count(ctx, shader, d3d12_resource(images[i].resource)); 1732bf215546Sopenharmony_ci 1733bf215546Sopenharmony_ci if (images[i].resource->target != PIPE_BUFFER && 1734bf215546Sopenharmony_ci !is_valid_uav_cast(images[i].resource->format, images[i].format) && 1735bf215546Sopenharmony_ci d3d12_get_typeless_format(images[i].format) != 1736bf215546Sopenharmony_ci d3d12_get_typeless_format(images[i].resource->format)) { 1737bf215546Sopenharmony_ci /* Can't use D3D casting, have to use shader lowering instead */ 1738bf215546Sopenharmony_ci ctx->image_view_emulation_formats[shader][i] = 1739bf215546Sopenharmony_ci get_shader_image_emulation_format(images[i].resource->format); 1740bf215546Sopenharmony_ci } 1741bf215546Sopenharmony_ci } else 1742bf215546Sopenharmony_ci memset(slot, 0, sizeof(*slot)); 1743bf215546Sopenharmony_ci } 1744bf215546Sopenharmony_ci 1745bf215546Sopenharmony_ci if (images) { 1746bf215546Sopenharmony_ci ctx->num_image_views[shader] = MAX2(ctx->num_image_views[shader], count + start_slot); 1747bf215546Sopenharmony_ci } else { 1748bf215546Sopenharmony_ci ctx->num_image_views[shader] = 0; 1749bf215546Sopenharmony_ci for (int i = start_slot + count - 1; i >= (int)start_slot; --i) { 1750bf215546Sopenharmony_ci if (ctx->image_views[shader][i].resource) { 1751bf215546Sopenharmony_ci ctx->num_image_views[shader] = i; 1752bf215546Sopenharmony_ci break; 1753bf215546Sopenharmony_ci } 1754bf215546Sopenharmony_ci } 1755bf215546Sopenharmony_ci } 1756bf215546Sopenharmony_ci ctx->shader_dirty[shader] |= D3D12_SHADER_DIRTY_IMAGE; 1757bf215546Sopenharmony_ci} 1758bf215546Sopenharmony_ci 1759bf215546Sopenharmony_civoid 1760bf215546Sopenharmony_cid3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resource *res) { 1761bf215546Sopenharmony_ci // For each shader type, if the resource is currently bound as CBV, SRV, or UAV 1762bf215546Sopenharmony_ci // set the context shader_dirty bit. 1763bf215546Sopenharmony_ci for (uint i = 0; i < PIPE_SHADER_TYPES; ++i) { 1764bf215546Sopenharmony_ci if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_CBV] > 0) { 1765bf215546Sopenharmony_ci ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF; 1766bf215546Sopenharmony_ci } 1767bf215546Sopenharmony_ci 1768bf215546Sopenharmony_ci if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SRV] > 0) { 1769bf215546Sopenharmony_ci ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS; 1770bf215546Sopenharmony_ci } 1771bf215546Sopenharmony_ci 1772bf215546Sopenharmony_ci if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_SSBO] > 0) { 1773bf215546Sopenharmony_ci ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO; 1774bf215546Sopenharmony_ci } 1775bf215546Sopenharmony_ci 1776bf215546Sopenharmony_ci if (res->bind_counts[i][D3D12_RESOURCE_BINDING_TYPE_IMAGE] > 0) { 1777bf215546Sopenharmony_ci ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE; 1778bf215546Sopenharmony_ci } 1779bf215546Sopenharmony_ci } 1780bf215546Sopenharmony_ci} 1781bf215546Sopenharmony_ci 1782bf215546Sopenharmony_cibool 1783bf215546Sopenharmony_cid3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor) 1784bf215546Sopenharmony_ci{ 1785bf215546Sopenharmony_ci if (ctx->fake_so_buffer_factor == factor) 1786bf215546Sopenharmony_ci return true; 1787bf215546Sopenharmony_ci 1788bf215546Sopenharmony_ci d3d12_disable_fake_so_buffers(ctx); 1789bf215546Sopenharmony_ci 1790bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 1791bf215546Sopenharmony_ci struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i]; 1792bf215546Sopenharmony_ci struct d3d12_stream_output_target *fake_target; 1793bf215546Sopenharmony_ci 1794bf215546Sopenharmony_ci fake_target = CALLOC_STRUCT(d3d12_stream_output_target); 1795bf215546Sopenharmony_ci if (!fake_target) 1796bf215546Sopenharmony_ci return false; 1797bf215546Sopenharmony_ci pipe_reference_init(&fake_target->base.reference, 1); 1798bf215546Sopenharmony_ci fake_target->base.context = &ctx->base; 1799bf215546Sopenharmony_ci 1800bf215546Sopenharmony_ci d3d12_resource_wait_idle(ctx, d3d12_resource(target->base.buffer), false); 1801bf215546Sopenharmony_ci 1802bf215546Sopenharmony_ci /* Check if another target is using the same buffer */ 1803bf215546Sopenharmony_ci for (unsigned j = 0; j < i; ++j) { 1804bf215546Sopenharmony_ci if (ctx->so_targets[j] && ctx->so_targets[j]->buffer == target->base.buffer) { 1805bf215546Sopenharmony_ci struct d3d12_stream_output_target *prev_target = 1806bf215546Sopenharmony_ci (struct d3d12_stream_output_target *)ctx->fake_so_targets[j]; 1807bf215546Sopenharmony_ci pipe_resource_reference(&fake_target->base.buffer, prev_target->base.buffer); 1808bf215546Sopenharmony_ci pipe_resource_reference(&fake_target->fill_buffer, prev_target->fill_buffer); 1809bf215546Sopenharmony_ci fake_target->fill_buffer_offset = prev_target->fill_buffer_offset; 1810bf215546Sopenharmony_ci break; 1811bf215546Sopenharmony_ci } 1812bf215546Sopenharmony_ci } 1813bf215546Sopenharmony_ci 1814bf215546Sopenharmony_ci /* Create new SO buffer 6x (2 triangles instead of 1 point) the original size if not */ 1815bf215546Sopenharmony_ci if (!fake_target->base.buffer) { 1816bf215546Sopenharmony_ci fake_target->base.buffer = pipe_buffer_create(ctx->base.screen, 1817bf215546Sopenharmony_ci PIPE_BIND_STREAM_OUTPUT, 1818bf215546Sopenharmony_ci PIPE_USAGE_STAGING, 1819bf215546Sopenharmony_ci target->base.buffer->width0 * factor); 1820bf215546Sopenharmony_ci u_suballocator_alloc(&ctx->so_allocator, sizeof(uint32_t) * 5, 256, 1821bf215546Sopenharmony_ci &fake_target->fill_buffer_offset, &fake_target->fill_buffer); 1822bf215546Sopenharmony_ci update_so_fill_buffer_count(ctx, fake_target->fill_buffer, fake_target->fill_buffer_offset, 0); 1823bf215546Sopenharmony_ci } 1824bf215546Sopenharmony_ci 1825bf215546Sopenharmony_ci fake_target->base.buffer_offset = target->base.buffer_offset * factor; 1826bf215546Sopenharmony_ci /* TODO: This will mess with SO statistics/overflow queries, but we're already missing things there */ 1827bf215546Sopenharmony_ci fake_target->base.buffer_size = target->base.buffer_size * factor; 1828bf215546Sopenharmony_ci ctx->fake_so_targets[i] = &fake_target->base; 1829bf215546Sopenharmony_ci fill_stream_output_buffer_view(&ctx->fake_so_buffer_views[i], fake_target); 1830bf215546Sopenharmony_ci } 1831bf215546Sopenharmony_ci 1832bf215546Sopenharmony_ci ctx->fake_so_buffer_factor = factor; 1833bf215546Sopenharmony_ci ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 1834bf215546Sopenharmony_ci 1835bf215546Sopenharmony_ci return true; 1836bf215546Sopenharmony_ci} 1837bf215546Sopenharmony_ci 1838bf215546Sopenharmony_cibool 1839bf215546Sopenharmony_cid3d12_disable_fake_so_buffers(struct d3d12_context *ctx) 1840bf215546Sopenharmony_ci{ 1841bf215546Sopenharmony_ci if (ctx->fake_so_buffer_factor == 0) 1842bf215546Sopenharmony_ci return true; 1843bf215546Sopenharmony_ci 1844bf215546Sopenharmony_ci d3d12_flush_cmdlist_and_wait(ctx); 1845bf215546Sopenharmony_ci 1846bf215546Sopenharmony_ci bool cs_state_saved = false; 1847bf215546Sopenharmony_ci d3d12_compute_transform_save_restore save; 1848bf215546Sopenharmony_ci 1849bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 1850bf215546Sopenharmony_ci struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i]; 1851bf215546Sopenharmony_ci struct d3d12_stream_output_target *fake_target = (struct d3d12_stream_output_target *)ctx->fake_so_targets[i]; 1852bf215546Sopenharmony_ci 1853bf215546Sopenharmony_ci if (fake_target == NULL) 1854bf215546Sopenharmony_ci continue; 1855bf215546Sopenharmony_ci 1856bf215546Sopenharmony_ci if (!cs_state_saved) { 1857bf215546Sopenharmony_ci cs_state_saved = true; 1858bf215546Sopenharmony_ci d3d12_save_compute_transform_state(ctx, &save); 1859bf215546Sopenharmony_ci } 1860bf215546Sopenharmony_ci 1861bf215546Sopenharmony_ci d3d12_compute_transform_key key; 1862bf215546Sopenharmony_ci memset(&key, 0, sizeof(key)); 1863bf215546Sopenharmony_ci key.type = d3d12_compute_transform_type::fake_so_buffer_vertex_count; 1864bf215546Sopenharmony_ci ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key)); 1865bf215546Sopenharmony_ci 1866bf215546Sopenharmony_ci ctx->transform_state_vars[0] = ctx->gfx_pipeline_state.so_info.stride[i]; 1867bf215546Sopenharmony_ci ctx->transform_state_vars[1] = ctx->fake_so_buffer_factor; 1868bf215546Sopenharmony_ci 1869bf215546Sopenharmony_ci pipe_shader_buffer new_cs_ssbos[3]; 1870bf215546Sopenharmony_ci new_cs_ssbos[0].buffer = fake_target->fill_buffer; 1871bf215546Sopenharmony_ci new_cs_ssbos[0].buffer_offset = fake_target->fill_buffer_offset; 1872bf215546Sopenharmony_ci new_cs_ssbos[0].buffer_size = fake_target->fill_buffer->width0 - fake_target->fill_buffer_offset; 1873bf215546Sopenharmony_ci 1874bf215546Sopenharmony_ci new_cs_ssbos[1].buffer = target->fill_buffer; 1875bf215546Sopenharmony_ci new_cs_ssbos[1].buffer_offset = target->fill_buffer_offset; 1876bf215546Sopenharmony_ci new_cs_ssbos[1].buffer_size = target->fill_buffer->width0 - target->fill_buffer_offset; 1877bf215546Sopenharmony_ci ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 2, new_cs_ssbos, 2); 1878bf215546Sopenharmony_ci 1879bf215546Sopenharmony_ci pipe_grid_info grid = {}; 1880bf215546Sopenharmony_ci grid.block[0] = grid.block[1] = grid.block[2] = 1; 1881bf215546Sopenharmony_ci grid.grid[0] = grid.grid[1] = grid.grid[2] = 1; 1882bf215546Sopenharmony_ci ctx->base.launch_grid(&ctx->base, &grid); 1883bf215546Sopenharmony_ci 1884bf215546Sopenharmony_ci key.type = d3d12_compute_transform_type::fake_so_buffer_copy_back; 1885bf215546Sopenharmony_ci key.fake_so_buffer_copy_back.stride = ctx->gfx_pipeline_state.so_info.stride[i]; 1886bf215546Sopenharmony_ci for (unsigned j = 0; j < ctx->gfx_pipeline_state.so_info.num_outputs; ++j) { 1887bf215546Sopenharmony_ci auto& output = ctx->gfx_pipeline_state.so_info.output[j]; 1888bf215546Sopenharmony_ci if (output.output_buffer != i) 1889bf215546Sopenharmony_ci continue; 1890bf215546Sopenharmony_ci 1891bf215546Sopenharmony_ci if (key.fake_so_buffer_copy_back.num_ranges > 0) { 1892bf215546Sopenharmony_ci auto& last_range = key.fake_so_buffer_copy_back.ranges[key.fake_so_buffer_copy_back.num_ranges - 1]; 1893bf215546Sopenharmony_ci if (output.dst_offset * 4 == last_range.offset + last_range.size) { 1894bf215546Sopenharmony_ci last_range.size += output.num_components * 4; 1895bf215546Sopenharmony_ci continue; 1896bf215546Sopenharmony_ci } 1897bf215546Sopenharmony_ci } 1898bf215546Sopenharmony_ci 1899bf215546Sopenharmony_ci auto& new_range = key.fake_so_buffer_copy_back.ranges[key.fake_so_buffer_copy_back.num_ranges++]; 1900bf215546Sopenharmony_ci new_range.offset = output.dst_offset * 4; 1901bf215546Sopenharmony_ci new_range.size = output.num_components * 4; 1902bf215546Sopenharmony_ci } 1903bf215546Sopenharmony_ci ctx->base.bind_compute_state(&ctx->base, d3d12_get_compute_transform(ctx, &key)); 1904bf215546Sopenharmony_ci 1905bf215546Sopenharmony_ci ctx->transform_state_vars[0] = ctx->fake_so_buffer_factor; 1906bf215546Sopenharmony_ci 1907bf215546Sopenharmony_ci new_cs_ssbos[0].buffer = target->base.buffer; 1908bf215546Sopenharmony_ci new_cs_ssbos[0].buffer_offset = target->base.buffer_offset; 1909bf215546Sopenharmony_ci new_cs_ssbos[0].buffer_size = target->base.buffer_size; 1910bf215546Sopenharmony_ci new_cs_ssbos[1].buffer = fake_target->base.buffer; 1911bf215546Sopenharmony_ci new_cs_ssbos[1].buffer_offset = fake_target->base.buffer_offset; 1912bf215546Sopenharmony_ci new_cs_ssbos[1].buffer_size = fake_target->base.buffer_size; 1913bf215546Sopenharmony_ci ctx->base.set_shader_buffers(&ctx->base, PIPE_SHADER_COMPUTE, 0, 2, new_cs_ssbos, 2); 1914bf215546Sopenharmony_ci 1915bf215546Sopenharmony_ci pipe_constant_buffer cbuf = {}; 1916bf215546Sopenharmony_ci cbuf.buffer = fake_target->fill_buffer; 1917bf215546Sopenharmony_ci cbuf.buffer_offset = fake_target->fill_buffer_offset; 1918bf215546Sopenharmony_ci cbuf.buffer_size = fake_target->fill_buffer->width0 - cbuf.buffer_offset; 1919bf215546Sopenharmony_ci ctx->base.set_constant_buffer(&ctx->base, PIPE_SHADER_COMPUTE, 1, false, &cbuf); 1920bf215546Sopenharmony_ci 1921bf215546Sopenharmony_ci grid.indirect = fake_target->fill_buffer; 1922bf215546Sopenharmony_ci grid.indirect_offset = fake_target->fill_buffer_offset + 4; 1923bf215546Sopenharmony_ci ctx->base.launch_grid(&ctx->base, &grid); 1924bf215546Sopenharmony_ci 1925bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->fake_so_targets[i], NULL); 1926bf215546Sopenharmony_ci ctx->fake_so_buffer_views[i].SizeInBytes = 0; 1927bf215546Sopenharmony_ci 1928bf215546Sopenharmony_ci /* Make sure the buffer is not copied twice */ 1929bf215546Sopenharmony_ci for (unsigned j = i + 1; j <= ctx->gfx_pipeline_state.num_so_targets; ++j) { 1930bf215546Sopenharmony_ci if (ctx->so_targets[j] && ctx->so_targets[j]->buffer == target->base.buffer) 1931bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->fake_so_targets[j], NULL); 1932bf215546Sopenharmony_ci } 1933bf215546Sopenharmony_ci } 1934bf215546Sopenharmony_ci 1935bf215546Sopenharmony_ci ctx->fake_so_buffer_factor = 0; 1936bf215546Sopenharmony_ci ctx->cmdlist_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 1937bf215546Sopenharmony_ci 1938bf215546Sopenharmony_ci if (cs_state_saved) 1939bf215546Sopenharmony_ci d3d12_restore_compute_transform_state(ctx, &save); 1940bf215546Sopenharmony_ci 1941bf215546Sopenharmony_ci return true; 1942bf215546Sopenharmony_ci} 1943bf215546Sopenharmony_ci 1944bf215546Sopenharmony_civoid 1945bf215546Sopenharmony_cid3d12_flush_cmdlist(struct d3d12_context *ctx) 1946bf215546Sopenharmony_ci{ 1947bf215546Sopenharmony_ci d3d12_end_batch(ctx, d3d12_current_batch(ctx)); 1948bf215546Sopenharmony_ci 1949bf215546Sopenharmony_ci ctx->current_batch_idx++; 1950bf215546Sopenharmony_ci if (ctx->current_batch_idx == ARRAY_SIZE(ctx->batches)) 1951bf215546Sopenharmony_ci ctx->current_batch_idx = 0; 1952bf215546Sopenharmony_ci 1953bf215546Sopenharmony_ci d3d12_start_batch(ctx, d3d12_current_batch(ctx)); 1954bf215546Sopenharmony_ci} 1955bf215546Sopenharmony_ci 1956bf215546Sopenharmony_civoid 1957bf215546Sopenharmony_cid3d12_flush_cmdlist_and_wait(struct d3d12_context *ctx) 1958bf215546Sopenharmony_ci{ 1959bf215546Sopenharmony_ci struct d3d12_batch *batch = d3d12_current_batch(ctx); 1960bf215546Sopenharmony_ci 1961bf215546Sopenharmony_ci d3d12_foreach_submitted_batch(ctx, old_batch) 1962bf215546Sopenharmony_ci d3d12_reset_batch(ctx, old_batch, PIPE_TIMEOUT_INFINITE); 1963bf215546Sopenharmony_ci d3d12_flush_cmdlist(ctx); 1964bf215546Sopenharmony_ci d3d12_reset_batch(ctx, batch, PIPE_TIMEOUT_INFINITE); 1965bf215546Sopenharmony_ci} 1966bf215546Sopenharmony_ci 1967bf215546Sopenharmony_cistatic void 1968bf215546Sopenharmony_cid3d12_clear_render_target(struct pipe_context *pctx, 1969bf215546Sopenharmony_ci struct pipe_surface *psurf, 1970bf215546Sopenharmony_ci const union pipe_color_union *color, 1971bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, 1972bf215546Sopenharmony_ci unsigned width, unsigned height, 1973bf215546Sopenharmony_ci bool render_condition_enabled) 1974bf215546Sopenharmony_ci{ 1975bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 1976bf215546Sopenharmony_ci struct d3d12_surface *surf = d3d12_surface(psurf); 1977bf215546Sopenharmony_ci 1978bf215546Sopenharmony_ci if (!render_condition_enabled && ctx->current_predication) 1979bf215546Sopenharmony_ci ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); 1980bf215546Sopenharmony_ci 1981bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(psurf->texture); 1982bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, res, 1983bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_RENDER_TARGET, 1984bf215546Sopenharmony_ci D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 1985bf215546Sopenharmony_ci d3d12_apply_resource_states(ctx, false); 1986bf215546Sopenharmony_ci 1987bf215546Sopenharmony_ci enum pipe_format format = psurf->texture->format; 1988bf215546Sopenharmony_ci float clear_color[4]; 1989bf215546Sopenharmony_ci 1990bf215546Sopenharmony_ci if (util_format_is_pure_uint(format)) { 1991bf215546Sopenharmony_ci for (int c = 0; c < 4; ++c) 1992bf215546Sopenharmony_ci clear_color[c] = color->ui[c]; 1993bf215546Sopenharmony_ci } else if (util_format_is_pure_sint(format)) { 1994bf215546Sopenharmony_ci for (int c = 0; c < 4; ++c) 1995bf215546Sopenharmony_ci clear_color[c] = color->i[c]; 1996bf215546Sopenharmony_ci } else { 1997bf215546Sopenharmony_ci for (int c = 0; c < 4; ++c) 1998bf215546Sopenharmony_ci clear_color[c] = color->f[c]; 1999bf215546Sopenharmony_ci } 2000bf215546Sopenharmony_ci 2001bf215546Sopenharmony_ci if (!(util_format_colormask(util_format_description(psurf->texture->format)) & 2002bf215546Sopenharmony_ci PIPE_MASK_A)) 2003bf215546Sopenharmony_ci clear_color[3] = 1.0f; 2004bf215546Sopenharmony_ci 2005bf215546Sopenharmony_ci D3D12_RECT rect = { (int)dstx, (int)dsty, 2006bf215546Sopenharmony_ci (int)dstx + (int)width, 2007bf215546Sopenharmony_ci (int)dsty + (int)height }; 2008bf215546Sopenharmony_ci ctx->cmdlist->ClearRenderTargetView(surf->desc_handle.cpu_handle, 2009bf215546Sopenharmony_ci clear_color, 1, &rect); 2010bf215546Sopenharmony_ci 2011bf215546Sopenharmony_ci d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf); 2012bf215546Sopenharmony_ci 2013bf215546Sopenharmony_ci if (!render_condition_enabled && ctx->current_predication) { 2014bf215546Sopenharmony_ci d3d12_enable_predication(ctx); 2015bf215546Sopenharmony_ci } 2016bf215546Sopenharmony_ci} 2017bf215546Sopenharmony_ci 2018bf215546Sopenharmony_cistatic void 2019bf215546Sopenharmony_cid3d12_clear_depth_stencil(struct pipe_context *pctx, 2020bf215546Sopenharmony_ci struct pipe_surface *psurf, 2021bf215546Sopenharmony_ci unsigned clear_flags, 2022bf215546Sopenharmony_ci double depth, 2023bf215546Sopenharmony_ci unsigned stencil, 2024bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, 2025bf215546Sopenharmony_ci unsigned width, unsigned height, 2026bf215546Sopenharmony_ci bool render_condition_enabled) 2027bf215546Sopenharmony_ci{ 2028bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 2029bf215546Sopenharmony_ci struct d3d12_surface *surf = d3d12_surface(psurf); 2030bf215546Sopenharmony_ci 2031bf215546Sopenharmony_ci if (!render_condition_enabled && ctx->current_predication) 2032bf215546Sopenharmony_ci ctx->cmdlist->SetPredication(NULL, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); 2033bf215546Sopenharmony_ci 2034bf215546Sopenharmony_ci D3D12_CLEAR_FLAGS flags = (D3D12_CLEAR_FLAGS)0; 2035bf215546Sopenharmony_ci if (clear_flags & PIPE_CLEAR_DEPTH) 2036bf215546Sopenharmony_ci flags |= D3D12_CLEAR_FLAG_DEPTH; 2037bf215546Sopenharmony_ci if (clear_flags & PIPE_CLEAR_STENCIL) 2038bf215546Sopenharmony_ci flags |= D3D12_CLEAR_FLAG_STENCIL; 2039bf215546Sopenharmony_ci 2040bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(ctx->fb.zsbuf->texture); 2041bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, res, 2042bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_DEPTH_WRITE, 2043bf215546Sopenharmony_ci D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 2044bf215546Sopenharmony_ci d3d12_apply_resource_states(ctx, false); 2045bf215546Sopenharmony_ci 2046bf215546Sopenharmony_ci D3D12_RECT rect = { (int)dstx, (int)dsty, 2047bf215546Sopenharmony_ci (int)dstx + (int)width, 2048bf215546Sopenharmony_ci (int)dsty + (int)height }; 2049bf215546Sopenharmony_ci ctx->cmdlist->ClearDepthStencilView(surf->desc_handle.cpu_handle, flags, 2050bf215546Sopenharmony_ci depth, stencil, 1, &rect); 2051bf215546Sopenharmony_ci 2052bf215546Sopenharmony_ci d3d12_batch_reference_surface_texture(d3d12_current_batch(ctx), surf); 2053bf215546Sopenharmony_ci 2054bf215546Sopenharmony_ci if (!render_condition_enabled && ctx->current_predication) { 2055bf215546Sopenharmony_ci d3d12_enable_predication(ctx); 2056bf215546Sopenharmony_ci } 2057bf215546Sopenharmony_ci} 2058bf215546Sopenharmony_ci 2059bf215546Sopenharmony_cistatic void 2060bf215546Sopenharmony_cid3d12_clear(struct pipe_context *pctx, 2061bf215546Sopenharmony_ci unsigned buffers, 2062bf215546Sopenharmony_ci const struct pipe_scissor_state *scissor_state, 2063bf215546Sopenharmony_ci const union pipe_color_union *color, 2064bf215546Sopenharmony_ci double depth, unsigned stencil) 2065bf215546Sopenharmony_ci{ 2066bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 2067bf215546Sopenharmony_ci 2068bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_COLOR) { 2069bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 2070bf215546Sopenharmony_ci if (buffers & (PIPE_CLEAR_COLOR0 << i)) { 2071bf215546Sopenharmony_ci struct pipe_surface *psurf = ctx->fb.cbufs[i]; 2072bf215546Sopenharmony_ci d3d12_clear_render_target(pctx, psurf, color, 2073bf215546Sopenharmony_ci 0, 0, psurf->width, psurf->height, 2074bf215546Sopenharmony_ci true); 2075bf215546Sopenharmony_ci } 2076bf215546Sopenharmony_ci } 2077bf215546Sopenharmony_ci } 2078bf215546Sopenharmony_ci 2079bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_DEPTHSTENCIL && ctx->fb.zsbuf) { 2080bf215546Sopenharmony_ci struct pipe_surface *psurf = ctx->fb.zsbuf; 2081bf215546Sopenharmony_ci d3d12_clear_depth_stencil(pctx, psurf, 2082bf215546Sopenharmony_ci buffers & PIPE_CLEAR_DEPTHSTENCIL, 2083bf215546Sopenharmony_ci depth, stencil, 2084bf215546Sopenharmony_ci 0, 0, psurf->width, psurf->height, 2085bf215546Sopenharmony_ci true); 2086bf215546Sopenharmony_ci } 2087bf215546Sopenharmony_ci} 2088bf215546Sopenharmony_ci 2089bf215546Sopenharmony_cistatic void 2090bf215546Sopenharmony_cid3d12_flush(struct pipe_context *pipe, 2091bf215546Sopenharmony_ci struct pipe_fence_handle **fence, 2092bf215546Sopenharmony_ci unsigned flags) 2093bf215546Sopenharmony_ci{ 2094bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pipe); 2095bf215546Sopenharmony_ci struct d3d12_batch *batch = d3d12_current_batch(ctx); 2096bf215546Sopenharmony_ci 2097bf215546Sopenharmony_ci d3d12_flush_cmdlist(ctx); 2098bf215546Sopenharmony_ci 2099bf215546Sopenharmony_ci if (fence) 2100bf215546Sopenharmony_ci d3d12_fence_reference((struct d3d12_fence **)fence, batch->fence); 2101bf215546Sopenharmony_ci} 2102bf215546Sopenharmony_ci 2103bf215546Sopenharmony_cistatic void 2104bf215546Sopenharmony_cid3d12_flush_resource(struct pipe_context *pctx, 2105bf215546Sopenharmony_ci struct pipe_resource *pres) 2106bf215546Sopenharmony_ci{ 2107bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 2108bf215546Sopenharmony_ci struct d3d12_resource *res = d3d12_resource(pres); 2109bf215546Sopenharmony_ci 2110bf215546Sopenharmony_ci d3d12_transition_resource_state(ctx, res, 2111bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_COMMON, 2112bf215546Sopenharmony_ci D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS); 2113bf215546Sopenharmony_ci d3d12_apply_resource_states(ctx, false); 2114bf215546Sopenharmony_ci} 2115bf215546Sopenharmony_ci 2116bf215546Sopenharmony_cistatic void 2117bf215546Sopenharmony_cid3d12_signal(struct pipe_context *pipe, 2118bf215546Sopenharmony_ci struct pipe_fence_handle *pfence) 2119bf215546Sopenharmony_ci{ 2120bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pipe->screen); 2121bf215546Sopenharmony_ci struct d3d12_fence *fence = d3d12_fence(pfence); 2122bf215546Sopenharmony_ci d3d12_flush_cmdlist(d3d12_context(pipe)); 2123bf215546Sopenharmony_ci screen->cmdqueue->Signal(fence->cmdqueue_fence, fence->value); 2124bf215546Sopenharmony_ci} 2125bf215546Sopenharmony_ci 2126bf215546Sopenharmony_cistatic void 2127bf215546Sopenharmony_cid3d12_wait(struct pipe_context *pipe, struct pipe_fence_handle *pfence) 2128bf215546Sopenharmony_ci{ 2129bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pipe->screen); 2130bf215546Sopenharmony_ci struct d3d12_fence *fence = d3d12_fence(pfence); 2131bf215546Sopenharmony_ci d3d12_flush_cmdlist(d3d12_context(pipe)); 2132bf215546Sopenharmony_ci screen->cmdqueue->Wait(fence->cmdqueue_fence, fence->value); 2133bf215546Sopenharmony_ci} 2134bf215546Sopenharmony_ci 2135bf215546Sopenharmony_cistatic void 2136bf215546Sopenharmony_cid3d12_init_null_sampler(struct d3d12_context *ctx) 2137bf215546Sopenharmony_ci{ 2138bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 2139bf215546Sopenharmony_ci 2140bf215546Sopenharmony_ci d3d12_descriptor_pool_alloc_handle(ctx->sampler_pool, &ctx->null_sampler); 2141bf215546Sopenharmony_ci 2142bf215546Sopenharmony_ci D3D12_SAMPLER_DESC desc; 2143bf215546Sopenharmony_ci desc.Filter = D3D12_FILTER_ANISOTROPIC; 2144bf215546Sopenharmony_ci desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; 2145bf215546Sopenharmony_ci desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; 2146bf215546Sopenharmony_ci desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; 2147bf215546Sopenharmony_ci desc.MipLODBias = 0.0f; 2148bf215546Sopenharmony_ci desc.MaxAnisotropy = 0; 2149bf215546Sopenharmony_ci desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; 2150bf215546Sopenharmony_ci desc.MinLOD = 0.0f; 2151bf215546Sopenharmony_ci desc.MaxLOD = 0.0f; 2152bf215546Sopenharmony_ci memset(desc.BorderColor, 0, sizeof(desc.BorderColor)); 2153bf215546Sopenharmony_ci screen->dev->CreateSampler(&desc, ctx->null_sampler.cpu_handle); 2154bf215546Sopenharmony_ci} 2155bf215546Sopenharmony_ci 2156bf215546Sopenharmony_cistatic uint64_t 2157bf215546Sopenharmony_cid3d12_get_timestamp(struct pipe_context *pctx) 2158bf215546Sopenharmony_ci{ 2159bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 2160bf215546Sopenharmony_ci 2161bf215546Sopenharmony_ci if (!ctx->timestamp_query) 2162bf215546Sopenharmony_ci ctx->timestamp_query = pctx->create_query(pctx, PIPE_QUERY_TIMESTAMP, 0); 2163bf215546Sopenharmony_ci 2164bf215546Sopenharmony_ci pipe_query_result result; 2165bf215546Sopenharmony_ci pctx->end_query(pctx, ctx->timestamp_query); 2166bf215546Sopenharmony_ci pctx->get_query_result(pctx, ctx->timestamp_query, true, &result); 2167bf215546Sopenharmony_ci return result.u64; 2168bf215546Sopenharmony_ci} 2169bf215546Sopenharmony_ci 2170bf215546Sopenharmony_cistatic void 2171bf215546Sopenharmony_cid3d12_rebind_buffer(struct d3d12_context *ctx, struct d3d12_resource *res) 2172bf215546Sopenharmony_ci{ 2173bf215546Sopenharmony_ci if (res->base.b.bind & PIPE_BIND_VERTEX_BUFFER) { 2174bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->num_vbs; ++i) { 2175bf215546Sopenharmony_ci struct pipe_vertex_buffer *buf = &ctx->vbs[i]; 2176bf215546Sopenharmony_ci 2177bf215546Sopenharmony_ci if (!buf->is_user_buffer && &res->base.b == buf->buffer.resource) { 2178bf215546Sopenharmony_ci ctx->vbvs[i].BufferLocation = d3d12_resource_gpu_virtual_address(res) + buf->buffer_offset; 2179bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS; 2180bf215546Sopenharmony_ci } 2181bf215546Sopenharmony_ci } 2182bf215546Sopenharmony_ci } 2183bf215546Sopenharmony_ci 2184bf215546Sopenharmony_ci if (res->base.b.bind & PIPE_BIND_STREAM_OUTPUT) { 2185bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 2186bf215546Sopenharmony_ci struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)ctx->so_targets[i]; 2187bf215546Sopenharmony_ci assert(!target || target->fill_buffer != &res->base.b); 2188bf215546Sopenharmony_ci if (target && target->base.buffer == &res->base.b) { 2189bf215546Sopenharmony_ci fill_stream_output_buffer_view(&ctx->so_buffer_views[i], target); 2190bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 2191bf215546Sopenharmony_ci } 2192bf215546Sopenharmony_ci 2193bf215546Sopenharmony_ci assert(!ctx->fake_so_targets[i] || ctx->fake_so_targets[i]->buffer != &res->base.b); 2194bf215546Sopenharmony_ci } 2195bf215546Sopenharmony_ci } 2196bf215546Sopenharmony_ci 2197bf215546Sopenharmony_ci d3d12_invalidate_context_bindings(ctx, res); 2198bf215546Sopenharmony_ci} 2199bf215546Sopenharmony_ci 2200bf215546Sopenharmony_cistatic void 2201bf215546Sopenharmony_cid3d12_replace_buffer_storage(struct pipe_context *pctx, 2202bf215546Sopenharmony_ci struct pipe_resource *pdst, 2203bf215546Sopenharmony_ci struct pipe_resource *psrc, 2204bf215546Sopenharmony_ci unsigned minimum_num_rebinds, 2205bf215546Sopenharmony_ci uint32_t rebind_mask, 2206bf215546Sopenharmony_ci uint32_t delete_buffer_id) 2207bf215546Sopenharmony_ci{ 2208bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 2209bf215546Sopenharmony_ci struct d3d12_resource *dst = d3d12_resource(pdst); 2210bf215546Sopenharmony_ci struct d3d12_resource *src = d3d12_resource(psrc); 2211bf215546Sopenharmony_ci 2212bf215546Sopenharmony_ci struct d3d12_bo *old_bo = dst->bo; 2213bf215546Sopenharmony_ci d3d12_bo_reference(src->bo); 2214bf215546Sopenharmony_ci dst->bo = src->bo; 2215bf215546Sopenharmony_ci p_atomic_inc(&dst->generation_id); 2216bf215546Sopenharmony_ci d3d12_rebind_buffer(ctx, dst); 2217bf215546Sopenharmony_ci d3d12_bo_unreference(old_bo); 2218bf215546Sopenharmony_ci} 2219bf215546Sopenharmony_ci 2220bf215546Sopenharmony_cistatic void 2221bf215546Sopenharmony_cid3d12_memory_barrier(struct pipe_context *pctx, unsigned flags) 2222bf215546Sopenharmony_ci{ 2223bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 2224bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_VERTEX_BUFFER) 2225bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_VERTEX_BUFFERS; 2226bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_INDEX_BUFFER) 2227bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_INDEX_BUFFER; 2228bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_FRAMEBUFFER) 2229bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_FRAMEBUFFER; 2230bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_STREAMOUT_BUFFER) 2231bf215546Sopenharmony_ci ctx->state_dirty |= D3D12_DIRTY_STREAM_OUTPUT; 2232bf215546Sopenharmony_ci 2233bf215546Sopenharmony_ci /* TODO: 2234bf215546Sopenharmony_ci * PIPE_BARRIER_INDIRECT_BUFFER 2235bf215546Sopenharmony_ci */ 2236bf215546Sopenharmony_ci 2237bf215546Sopenharmony_ci for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 2238bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_CONSTANT_BUFFER) 2239bf215546Sopenharmony_ci ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_CONSTBUF; 2240bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_TEXTURE) 2241bf215546Sopenharmony_ci ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS; 2242bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_SHADER_BUFFER) 2243bf215546Sopenharmony_ci ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_SSBO; 2244bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_IMAGE) 2245bf215546Sopenharmony_ci ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_IMAGE; 2246bf215546Sopenharmony_ci } 2247bf215546Sopenharmony_ci 2248bf215546Sopenharmony_ci /* Indicate that UAVs shouldn't override transitions. Ignore barriers that are only 2249bf215546Sopenharmony_ci * for UAVs or other fixed-function state that doesn't need a draw to resolve. 2250bf215546Sopenharmony_ci */ 2251bf215546Sopenharmony_ci const unsigned ignored_barrier_flags = 2252bf215546Sopenharmony_ci PIPE_BARRIER_IMAGE | 2253bf215546Sopenharmony_ci PIPE_BARRIER_SHADER_BUFFER | 2254bf215546Sopenharmony_ci PIPE_BARRIER_UPDATE | 2255bf215546Sopenharmony_ci PIPE_BARRIER_MAPPED_BUFFER | 2256bf215546Sopenharmony_ci PIPE_BARRIER_QUERY_BUFFER; 2257bf215546Sopenharmony_ci d3d12_current_batch(ctx)->pending_memory_barrier = (flags & ~ignored_barrier_flags) != 0; 2258bf215546Sopenharmony_ci 2259bf215546Sopenharmony_ci if (flags & (PIPE_BARRIER_IMAGE | PIPE_BARRIER_SHADER_BUFFER)) { 2260bf215546Sopenharmony_ci D3D12_RESOURCE_BARRIER uavBarrier; 2261bf215546Sopenharmony_ci uavBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; 2262bf215546Sopenharmony_ci uavBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; 2263bf215546Sopenharmony_ci uavBarrier.UAV.pResource = nullptr; 2264bf215546Sopenharmony_ci ctx->cmdlist->ResourceBarrier(1, &uavBarrier); 2265bf215546Sopenharmony_ci } 2266bf215546Sopenharmony_ci} 2267bf215546Sopenharmony_ci 2268bf215546Sopenharmony_cistatic void 2269bf215546Sopenharmony_cid3d12_get_sample_position(struct pipe_context *pctx, unsigned sample_count, unsigned sample_index, 2270bf215546Sopenharmony_ci float *positions) 2271bf215546Sopenharmony_ci{ 2272bf215546Sopenharmony_ci /* Sample patterns transcribed from 2273bf215546Sopenharmony_ci * https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels 2274bf215546Sopenharmony_ci */ 2275bf215546Sopenharmony_ci static const int sample_pattern_1sample[2] = { 0, 0 }; 2276bf215546Sopenharmony_ci static const int sample_pattern_2samples[2][2] = { 2277bf215546Sopenharmony_ci { 4, 4 }, 2278bf215546Sopenharmony_ci { -4, -4 }, 2279bf215546Sopenharmony_ci }; 2280bf215546Sopenharmony_ci static const int sample_pattern_4samples[4][2] = { 2281bf215546Sopenharmony_ci { -2, -6 }, 2282bf215546Sopenharmony_ci { 6, -2 }, 2283bf215546Sopenharmony_ci { -6, 2 }, 2284bf215546Sopenharmony_ci { 2, 6 }, 2285bf215546Sopenharmony_ci }; 2286bf215546Sopenharmony_ci static const int sample_pattern_8samples[8][2] = { 2287bf215546Sopenharmony_ci { 1, -3 }, 2288bf215546Sopenharmony_ci { -1, 3 }, 2289bf215546Sopenharmony_ci { 5, 1 }, 2290bf215546Sopenharmony_ci { -3, -5 }, 2291bf215546Sopenharmony_ci { -5, 5 }, 2292bf215546Sopenharmony_ci { -7, -1 }, 2293bf215546Sopenharmony_ci { 3, 7 }, 2294bf215546Sopenharmony_ci { 7, -7 }, 2295bf215546Sopenharmony_ci }; 2296bf215546Sopenharmony_ci static const int sample_pattern_16samples[16][2] = { 2297bf215546Sopenharmony_ci { 1, 1 }, 2298bf215546Sopenharmony_ci { -1, -3 }, 2299bf215546Sopenharmony_ci { -3, 2 }, 2300bf215546Sopenharmony_ci { 4, -1 }, 2301bf215546Sopenharmony_ci { -5, -2 }, 2302bf215546Sopenharmony_ci { 2, 5 }, 2303bf215546Sopenharmony_ci { 5, 3 }, 2304bf215546Sopenharmony_ci { 3, -5 }, 2305bf215546Sopenharmony_ci { -2, 6 }, 2306bf215546Sopenharmony_ci { 0, -7 }, 2307bf215546Sopenharmony_ci { -4, -6 }, 2308bf215546Sopenharmony_ci { -6, 4 }, 2309bf215546Sopenharmony_ci { -8, 0 }, 2310bf215546Sopenharmony_ci { 7, -4 }, 2311bf215546Sopenharmony_ci { 6, 7 }, 2312bf215546Sopenharmony_ci { -7, -8 }, 2313bf215546Sopenharmony_ci }; 2314bf215546Sopenharmony_ci const int *samples; 2315bf215546Sopenharmony_ci switch (sample_count) { 2316bf215546Sopenharmony_ci case 1: 2317bf215546Sopenharmony_ci default: 2318bf215546Sopenharmony_ci samples = sample_pattern_1sample; 2319bf215546Sopenharmony_ci break; 2320bf215546Sopenharmony_ci case 2: 2321bf215546Sopenharmony_ci samples = sample_pattern_2samples[sample_index]; 2322bf215546Sopenharmony_ci break; 2323bf215546Sopenharmony_ci case 4: 2324bf215546Sopenharmony_ci samples = sample_pattern_4samples[sample_index]; 2325bf215546Sopenharmony_ci break; 2326bf215546Sopenharmony_ci case 8: 2327bf215546Sopenharmony_ci samples = sample_pattern_8samples[sample_index]; 2328bf215546Sopenharmony_ci break; 2329bf215546Sopenharmony_ci case 16: 2330bf215546Sopenharmony_ci samples = sample_pattern_16samples[sample_index]; 2331bf215546Sopenharmony_ci break; 2332bf215546Sopenharmony_ci } 2333bf215546Sopenharmony_ci 2334bf215546Sopenharmony_ci /* GL coords go from 0 -> 1, D3D from -0.5 -> 0.5 */ 2335bf215546Sopenharmony_ci for (unsigned i = 0; i < 2; ++i) 2336bf215546Sopenharmony_ci positions[i] = (float)(samples[i] + 8) / 16.0f; 2337bf215546Sopenharmony_ci} 2338bf215546Sopenharmony_ci 2339bf215546Sopenharmony_cistatic void 2340bf215546Sopenharmony_cid3d12_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices) 2341bf215546Sopenharmony_ci{ 2342bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 2343bf215546Sopenharmony_ci ctx->patch_vertices = patch_vertices; 2344bf215546Sopenharmony_ci ctx->cmdlist_dirty |= D3D12_DIRTY_PRIM_MODE; 2345bf215546Sopenharmony_ci} 2346bf215546Sopenharmony_ci 2347bf215546Sopenharmony_cistatic void 2348bf215546Sopenharmony_cid3d12_set_tess_state(struct pipe_context *pctx, 2349bf215546Sopenharmony_ci const float default_outer_level[4], 2350bf215546Sopenharmony_ci const float default_inner_level[2]) 2351bf215546Sopenharmony_ci{ 2352bf215546Sopenharmony_ci struct d3d12_context *ctx = d3d12_context(pctx); 2353bf215546Sopenharmony_ci memcpy(ctx->default_outer_tess_factor, default_outer_level, sizeof(ctx->default_outer_tess_factor)); 2354bf215546Sopenharmony_ci memcpy(ctx->default_inner_tess_factor, default_inner_level, sizeof(ctx->default_inner_tess_factor)); 2355bf215546Sopenharmony_ci} 2356bf215546Sopenharmony_ci 2357bf215546Sopenharmony_cistatic enum pipe_reset_status 2358bf215546Sopenharmony_cid3d12_get_reset_status(struct pipe_context *pctx) 2359bf215546Sopenharmony_ci{ 2360bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pctx->screen); 2361bf215546Sopenharmony_ci HRESULT hr = screen->dev->GetDeviceRemovedReason(); 2362bf215546Sopenharmony_ci switch (hr) { 2363bf215546Sopenharmony_ci case DXGI_ERROR_DEVICE_HUNG: 2364bf215546Sopenharmony_ci case DXGI_ERROR_INVALID_CALL: 2365bf215546Sopenharmony_ci return PIPE_GUILTY_CONTEXT_RESET; 2366bf215546Sopenharmony_ci case DXGI_ERROR_DEVICE_RESET: 2367bf215546Sopenharmony_ci return PIPE_INNOCENT_CONTEXT_RESET; 2368bf215546Sopenharmony_ci default: 2369bf215546Sopenharmony_ci return SUCCEEDED(hr) ? PIPE_NO_RESET : PIPE_UNKNOWN_CONTEXT_RESET; 2370bf215546Sopenharmony_ci } 2371bf215546Sopenharmony_ci} 2372bf215546Sopenharmony_ci 2373bf215546Sopenharmony_ci#ifdef HAVE_GALLIUM_D3D12_VIDEO 2374bf215546Sopenharmony_cistruct pipe_video_codec* 2375bf215546Sopenharmony_cid3d12_video_create_codec(struct pipe_context *context, 2376bf215546Sopenharmony_ci const struct pipe_video_codec *templat) 2377bf215546Sopenharmony_ci{ 2378bf215546Sopenharmony_ci if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 2379bf215546Sopenharmony_ci return d3d12_video_encoder_create_encoder(context, templat); 2380bf215546Sopenharmony_ci } else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { 2381bf215546Sopenharmony_ci return d3d12_video_create_decoder(context, templat); 2382bf215546Sopenharmony_ci } else if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) { 2383bf215546Sopenharmony_ci return d3d12_video_processor_create(context, templat); 2384bf215546Sopenharmony_ci } else { 2385bf215546Sopenharmony_ci debug_printf("D3D12: Unsupported video codec entrypoint %d\n", templat->entrypoint); 2386bf215546Sopenharmony_ci return nullptr; 2387bf215546Sopenharmony_ci } 2388bf215546Sopenharmony_ci} 2389bf215546Sopenharmony_ci#endif 2390bf215546Sopenharmony_ci 2391bf215546Sopenharmony_cistruct pipe_context * 2392bf215546Sopenharmony_cid3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) 2393bf215546Sopenharmony_ci{ 2394bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(pscreen); 2395bf215546Sopenharmony_ci if (FAILED(screen->dev->GetDeviceRemovedReason())) { 2396bf215546Sopenharmony_ci /* Attempt recovery, but this may fail */ 2397bf215546Sopenharmony_ci screen->deinit(screen); 2398bf215546Sopenharmony_ci if (!screen->init(screen)) { 2399bf215546Sopenharmony_ci debug_printf("D3D12: failed to reset screen\n"); 2400bf215546Sopenharmony_ci return nullptr; 2401bf215546Sopenharmony_ci } 2402bf215546Sopenharmony_ci } 2403bf215546Sopenharmony_ci 2404bf215546Sopenharmony_ci struct d3d12_context *ctx = CALLOC_STRUCT(d3d12_context); 2405bf215546Sopenharmony_ci if (!ctx) 2406bf215546Sopenharmony_ci return NULL; 2407bf215546Sopenharmony_ci 2408bf215546Sopenharmony_ci ctx->base.screen = pscreen; 2409bf215546Sopenharmony_ci ctx->base.priv = priv; 2410bf215546Sopenharmony_ci 2411bf215546Sopenharmony_ci ctx->base.destroy = d3d12_context_destroy; 2412bf215546Sopenharmony_ci 2413bf215546Sopenharmony_ci ctx->base.create_vertex_elements_state = d3d12_create_vertex_elements_state; 2414bf215546Sopenharmony_ci ctx->base.bind_vertex_elements_state = d3d12_bind_vertex_elements_state; 2415bf215546Sopenharmony_ci ctx->base.delete_vertex_elements_state = d3d12_delete_vertex_elements_state; 2416bf215546Sopenharmony_ci 2417bf215546Sopenharmony_ci ctx->base.create_blend_state = d3d12_create_blend_state; 2418bf215546Sopenharmony_ci ctx->base.bind_blend_state = d3d12_bind_blend_state; 2419bf215546Sopenharmony_ci ctx->base.delete_blend_state = d3d12_delete_blend_state; 2420bf215546Sopenharmony_ci 2421bf215546Sopenharmony_ci ctx->base.create_depth_stencil_alpha_state = d3d12_create_depth_stencil_alpha_state; 2422bf215546Sopenharmony_ci ctx->base.bind_depth_stencil_alpha_state = d3d12_bind_depth_stencil_alpha_state; 2423bf215546Sopenharmony_ci ctx->base.delete_depth_stencil_alpha_state = d3d12_delete_depth_stencil_alpha_state; 2424bf215546Sopenharmony_ci 2425bf215546Sopenharmony_ci ctx->base.create_rasterizer_state = d3d12_create_rasterizer_state; 2426bf215546Sopenharmony_ci ctx->base.bind_rasterizer_state = d3d12_bind_rasterizer_state; 2427bf215546Sopenharmony_ci ctx->base.delete_rasterizer_state = d3d12_delete_rasterizer_state; 2428bf215546Sopenharmony_ci 2429bf215546Sopenharmony_ci ctx->base.create_sampler_state = d3d12_create_sampler_state; 2430bf215546Sopenharmony_ci ctx->base.bind_sampler_states = d3d12_bind_sampler_states; 2431bf215546Sopenharmony_ci ctx->base.delete_sampler_state = d3d12_delete_sampler_state; 2432bf215546Sopenharmony_ci 2433bf215546Sopenharmony_ci ctx->base.create_sampler_view = d3d12_create_sampler_view; 2434bf215546Sopenharmony_ci ctx->base.set_sampler_views = d3d12_set_sampler_views; 2435bf215546Sopenharmony_ci ctx->base.sampler_view_destroy = d3d12_destroy_sampler_view; 2436bf215546Sopenharmony_ci 2437bf215546Sopenharmony_ci ctx->base.create_vs_state = d3d12_create_vs_state; 2438bf215546Sopenharmony_ci ctx->base.bind_vs_state = d3d12_bind_vs_state; 2439bf215546Sopenharmony_ci ctx->base.delete_vs_state = d3d12_delete_vs_state; 2440bf215546Sopenharmony_ci 2441bf215546Sopenharmony_ci ctx->base.create_fs_state = d3d12_create_fs_state; 2442bf215546Sopenharmony_ci ctx->base.bind_fs_state = d3d12_bind_fs_state; 2443bf215546Sopenharmony_ci ctx->base.delete_fs_state = d3d12_delete_fs_state; 2444bf215546Sopenharmony_ci 2445bf215546Sopenharmony_ci ctx->base.create_gs_state = d3d12_create_gs_state; 2446bf215546Sopenharmony_ci ctx->base.bind_gs_state = d3d12_bind_gs_state; 2447bf215546Sopenharmony_ci ctx->base.delete_gs_state = d3d12_delete_gs_state; 2448bf215546Sopenharmony_ci 2449bf215546Sopenharmony_ci ctx->base.create_tcs_state = d3d12_create_tcs_state; 2450bf215546Sopenharmony_ci ctx->base.bind_tcs_state = d3d12_bind_tcs_state; 2451bf215546Sopenharmony_ci ctx->base.delete_tcs_state = d3d12_delete_tcs_state; 2452bf215546Sopenharmony_ci 2453bf215546Sopenharmony_ci ctx->base.create_tes_state = d3d12_create_tes_state; 2454bf215546Sopenharmony_ci ctx->base.bind_tes_state = d3d12_bind_tes_state; 2455bf215546Sopenharmony_ci ctx->base.delete_tes_state = d3d12_delete_tes_state; 2456bf215546Sopenharmony_ci 2457bf215546Sopenharmony_ci ctx->base.set_patch_vertices = d3d12_set_patch_vertices; 2458bf215546Sopenharmony_ci ctx->base.set_tess_state = d3d12_set_tess_state; 2459bf215546Sopenharmony_ci 2460bf215546Sopenharmony_ci ctx->base.create_compute_state = d3d12_create_compute_state; 2461bf215546Sopenharmony_ci ctx->base.bind_compute_state = d3d12_bind_compute_state; 2462bf215546Sopenharmony_ci ctx->base.delete_compute_state = d3d12_delete_compute_state; 2463bf215546Sopenharmony_ci 2464bf215546Sopenharmony_ci ctx->base.set_polygon_stipple = d3d12_set_polygon_stipple; 2465bf215546Sopenharmony_ci ctx->base.set_vertex_buffers = d3d12_set_vertex_buffers; 2466bf215546Sopenharmony_ci ctx->base.set_viewport_states = d3d12_set_viewport_states; 2467bf215546Sopenharmony_ci ctx->base.set_scissor_states = d3d12_set_scissor_states; 2468bf215546Sopenharmony_ci ctx->base.set_constant_buffer = d3d12_set_constant_buffer; 2469bf215546Sopenharmony_ci ctx->base.set_framebuffer_state = d3d12_set_framebuffer_state; 2470bf215546Sopenharmony_ci ctx->base.set_clip_state = d3d12_set_clip_state; 2471bf215546Sopenharmony_ci ctx->base.set_blend_color = d3d12_set_blend_color; 2472bf215546Sopenharmony_ci ctx->base.set_sample_mask = d3d12_set_sample_mask; 2473bf215546Sopenharmony_ci ctx->base.set_stencil_ref = d3d12_set_stencil_ref; 2474bf215546Sopenharmony_ci 2475bf215546Sopenharmony_ci ctx->base.create_stream_output_target = d3d12_create_stream_output_target; 2476bf215546Sopenharmony_ci ctx->base.stream_output_target_destroy = d3d12_stream_output_target_destroy; 2477bf215546Sopenharmony_ci ctx->base.set_stream_output_targets = d3d12_set_stream_output_targets; 2478bf215546Sopenharmony_ci 2479bf215546Sopenharmony_ci ctx->base.set_shader_buffers = d3d12_set_shader_buffers; 2480bf215546Sopenharmony_ci ctx->base.set_shader_images = d3d12_set_shader_images; 2481bf215546Sopenharmony_ci 2482bf215546Sopenharmony_ci ctx->base.get_timestamp = d3d12_get_timestamp; 2483bf215546Sopenharmony_ci 2484bf215546Sopenharmony_ci ctx->base.clear = d3d12_clear; 2485bf215546Sopenharmony_ci ctx->base.clear_render_target = d3d12_clear_render_target; 2486bf215546Sopenharmony_ci ctx->base.clear_depth_stencil = d3d12_clear_depth_stencil; 2487bf215546Sopenharmony_ci ctx->base.draw_vbo = d3d12_draw_vbo; 2488bf215546Sopenharmony_ci ctx->base.launch_grid = d3d12_launch_grid; 2489bf215546Sopenharmony_ci ctx->base.flush = d3d12_flush; 2490bf215546Sopenharmony_ci ctx->base.flush_resource = d3d12_flush_resource; 2491bf215546Sopenharmony_ci 2492bf215546Sopenharmony_ci ctx->base.fence_server_signal = d3d12_signal; 2493bf215546Sopenharmony_ci ctx->base.fence_server_sync = d3d12_wait; 2494bf215546Sopenharmony_ci 2495bf215546Sopenharmony_ci ctx->base.memory_barrier = d3d12_memory_barrier; 2496bf215546Sopenharmony_ci 2497bf215546Sopenharmony_ci ctx->base.get_sample_position = d3d12_get_sample_position; 2498bf215546Sopenharmony_ci 2499bf215546Sopenharmony_ci ctx->base.get_device_reset_status = d3d12_get_reset_status; 2500bf215546Sopenharmony_ci 2501bf215546Sopenharmony_ci ctx->gfx_pipeline_state.sample_mask = ~0; 2502bf215546Sopenharmony_ci 2503bf215546Sopenharmony_ci d3d12_context_surface_init(&ctx->base); 2504bf215546Sopenharmony_ci d3d12_context_resource_init(&ctx->base); 2505bf215546Sopenharmony_ci d3d12_context_query_init(&ctx->base); 2506bf215546Sopenharmony_ci d3d12_context_blit_init(&ctx->base); 2507bf215546Sopenharmony_ci 2508bf215546Sopenharmony_ci#ifdef HAVE_GALLIUM_D3D12_VIDEO 2509bf215546Sopenharmony_ci // Add d3d12 video functions entrypoints 2510bf215546Sopenharmony_ci ctx->base.create_video_codec = d3d12_video_create_codec; 2511bf215546Sopenharmony_ci ctx->base.create_video_buffer = d3d12_video_buffer_create; 2512bf215546Sopenharmony_ci#endif 2513bf215546Sopenharmony_ci slab_create_child(&ctx->transfer_pool, &d3d12_screen(pscreen)->transfer_pool); 2514bf215546Sopenharmony_ci slab_create_child(&ctx->transfer_pool_unsync, &d3d12_screen(pscreen)->transfer_pool); 2515bf215546Sopenharmony_ci 2516bf215546Sopenharmony_ci ctx->base.stream_uploader = u_upload_create_default(&ctx->base); 2517bf215546Sopenharmony_ci ctx->base.const_uploader = u_upload_create_default(&ctx->base); 2518bf215546Sopenharmony_ci u_suballocator_init(&ctx->so_allocator, &ctx->base, 4096, 0, 2519bf215546Sopenharmony_ci PIPE_USAGE_DEFAULT, 2520bf215546Sopenharmony_ci 0, false); 2521bf215546Sopenharmony_ci 2522bf215546Sopenharmony_ci struct primconvert_config cfg = {}; 2523bf215546Sopenharmony_ci cfg.primtypes_mask = 1 << PIPE_PRIM_POINTS | 2524bf215546Sopenharmony_ci 1 << PIPE_PRIM_LINES | 2525bf215546Sopenharmony_ci 1 << PIPE_PRIM_LINE_STRIP | 2526bf215546Sopenharmony_ci 1 << PIPE_PRIM_TRIANGLES | 2527bf215546Sopenharmony_ci 1 << PIPE_PRIM_TRIANGLE_STRIP; 2528bf215546Sopenharmony_ci cfg.restart_primtypes_mask = cfg.primtypes_mask; 2529bf215546Sopenharmony_ci cfg.fixed_prim_restart = true; 2530bf215546Sopenharmony_ci ctx->primconvert = util_primconvert_create_config(&ctx->base, &cfg); 2531bf215546Sopenharmony_ci if (!ctx->primconvert) { 2532bf215546Sopenharmony_ci debug_printf("D3D12: failed to create primconvert\n"); 2533bf215546Sopenharmony_ci return NULL; 2534bf215546Sopenharmony_ci } 2535bf215546Sopenharmony_ci 2536bf215546Sopenharmony_ci d3d12_gfx_pipeline_state_cache_init(ctx); 2537bf215546Sopenharmony_ci d3d12_compute_pipeline_state_cache_init(ctx); 2538bf215546Sopenharmony_ci d3d12_root_signature_cache_init(ctx); 2539bf215546Sopenharmony_ci d3d12_cmd_signature_cache_init(ctx); 2540bf215546Sopenharmony_ci d3d12_gs_variant_cache_init(ctx); 2541bf215546Sopenharmony_ci d3d12_tcs_variant_cache_init(ctx); 2542bf215546Sopenharmony_ci d3d12_compute_transform_cache_init(ctx); 2543bf215546Sopenharmony_ci d3d12_context_state_table_init(ctx); 2544bf215546Sopenharmony_ci 2545bf215546Sopenharmony_ci util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT); 2546bf215546Sopenharmony_ci if (!d3d12_mod) { 2547bf215546Sopenharmony_ci debug_printf("D3D12: failed to load D3D12.DLL\n"); 2548bf215546Sopenharmony_ci return NULL; 2549bf215546Sopenharmony_ci } 2550bf215546Sopenharmony_ci ctx->D3D12SerializeVersionedRootSignature = 2551bf215546Sopenharmony_ci (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)util_dl_get_proc_address(d3d12_mod, "D3D12SerializeVersionedRootSignature"); 2552bf215546Sopenharmony_ci 2553bf215546Sopenharmony_ci ctx->submit_id = (uint64_t)p_atomic_add_return(&screen->ctx_count, 1) << 32ull; 2554bf215546Sopenharmony_ci 2555bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); ++i) { 2556bf215546Sopenharmony_ci if (!d3d12_init_batch(ctx, &ctx->batches[i])) { 2557bf215546Sopenharmony_ci FREE(ctx); 2558bf215546Sopenharmony_ci return NULL; 2559bf215546Sopenharmony_ci } 2560bf215546Sopenharmony_ci } 2561bf215546Sopenharmony_ci d3d12_start_batch(ctx, &ctx->batches[0]); 2562bf215546Sopenharmony_ci 2563bf215546Sopenharmony_ci ctx->sampler_pool = d3d12_descriptor_pool_new(screen, 2564bf215546Sopenharmony_ci D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 2565bf215546Sopenharmony_ci 64); 2566bf215546Sopenharmony_ci if (!ctx->sampler_pool) { 2567bf215546Sopenharmony_ci FREE(ctx); 2568bf215546Sopenharmony_ci return NULL; 2569bf215546Sopenharmony_ci } 2570bf215546Sopenharmony_ci d3d12_init_null_sampler(ctx); 2571bf215546Sopenharmony_ci 2572bf215546Sopenharmony_ci#ifdef _WIN32 2573bf215546Sopenharmony_ci if (!(d3d12_debug & D3D12_DEBUG_EXPERIMENTAL) || 2574bf215546Sopenharmony_ci (d3d12_debug & D3D12_DEBUG_DISASS)) 2575bf215546Sopenharmony_ci ctx->dxil_validator = dxil_create_validator(NULL); 2576bf215546Sopenharmony_ci#endif 2577bf215546Sopenharmony_ci 2578bf215546Sopenharmony_ci ctx->blitter = util_blitter_create(&ctx->base); 2579bf215546Sopenharmony_ci if (!ctx->blitter) 2580bf215546Sopenharmony_ci return NULL; 2581bf215546Sopenharmony_ci 2582bf215546Sopenharmony_ci if (!d3d12_init_polygon_stipple(&ctx->base)) { 2583bf215546Sopenharmony_ci debug_printf("D3D12: failed to initialize polygon stipple resources\n"); 2584bf215546Sopenharmony_ci FREE(ctx); 2585bf215546Sopenharmony_ci return NULL; 2586bf215546Sopenharmony_ci } 2587bf215546Sopenharmony_ci 2588bf215546Sopenharmony_ci mtx_lock(&screen->submit_mutex); 2589bf215546Sopenharmony_ci list_addtail(&ctx->context_list_entry, &screen->context_list); 2590bf215546Sopenharmony_ci mtx_unlock(&screen->submit_mutex); 2591bf215546Sopenharmony_ci 2592bf215546Sopenharmony_ci if (flags & PIPE_CONTEXT_PREFER_THREADED) 2593bf215546Sopenharmony_ci return threaded_context_create(&ctx->base, 2594bf215546Sopenharmony_ci &screen->transfer_pool, 2595bf215546Sopenharmony_ci d3d12_replace_buffer_storage, 2596bf215546Sopenharmony_ci NULL, 2597bf215546Sopenharmony_ci &ctx->threaded_context); 2598bf215546Sopenharmony_ci 2599bf215546Sopenharmony_ci return &ctx->base; 2600bf215546Sopenharmony_ci} 2601bf215546Sopenharmony_ci 2602bf215546Sopenharmony_cibool 2603bf215546Sopenharmony_cid3d12_need_zero_one_depth_range(struct d3d12_context *ctx) 2604bf215546Sopenharmony_ci{ 2605bf215546Sopenharmony_ci struct d3d12_shader_selector *fs = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]; 2606bf215546Sopenharmony_ci 2607bf215546Sopenharmony_ci /** 2608bf215546Sopenharmony_ci * OpenGL Compatibility spec, section 15.2.3 (Shader Outputs) says 2609bf215546Sopenharmony_ci * the following: 2610bf215546Sopenharmony_ci * 2611bf215546Sopenharmony_ci * For fixed-point depth buffers, the final fragment depth written by 2612bf215546Sopenharmony_ci * a fragment shader is first clamped to [0, 1] and then converted to 2613bf215546Sopenharmony_ci * fixed-point as if it were a window z value (see section 13.8.1). 2614bf215546Sopenharmony_ci * For floating-point depth buffers, conversion is not performed but 2615bf215546Sopenharmony_ci * clamping is. Note that the depth range computation is not applied 2616bf215546Sopenharmony_ci * here, only the conversion to fixed-point. 2617bf215546Sopenharmony_ci * 2618bf215546Sopenharmony_ci * However, the D3D11.3 Functional Spec, section 17.10 (Depth Clamp) says 2619bf215546Sopenharmony_ci * the following: 2620bf215546Sopenharmony_ci * 2621bf215546Sopenharmony_ci * Depth values that reach the Output Merger, whether coming from 2622bf215546Sopenharmony_ci * interpolation or from Pixel Shader output (replacing the 2623bf215546Sopenharmony_ci * interpolated z), are always clamped: 2624bf215546Sopenharmony_ci * z = min(Viewport.MaxDepth,max(Viewport.MinDepth,z)) 2625bf215546Sopenharmony_ci * following the D3D11 Floating Point Rules(3.1) for min/max. 2626bf215546Sopenharmony_ci * 2627bf215546Sopenharmony_ci * This means that we can't always use the fixed-function viewport-mapping 2628bf215546Sopenharmony_ci * D3D provides. 2629bf215546Sopenharmony_ci * 2630bf215546Sopenharmony_ci * There's only one case where the difference matters: When the fragment 2631bf215546Sopenharmony_ci * shader writes a non-implicit value to gl_FragDepth. In all other 2632bf215546Sopenharmony_ci * cases, the fragment either shouldn't have been rasterized in the 2633bf215546Sopenharmony_ci * first place, or the implicit gl_FragCoord.z-value should already have 2634bf215546Sopenharmony_ci * been clamped to the depth-range. 2635bf215546Sopenharmony_ci * 2636bf215546Sopenharmony_ci * For simplicity, let's assume that an explicitly written frag-result 2637bf215546Sopenharmony_ci * doesn't simply forward the value of gl_FragCoord.z. If it does, we'll 2638bf215546Sopenharmony_ci * end up generating needless code, but the result will be correct. 2639bf215546Sopenharmony_ci */ 2640bf215546Sopenharmony_ci 2641bf215546Sopenharmony_ci return fs->initial->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH); 2642bf215546Sopenharmony_ci} 2643