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 #include "d3d12_nir_lower_texcmp.h"
31
32 #include "dxil_nir_lower_int_samplers.h"
33
34 #include "pipe/p_context.h"
35 #include "pipe/p_state.h"
36 #include "util/list.h"
37 #include "util/slab.h"
38 #include "util/u_suballoc.h"
39
40 #include <directx/d3d12.h>
41
42 #define D3D12_GFX_SHADER_STAGES (PIPE_SHADER_TYPES - 1)
43
44 enum d3d12_dirty_flags
45 {
46 D3D12_DIRTY_NONE = 0,
47 D3D12_DIRTY_BLEND = (1 << 0),
48 D3D12_DIRTY_RASTERIZER = (1 << 1),
49 D3D12_DIRTY_ZSA = (1 << 2),
50 D3D12_DIRTY_VERTEX_ELEMENTS = (1 << 3),
51 D3D12_DIRTY_BLEND_COLOR = (1 << 4),
52 D3D12_DIRTY_STENCIL_REF = (1 << 5),
53 D3D12_DIRTY_SAMPLE_MASK = (1 << 6),
54 D3D12_DIRTY_VIEWPORT = (1 << 7),
55 D3D12_DIRTY_FRAMEBUFFER = (1 << 8),
56 D3D12_DIRTY_SCISSOR = (1 << 9),
57 D3D12_DIRTY_VERTEX_BUFFERS = (1 << 10),
58 D3D12_DIRTY_INDEX_BUFFER = (1 << 11),
59 D3D12_DIRTY_PRIM_MODE = (1 << 12),
60 D3D12_DIRTY_SHADER = (1 << 13),
61 D3D12_DIRTY_ROOT_SIGNATURE = (1 << 14),
62 D3D12_DIRTY_STREAM_OUTPUT = (1 << 15),
63 D3D12_DIRTY_STRIP_CUT_VALUE = (1 << 16),
64 };
65
66 enum 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 };
72
73 #define D3D12_DIRTY_PSO (D3D12_DIRTY_BLEND | D3D12_DIRTY_RASTERIZER | D3D12_DIRTY_ZSA | \
74 D3D12_DIRTY_FRAMEBUFFER | D3D12_DIRTY_SAMPLE_MASK | \
75 D3D12_DIRTY_VERTEX_ELEMENTS | D3D12_DIRTY_PRIM_MODE | \
76 D3D12_DIRTY_SHADER | D3D12_DIRTY_ROOT_SIGNATURE | \
77 D3D12_DIRTY_STRIP_CUT_VALUE)
78
79 #define D3D12_SHADER_DIRTY_ALL (D3D12_SHADER_DIRTY_CONSTBUF | D3D12_SHADER_DIRTY_SAMPLER_VIEWS | \
80 D3D12_SHADER_DIRTY_SAMPLERS)
81
82 enum d3d12_binding_type {
83 D3D12_BINDING_CONSTANT_BUFFER,
84 D3D12_BINDING_SHADER_RESOURCE_VIEW,
85 D3D12_BINDING_SAMPLER,
86 D3D12_BINDING_STATE_VARS,
87 D3D12_NUM_BINDING_TYPES
88 };
89
90 struct d3d12_sampler_state {
91 struct d3d12_descriptor_handle handle, handle_without_shadow;
92 bool is_integer_texture;
93 bool is_shadow_sampler;
94 enum pipe_tex_wrap wrap_r;
95 enum pipe_tex_wrap wrap_s;
96 enum pipe_tex_wrap wrap_t;
97 enum pipe_tex_filter filter;
98 float lod_bias;
99 float min_lod, max_lod;
100 float border_color[4];
101 enum pipe_compare_func compare_func;
102 };
103
104 enum d3d12_blend_factor_flags {
105 D3D12_BLEND_FACTOR_NONE = 0,
106 D3D12_BLEND_FACTOR_COLOR = 1 << 0,
107 D3D12_BLEND_FACTOR_ALPHA = 1 << 1,
108 D3D12_BLEND_FACTOR_ANY = 1 << 2,
109 };
110
111 struct d3d12_sampler_view {
112 struct pipe_sampler_view base;
113 struct d3d12_descriptor_handle handle;
114 unsigned mip_levels;
115 unsigned array_size;
116 unsigned swizzle_override_r:3; /**< PIPE_SWIZZLE_x for red component */
117 unsigned swizzle_override_g:3; /**< PIPE_SWIZZLE_x for green component */
118 unsigned swizzle_override_b:3; /**< PIPE_SWIZZLE_x for blue component */
119 unsigned swizzle_override_a:3; /**< PIPE_SWIZZLE_x for alpha component */
120 };
121
122 static inline struct d3d12_sampler_view *
d3d12_sampler_view(struct pipe_sampler_view * pview)123 d3d12_sampler_view(struct pipe_sampler_view *pview)
124 {
125 return (struct d3d12_sampler_view *)pview;
126 }
127
128 struct d3d12_stream_output_target {
129 struct pipe_stream_output_target base;
130 struct pipe_resource *fill_buffer;
131 unsigned fill_buffer_offset;
132 uint64_t cached_filled_size;
133 };
134
135 struct d3d12_shader_state {
136 struct d3d12_shader *current;
137 unsigned state_dirty;
138 };
139
140 struct blitter_context;
141 struct primconvert_context;
142 struct d3d12_validation_tools;
143
144 #ifdef __cplusplus
145 class ResourceStateManager;
146 #endif
147
148 struct d3d12_context {
149 struct pipe_context base;
150 struct slab_child_pool transfer_pool;
151 struct primconvert_context *primconvert;
152 struct blitter_context *blitter;
153 struct u_suballocator query_allocator;
154 struct u_suballocator so_allocator;
155 struct hash_table *pso_cache;
156 struct hash_table *root_signature_cache;
157 struct hash_table *gs_variant_cache;
158
159 struct d3d12_batch batches[4];
160 unsigned current_batch_idx;
161
162 struct pipe_constant_buffer cbufs[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
163 struct pipe_framebuffer_state fb;
164 struct pipe_vertex_buffer vbs[PIPE_MAX_ATTRIBS];
165 D3D12_VERTEX_BUFFER_VIEW vbvs[PIPE_MAX_ATTRIBS];
166 unsigned num_vbs;
167 float flip_y;
168 bool need_zero_one_depth_range;
169 enum pipe_prim_type initial_api_prim;
170 struct pipe_viewport_state viewport_states[PIPE_MAX_VIEWPORTS];
171 D3D12_VIEWPORT viewports[PIPE_MAX_VIEWPORTS];
172 unsigned num_viewports;
173 struct pipe_scissor_state scissor_states[PIPE_MAX_VIEWPORTS];
174 D3D12_RECT scissors[PIPE_MAX_VIEWPORTS];
175 float blend_factor[4];
176 struct pipe_stencil_ref stencil_ref;
177 struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
178 unsigned num_sampler_views[PIPE_SHADER_TYPES];
179 unsigned has_int_samplers;
180 struct d3d12_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
181 unsigned num_samplers[PIPE_SHADER_TYPES];
182 D3D12_INDEX_BUFFER_VIEW ibv;
183 dxil_wrap_sampler_state tex_wrap_states[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
184 dxil_texture_swizzle_state tex_swizzle_state[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
185 enum compare_func tex_compare_func[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
186
187 struct {
188 bool enabled;
189 uint32_t pattern[32];
190 struct pipe_resource *texture;
191 struct pipe_sampler_view *sampler_view;
192 struct d3d12_sampler_state *sampler_cso;
193 } pstipple;
194
195 struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS];
196 D3D12_STREAM_OUTPUT_BUFFER_VIEW so_buffer_views[PIPE_MAX_SO_BUFFERS];
197 struct pipe_stream_output_target *fake_so_targets[PIPE_MAX_SO_BUFFERS];
198 D3D12_STREAM_OUTPUT_BUFFER_VIEW fake_so_buffer_views[PIPE_MAX_SO_BUFFERS];
199 unsigned fake_so_buffer_factor;
200
201 struct d3d12_shader_selector *gfx_stages[D3D12_GFX_SHADER_STAGES];
202
203 struct d3d12_gfx_pipeline_state gfx_pipeline_state;
204 unsigned shader_dirty[D3D12_GFX_SHADER_STAGES];
205 unsigned state_dirty;
206 unsigned cmdlist_dirty;
207 ID3D12PipelineState *current_pso;
208 bool reverse_depth_range;
209
210 ID3D12Fence *cmdqueue_fence;
211 uint64_t fence_value;
212 ID3D12GraphicsCommandList *cmdlist;
213
214 struct list_head active_queries;
215 bool queries_disabled;
216
217 struct d3d12_descriptor_pool *sampler_pool;
218 struct d3d12_descriptor_handle null_sampler;
219
220 PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE D3D12SerializeVersionedRootSignature;
221 struct d3d12_validation_tools *validation_tools;
222
223 struct d3d12_resource *current_predication;
224
225 #ifdef __cplusplus
226 ResourceStateManager *resource_state_manager;
227 #else
228 void *resource_state_manager; /* opaque pointer; we don't know about classes in C */
229 #endif
230 struct pipe_query *timestamp_query;
231
232 /* used by d3d12_blit.cpp */
233 void *stencil_resolve_vs, *stencil_resolve_fs, *stencil_resolve_fs_no_flip, *sampler_state;
234 };
235
236 static inline struct d3d12_context *
d3d12_context(struct pipe_context * context)237 d3d12_context(struct pipe_context *context)
238 {
239 return (struct d3d12_context *)context;
240 }
241
242 static inline struct d3d12_batch *
d3d12_current_batch(struct d3d12_context * ctx)243 d3d12_current_batch(struct d3d12_context *ctx)
244 {
245 assert(ctx->current_batch_idx < ARRAY_SIZE(ctx->batches));
246 return ctx->batches + ctx->current_batch_idx;
247 }
248
249 #define d3d12_foreach_submitted_batch(ctx, batch) \
250 unsigned oldest = (ctx->current_batch_idx + 1) % ARRAY_SIZE(ctx->batches); \
251 while (ctx->batches[oldest].fence == NULL && oldest != ctx->current_batch_idx) \
252 oldest = (oldest + 1) % ARRAY_SIZE(ctx->batches); \
253 struct d3d12_batch *batch = &ctx->batches[oldest]; \
254 for (; oldest != ctx->current_batch_idx; \
255 oldest = (oldest + 1) % ARRAY_SIZE(ctx->batches), \
256 batch = &ctx->batches[oldest])
257
258 struct pipe_context *
259 d3d12_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags);
260
261 bool
262 d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor);
263
264 bool
265 d3d12_disable_fake_so_buffers(struct d3d12_context *ctx);
266
267 void
268 d3d12_flush_cmdlist(struct d3d12_context *ctx);
269
270 void
271 d3d12_flush_cmdlist_and_wait(struct d3d12_context *ctx);
272
273
274 enum d3d12_bind_invalidate_option {
275 D3D12_BIND_INVALIDATE_NONE,
276 D3D12_BIND_INVALIDATE_FULL,
277 };
278
279 void
280 d3d12_transition_resource_state(struct d3d12_context* ctx,
281 struct d3d12_resource* res,
282 D3D12_RESOURCE_STATES state,
283 d3d12_bind_invalidate_option bind_invalidate);
284
285 void
286 d3d12_transition_subresources_state(struct d3d12_context *ctx,
287 struct d3d12_resource *res,
288 unsigned start_level, unsigned num_levels,
289 unsigned start_layer, unsigned num_layers,
290 unsigned start_plane, unsigned num_planes,
291 D3D12_RESOURCE_STATES state,
292 d3d12_bind_invalidate_option bind_invalidate);
293
294 void
295 d3d12_apply_resource_states(struct d3d12_context* ctx);
296
297 void
298 d3d12_draw_vbo(struct pipe_context *pctx,
299 const struct pipe_draw_info *dinfo,
300 unsigned drawid_offset,
301 const struct pipe_draw_indirect_info *indirect,
302 const struct pipe_draw_start_count_bias *draws,
303 unsigned num_draws);
304
305 void
306 d3d12_blit(struct pipe_context *pctx,
307 const struct pipe_blit_info *info);
308
309 void
310 d3d12_context_query_init(struct pipe_context *pctx);
311
312 bool
313 d3d12_need_zero_one_depth_range(struct d3d12_context *ctx);
314
315 #endif
316