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