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