1/*
2 * Copyright © Microsoft Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#ifndef D3D12_CONTEXT_H
25#define D3D12_CONTEXT_H
26
27#include "d3d12_batch.h"
28#include "d3d12_descriptor_pool.h"
29#include "d3d12_pipeline_state.h"
30
31#include "dxil_nir_lower_int_samplers.h"
32
33#include "pipe/p_context.h"
34#include "pipe/p_state.h"
35#include "util/list.h"
36#include "util/slab.h"
37#include "util/u_suballoc.h"
38#include "util/u_threaded_context.h"
39
40#define D3D12_GFX_SHADER_STAGES (PIPE_SHADER_TYPES - 1)
41
42enum d3d12_dirty_flags
43{
44   D3D12_DIRTY_NONE             = 0,
45   D3D12_DIRTY_BLEND            = (1 << 0),
46   D3D12_DIRTY_RASTERIZER       = (1 << 1),
47   D3D12_DIRTY_ZSA              = (1 << 2),
48   D3D12_DIRTY_VERTEX_ELEMENTS  = (1 << 3),
49   D3D12_DIRTY_BLEND_COLOR      = (1 << 4),
50   D3D12_DIRTY_STENCIL_REF      = (1 << 5),
51   D3D12_DIRTY_SAMPLE_MASK      = (1 << 6),
52   D3D12_DIRTY_VIEWPORT         = (1 << 7),
53   D3D12_DIRTY_FRAMEBUFFER      = (1 << 8),
54   D3D12_DIRTY_SCISSOR          = (1 << 9),
55   D3D12_DIRTY_VERTEX_BUFFERS   = (1 << 10),
56   D3D12_DIRTY_INDEX_BUFFER     = (1 << 11),
57   D3D12_DIRTY_PRIM_MODE        = (1 << 12),
58   D3D12_DIRTY_SHADER           = (1 << 13),
59   D3D12_DIRTY_ROOT_SIGNATURE   = (1 << 14),
60   D3D12_DIRTY_STREAM_OUTPUT    = (1 << 15),
61   D3D12_DIRTY_STRIP_CUT_VALUE  = (1 << 16),
62   D3D12_DIRTY_COMPUTE_SHADER   = (1 << 17),
63   D3D12_DIRTY_COMPUTE_ROOT_SIGNATURE = (1 << 18),
64};
65
66enum d3d12_shader_dirty_flags
67{
68   D3D12_SHADER_DIRTY_CONSTBUF      = (1 << 0),
69   D3D12_SHADER_DIRTY_SAMPLER_VIEWS = (1 << 1),
70   D3D12_SHADER_DIRTY_SAMPLERS      = (1 << 2),
71   D3D12_SHADER_DIRTY_SSBO          = (1 << 3),
72   D3D12_SHADER_DIRTY_IMAGE         = (1 << 4),
73};
74
75#define D3D12_DIRTY_GFX_PSO (D3D12_DIRTY_BLEND | D3D12_DIRTY_RASTERIZER | D3D12_DIRTY_ZSA | \
76                             D3D12_DIRTY_FRAMEBUFFER | D3D12_DIRTY_SAMPLE_MASK | \
77                             D3D12_DIRTY_VERTEX_ELEMENTS | D3D12_DIRTY_PRIM_MODE | \
78                             D3D12_DIRTY_SHADER | D3D12_DIRTY_ROOT_SIGNATURE | \
79                             D3D12_DIRTY_STRIP_CUT_VALUE | D3D12_DIRTY_STREAM_OUTPUT)
80#define D3D12_DIRTY_COMPUTE_PSO (D3D12_DIRTY_COMPUTE_SHADER | D3D12_DIRTY_COMPUTE_ROOT_SIGNATURE)
81
82#define D3D12_DIRTY_COMPUTE_MASK (D3D12_DIRTY_COMPUTE_SHADER | D3D12_DIRTY_COMPUTE_ROOT_SIGNATURE)
83#define D3D12_DIRTY_GFX_MASK ~D3D12_DIRTY_COMPUTE_MASK
84
85
86#define D3D12_SHADER_DIRTY_ALL (D3D12_SHADER_DIRTY_CONSTBUF | D3D12_SHADER_DIRTY_SAMPLER_VIEWS | \
87                                D3D12_SHADER_DIRTY_SAMPLERS | D3D12_SHADER_DIRTY_SSBO | \
88                                D3D12_SHADER_DIRTY_IMAGE)
89
90enum d3d12_binding_type {
91   D3D12_BINDING_CONSTANT_BUFFER,
92   D3D12_BINDING_SHADER_RESOURCE_VIEW,
93   D3D12_BINDING_SAMPLER,
94   D3D12_BINDING_STATE_VARS,
95   D3D12_BINDING_SSBO,
96   D3D12_BINDING_IMAGE,
97   D3D12_NUM_BINDING_TYPES
98};
99
100struct d3d12_sampler_state {
101   struct d3d12_descriptor_handle handle, handle_without_shadow;
102   bool is_integer_texture;
103   bool is_shadow_sampler;
104   enum pipe_tex_wrap wrap_r;
105   enum pipe_tex_wrap wrap_s;
106   enum pipe_tex_wrap wrap_t;
107   enum pipe_tex_filter filter;
108   float lod_bias;
109   float min_lod, max_lod;
110   float border_color[4];
111   enum pipe_compare_func compare_func;
112};
113
114enum d3d12_blend_factor_flags {
115   D3D12_BLEND_FACTOR_NONE  = 0,
116   D3D12_BLEND_FACTOR_COLOR = 1 << 0,
117   D3D12_BLEND_FACTOR_ALPHA = 1 << 1,
118   D3D12_BLEND_FACTOR_ANY   = 1 << 2,
119};
120
121struct d3d12_sampler_view {
122   struct pipe_sampler_view base;
123   struct d3d12_descriptor_handle handle;
124   unsigned mip_levels;
125   unsigned array_size;
126   unsigned texture_generation_id;
127   unsigned swizzle_override_r:3;         /**< PIPE_SWIZZLE_x for red component */
128   unsigned swizzle_override_g:3;         /**< PIPE_SWIZZLE_x for green component */
129   unsigned swizzle_override_b:3;         /**< PIPE_SWIZZLE_x for blue component */
130   unsigned swizzle_override_a:3;         /**< PIPE_SWIZZLE_x for alpha component */
131};
132
133static inline struct d3d12_sampler_view *
134d3d12_sampler_view(struct pipe_sampler_view *pview)
135{
136   return (struct d3d12_sampler_view *)pview;
137}
138
139struct d3d12_stream_output_target {
140   struct pipe_stream_output_target base;
141   struct pipe_resource *fill_buffer;
142   unsigned fill_buffer_offset;
143};
144
145struct d3d12_shader_state {
146   struct d3d12_shader *current;
147   unsigned state_dirty;
148};
149
150struct blitter_context;
151struct primconvert_context;
152
153#ifdef _WIN32
154struct dxil_validator;
155#endif
156
157#ifdef __cplusplus
158class ResourceStateManager;
159#endif
160
161struct d3d12_context {
162   struct pipe_context base;
163   struct slab_child_pool transfer_pool;
164   struct slab_child_pool transfer_pool_unsync;
165   struct list_head context_list_entry;
166   struct threaded_context *threaded_context;
167   struct primconvert_context *primconvert;
168   struct blitter_context *blitter;
169   struct u_suballocator query_allocator;
170   struct u_suballocator so_allocator;
171   struct hash_table *pso_cache;
172   struct hash_table *compute_pso_cache;
173   struct hash_table *root_signature_cache;
174   struct hash_table *cmd_signature_cache;
175   struct hash_table *gs_variant_cache;
176   struct hash_table *tcs_variant_cache;
177   struct hash_table *compute_transform_cache;
178   struct hash_table_u64 *bo_state_table;
179
180   struct d3d12_batch batches[4];
181   unsigned current_batch_idx;
182
183   struct util_dynarray recently_destroyed_bos;
184   struct util_dynarray barrier_scratch;
185   struct set *pending_barriers_bos;
186
187   struct pipe_constant_buffer cbufs[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
188   struct pipe_framebuffer_state fb;
189   struct pipe_vertex_buffer vbs[PIPE_MAX_ATTRIBS];
190   D3D12_VERTEX_BUFFER_VIEW vbvs[PIPE_MAX_ATTRIBS];
191   unsigned num_vbs;
192   float flip_y;
193   bool need_zero_one_depth_range;
194   enum pipe_prim_type initial_api_prim;
195   struct pipe_viewport_state viewport_states[PIPE_MAX_VIEWPORTS];
196   D3D12_VIEWPORT viewports[PIPE_MAX_VIEWPORTS];
197   unsigned num_viewports;
198   struct pipe_scissor_state scissor_states[PIPE_MAX_VIEWPORTS];
199   D3D12_RECT scissors[PIPE_MAX_VIEWPORTS];
200   float blend_factor[4];
201   struct pipe_stencil_ref stencil_ref;
202   struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
203   unsigned num_sampler_views[PIPE_SHADER_TYPES];
204   unsigned has_int_samplers;
205   struct pipe_shader_buffer ssbo_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
206   unsigned num_ssbo_views[PIPE_SHADER_TYPES];
207   struct pipe_image_view image_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
208   enum pipe_format image_view_emulation_formats[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
209   unsigned num_image_views[PIPE_SHADER_TYPES];
210   struct d3d12_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
211   unsigned num_samplers[PIPE_SHADER_TYPES];
212   D3D12_INDEX_BUFFER_VIEW ibv;
213   dxil_wrap_sampler_state tex_wrap_states[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
214   dxil_texture_swizzle_state tex_swizzle_state[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
215   enum compare_func tex_compare_func[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
216
217   struct {
218      bool enabled;
219      uint32_t pattern[32];
220      struct pipe_resource *texture;
221      struct pipe_sampler_view *sampler_view;
222      struct d3d12_sampler_state *sampler_cso;
223   } pstipple;
224
225   struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS];
226   D3D12_STREAM_OUTPUT_BUFFER_VIEW so_buffer_views[PIPE_MAX_SO_BUFFERS];
227   struct pipe_stream_output_target *fake_so_targets[PIPE_MAX_SO_BUFFERS];
228   D3D12_STREAM_OUTPUT_BUFFER_VIEW fake_so_buffer_views[PIPE_MAX_SO_BUFFERS];
229   unsigned fake_so_buffer_factor;
230   uint8_t patch_vertices;
231   float default_outer_tess_factor[4];
232   float default_inner_tess_factor[2];
233
234   struct d3d12_shader_selector *gfx_stages[D3D12_GFX_SHADER_STAGES];
235   struct d3d12_shader_selector *compute_state;
236
237   struct d3d12_gfx_pipeline_state gfx_pipeline_state;
238   struct d3d12_compute_pipeline_state compute_pipeline_state;
239   unsigned shader_dirty[PIPE_SHADER_TYPES];
240   unsigned state_dirty;
241   unsigned cmdlist_dirty;
242   ID3D12PipelineState *current_gfx_pso;
243   ID3D12PipelineState *current_compute_pso;
244   uint16_t reverse_depth_range;
245
246   uint64_t submit_id;
247   ID3D12GraphicsCommandList *cmdlist;
248   ID3D12GraphicsCommandList *state_fixup_cmdlist;
249
250   struct list_head active_queries;
251   bool queries_disabled;
252
253   struct d3d12_descriptor_pool *sampler_pool;
254   struct d3d12_descriptor_handle null_sampler;
255
256   PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE D3D12SerializeVersionedRootSignature;
257#ifdef _WIN32
258   struct dxil_validator *dxil_validator;
259#endif
260
261   struct d3d12_resource *current_predication;
262   bool predication_condition;
263
264   uint32_t transform_state_vars[4];
265
266#ifdef __cplusplus
267   ResourceStateManager *resource_state_manager;
268#else
269   void *resource_state_manager; /* opaque pointer; we don't know about classes in C */
270#endif
271   struct pipe_query *timestamp_query;
272
273   /* used by d3d12_blit.cpp */
274   void *stencil_resolve_vs, *stencil_resolve_fs, *stencil_resolve_fs_no_flip, *sampler_state;
275};
276
277static inline struct d3d12_context *
278d3d12_context(struct pipe_context *context)
279{
280   return (struct d3d12_context *)context;
281}
282
283static inline struct d3d12_batch *
284d3d12_current_batch(struct d3d12_context *ctx)
285{
286   assert(ctx->current_batch_idx < ARRAY_SIZE(ctx->batches));
287   return ctx->batches + ctx->current_batch_idx;
288}
289
290#define d3d12_foreach_submitted_batch(ctx, batch) \
291   unsigned oldest = (ctx->current_batch_idx + 1) % ARRAY_SIZE(ctx->batches); \
292   while (ctx->batches[oldest].fence == NULL && oldest != ctx->current_batch_idx) \
293      oldest = (oldest + 1) % ARRAY_SIZE(ctx->batches); \
294   struct d3d12_batch *batch = &ctx->batches[oldest]; \
295   for (; oldest != ctx->current_batch_idx; \
296        oldest = (oldest + 1) % ARRAY_SIZE(ctx->batches), \
297        batch = &ctx->batches[oldest])
298
299struct pipe_context *
300d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags);
301
302bool
303d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor);
304
305bool
306d3d12_disable_fake_so_buffers(struct d3d12_context *ctx);
307
308void
309d3d12_flush_cmdlist(struct d3d12_context *ctx);
310
311void
312d3d12_flush_cmdlist_and_wait(struct d3d12_context *ctx);
313
314
315enum d3d12_transition_flags {
316   D3D12_TRANSITION_FLAG_NONE = 0,
317   D3D12_TRANSITION_FLAG_INVALIDATE_BINDINGS = 1,
318   D3D12_TRANSITION_FLAG_ACCUMULATE_STATE = 2,
319};
320
321void
322d3d12_transition_resource_state(struct d3d12_context* ctx,
323                                struct d3d12_resource* res,
324                                D3D12_RESOURCE_STATES state,
325                                d3d12_transition_flags flags);
326
327void
328d3d12_transition_subresources_state(struct d3d12_context *ctx,
329                                    struct d3d12_resource *res,
330                                    unsigned start_level, unsigned num_levels,
331                                    unsigned start_layer, unsigned num_layers,
332                                    unsigned start_plane, unsigned num_planes,
333                                    D3D12_RESOURCE_STATES state,
334                                    d3d12_transition_flags flags);
335
336void
337d3d12_apply_resource_states(struct d3d12_context* ctx, bool is_implicit_dispatch);
338
339void
340d3d12_draw_vbo(struct pipe_context *pctx,
341               const struct pipe_draw_info *dinfo,
342               unsigned drawid_offset,
343               const struct pipe_draw_indirect_info *indirect,
344               const struct pipe_draw_start_count_bias *draws,
345               unsigned num_draws);
346
347void
348d3d12_launch_grid(struct pipe_context *pctx,
349                  const struct pipe_grid_info *info);
350
351void
352d3d12_blit(struct pipe_context *pctx,
353           const struct pipe_blit_info *info);
354
355void
356d3d12_context_query_init(struct pipe_context *pctx);
357
358bool
359d3d12_need_zero_one_depth_range(struct d3d12_context *ctx);
360
361void
362d3d12_init_sampler_view_descriptor(struct d3d12_sampler_view *sampler_view);
363
364void
365d3d12_invalidate_context_bindings(struct d3d12_context *ctx, struct d3d12_resource *res);
366
367#ifdef HAVE_GALLIUM_D3D12_VIDEO
368struct pipe_video_codec* d3d12_video_create_codec( struct pipe_context *context,
369                                                const struct pipe_video_codec *t);
370#endif
371
372#endif
373