xref: /aosp_15_r20/external/mesa3d/src/microsoft/vulkan/dzn_pipeline.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © Microsoft Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "dzn_private.h"
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #include "spirv/nir_spirv.h"
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker #include "dxil_nir.h"
29*61046927SAndroid Build Coastguard Worker #include "nir_to_dxil.h"
30*61046927SAndroid Build Coastguard Worker #include "dxil_spirv_nir.h"
31*61046927SAndroid Build Coastguard Worker #include "spirv_to_dxil.h"
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include "dxil_validator.h"
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker #include "vk_alloc.h"
36*61046927SAndroid Build Coastguard Worker #include "vk_util.h"
37*61046927SAndroid Build Coastguard Worker #include "vk_format.h"
38*61046927SAndroid Build Coastguard Worker #include "vk_pipeline.h"
39*61046927SAndroid Build Coastguard Worker #include "vk_pipeline_cache.h"
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker #define d3d12_pipeline_state_stream_new_desc(__stream, __maxstreamsz, __id, __type, __desc) \
44*61046927SAndroid Build Coastguard Worker    __type *__desc; \
45*61046927SAndroid Build Coastguard Worker    do { \
46*61046927SAndroid Build Coastguard Worker       struct { \
47*61046927SAndroid Build Coastguard Worker          D3D12_PIPELINE_STATE_SUBOBJECT_TYPE type; \
48*61046927SAndroid Build Coastguard Worker          __type desc; \
49*61046927SAndroid Build Coastguard Worker       } *__wrapper; \
50*61046927SAndroid Build Coastguard Worker       (__stream)->SizeInBytes = ALIGN_POT((__stream)->SizeInBytes, alignof(void *)); \
51*61046927SAndroid Build Coastguard Worker       __wrapper = (void *)((uint8_t *)(__stream)->pPipelineStateSubobjectStream + (__stream)->SizeInBytes); \
52*61046927SAndroid Build Coastguard Worker       (__stream)->SizeInBytes += sizeof(*__wrapper); \
53*61046927SAndroid Build Coastguard Worker       assert((__stream)->SizeInBytes <= __maxstreamsz); \
54*61046927SAndroid Build Coastguard Worker       __wrapper->type = __id; \
55*61046927SAndroid Build Coastguard Worker       __desc = &__wrapper->desc; \
56*61046927SAndroid Build Coastguard Worker       memset(__desc, 0, sizeof(*__desc)); \
57*61046927SAndroid Build Coastguard Worker    } while (0)
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker #define d3d12_pipeline_state_stream_new_desc_abbrev(__stream, __maxstreamsz, __id, __type, __desc) \
60*61046927SAndroid Build Coastguard Worker    d3d12_pipeline_state_stream_new_desc(__stream, __maxstreamsz, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ ## __id, __type, __desc)
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker #define d3d12_gfx_pipeline_state_stream_new_desc(__stream, __id, __type, __desc) \
63*61046927SAndroid Build Coastguard Worker    d3d12_pipeline_state_stream_new_desc_abbrev(__stream, MAX_GFX_PIPELINE_STATE_STREAM_SIZE, __id, __type, __desc)
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker #define d3d12_compute_pipeline_state_stream_new_desc(__stream, __id, __type, __desc) \
66*61046927SAndroid Build Coastguard Worker    d3d12_pipeline_state_stream_new_desc_abbrev(__stream, MAX_COMPUTE_PIPELINE_STATE_STREAM_SIZE, __id, __type, __desc)
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker static bool
gfx_pipeline_variant_key_equal(const void * a,const void * b)69*61046927SAndroid Build Coastguard Worker gfx_pipeline_variant_key_equal(const void *a, const void *b)
70*61046927SAndroid Build Coastguard Worker {
71*61046927SAndroid Build Coastguard Worker    return !memcmp(a, b, sizeof(struct dzn_graphics_pipeline_variant_key));
72*61046927SAndroid Build Coastguard Worker }
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker static uint32_t
gfx_pipeline_variant_key_hash(const void * key)75*61046927SAndroid Build Coastguard Worker gfx_pipeline_variant_key_hash(const void *key)
76*61046927SAndroid Build Coastguard Worker {
77*61046927SAndroid Build Coastguard Worker    return _mesa_hash_data(key, sizeof(struct dzn_graphics_pipeline_variant_key));
78*61046927SAndroid Build Coastguard Worker }
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker static bool
gfx_pipeline_cmd_signature_key_equal(const void * a,const void * b)81*61046927SAndroid Build Coastguard Worker gfx_pipeline_cmd_signature_key_equal(const void *a, const void *b)
82*61046927SAndroid Build Coastguard Worker {
83*61046927SAndroid Build Coastguard Worker    return !memcmp(a, b, sizeof(struct dzn_indirect_draw_cmd_sig_key));
84*61046927SAndroid Build Coastguard Worker }
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker static uint32_t
gfx_pipeline_cmd_signature_key_hash(const void * key)87*61046927SAndroid Build Coastguard Worker gfx_pipeline_cmd_signature_key_hash(const void *key)
88*61046927SAndroid Build Coastguard Worker {
89*61046927SAndroid Build Coastguard Worker    return _mesa_hash_data(key, sizeof(struct dzn_indirect_draw_cmd_sig_key));
90*61046927SAndroid Build Coastguard Worker }
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker struct dzn_cached_blob {
93*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_object base;
94*61046927SAndroid Build Coastguard Worker    uint8_t hash[SHA1_DIGEST_LENGTH];
95*61046927SAndroid Build Coastguard Worker    const void *data;
96*61046927SAndroid Build Coastguard Worker    size_t size;
97*61046927SAndroid Build Coastguard Worker };
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker static bool
dzn_cached_blob_serialize(struct vk_pipeline_cache_object * object,struct blob * blob)100*61046927SAndroid Build Coastguard Worker dzn_cached_blob_serialize(struct vk_pipeline_cache_object *object,
101*61046927SAndroid Build Coastguard Worker                           struct blob *blob)
102*61046927SAndroid Build Coastguard Worker {
103*61046927SAndroid Build Coastguard Worker    struct dzn_cached_blob *cached_blob =
104*61046927SAndroid Build Coastguard Worker       container_of(object, struct dzn_cached_blob, base);
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker    blob_write_bytes(blob, cached_blob->data, cached_blob->size);
107*61046927SAndroid Build Coastguard Worker    return true;
108*61046927SAndroid Build Coastguard Worker }
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker static void
dzn_cached_blob_destroy(struct vk_device * device,struct vk_pipeline_cache_object * object)111*61046927SAndroid Build Coastguard Worker dzn_cached_blob_destroy(struct vk_device *device,
112*61046927SAndroid Build Coastguard Worker                         struct vk_pipeline_cache_object *object)
113*61046927SAndroid Build Coastguard Worker {
114*61046927SAndroid Build Coastguard Worker    struct dzn_cached_blob *shader =
115*61046927SAndroid Build Coastguard Worker       container_of(object, struct dzn_cached_blob, base);
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    vk_free(&device->alloc, shader);
118*61046927SAndroid Build Coastguard Worker }
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker static struct vk_pipeline_cache_object *
121*61046927SAndroid Build Coastguard Worker dzn_cached_blob_create(struct vk_device *device,
122*61046927SAndroid Build Coastguard Worker                        const void *hash,
123*61046927SAndroid Build Coastguard Worker                        const void *data,
124*61046927SAndroid Build Coastguard Worker                        size_t data_size);
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker static struct vk_pipeline_cache_object *
dzn_cached_blob_deserialize(struct vk_pipeline_cache * cache,const void * key_data,size_t key_size,struct blob_reader * blob)127*61046927SAndroid Build Coastguard Worker dzn_cached_blob_deserialize(struct vk_pipeline_cache *cache,
128*61046927SAndroid Build Coastguard Worker                             const void *key_data, size_t key_size,
129*61046927SAndroid Build Coastguard Worker                             struct blob_reader *blob)
130*61046927SAndroid Build Coastguard Worker {
131*61046927SAndroid Build Coastguard Worker    size_t data_size = blob->end - blob->current;
132*61046927SAndroid Build Coastguard Worker    assert(key_size == SHA1_DIGEST_LENGTH);
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker    return dzn_cached_blob_create(cache->base.device, key_data,
135*61046927SAndroid Build Coastguard Worker                                  blob_read_bytes(blob, data_size), data_size);
136*61046927SAndroid Build Coastguard Worker }
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_cache_object_ops dzn_cached_blob_ops = {
139*61046927SAndroid Build Coastguard Worker    .serialize = dzn_cached_blob_serialize,
140*61046927SAndroid Build Coastguard Worker    .deserialize = dzn_cached_blob_deserialize,
141*61046927SAndroid Build Coastguard Worker    .destroy = dzn_cached_blob_destroy,
142*61046927SAndroid Build Coastguard Worker };
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker static struct vk_pipeline_cache_object *
dzn_cached_blob_create(struct vk_device * device,const void * hash,const void * data,size_t data_size)146*61046927SAndroid Build Coastguard Worker dzn_cached_blob_create(struct vk_device *device,
147*61046927SAndroid Build Coastguard Worker                        const void *hash,
148*61046927SAndroid Build Coastguard Worker                        const void *data,
149*61046927SAndroid Build Coastguard Worker                        size_t data_size)
150*61046927SAndroid Build Coastguard Worker {
151*61046927SAndroid Build Coastguard Worker    VK_MULTIALLOC(ma);
152*61046927SAndroid Build Coastguard Worker    VK_MULTIALLOC_DECL(&ma, struct dzn_cached_blob, blob, 1);
153*61046927SAndroid Build Coastguard Worker    VK_MULTIALLOC_DECL(&ma, uint8_t, copy, data_size);
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker    if (!vk_multialloc_alloc(&ma, &device->alloc,
156*61046927SAndroid Build Coastguard Worker                             VK_SYSTEM_ALLOCATION_SCOPE_DEVICE))
157*61046927SAndroid Build Coastguard Worker       return NULL;
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker    memcpy(blob->hash, hash, sizeof(blob->hash));
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_init(device, &blob->base,
162*61046927SAndroid Build Coastguard Worker                                  &dzn_cached_blob_ops,
163*61046927SAndroid Build Coastguard Worker                                  blob->hash, sizeof(blob->hash));
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    if (data)
166*61046927SAndroid Build Coastguard Worker       memcpy(copy, data, data_size);
167*61046927SAndroid Build Coastguard Worker    blob->data = copy;
168*61046927SAndroid Build Coastguard Worker    blob->size = data_size;
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker    return &blob->base;
171*61046927SAndroid Build Coastguard Worker }
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker static VkResult
dzn_graphics_pipeline_prepare_for_variants(struct dzn_device * device,struct dzn_graphics_pipeline * pipeline)174*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_prepare_for_variants(struct dzn_device *device,
175*61046927SAndroid Build Coastguard Worker                                            struct dzn_graphics_pipeline *pipeline)
176*61046927SAndroid Build Coastguard Worker {
177*61046927SAndroid Build Coastguard Worker    if (pipeline->variants)
178*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker    pipeline->variants =
181*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_create(NULL,
182*61046927SAndroid Build Coastguard Worker                               gfx_pipeline_variant_key_hash,
183*61046927SAndroid Build Coastguard Worker                               gfx_pipeline_variant_key_equal);
184*61046927SAndroid Build Coastguard Worker    if (!pipeline->variants)
185*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
188*61046927SAndroid Build Coastguard Worker }
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker static dxil_spirv_shader_stage
to_dxil_shader_stage(VkShaderStageFlagBits in)191*61046927SAndroid Build Coastguard Worker to_dxil_shader_stage(VkShaderStageFlagBits in)
192*61046927SAndroid Build Coastguard Worker {
193*61046927SAndroid Build Coastguard Worker    switch (in) {
194*61046927SAndroid Build Coastguard Worker    case VK_SHADER_STAGE_VERTEX_BIT: return DXIL_SPIRV_SHADER_VERTEX;
195*61046927SAndroid Build Coastguard Worker    case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return DXIL_SPIRV_SHADER_TESS_CTRL;
196*61046927SAndroid Build Coastguard Worker    case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return DXIL_SPIRV_SHADER_TESS_EVAL;
197*61046927SAndroid Build Coastguard Worker    case VK_SHADER_STAGE_GEOMETRY_BIT: return DXIL_SPIRV_SHADER_GEOMETRY;
198*61046927SAndroid Build Coastguard Worker    case VK_SHADER_STAGE_FRAGMENT_BIT: return DXIL_SPIRV_SHADER_FRAGMENT;
199*61046927SAndroid Build Coastguard Worker    case VK_SHADER_STAGE_COMPUTE_BIT: return DXIL_SPIRV_SHADER_COMPUTE;
200*61046927SAndroid Build Coastguard Worker    default: unreachable("Unsupported stage");
201*61046927SAndroid Build Coastguard Worker    }
202*61046927SAndroid Build Coastguard Worker }
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker struct dzn_nir_options {
205*61046927SAndroid Build Coastguard Worker    enum dxil_spirv_yz_flip_mode yz_flip_mode;
206*61046927SAndroid Build Coastguard Worker    uint16_t y_flip_mask, z_flip_mask;
207*61046927SAndroid Build Coastguard Worker    bool force_sample_rate_shading;
208*61046927SAndroid Build Coastguard Worker    bool lower_view_index;
209*61046927SAndroid Build Coastguard Worker    bool lower_view_index_to_rt_layer;
210*61046927SAndroid Build Coastguard Worker    enum pipe_format *vi_conversions;
211*61046927SAndroid Build Coastguard Worker    const nir_shader_compiler_options *nir_opts;
212*61046927SAndroid Build Coastguard Worker };
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker static VkResult
dzn_pipeline_get_nir_shader(struct dzn_device * device,const struct dzn_pipeline_layout * layout,struct vk_pipeline_cache * cache,const uint8_t * hash,VkPipelineCreateFlags2KHR pipeline_flags,const VkPipelineShaderStageCreateInfo * stage_info,gl_shader_stage stage,const struct dzn_nir_options * options,struct dxil_spirv_metadata * metadata,nir_shader ** nir)215*61046927SAndroid Build Coastguard Worker dzn_pipeline_get_nir_shader(struct dzn_device *device,
216*61046927SAndroid Build Coastguard Worker                             const struct dzn_pipeline_layout *layout,
217*61046927SAndroid Build Coastguard Worker                             struct vk_pipeline_cache *cache,
218*61046927SAndroid Build Coastguard Worker                             const uint8_t *hash,
219*61046927SAndroid Build Coastguard Worker                             VkPipelineCreateFlags2KHR pipeline_flags,
220*61046927SAndroid Build Coastguard Worker                             const VkPipelineShaderStageCreateInfo *stage_info,
221*61046927SAndroid Build Coastguard Worker                             gl_shader_stage stage,
222*61046927SAndroid Build Coastguard Worker                             const struct dzn_nir_options *options,
223*61046927SAndroid Build Coastguard Worker                             struct dxil_spirv_metadata *metadata,
224*61046927SAndroid Build Coastguard Worker                             nir_shader **nir)
225*61046927SAndroid Build Coastguard Worker {
226*61046927SAndroid Build Coastguard Worker    if (cache) {
227*61046927SAndroid Build Coastguard Worker       *nir = vk_pipeline_cache_lookup_nir(cache, hash, SHA1_DIGEST_LENGTH,
228*61046927SAndroid Build Coastguard Worker                                           options->nir_opts, NULL, NULL);
229*61046927SAndroid Build Coastguard Worker       if (*nir) {
230*61046927SAndroid Build Coastguard Worker          /* This bit is explicitly added into the info before caching, since this sysval wouldn't
231*61046927SAndroid Build Coastguard Worker           * actually be present for this bit to be set by info gathering. */
232*61046927SAndroid Build Coastguard Worker          if ((*nir)->info.stage == MESA_SHADER_VERTEX &&
233*61046927SAndroid Build Coastguard Worker              BITSET_TEST((*nir)->info.system_values_read, SYSTEM_VALUE_FIRST_VERTEX))
234*61046927SAndroid Build Coastguard Worker             metadata->needs_draw_sysvals = true;
235*61046927SAndroid Build Coastguard Worker          return VK_SUCCESS;
236*61046927SAndroid Build Coastguard Worker       }
237*61046927SAndroid Build Coastguard Worker    }
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev =
240*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical, struct dzn_physical_device, vk);
241*61046927SAndroid Build Coastguard Worker    const struct spirv_to_nir_options *spirv_opts = dxil_spirv_nir_get_spirv_options();
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker    VkResult result =
244*61046927SAndroid Build Coastguard Worker       vk_pipeline_shader_stage_to_nir(&device->vk, pipeline_flags, stage_info,
245*61046927SAndroid Build Coastguard Worker                                       spirv_opts, options->nir_opts, NULL, nir);
246*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
247*61046927SAndroid Build Coastguard Worker       return result;
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    struct dxil_spirv_runtime_conf conf = {
250*61046927SAndroid Build Coastguard Worker       .runtime_data_cbv = {
251*61046927SAndroid Build Coastguard Worker          .register_space = DZN_REGISTER_SPACE_SYSVALS,
252*61046927SAndroid Build Coastguard Worker          .base_shader_register = 0,
253*61046927SAndroid Build Coastguard Worker       },
254*61046927SAndroid Build Coastguard Worker       .push_constant_cbv = {
255*61046927SAndroid Build Coastguard Worker          .register_space = DZN_REGISTER_SPACE_PUSH_CONSTANT,
256*61046927SAndroid Build Coastguard Worker          .base_shader_register = 0,
257*61046927SAndroid Build Coastguard Worker       },
258*61046927SAndroid Build Coastguard Worker       .first_vertex_and_base_instance_mode = pdev->options21.ExtendedCommandInfoSupported ?
259*61046927SAndroid Build Coastguard Worker             DXIL_SPIRV_SYSVAL_TYPE_NATIVE : DXIL_SPIRV_SYSVAL_TYPE_RUNTIME_DATA,
260*61046927SAndroid Build Coastguard Worker       .workgroup_id_mode = DXIL_SPIRV_SYSVAL_TYPE_RUNTIME_DATA,
261*61046927SAndroid Build Coastguard Worker       .yz_flip = {
262*61046927SAndroid Build Coastguard Worker          .mode = options->yz_flip_mode,
263*61046927SAndroid Build Coastguard Worker          .y_mask = options->y_flip_mask,
264*61046927SAndroid Build Coastguard Worker          .z_mask = options->z_flip_mask,
265*61046927SAndroid Build Coastguard Worker       },
266*61046927SAndroid Build Coastguard Worker       .declared_read_only_images_as_srvs = !device->bindless,
267*61046927SAndroid Build Coastguard Worker       .inferred_read_only_images_as_srvs = !device->bindless,
268*61046927SAndroid Build Coastguard Worker       .force_sample_rate_shading = options->force_sample_rate_shading,
269*61046927SAndroid Build Coastguard Worker       .lower_view_index = options->lower_view_index,
270*61046927SAndroid Build Coastguard Worker       .lower_view_index_to_rt_layer = options->lower_view_index_to_rt_layer,
271*61046927SAndroid Build Coastguard Worker       .shader_model_max = dzn_get_shader_model(pdev),
272*61046927SAndroid Build Coastguard Worker    };
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker    dxil_spirv_nir_passes(*nir, &conf, metadata);
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker    if (stage == MESA_SHADER_VERTEX) {
277*61046927SAndroid Build Coastguard Worker       bool needs_conv = false;
278*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
279*61046927SAndroid Build Coastguard Worker          if (options->vi_conversions[i] != PIPE_FORMAT_NONE)
280*61046927SAndroid Build Coastguard Worker             needs_conv = true;
281*61046927SAndroid Build Coastguard Worker       }
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker       if (needs_conv)
284*61046927SAndroid Build Coastguard Worker          NIR_PASS_V(*nir, dxil_nir_lower_vs_vertex_conversion, options->vi_conversions);
285*61046927SAndroid Build Coastguard Worker    }
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker    if (cache) {
288*61046927SAndroid Build Coastguard Worker       /* Cache this additional metadata */
289*61046927SAndroid Build Coastguard Worker       if (metadata->needs_draw_sysvals)
290*61046927SAndroid Build Coastguard Worker          BITSET_SET((*nir)->info.system_values_read, SYSTEM_VALUE_FIRST_VERTEX);
291*61046927SAndroid Build Coastguard Worker       vk_pipeline_cache_add_nir(cache, hash, SHA1_DIGEST_LENGTH, *nir);
292*61046927SAndroid Build Coastguard Worker    }
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
295*61046927SAndroid Build Coastguard Worker }
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker static bool
adjust_resource_index_binding(struct nir_builder * builder,nir_intrinsic_instr * intrin,void * cb_data)298*61046927SAndroid Build Coastguard Worker adjust_resource_index_binding(struct nir_builder *builder,
299*61046927SAndroid Build Coastguard Worker                               nir_intrinsic_instr *intrin,
300*61046927SAndroid Build Coastguard Worker                               void *cb_data)
301*61046927SAndroid Build Coastguard Worker {
302*61046927SAndroid Build Coastguard Worker    if (intrin->intrinsic != nir_intrinsic_vulkan_resource_index)
303*61046927SAndroid Build Coastguard Worker       return false;
304*61046927SAndroid Build Coastguard Worker 
305*61046927SAndroid Build Coastguard Worker    const struct dzn_pipeline_layout *layout = cb_data;
306*61046927SAndroid Build Coastguard Worker    unsigned set = nir_intrinsic_desc_set(intrin);
307*61046927SAndroid Build Coastguard Worker    unsigned binding = nir_intrinsic_binding(intrin);
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker    if (set >= layout->set_count ||
310*61046927SAndroid Build Coastguard Worker        binding >= layout->binding_translation[set].binding_count)
311*61046927SAndroid Build Coastguard Worker       return false;
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker    binding = layout->binding_translation[set].base_reg[binding];
314*61046927SAndroid Build Coastguard Worker    nir_intrinsic_set_binding(intrin, binding);
315*61046927SAndroid Build Coastguard Worker 
316*61046927SAndroid Build Coastguard Worker    return true;
317*61046927SAndroid Build Coastguard Worker }
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker static void
adjust_to_bindless_cb(struct dxil_spirv_binding_remapping * inout,void * context)320*61046927SAndroid Build Coastguard Worker adjust_to_bindless_cb(struct dxil_spirv_binding_remapping *inout, void *context)
321*61046927SAndroid Build Coastguard Worker {
322*61046927SAndroid Build Coastguard Worker    const struct dzn_pipeline_layout *layout = context;
323*61046927SAndroid Build Coastguard Worker    assert(inout->descriptor_set < layout->set_count);
324*61046927SAndroid Build Coastguard Worker    uint32_t new_binding = layout->binding_translation[inout->descriptor_set].base_reg[inout->binding];
325*61046927SAndroid Build Coastguard Worker    switch (layout->binding_translation[inout->descriptor_set].binding_class[inout->binding]) {
326*61046927SAndroid Build Coastguard Worker    case DZN_PIPELINE_BINDING_DYNAMIC_BUFFER:
327*61046927SAndroid Build Coastguard Worker       inout->descriptor_set = layout->set_count;
328*61046927SAndroid Build Coastguard Worker       FALLTHROUGH;
329*61046927SAndroid Build Coastguard Worker    case DZN_PIPELINE_BINDING_STATIC_SAMPLER:
330*61046927SAndroid Build Coastguard Worker       if (inout->is_sampler) {
331*61046927SAndroid Build Coastguard Worker          inout->descriptor_set = ~0;
332*61046927SAndroid Build Coastguard Worker          break;
333*61046927SAndroid Build Coastguard Worker       }
334*61046927SAndroid Build Coastguard Worker       FALLTHROUGH;
335*61046927SAndroid Build Coastguard Worker    case DZN_PIPELINE_BINDING_NORMAL:
336*61046927SAndroid Build Coastguard Worker       inout->binding = new_binding;
337*61046927SAndroid Build Coastguard Worker       break;
338*61046927SAndroid Build Coastguard Worker    default:
339*61046927SAndroid Build Coastguard Worker       unreachable("Invalid binding type");
340*61046927SAndroid Build Coastguard Worker    }
341*61046927SAndroid Build Coastguard Worker }
342*61046927SAndroid Build Coastguard Worker 
343*61046927SAndroid Build Coastguard Worker static bool
adjust_var_bindings(nir_shader * shader,struct dzn_device * device,const struct dzn_pipeline_layout * layout,uint8_t * bindings_hash)344*61046927SAndroid Build Coastguard Worker adjust_var_bindings(nir_shader *shader,
345*61046927SAndroid Build Coastguard Worker                     struct dzn_device *device,
346*61046927SAndroid Build Coastguard Worker                     const struct dzn_pipeline_layout *layout,
347*61046927SAndroid Build Coastguard Worker                     uint8_t *bindings_hash)
348*61046927SAndroid Build Coastguard Worker {
349*61046927SAndroid Build Coastguard Worker    uint32_t modes = nir_var_image | nir_var_uniform | nir_var_mem_ubo | nir_var_mem_ssbo;
350*61046927SAndroid Build Coastguard Worker    struct mesa_sha1 bindings_hash_ctx;
351*61046927SAndroid Build Coastguard Worker 
352*61046927SAndroid Build Coastguard Worker    if (bindings_hash)
353*61046927SAndroid Build Coastguard Worker       _mesa_sha1_init(&bindings_hash_ctx);
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker    nir_foreach_variable_with_modes(var, shader, modes) {
356*61046927SAndroid Build Coastguard Worker       if (var->data.mode == nir_var_uniform) {
357*61046927SAndroid Build Coastguard Worker          const struct glsl_type *type = glsl_without_array(var->type);
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker          if (!glsl_type_is_sampler(type) && !glsl_type_is_texture(type))
360*61046927SAndroid Build Coastguard Worker             continue;
361*61046927SAndroid Build Coastguard Worker       }
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker       unsigned s = var->data.descriptor_set, b = var->data.binding;
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker       if (s >= layout->set_count)
366*61046927SAndroid Build Coastguard Worker          continue;
367*61046927SAndroid Build Coastguard Worker 
368*61046927SAndroid Build Coastguard Worker       assert(b < layout->binding_translation[s].binding_count);
369*61046927SAndroid Build Coastguard Worker       if (!device->bindless)
370*61046927SAndroid Build Coastguard Worker          var->data.binding = layout->binding_translation[s].base_reg[b];
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker       if (bindings_hash) {
373*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&bindings_hash_ctx, &s, sizeof(s));
374*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&bindings_hash_ctx, &b, sizeof(b));
375*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&bindings_hash_ctx, &var->data.binding, sizeof(var->data.binding));
376*61046927SAndroid Build Coastguard Worker       }
377*61046927SAndroid Build Coastguard Worker    }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker    if (bindings_hash)
380*61046927SAndroid Build Coastguard Worker       _mesa_sha1_final(&bindings_hash_ctx, bindings_hash);
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    if (device->bindless) {
383*61046927SAndroid Build Coastguard Worker       struct dxil_spirv_nir_lower_bindless_options options = {
384*61046927SAndroid Build Coastguard Worker          .dynamic_buffer_binding = layout->dynamic_buffer_count ? layout->set_count : ~0,
385*61046927SAndroid Build Coastguard Worker          .num_descriptor_sets = layout->set_count,
386*61046927SAndroid Build Coastguard Worker          .callback_context = (void *)layout,
387*61046927SAndroid Build Coastguard Worker          .remap_binding = adjust_to_bindless_cb
388*61046927SAndroid Build Coastguard Worker       };
389*61046927SAndroid Build Coastguard Worker       bool ret = dxil_spirv_nir_lower_bindless(shader, &options);
390*61046927SAndroid Build Coastguard Worker       /* We skipped remapping variable bindings in the hashing loop, but if there's static
391*61046927SAndroid Build Coastguard Worker        * samplers still declared, we need to remap those now. */
392*61046927SAndroid Build Coastguard Worker       nir_foreach_variable_with_modes(var, shader, nir_var_uniform) {
393*61046927SAndroid Build Coastguard Worker          assert(glsl_type_is_sampler(glsl_without_array(var->type)));
394*61046927SAndroid Build Coastguard Worker          var->data.binding = layout->binding_translation[var->data.descriptor_set].base_reg[var->data.binding];
395*61046927SAndroid Build Coastguard Worker       }
396*61046927SAndroid Build Coastguard Worker       return ret;
397*61046927SAndroid Build Coastguard Worker    } else {
398*61046927SAndroid Build Coastguard Worker       return nir_shader_intrinsics_pass(shader, adjust_resource_index_binding,
399*61046927SAndroid Build Coastguard Worker                                           nir_metadata_all, (void *)layout);
400*61046927SAndroid Build Coastguard Worker    }
401*61046927SAndroid Build Coastguard Worker }
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker enum dxil_shader_model
dzn_get_shader_model(const struct dzn_physical_device * pdev)404*61046927SAndroid Build Coastguard Worker    dzn_get_shader_model(const struct dzn_physical_device *pdev)
405*61046927SAndroid Build Coastguard Worker {
406*61046927SAndroid Build Coastguard Worker    static_assert(D3D_SHADER_MODEL_6_0 == 0x60 && SHADER_MODEL_6_0 == 0x60000, "Validating math below");
407*61046927SAndroid Build Coastguard Worker    static_assert(D3D_SHADER_MODEL_6_8 == 0x68 && SHADER_MODEL_6_8 == 0x60008, "Validating math below");
408*61046927SAndroid Build Coastguard Worker    return ((pdev->shader_model & 0xf0) << 12) | (pdev->shader_model & 0xf);
409*61046927SAndroid Build Coastguard Worker }
410*61046927SAndroid Build Coastguard Worker 
411*61046927SAndroid Build Coastguard Worker static VkResult
dzn_pipeline_compile_shader(struct dzn_device * device,nir_shader * nir,uint32_t input_clip_size,D3D12_SHADER_BYTECODE * slot)412*61046927SAndroid Build Coastguard Worker dzn_pipeline_compile_shader(struct dzn_device *device,
413*61046927SAndroid Build Coastguard Worker                             nir_shader *nir,
414*61046927SAndroid Build Coastguard Worker                             uint32_t input_clip_size,
415*61046927SAndroid Build Coastguard Worker                             D3D12_SHADER_BYTECODE *slot)
416*61046927SAndroid Build Coastguard Worker {
417*61046927SAndroid Build Coastguard Worker    struct dzn_instance *instance =
418*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical->instance, struct dzn_instance, vk);
419*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev =
420*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical, struct dzn_physical_device, vk);
421*61046927SAndroid Build Coastguard Worker    struct nir_to_dxil_options opts = {
422*61046927SAndroid Build Coastguard Worker       .environment = DXIL_ENVIRONMENT_VULKAN,
423*61046927SAndroid Build Coastguard Worker       .lower_int16 = !pdev->options4.Native16BitShaderOpsSupported &&
424*61046927SAndroid Build Coastguard Worker       /* Don't lower 16-bit types if they can only come from min-precision */
425*61046927SAndroid Build Coastguard Worker          (device->vk.enabled_extensions.KHR_shader_float16_int8 ||
426*61046927SAndroid Build Coastguard Worker           device->vk.enabled_features.shaderFloat16 ||
427*61046927SAndroid Build Coastguard Worker           device->vk.enabled_features.shaderInt16),
428*61046927SAndroid Build Coastguard Worker       .shader_model_max = dzn_get_shader_model(pdev),
429*61046927SAndroid Build Coastguard Worker       .input_clip_size = input_clip_size,
430*61046927SAndroid Build Coastguard Worker #ifdef _WIN32
431*61046927SAndroid Build Coastguard Worker       .validator_version_max = dxil_get_validator_version(instance->dxil_validator),
432*61046927SAndroid Build Coastguard Worker #endif
433*61046927SAndroid Build Coastguard Worker    };
434*61046927SAndroid Build Coastguard Worker    struct blob dxil_blob;
435*61046927SAndroid Build Coastguard Worker    VkResult result = VK_SUCCESS;
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
438*61046927SAndroid Build Coastguard Worker    if (instance->debug_flags & DZN_DEBUG_NIR)
439*61046927SAndroid Build Coastguard Worker       nir_print_shader(nir, stderr);
440*61046927SAndroid Build Coastguard Worker 
441*61046927SAndroid Build Coastguard Worker    if (nir_to_dxil(nir, &opts, NULL, &dxil_blob)) {
442*61046927SAndroid Build Coastguard Worker       blob_finish_get_buffer(&dxil_blob, (void **)&slot->pShaderBytecode,
443*61046927SAndroid Build Coastguard Worker                              (size_t *)&slot->BytecodeLength);
444*61046927SAndroid Build Coastguard Worker    } else {
445*61046927SAndroid Build Coastguard Worker       result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
446*61046927SAndroid Build Coastguard Worker    }
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker    if (dxil_blob.allocated)
449*61046927SAndroid Build Coastguard Worker       blob_finish(&dxil_blob);
450*61046927SAndroid Build Coastguard Worker 
451*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
452*61046927SAndroid Build Coastguard Worker       return result;
453*61046927SAndroid Build Coastguard Worker 
454*61046927SAndroid Build Coastguard Worker #ifdef _WIN32
455*61046927SAndroid Build Coastguard Worker    char *err;
456*61046927SAndroid Build Coastguard Worker    bool res = dxil_validate_module(instance->dxil_validator,
457*61046927SAndroid Build Coastguard Worker                                    (void *)slot->pShaderBytecode,
458*61046927SAndroid Build Coastguard Worker                                    slot->BytecodeLength, &err);
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker    if (instance->debug_flags & DZN_DEBUG_DXIL) {
461*61046927SAndroid Build Coastguard Worker       char *disasm = dxil_disasm_module(instance->dxil_validator,
462*61046927SAndroid Build Coastguard Worker                                         (void *)slot->pShaderBytecode,
463*61046927SAndroid Build Coastguard Worker                                         slot->BytecodeLength);
464*61046927SAndroid Build Coastguard Worker       if (disasm) {
465*61046927SAndroid Build Coastguard Worker          fprintf(stderr,
466*61046927SAndroid Build Coastguard Worker                  "== BEGIN SHADER ============================================\n"
467*61046927SAndroid Build Coastguard Worker                  "%s\n"
468*61046927SAndroid Build Coastguard Worker                  "== END SHADER ==============================================\n",
469*61046927SAndroid Build Coastguard Worker                   disasm);
470*61046927SAndroid Build Coastguard Worker          ralloc_free(disasm);
471*61046927SAndroid Build Coastguard Worker       }
472*61046927SAndroid Build Coastguard Worker    }
473*61046927SAndroid Build Coastguard Worker 
474*61046927SAndroid Build Coastguard Worker    if (!res && !(instance->debug_flags & DZN_DEBUG_EXPERIMENTAL)) {
475*61046927SAndroid Build Coastguard Worker       if (err) {
476*61046927SAndroid Build Coastguard Worker          mesa_loge(
477*61046927SAndroid Build Coastguard Worker                "== VALIDATION ERROR =============================================\n"
478*61046927SAndroid Build Coastguard Worker                "%s\n"
479*61046927SAndroid Build Coastguard Worker                "== END ==========================================================\n",
480*61046927SAndroid Build Coastguard Worker                err);
481*61046927SAndroid Build Coastguard Worker          ralloc_free(err);
482*61046927SAndroid Build Coastguard Worker       }
483*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
484*61046927SAndroid Build Coastguard Worker    }
485*61046927SAndroid Build Coastguard Worker #endif
486*61046927SAndroid Build Coastguard Worker 
487*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
488*61046927SAndroid Build Coastguard Worker }
489*61046927SAndroid Build Coastguard Worker 
490*61046927SAndroid Build Coastguard Worker static D3D12_SHADER_BYTECODE *
dzn_pipeline_get_gfx_shader_slot(D3D12_PIPELINE_STATE_STREAM_DESC * stream,gl_shader_stage in)491*61046927SAndroid Build Coastguard Worker dzn_pipeline_get_gfx_shader_slot(D3D12_PIPELINE_STATE_STREAM_DESC *stream,
492*61046927SAndroid Build Coastguard Worker                                  gl_shader_stage in)
493*61046927SAndroid Build Coastguard Worker {
494*61046927SAndroid Build Coastguard Worker    switch (in) {
495*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_VERTEX: {
496*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(stream, VS, D3D12_SHADER_BYTECODE, desc);
497*61046927SAndroid Build Coastguard Worker       return desc;
498*61046927SAndroid Build Coastguard Worker    }
499*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_CTRL: {
500*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(stream, HS, D3D12_SHADER_BYTECODE, desc);
501*61046927SAndroid Build Coastguard Worker       return desc;
502*61046927SAndroid Build Coastguard Worker    }
503*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_EVAL: {
504*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(stream, DS, D3D12_SHADER_BYTECODE, desc);
505*61046927SAndroid Build Coastguard Worker       return desc;
506*61046927SAndroid Build Coastguard Worker    }
507*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_GEOMETRY: {
508*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(stream, GS, D3D12_SHADER_BYTECODE, desc);
509*61046927SAndroid Build Coastguard Worker       return desc;
510*61046927SAndroid Build Coastguard Worker    }
511*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_FRAGMENT: {
512*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(stream, PS, D3D12_SHADER_BYTECODE, desc);
513*61046927SAndroid Build Coastguard Worker       return desc;
514*61046927SAndroid Build Coastguard Worker    }
515*61046927SAndroid Build Coastguard Worker    default: unreachable("Unsupported stage");
516*61046927SAndroid Build Coastguard Worker    }
517*61046927SAndroid Build Coastguard Worker }
518*61046927SAndroid Build Coastguard Worker 
519*61046927SAndroid Build Coastguard Worker struct dzn_cached_dxil_shader_header {
520*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage;
521*61046927SAndroid Build Coastguard Worker    size_t size;
522*61046927SAndroid Build Coastguard Worker    uint8_t data[0];
523*61046927SAndroid Build Coastguard Worker };
524*61046927SAndroid Build Coastguard Worker 
525*61046927SAndroid Build Coastguard Worker static VkResult
dzn_pipeline_cache_lookup_dxil_shader(struct vk_pipeline_cache * cache,const uint8_t * dxil_hash,gl_shader_stage * stage,D3D12_SHADER_BYTECODE * bc)526*61046927SAndroid Build Coastguard Worker dzn_pipeline_cache_lookup_dxil_shader(struct vk_pipeline_cache *cache,
527*61046927SAndroid Build Coastguard Worker                                       const uint8_t *dxil_hash,
528*61046927SAndroid Build Coastguard Worker                                       gl_shader_stage *stage,
529*61046927SAndroid Build Coastguard Worker                                       D3D12_SHADER_BYTECODE *bc)
530*61046927SAndroid Build Coastguard Worker {
531*61046927SAndroid Build Coastguard Worker    *stage = MESA_SHADER_NONE;
532*61046927SAndroid Build Coastguard Worker 
533*61046927SAndroid Build Coastguard Worker    if (!cache)
534*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
535*61046927SAndroid Build Coastguard Worker 
536*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_object *cache_obj = NULL;
537*61046927SAndroid Build Coastguard Worker 
538*61046927SAndroid Build Coastguard Worker    cache_obj =
539*61046927SAndroid Build Coastguard Worker       vk_pipeline_cache_lookup_object(cache, dxil_hash, SHA1_DIGEST_LENGTH,
540*61046927SAndroid Build Coastguard Worker                                       &dzn_cached_blob_ops,
541*61046927SAndroid Build Coastguard Worker                                       NULL);
542*61046927SAndroid Build Coastguard Worker    if (!cache_obj)
543*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
544*61046927SAndroid Build Coastguard Worker 
545*61046927SAndroid Build Coastguard Worker    struct dzn_cached_blob *cached_blob =
546*61046927SAndroid Build Coastguard Worker       container_of(cache_obj, struct dzn_cached_blob, base);
547*61046927SAndroid Build Coastguard Worker    VkResult ret = VK_SUCCESS;
548*61046927SAndroid Build Coastguard Worker 
549*61046927SAndroid Build Coastguard Worker    assert(sizeof(struct dzn_cached_dxil_shader_header) <= cached_blob->size);
550*61046927SAndroid Build Coastguard Worker 
551*61046927SAndroid Build Coastguard Worker    const struct dzn_cached_dxil_shader_header *info =
552*61046927SAndroid Build Coastguard Worker       (struct dzn_cached_dxil_shader_header *)(cached_blob->data);
553*61046927SAndroid Build Coastguard Worker 
554*61046927SAndroid Build Coastguard Worker    assert(sizeof(struct dzn_cached_dxil_shader_header) + info->size <= cached_blob->size);
555*61046927SAndroid Build Coastguard Worker    assert(info->stage > MESA_SHADER_NONE && info->stage < MESA_VULKAN_SHADER_STAGES);
556*61046927SAndroid Build Coastguard Worker    assert(info->size > 0);
557*61046927SAndroid Build Coastguard Worker 
558*61046927SAndroid Build Coastguard Worker    void *code = malloc(info->size);
559*61046927SAndroid Build Coastguard Worker    if (!code) {
560*61046927SAndroid Build Coastguard Worker       ret = vk_error(cache->base.device, VK_ERROR_OUT_OF_HOST_MEMORY);
561*61046927SAndroid Build Coastguard Worker       goto out;
562*61046927SAndroid Build Coastguard Worker    }
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker    memcpy(code, info->data, info->size);
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker    bc->pShaderBytecode = code;
567*61046927SAndroid Build Coastguard Worker    bc->BytecodeLength = info->size;
568*61046927SAndroid Build Coastguard Worker    *stage = info->stage;
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker out:
571*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_unref(cache->base.device, cache_obj);
572*61046927SAndroid Build Coastguard Worker    return ret;
573*61046927SAndroid Build Coastguard Worker }
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker static void
dzn_pipeline_cache_add_dxil_shader(struct vk_pipeline_cache * cache,const uint8_t * dxil_hash,gl_shader_stage stage,const D3D12_SHADER_BYTECODE * bc)576*61046927SAndroid Build Coastguard Worker dzn_pipeline_cache_add_dxil_shader(struct vk_pipeline_cache *cache,
577*61046927SAndroid Build Coastguard Worker                                    const uint8_t *dxil_hash,
578*61046927SAndroid Build Coastguard Worker                                    gl_shader_stage stage,
579*61046927SAndroid Build Coastguard Worker                                    const D3D12_SHADER_BYTECODE *bc)
580*61046927SAndroid Build Coastguard Worker {
581*61046927SAndroid Build Coastguard Worker    size_t size = sizeof(struct dzn_cached_dxil_shader_header) +
582*61046927SAndroid Build Coastguard Worker                  bc->BytecodeLength;
583*61046927SAndroid Build Coastguard Worker 
584*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_object *cache_obj =
585*61046927SAndroid Build Coastguard Worker       dzn_cached_blob_create(cache->base.device, dxil_hash, NULL, size);
586*61046927SAndroid Build Coastguard Worker    if (!cache_obj)
587*61046927SAndroid Build Coastguard Worker       return;
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker    struct dzn_cached_blob *cached_blob =
590*61046927SAndroid Build Coastguard Worker       container_of(cache_obj, struct dzn_cached_blob, base);
591*61046927SAndroid Build Coastguard Worker    struct dzn_cached_dxil_shader_header *info =
592*61046927SAndroid Build Coastguard Worker       (struct dzn_cached_dxil_shader_header *)(cached_blob->data);
593*61046927SAndroid Build Coastguard Worker    info->stage = stage;
594*61046927SAndroid Build Coastguard Worker    info->size = bc->BytecodeLength;
595*61046927SAndroid Build Coastguard Worker    memcpy(info->data, bc->pShaderBytecode, bc->BytecodeLength);
596*61046927SAndroid Build Coastguard Worker 
597*61046927SAndroid Build Coastguard Worker    cache_obj = vk_pipeline_cache_add_object(cache, cache_obj);
598*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_unref(cache->base.device, cache_obj);
599*61046927SAndroid Build Coastguard Worker }
600*61046927SAndroid Build Coastguard Worker 
601*61046927SAndroid Build Coastguard Worker struct dzn_cached_gfx_pipeline_header {
602*61046927SAndroid Build Coastguard Worker    uint32_t stages : 30;
603*61046927SAndroid Build Coastguard Worker    uint32_t needs_draw_sysvals : 1;
604*61046927SAndroid Build Coastguard Worker    uint32_t rast_disabled_from_missing_position : 1;
605*61046927SAndroid Build Coastguard Worker    uint32_t input_count;
606*61046927SAndroid Build Coastguard Worker };
607*61046927SAndroid Build Coastguard Worker 
608*61046927SAndroid Build Coastguard Worker static VkResult
dzn_pipeline_cache_lookup_gfx_pipeline(struct dzn_graphics_pipeline * pipeline,struct vk_pipeline_cache * cache,const uint8_t * pipeline_hash,bool * cache_hit)609*61046927SAndroid Build Coastguard Worker dzn_pipeline_cache_lookup_gfx_pipeline(struct dzn_graphics_pipeline *pipeline,
610*61046927SAndroid Build Coastguard Worker                                        struct vk_pipeline_cache *cache,
611*61046927SAndroid Build Coastguard Worker                                        const uint8_t *pipeline_hash,
612*61046927SAndroid Build Coastguard Worker                                        bool *cache_hit)
613*61046927SAndroid Build Coastguard Worker {
614*61046927SAndroid Build Coastguard Worker    *cache_hit = false;
615*61046927SAndroid Build Coastguard Worker 
616*61046927SAndroid Build Coastguard Worker    if (!cache)
617*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_object *cache_obj = NULL;
620*61046927SAndroid Build Coastguard Worker 
621*61046927SAndroid Build Coastguard Worker    cache_obj =
622*61046927SAndroid Build Coastguard Worker       vk_pipeline_cache_lookup_object(cache, pipeline_hash, SHA1_DIGEST_LENGTH,
623*61046927SAndroid Build Coastguard Worker                                       &dzn_cached_blob_ops,
624*61046927SAndroid Build Coastguard Worker                                       NULL);
625*61046927SAndroid Build Coastguard Worker    if (!cache_obj)
626*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
627*61046927SAndroid Build Coastguard Worker 
628*61046927SAndroid Build Coastguard Worker    struct dzn_cached_blob *cached_blob =
629*61046927SAndroid Build Coastguard Worker       container_of(cache_obj, struct dzn_cached_blob, base);
630*61046927SAndroid Build Coastguard Worker    D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc =
631*61046927SAndroid Build Coastguard Worker       &pipeline->templates.stream_desc;
632*61046927SAndroid Build Coastguard Worker 
633*61046927SAndroid Build Coastguard Worker    const struct dzn_cached_gfx_pipeline_header *info =
634*61046927SAndroid Build Coastguard Worker       (const struct dzn_cached_gfx_pipeline_header *)(cached_blob->data);
635*61046927SAndroid Build Coastguard Worker    size_t offset = ALIGN_POT(sizeof(*info), alignof(D3D12_INPUT_ELEMENT_DESC));
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker    assert(cached_blob->size >= sizeof(*info));
638*61046927SAndroid Build Coastguard Worker 
639*61046927SAndroid Build Coastguard Worker    if (info->input_count > 0) {
640*61046927SAndroid Build Coastguard Worker       const D3D12_INPUT_ELEMENT_DESC *inputs =
641*61046927SAndroid Build Coastguard Worker          (const D3D12_INPUT_ELEMENT_DESC *)((uint8_t *)cached_blob->data + offset);
642*61046927SAndroid Build Coastguard Worker 
643*61046927SAndroid Build Coastguard Worker       assert(cached_blob->size >= offset + sizeof(*inputs) * info->input_count);
644*61046927SAndroid Build Coastguard Worker 
645*61046927SAndroid Build Coastguard Worker       memcpy(pipeline->templates.inputs, inputs,
646*61046927SAndroid Build Coastguard Worker              sizeof(*inputs) * info->input_count);
647*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, INPUT_LAYOUT, D3D12_INPUT_LAYOUT_DESC, desc);
648*61046927SAndroid Build Coastguard Worker       desc->pInputElementDescs = pipeline->templates.inputs;
649*61046927SAndroid Build Coastguard Worker       desc->NumElements = info->input_count;
650*61046927SAndroid Build Coastguard Worker       offset += sizeof(*inputs) * info->input_count;
651*61046927SAndroid Build Coastguard Worker    }
652*61046927SAndroid Build Coastguard Worker 
653*61046927SAndroid Build Coastguard Worker    assert(cached_blob->size == offset + util_bitcount(info->stages) * SHA1_DIGEST_LENGTH);
654*61046927SAndroid Build Coastguard Worker 
655*61046927SAndroid Build Coastguard Worker    u_foreach_bit(s, info->stages) {
656*61046927SAndroid Build Coastguard Worker       uint8_t *dxil_hash = (uint8_t *)cached_blob->data + offset;
657*61046927SAndroid Build Coastguard Worker       gl_shader_stage stage;
658*61046927SAndroid Build Coastguard Worker 
659*61046927SAndroid Build Coastguard Worker       D3D12_SHADER_BYTECODE *slot =
660*61046927SAndroid Build Coastguard Worker          dzn_pipeline_get_gfx_shader_slot(stream_desc, s);
661*61046927SAndroid Build Coastguard Worker 
662*61046927SAndroid Build Coastguard Worker       VkResult ret =
663*61046927SAndroid Build Coastguard Worker          dzn_pipeline_cache_lookup_dxil_shader(cache, dxil_hash, &stage, slot);
664*61046927SAndroid Build Coastguard Worker       if (ret != VK_SUCCESS)
665*61046927SAndroid Build Coastguard Worker          return ret;
666*61046927SAndroid Build Coastguard Worker 
667*61046927SAndroid Build Coastguard Worker       assert(stage == s);
668*61046927SAndroid Build Coastguard Worker       offset += SHA1_DIGEST_LENGTH;
669*61046927SAndroid Build Coastguard Worker    }
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker    pipeline->rast_disabled_from_missing_position = info->rast_disabled_from_missing_position;
672*61046927SAndroid Build Coastguard Worker    pipeline->needs_draw_sysvals = info->needs_draw_sysvals;
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker    *cache_hit = true;
675*61046927SAndroid Build Coastguard Worker 
676*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_unref(cache->base.device, cache_obj);
677*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
678*61046927SAndroid Build Coastguard Worker }
679*61046927SAndroid Build Coastguard Worker 
680*61046927SAndroid Build Coastguard Worker static void
dzn_pipeline_cache_add_gfx_pipeline(struct dzn_graphics_pipeline * pipeline,struct vk_pipeline_cache * cache,uint32_t vertex_input_count,const uint8_t * pipeline_hash,const uint8_t * const * dxil_hashes)681*61046927SAndroid Build Coastguard Worker dzn_pipeline_cache_add_gfx_pipeline(struct dzn_graphics_pipeline *pipeline,
682*61046927SAndroid Build Coastguard Worker                                     struct vk_pipeline_cache *cache,
683*61046927SAndroid Build Coastguard Worker                                     uint32_t vertex_input_count,
684*61046927SAndroid Build Coastguard Worker                                     const uint8_t *pipeline_hash,
685*61046927SAndroid Build Coastguard Worker                                     const uint8_t *const *dxil_hashes)
686*61046927SAndroid Build Coastguard Worker {
687*61046927SAndroid Build Coastguard Worker    size_t offset =
688*61046927SAndroid Build Coastguard Worker       ALIGN_POT(sizeof(struct dzn_cached_gfx_pipeline_header), alignof(D3D12_INPUT_ELEMENT_DESC)) +
689*61046927SAndroid Build Coastguard Worker       (sizeof(D3D12_INPUT_ELEMENT_DESC) * vertex_input_count);
690*61046927SAndroid Build Coastguard Worker    uint32_t stages = 0;
691*61046927SAndroid Build Coastguard Worker 
692*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < MESA_VULKAN_SHADER_STAGES; i++) {
693*61046927SAndroid Build Coastguard Worker       if (pipeline->templates.shaders[i].bc) {
694*61046927SAndroid Build Coastguard Worker          stages |= BITFIELD_BIT(i);
695*61046927SAndroid Build Coastguard Worker          offset += SHA1_DIGEST_LENGTH;
696*61046927SAndroid Build Coastguard Worker       }
697*61046927SAndroid Build Coastguard Worker    }
698*61046927SAndroid Build Coastguard Worker 
699*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_object *cache_obj =
700*61046927SAndroid Build Coastguard Worker       dzn_cached_blob_create(cache->base.device, pipeline_hash, NULL, offset);
701*61046927SAndroid Build Coastguard Worker    if (!cache_obj)
702*61046927SAndroid Build Coastguard Worker       return;
703*61046927SAndroid Build Coastguard Worker 
704*61046927SAndroid Build Coastguard Worker    struct dzn_cached_blob *cached_blob =
705*61046927SAndroid Build Coastguard Worker       container_of(cache_obj, struct dzn_cached_blob, base);
706*61046927SAndroid Build Coastguard Worker 
707*61046927SAndroid Build Coastguard Worker    offset = 0;
708*61046927SAndroid Build Coastguard Worker    struct dzn_cached_gfx_pipeline_header *info =
709*61046927SAndroid Build Coastguard Worker       (struct dzn_cached_gfx_pipeline_header *)(cached_blob->data);
710*61046927SAndroid Build Coastguard Worker 
711*61046927SAndroid Build Coastguard Worker    info->input_count = vertex_input_count;
712*61046927SAndroid Build Coastguard Worker    info->stages = stages;
713*61046927SAndroid Build Coastguard Worker    info->needs_draw_sysvals = pipeline->needs_draw_sysvals;
714*61046927SAndroid Build Coastguard Worker    info->rast_disabled_from_missing_position = pipeline->rast_disabled_from_missing_position;
715*61046927SAndroid Build Coastguard Worker 
716*61046927SAndroid Build Coastguard Worker    offset = ALIGN_POT(offset + sizeof(*info), alignof(D3D12_INPUT_ELEMENT_DESC));
717*61046927SAndroid Build Coastguard Worker 
718*61046927SAndroid Build Coastguard Worker    D3D12_INPUT_ELEMENT_DESC *inputs =
719*61046927SAndroid Build Coastguard Worker       (D3D12_INPUT_ELEMENT_DESC *)((uint8_t *)cached_blob->data + offset);
720*61046927SAndroid Build Coastguard Worker    memcpy(inputs, pipeline->templates.inputs,
721*61046927SAndroid Build Coastguard Worker           sizeof(*inputs) * vertex_input_count);
722*61046927SAndroid Build Coastguard Worker    offset += sizeof(*inputs) * vertex_input_count;
723*61046927SAndroid Build Coastguard Worker 
724*61046927SAndroid Build Coastguard Worker    u_foreach_bit(s, stages) {
725*61046927SAndroid Build Coastguard Worker       uint8_t *dxil_hash = (uint8_t *)cached_blob->data + offset;
726*61046927SAndroid Build Coastguard Worker 
727*61046927SAndroid Build Coastguard Worker       memcpy(dxil_hash, dxil_hashes[s], SHA1_DIGEST_LENGTH);
728*61046927SAndroid Build Coastguard Worker       offset += SHA1_DIGEST_LENGTH;
729*61046927SAndroid Build Coastguard Worker    }
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker    cache_obj = vk_pipeline_cache_add_object(cache, cache_obj);
732*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_unref(cache->base.device, cache_obj);
733*61046927SAndroid Build Coastguard Worker }
734*61046927SAndroid Build Coastguard Worker 
735*61046927SAndroid Build Coastguard Worker static void
dzn_graphics_pipeline_hash_attribs(D3D12_INPUT_ELEMENT_DESC * attribs,enum pipe_format * vi_conversions,uint8_t * result)736*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_hash_attribs(D3D12_INPUT_ELEMENT_DESC *attribs,
737*61046927SAndroid Build Coastguard Worker                                    enum pipe_format *vi_conversions,
738*61046927SAndroid Build Coastguard Worker                                    uint8_t *result)
739*61046927SAndroid Build Coastguard Worker {
740*61046927SAndroid Build Coastguard Worker    struct mesa_sha1 ctx;
741*61046927SAndroid Build Coastguard Worker 
742*61046927SAndroid Build Coastguard Worker    _mesa_sha1_init(&ctx);
743*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&ctx, attribs, sizeof(*attribs) * MAX_VERTEX_GENERIC_ATTRIBS);
744*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&ctx, vi_conversions, sizeof(*vi_conversions) * MAX_VERTEX_GENERIC_ATTRIBS);
745*61046927SAndroid Build Coastguard Worker    _mesa_sha1_final(&ctx, result);
746*61046927SAndroid Build Coastguard Worker }
747*61046927SAndroid Build Coastguard Worker 
748*61046927SAndroid Build Coastguard Worker static VkResult
dzn_graphics_pipeline_compile_shaders(struct dzn_device * device,struct dzn_graphics_pipeline * pipeline,struct vk_pipeline_cache * cache,const struct dzn_pipeline_layout * layout,D3D12_PIPELINE_STATE_STREAM_DESC * out,D3D12_INPUT_ELEMENT_DESC * attribs,enum pipe_format * vi_conversions,const VkGraphicsPipelineCreateInfo * info)749*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_compile_shaders(struct dzn_device *device,
750*61046927SAndroid Build Coastguard Worker                                       struct dzn_graphics_pipeline *pipeline,
751*61046927SAndroid Build Coastguard Worker                                       struct vk_pipeline_cache *cache,
752*61046927SAndroid Build Coastguard Worker                                       const struct dzn_pipeline_layout *layout,
753*61046927SAndroid Build Coastguard Worker                                       D3D12_PIPELINE_STATE_STREAM_DESC *out,
754*61046927SAndroid Build Coastguard Worker                                       D3D12_INPUT_ELEMENT_DESC *attribs,
755*61046927SAndroid Build Coastguard Worker                                       enum pipe_format *vi_conversions,
756*61046927SAndroid Build Coastguard Worker                                       const VkGraphicsPipelineCreateInfo *info)
757*61046927SAndroid Build Coastguard Worker {
758*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev =
759*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical, struct dzn_physical_device, vk);
760*61046927SAndroid Build Coastguard Worker    const VkPipelineViewportStateCreateInfo *vp_info =
761*61046927SAndroid Build Coastguard Worker       info->pRasterizationState->rasterizerDiscardEnable ?
762*61046927SAndroid Build Coastguard Worker       NULL : info->pViewportState;
763*61046927SAndroid Build Coastguard Worker    struct {
764*61046927SAndroid Build Coastguard Worker       const VkPipelineShaderStageCreateInfo *info;
765*61046927SAndroid Build Coastguard Worker       uint8_t spirv_hash[SHA1_DIGEST_LENGTH];
766*61046927SAndroid Build Coastguard Worker       uint8_t dxil_hash[SHA1_DIGEST_LENGTH];
767*61046927SAndroid Build Coastguard Worker       uint8_t nir_hash[SHA1_DIGEST_LENGTH];
768*61046927SAndroid Build Coastguard Worker       uint8_t link_hashes[SHA1_DIGEST_LENGTH][2];
769*61046927SAndroid Build Coastguard Worker    } stages[MESA_VULKAN_SHADER_STAGES] = { 0 };
770*61046927SAndroid Build Coastguard Worker    const uint8_t *dxil_hashes[MESA_VULKAN_SHADER_STAGES] = { 0 };
771*61046927SAndroid Build Coastguard Worker    uint8_t attribs_hash[SHA1_DIGEST_LENGTH];
772*61046927SAndroid Build Coastguard Worker    uint8_t pipeline_hash[SHA1_DIGEST_LENGTH];
773*61046927SAndroid Build Coastguard Worker    gl_shader_stage last_raster_stage = MESA_SHADER_NONE;
774*61046927SAndroid Build Coastguard Worker    uint32_t active_stage_mask = 0;
775*61046927SAndroid Build Coastguard Worker    VkResult ret;
776*61046927SAndroid Build Coastguard Worker 
777*61046927SAndroid Build Coastguard Worker    /* First step: collect stage info in a table indexed by gl_shader_stage
778*61046927SAndroid Build Coastguard Worker     * so we can iterate over stages in pipeline order or reverse pipeline
779*61046927SAndroid Build Coastguard Worker     * order.
780*61046927SAndroid Build Coastguard Worker     */
781*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < info->stageCount; i++) {
782*61046927SAndroid Build Coastguard Worker       gl_shader_stage stage =
783*61046927SAndroid Build Coastguard Worker          vk_to_mesa_shader_stage(info->pStages[i].stage);
784*61046927SAndroid Build Coastguard Worker 
785*61046927SAndroid Build Coastguard Worker       assert(stage <= MESA_SHADER_FRAGMENT);
786*61046927SAndroid Build Coastguard Worker 
787*61046927SAndroid Build Coastguard Worker       if ((stage == MESA_SHADER_VERTEX ||
788*61046927SAndroid Build Coastguard Worker            stage == MESA_SHADER_TESS_EVAL ||
789*61046927SAndroid Build Coastguard Worker            stage == MESA_SHADER_GEOMETRY) &&
790*61046927SAndroid Build Coastguard Worker           last_raster_stage < stage)
791*61046927SAndroid Build Coastguard Worker          last_raster_stage = stage;
792*61046927SAndroid Build Coastguard Worker 
793*61046927SAndroid Build Coastguard Worker       if (stage == MESA_SHADER_FRAGMENT &&
794*61046927SAndroid Build Coastguard Worker           info->pRasterizationState &&
795*61046927SAndroid Build Coastguard Worker           (info->pRasterizationState->rasterizerDiscardEnable ||
796*61046927SAndroid Build Coastguard Worker            info->pRasterizationState->cullMode == VK_CULL_MODE_FRONT_AND_BACK)) {
797*61046927SAndroid Build Coastguard Worker          /* Disable rasterization (AKA leave fragment shader NULL) when
798*61046927SAndroid Build Coastguard Worker           * front+back culling or discard is set.
799*61046927SAndroid Build Coastguard Worker           */
800*61046927SAndroid Build Coastguard Worker          continue;
801*61046927SAndroid Build Coastguard Worker       }
802*61046927SAndroid Build Coastguard Worker 
803*61046927SAndroid Build Coastguard Worker       stages[stage].info = &info->pStages[i];
804*61046927SAndroid Build Coastguard Worker       active_stage_mask |= BITFIELD_BIT(stage);
805*61046927SAndroid Build Coastguard Worker    }
806*61046927SAndroid Build Coastguard Worker 
807*61046927SAndroid Build Coastguard Worker    pipeline->use_gs_for_polygon_mode_point =
808*61046927SAndroid Build Coastguard Worker       info->pRasterizationState &&
809*61046927SAndroid Build Coastguard Worker       info->pRasterizationState->polygonMode == VK_POLYGON_MODE_POINT &&
810*61046927SAndroid Build Coastguard Worker       !(active_stage_mask & (1 << MESA_SHADER_GEOMETRY));
811*61046927SAndroid Build Coastguard Worker    if (pipeline->use_gs_for_polygon_mode_point)
812*61046927SAndroid Build Coastguard Worker       last_raster_stage = MESA_SHADER_GEOMETRY;
813*61046927SAndroid Build Coastguard Worker 
814*61046927SAndroid Build Coastguard Worker    enum dxil_spirv_yz_flip_mode yz_flip_mode = DXIL_SPIRV_YZ_FLIP_NONE;
815*61046927SAndroid Build Coastguard Worker    uint16_t y_flip_mask = 0, z_flip_mask = 0;
816*61046927SAndroid Build Coastguard Worker    bool lower_view_index =
817*61046927SAndroid Build Coastguard Worker       !pipeline->multiview.native_view_instancing &&
818*61046927SAndroid Build Coastguard Worker       pipeline->multiview.view_mask > 1;
819*61046927SAndroid Build Coastguard Worker 
820*61046927SAndroid Build Coastguard Worker    if (pipeline->vp.dynamic) {
821*61046927SAndroid Build Coastguard Worker       yz_flip_mode = DXIL_SPIRV_YZ_FLIP_CONDITIONAL;
822*61046927SAndroid Build Coastguard Worker    } else if (vp_info) {
823*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; vp_info->pViewports && i < vp_info->viewportCount; i++) {
824*61046927SAndroid Build Coastguard Worker          if (vp_info->pViewports[i].height > 0)
825*61046927SAndroid Build Coastguard Worker             y_flip_mask |= BITFIELD_BIT(i);
826*61046927SAndroid Build Coastguard Worker 
827*61046927SAndroid Build Coastguard Worker          if (vp_info->pViewports[i].minDepth > vp_info->pViewports[i].maxDepth)
828*61046927SAndroid Build Coastguard Worker             z_flip_mask |= BITFIELD_BIT(i);
829*61046927SAndroid Build Coastguard Worker       }
830*61046927SAndroid Build Coastguard Worker 
831*61046927SAndroid Build Coastguard Worker       if (y_flip_mask && z_flip_mask)
832*61046927SAndroid Build Coastguard Worker          yz_flip_mode = DXIL_SPIRV_YZ_FLIP_UNCONDITIONAL;
833*61046927SAndroid Build Coastguard Worker       else if (z_flip_mask)
834*61046927SAndroid Build Coastguard Worker          yz_flip_mode = DXIL_SPIRV_Z_FLIP_UNCONDITIONAL;
835*61046927SAndroid Build Coastguard Worker       else if (y_flip_mask)
836*61046927SAndroid Build Coastguard Worker          yz_flip_mode = DXIL_SPIRV_Y_FLIP_UNCONDITIONAL;
837*61046927SAndroid Build Coastguard Worker    }
838*61046927SAndroid Build Coastguard Worker 
839*61046927SAndroid Build Coastguard Worker    bool force_sample_rate_shading =
840*61046927SAndroid Build Coastguard Worker       !info->pRasterizationState->rasterizerDiscardEnable &&
841*61046927SAndroid Build Coastguard Worker       info->pMultisampleState &&
842*61046927SAndroid Build Coastguard Worker       info->pMultisampleState->sampleShadingEnable;
843*61046927SAndroid Build Coastguard Worker 
844*61046927SAndroid Build Coastguard Worker    if (cache) {
845*61046927SAndroid Build Coastguard Worker       dzn_graphics_pipeline_hash_attribs(attribs, vi_conversions, attribs_hash);
846*61046927SAndroid Build Coastguard Worker 
847*61046927SAndroid Build Coastguard Worker       struct mesa_sha1 pipeline_hash_ctx;
848*61046927SAndroid Build Coastguard Worker 
849*61046927SAndroid Build Coastguard Worker       _mesa_sha1_init(&pipeline_hash_ctx);
850*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, &device->bindless, sizeof(device->bindless));
851*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, attribs_hash, sizeof(attribs_hash));
852*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, &yz_flip_mode, sizeof(yz_flip_mode));
853*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, &y_flip_mask, sizeof(y_flip_mask));
854*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, &z_flip_mask, sizeof(z_flip_mask));
855*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, &force_sample_rate_shading, sizeof(force_sample_rate_shading));
856*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, &lower_view_index, sizeof(lower_view_index));
857*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, &pipeline->use_gs_for_polygon_mode_point, sizeof(pipeline->use_gs_for_polygon_mode_point));
858*61046927SAndroid Build Coastguard Worker 
859*61046927SAndroid Build Coastguard Worker       u_foreach_bit(stage, active_stage_mask) {
860*61046927SAndroid Build Coastguard Worker          const VkPipelineShaderStageRequiredSubgroupSizeCreateInfo *subgroup_size =
861*61046927SAndroid Build Coastguard Worker             (const VkPipelineShaderStageRequiredSubgroupSizeCreateInfo *)
862*61046927SAndroid Build Coastguard Worker             vk_find_struct_const(stages[stage].info->pNext, PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO);
863*61046927SAndroid Build Coastguard Worker          enum gl_subgroup_size subgroup_enum = subgroup_size && subgroup_size->requiredSubgroupSize >= 8 ?
864*61046927SAndroid Build Coastguard Worker             subgroup_size->requiredSubgroupSize : SUBGROUP_SIZE_FULL_SUBGROUPS;
865*61046927SAndroid Build Coastguard Worker 
866*61046927SAndroid Build Coastguard Worker          vk_pipeline_hash_shader_stage(pipeline->base.flags, stages[stage].info, NULL, stages[stage].spirv_hash);
867*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&pipeline_hash_ctx, &subgroup_enum, sizeof(subgroup_enum));
868*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&pipeline_hash_ctx, stages[stage].spirv_hash, sizeof(stages[stage].spirv_hash));
869*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&pipeline_hash_ctx, layout->stages[stage].hash, sizeof(layout->stages[stage].hash));
870*61046927SAndroid Build Coastguard Worker       }
871*61046927SAndroid Build Coastguard Worker       _mesa_sha1_final(&pipeline_hash_ctx, pipeline_hash);
872*61046927SAndroid Build Coastguard Worker 
873*61046927SAndroid Build Coastguard Worker       bool cache_hit;
874*61046927SAndroid Build Coastguard Worker       ret = dzn_pipeline_cache_lookup_gfx_pipeline(pipeline, cache, pipeline_hash,
875*61046927SAndroid Build Coastguard Worker                                                    &cache_hit);
876*61046927SAndroid Build Coastguard Worker       if (ret != VK_SUCCESS)
877*61046927SAndroid Build Coastguard Worker          return ret;
878*61046927SAndroid Build Coastguard Worker 
879*61046927SAndroid Build Coastguard Worker       if (cache_hit)
880*61046927SAndroid Build Coastguard Worker          return VK_SUCCESS;
881*61046927SAndroid Build Coastguard Worker    }
882*61046927SAndroid Build Coastguard Worker 
883*61046927SAndroid Build Coastguard Worker    /* Second step: get NIR shaders for all stages. */
884*61046927SAndroid Build Coastguard Worker    nir_shader_compiler_options nir_opts;
885*61046927SAndroid Build Coastguard Worker    unsigned supported_bit_sizes = (pdev->options4.Native16BitShaderOpsSupported ? 16 : 0) | 32 | 64;
886*61046927SAndroid Build Coastguard Worker    dxil_get_nir_compiler_options(&nir_opts, dzn_get_shader_model(pdev), supported_bit_sizes, supported_bit_sizes);
887*61046927SAndroid Build Coastguard Worker    nir_opts.lower_base_vertex = true;
888*61046927SAndroid Build Coastguard Worker    u_foreach_bit(stage, active_stage_mask) {
889*61046927SAndroid Build Coastguard Worker       struct mesa_sha1 nir_hash_ctx;
890*61046927SAndroid Build Coastguard Worker 
891*61046927SAndroid Build Coastguard Worker       if (cache) {
892*61046927SAndroid Build Coastguard Worker          _mesa_sha1_init(&nir_hash_ctx);
893*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&nir_hash_ctx, &device->bindless, sizeof(device->bindless));
894*61046927SAndroid Build Coastguard Worker          if (stage != MESA_SHADER_FRAGMENT) {
895*61046927SAndroid Build Coastguard Worker             _mesa_sha1_update(&nir_hash_ctx, &lower_view_index, sizeof(lower_view_index));
896*61046927SAndroid Build Coastguard Worker             _mesa_sha1_update(&nir_hash_ctx, &force_sample_rate_shading, sizeof(force_sample_rate_shading));
897*61046927SAndroid Build Coastguard Worker          }
898*61046927SAndroid Build Coastguard Worker          if (stage == MESA_SHADER_VERTEX)
899*61046927SAndroid Build Coastguard Worker             _mesa_sha1_update(&nir_hash_ctx, attribs_hash, sizeof(attribs_hash));
900*61046927SAndroid Build Coastguard Worker          if (stage == last_raster_stage) {
901*61046927SAndroid Build Coastguard Worker             _mesa_sha1_update(&nir_hash_ctx, &yz_flip_mode, sizeof(yz_flip_mode));
902*61046927SAndroid Build Coastguard Worker             _mesa_sha1_update(&nir_hash_ctx, &y_flip_mask, sizeof(y_flip_mask));
903*61046927SAndroid Build Coastguard Worker             _mesa_sha1_update(&nir_hash_ctx, &z_flip_mask, sizeof(z_flip_mask));
904*61046927SAndroid Build Coastguard Worker             _mesa_sha1_update(&nir_hash_ctx, &lower_view_index, sizeof(lower_view_index));
905*61046927SAndroid Build Coastguard Worker          }
906*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&nir_hash_ctx, stages[stage].spirv_hash, sizeof(stages[stage].spirv_hash));
907*61046927SAndroid Build Coastguard Worker          _mesa_sha1_final(&nir_hash_ctx, stages[stage].nir_hash);
908*61046927SAndroid Build Coastguard Worker       }
909*61046927SAndroid Build Coastguard Worker 
910*61046927SAndroid Build Coastguard Worker       struct dzn_nir_options options = {
911*61046927SAndroid Build Coastguard Worker          .yz_flip_mode = stage == last_raster_stage ? yz_flip_mode : DXIL_SPIRV_YZ_FLIP_NONE,
912*61046927SAndroid Build Coastguard Worker          .y_flip_mask = y_flip_mask,
913*61046927SAndroid Build Coastguard Worker          .z_flip_mask = z_flip_mask,
914*61046927SAndroid Build Coastguard Worker          .force_sample_rate_shading = stage == MESA_SHADER_FRAGMENT ? force_sample_rate_shading : false,
915*61046927SAndroid Build Coastguard Worker          .lower_view_index = lower_view_index,
916*61046927SAndroid Build Coastguard Worker          .lower_view_index_to_rt_layer = stage == last_raster_stage ? lower_view_index : false,
917*61046927SAndroid Build Coastguard Worker          .vi_conversions = vi_conversions,
918*61046927SAndroid Build Coastguard Worker          .nir_opts = &nir_opts,
919*61046927SAndroid Build Coastguard Worker       };
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker       struct dxil_spirv_metadata metadata = { 0 };
922*61046927SAndroid Build Coastguard Worker       ret = dzn_pipeline_get_nir_shader(device, layout,
923*61046927SAndroid Build Coastguard Worker                                         cache, stages[stage].nir_hash,
924*61046927SAndroid Build Coastguard Worker                                         pipeline->base.flags,
925*61046927SAndroid Build Coastguard Worker                                         stages[stage].info, stage,
926*61046927SAndroid Build Coastguard Worker                                         &options, &metadata,
927*61046927SAndroid Build Coastguard Worker                                         &pipeline->templates.shaders[stage].nir);
928*61046927SAndroid Build Coastguard Worker       if (ret != VK_SUCCESS)
929*61046927SAndroid Build Coastguard Worker          return ret;
930*61046927SAndroid Build Coastguard Worker 
931*61046927SAndroid Build Coastguard Worker       if (stage == MESA_SHADER_VERTEX)
932*61046927SAndroid Build Coastguard Worker          pipeline->needs_draw_sysvals = metadata.needs_draw_sysvals;
933*61046927SAndroid Build Coastguard Worker    }
934*61046927SAndroid Build Coastguard Worker 
935*61046927SAndroid Build Coastguard Worker    if (pipeline->use_gs_for_polygon_mode_point) {
936*61046927SAndroid Build Coastguard Worker       /* TODO: Cache; handle TES */
937*61046927SAndroid Build Coastguard Worker       struct dzn_nir_point_gs_info gs_info = {
938*61046927SAndroid Build Coastguard Worker          .cull_mode = info->pRasterizationState->cullMode,
939*61046927SAndroid Build Coastguard Worker          .front_ccw = info->pRasterizationState->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE,
940*61046927SAndroid Build Coastguard Worker          .depth_bias = info->pRasterizationState->depthBiasEnable,
941*61046927SAndroid Build Coastguard Worker          .depth_bias_dynamic = pipeline->zsa.dynamic_depth_bias,
942*61046927SAndroid Build Coastguard Worker          .ds_fmt = pipeline->zsa.ds_fmt,
943*61046927SAndroid Build Coastguard Worker          .constant_depth_bias = info->pRasterizationState->depthBiasConstantFactor,
944*61046927SAndroid Build Coastguard Worker          .slope_scaled_depth_bias = info->pRasterizationState->depthBiasSlopeFactor,
945*61046927SAndroid Build Coastguard Worker          .depth_bias_clamp = info->pRasterizationState->depthBiasClamp,
946*61046927SAndroid Build Coastguard Worker          .runtime_data_cbv = {
947*61046927SAndroid Build Coastguard Worker             .register_space = DZN_REGISTER_SPACE_SYSVALS,
948*61046927SAndroid Build Coastguard Worker             .base_shader_register = 0,
949*61046927SAndroid Build Coastguard Worker          }
950*61046927SAndroid Build Coastguard Worker       };
951*61046927SAndroid Build Coastguard Worker       pipeline->templates.shaders[MESA_SHADER_GEOMETRY].nir =
952*61046927SAndroid Build Coastguard Worker          dzn_nir_polygon_point_mode_gs(pipeline->templates.shaders[MESA_SHADER_VERTEX].nir,
953*61046927SAndroid Build Coastguard Worker                                        &gs_info);
954*61046927SAndroid Build Coastguard Worker 
955*61046927SAndroid Build Coastguard Worker       struct dxil_spirv_runtime_conf conf = {
956*61046927SAndroid Build Coastguard Worker          .runtime_data_cbv = {
957*61046927SAndroid Build Coastguard Worker             .register_space = DZN_REGISTER_SPACE_SYSVALS,
958*61046927SAndroid Build Coastguard Worker             .base_shader_register = 0,
959*61046927SAndroid Build Coastguard Worker          },
960*61046927SAndroid Build Coastguard Worker          .yz_flip = {
961*61046927SAndroid Build Coastguard Worker             .mode = yz_flip_mode,
962*61046927SAndroid Build Coastguard Worker             .y_mask = y_flip_mask,
963*61046927SAndroid Build Coastguard Worker             .z_mask = z_flip_mask,
964*61046927SAndroid Build Coastguard Worker          },
965*61046927SAndroid Build Coastguard Worker       };
966*61046927SAndroid Build Coastguard Worker 
967*61046927SAndroid Build Coastguard Worker       bool requires_runtime_data;
968*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(pipeline->templates.shaders[MESA_SHADER_GEOMETRY].nir, dxil_spirv_nir_lower_yz_flip,
969*61046927SAndroid Build Coastguard Worker                  &conf, &requires_runtime_data);
970*61046927SAndroid Build Coastguard Worker 
971*61046927SAndroid Build Coastguard Worker       active_stage_mask |= (1 << MESA_SHADER_GEOMETRY);
972*61046927SAndroid Build Coastguard Worker       memcpy(stages[MESA_SHADER_GEOMETRY].spirv_hash, stages[MESA_SHADER_VERTEX].spirv_hash, SHA1_DIGEST_LENGTH);
973*61046927SAndroid Build Coastguard Worker 
974*61046927SAndroid Build Coastguard Worker       if ((active_stage_mask & (1 << MESA_SHADER_FRAGMENT)) &&
975*61046927SAndroid Build Coastguard Worker           BITSET_TEST(pipeline->templates.shaders[MESA_SHADER_FRAGMENT].nir->info.system_values_read, SYSTEM_VALUE_FRONT_FACE))
976*61046927SAndroid Build Coastguard Worker          NIR_PASS_V(pipeline->templates.shaders[MESA_SHADER_FRAGMENT].nir, dxil_nir_forward_front_face);
977*61046927SAndroid Build Coastguard Worker    }
978*61046927SAndroid Build Coastguard Worker 
979*61046927SAndroid Build Coastguard Worker    /* Third step: link those NIR shaders. We iterate in reverse order
980*61046927SAndroid Build Coastguard Worker     * so we can eliminate outputs that are never read by the next stage.
981*61046927SAndroid Build Coastguard Worker     */
982*61046927SAndroid Build Coastguard Worker    uint32_t link_mask = active_stage_mask;
983*61046927SAndroid Build Coastguard Worker    while (link_mask != 0) {
984*61046927SAndroid Build Coastguard Worker       gl_shader_stage stage = util_last_bit(link_mask) - 1;
985*61046927SAndroid Build Coastguard Worker       link_mask &= ~BITFIELD_BIT(stage);
986*61046927SAndroid Build Coastguard Worker       gl_shader_stage prev_stage = util_last_bit(link_mask) - 1;
987*61046927SAndroid Build Coastguard Worker 
988*61046927SAndroid Build Coastguard Worker       struct dxil_spirv_runtime_conf conf = {
989*61046927SAndroid Build Coastguard Worker          .runtime_data_cbv = {
990*61046927SAndroid Build Coastguard Worker             .register_space = DZN_REGISTER_SPACE_SYSVALS,
991*61046927SAndroid Build Coastguard Worker             .base_shader_register = 0,
992*61046927SAndroid Build Coastguard Worker       }};
993*61046927SAndroid Build Coastguard Worker 
994*61046927SAndroid Build Coastguard Worker       assert(pipeline->templates.shaders[stage].nir);
995*61046927SAndroid Build Coastguard Worker       struct dxil_spirv_metadata metadata = { 0 };
996*61046927SAndroid Build Coastguard Worker       dxil_spirv_nir_link(pipeline->templates.shaders[stage].nir,
997*61046927SAndroid Build Coastguard Worker                           prev_stage != MESA_SHADER_NONE ?
998*61046927SAndroid Build Coastguard Worker                           pipeline->templates.shaders[prev_stage].nir : NULL,
999*61046927SAndroid Build Coastguard Worker                           &conf, &metadata);
1000*61046927SAndroid Build Coastguard Worker 
1001*61046927SAndroid Build Coastguard Worker       if (prev_stage != MESA_SHADER_NONE) {
1002*61046927SAndroid Build Coastguard Worker          memcpy(stages[stage].link_hashes[0], stages[prev_stage].spirv_hash, SHA1_DIGEST_LENGTH);
1003*61046927SAndroid Build Coastguard Worker          memcpy(stages[prev_stage].link_hashes[1], stages[stage].spirv_hash, SHA1_DIGEST_LENGTH);
1004*61046927SAndroid Build Coastguard Worker       }
1005*61046927SAndroid Build Coastguard Worker    }
1006*61046927SAndroid Build Coastguard Worker 
1007*61046927SAndroid Build Coastguard Worker    u_foreach_bit(stage, active_stage_mask) {
1008*61046927SAndroid Build Coastguard Worker       uint8_t bindings_hash[SHA1_DIGEST_LENGTH];
1009*61046927SAndroid Build Coastguard Worker 
1010*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(pipeline->templates.shaders[stage].nir, adjust_var_bindings, device, layout,
1011*61046927SAndroid Build Coastguard Worker                  cache ? bindings_hash : NULL);
1012*61046927SAndroid Build Coastguard Worker 
1013*61046927SAndroid Build Coastguard Worker       if (cache) {
1014*61046927SAndroid Build Coastguard Worker          struct mesa_sha1 dxil_hash_ctx;
1015*61046927SAndroid Build Coastguard Worker 
1016*61046927SAndroid Build Coastguard Worker          _mesa_sha1_init(&dxil_hash_ctx);
1017*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&dxil_hash_ctx, stages[stage].nir_hash, sizeof(stages[stage].nir_hash));
1018*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&dxil_hash_ctx, stages[stage].spirv_hash, sizeof(stages[stage].spirv_hash));
1019*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&dxil_hash_ctx, stages[stage].link_hashes[0], sizeof(stages[stage].link_hashes[0]));
1020*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&dxil_hash_ctx, stages[stage].link_hashes[1], sizeof(stages[stage].link_hashes[1]));
1021*61046927SAndroid Build Coastguard Worker          _mesa_sha1_update(&dxil_hash_ctx, bindings_hash, sizeof(bindings_hash));
1022*61046927SAndroid Build Coastguard Worker          _mesa_sha1_final(&dxil_hash_ctx, stages[stage].dxil_hash);
1023*61046927SAndroid Build Coastguard Worker          dxil_hashes[stage] = stages[stage].dxil_hash;
1024*61046927SAndroid Build Coastguard Worker 
1025*61046927SAndroid Build Coastguard Worker          gl_shader_stage cached_stage;
1026*61046927SAndroid Build Coastguard Worker          D3D12_SHADER_BYTECODE bc;
1027*61046927SAndroid Build Coastguard Worker          ret = dzn_pipeline_cache_lookup_dxil_shader(cache, stages[stage].dxil_hash, &cached_stage, &bc);
1028*61046927SAndroid Build Coastguard Worker          if (ret != VK_SUCCESS)
1029*61046927SAndroid Build Coastguard Worker             return ret;
1030*61046927SAndroid Build Coastguard Worker 
1031*61046927SAndroid Build Coastguard Worker          if (cached_stage != MESA_SHADER_NONE) {
1032*61046927SAndroid Build Coastguard Worker             assert(cached_stage == stage);
1033*61046927SAndroid Build Coastguard Worker             D3D12_SHADER_BYTECODE *slot =
1034*61046927SAndroid Build Coastguard Worker                dzn_pipeline_get_gfx_shader_slot(out, stage);
1035*61046927SAndroid Build Coastguard Worker             *slot = bc;
1036*61046927SAndroid Build Coastguard Worker             pipeline->templates.shaders[stage].bc = slot;
1037*61046927SAndroid Build Coastguard Worker          }
1038*61046927SAndroid Build Coastguard Worker       }
1039*61046927SAndroid Build Coastguard Worker    }
1040*61046927SAndroid Build Coastguard Worker 
1041*61046927SAndroid Build Coastguard Worker    uint32_t vert_input_count = 0;
1042*61046927SAndroid Build Coastguard Worker    if (pipeline->templates.shaders[MESA_SHADER_VERTEX].nir) {
1043*61046927SAndroid Build Coastguard Worker       /* Now, declare one D3D12_INPUT_ELEMENT_DESC per VS input variable, so
1044*61046927SAndroid Build Coastguard Worker        * we can handle location overlaps properly.
1045*61046927SAndroid Build Coastguard Worker        */
1046*61046927SAndroid Build Coastguard Worker       nir_foreach_shader_in_variable(var, pipeline->templates.shaders[MESA_SHADER_VERTEX].nir) {
1047*61046927SAndroid Build Coastguard Worker          assert(var->data.location >= VERT_ATTRIB_GENERIC0);
1048*61046927SAndroid Build Coastguard Worker          unsigned loc = var->data.location - VERT_ATTRIB_GENERIC0;
1049*61046927SAndroid Build Coastguard Worker          assert(vert_input_count < D3D12_VS_INPUT_REGISTER_COUNT);
1050*61046927SAndroid Build Coastguard Worker          assert(loc < MAX_VERTEX_GENERIC_ATTRIBS);
1051*61046927SAndroid Build Coastguard Worker 
1052*61046927SAndroid Build Coastguard Worker          pipeline->templates.inputs[vert_input_count] = attribs[loc];
1053*61046927SAndroid Build Coastguard Worker          pipeline->templates.inputs[vert_input_count].SemanticIndex = vert_input_count;
1054*61046927SAndroid Build Coastguard Worker          var->data.driver_location = vert_input_count++;
1055*61046927SAndroid Build Coastguard Worker       }
1056*61046927SAndroid Build Coastguard Worker 
1057*61046927SAndroid Build Coastguard Worker       if (vert_input_count > 0) {
1058*61046927SAndroid Build Coastguard Worker          d3d12_gfx_pipeline_state_stream_new_desc(out, INPUT_LAYOUT, D3D12_INPUT_LAYOUT_DESC, desc);
1059*61046927SAndroid Build Coastguard Worker          desc->pInputElementDescs = pipeline->templates.inputs;
1060*61046927SAndroid Build Coastguard Worker          desc->NumElements = vert_input_count;
1061*61046927SAndroid Build Coastguard Worker       }
1062*61046927SAndroid Build Coastguard Worker    }
1063*61046927SAndroid Build Coastguard Worker 
1064*61046927SAndroid Build Coastguard Worker    /* Last step: translate NIR shaders into DXIL modules */
1065*61046927SAndroid Build Coastguard Worker    u_foreach_bit(stage, active_stage_mask) {
1066*61046927SAndroid Build Coastguard Worker       gl_shader_stage prev_stage =
1067*61046927SAndroid Build Coastguard Worker          util_last_bit(active_stage_mask & BITFIELD_MASK(stage)) - 1;
1068*61046927SAndroid Build Coastguard Worker       uint32_t prev_stage_output_clip_size = 0;
1069*61046927SAndroid Build Coastguard Worker       if (stage == MESA_SHADER_FRAGMENT) {
1070*61046927SAndroid Build Coastguard Worker          /* Disable rasterization if the last geometry stage doesn't
1071*61046927SAndroid Build Coastguard Worker           * write the position.
1072*61046927SAndroid Build Coastguard Worker           */
1073*61046927SAndroid Build Coastguard Worker          if (prev_stage == MESA_SHADER_NONE ||
1074*61046927SAndroid Build Coastguard Worker              !(pipeline->templates.shaders[prev_stage].nir->info.outputs_written & VARYING_BIT_POS)) {
1075*61046927SAndroid Build Coastguard Worker             pipeline->rast_disabled_from_missing_position = true;
1076*61046927SAndroid Build Coastguard Worker             /* Clear a cache hit if there was one. */
1077*61046927SAndroid Build Coastguard Worker             pipeline->templates.shaders[stage].bc = NULL;
1078*61046927SAndroid Build Coastguard Worker             continue;
1079*61046927SAndroid Build Coastguard Worker          }
1080*61046927SAndroid Build Coastguard Worker       } else if (prev_stage != MESA_SHADER_NONE) {
1081*61046927SAndroid Build Coastguard Worker          prev_stage_output_clip_size = pipeline->templates.shaders[prev_stage].nir->info.clip_distance_array_size;
1082*61046927SAndroid Build Coastguard Worker       }
1083*61046927SAndroid Build Coastguard Worker 
1084*61046927SAndroid Build Coastguard Worker       /* Cache hit, we can skip the compilation. */
1085*61046927SAndroid Build Coastguard Worker       if (pipeline->templates.shaders[stage].bc)
1086*61046927SAndroid Build Coastguard Worker          continue;
1087*61046927SAndroid Build Coastguard Worker 
1088*61046927SAndroid Build Coastguard Worker       D3D12_SHADER_BYTECODE *slot =
1089*61046927SAndroid Build Coastguard Worker          dzn_pipeline_get_gfx_shader_slot(out, stage);
1090*61046927SAndroid Build Coastguard Worker 
1091*61046927SAndroid Build Coastguard Worker       ret = dzn_pipeline_compile_shader(device, pipeline->templates.shaders[stage].nir, prev_stage_output_clip_size, slot);
1092*61046927SAndroid Build Coastguard Worker       if (ret != VK_SUCCESS)
1093*61046927SAndroid Build Coastguard Worker          return ret;
1094*61046927SAndroid Build Coastguard Worker 
1095*61046927SAndroid Build Coastguard Worker       pipeline->templates.shaders[stage].bc = slot;
1096*61046927SAndroid Build Coastguard Worker 
1097*61046927SAndroid Build Coastguard Worker       if (cache)
1098*61046927SAndroid Build Coastguard Worker          dzn_pipeline_cache_add_dxil_shader(cache, stages[stage].dxil_hash, stage, slot);
1099*61046927SAndroid Build Coastguard Worker    }
1100*61046927SAndroid Build Coastguard Worker 
1101*61046927SAndroid Build Coastguard Worker    if (cache)
1102*61046927SAndroid Build Coastguard Worker       dzn_pipeline_cache_add_gfx_pipeline(pipeline, cache, vert_input_count, pipeline_hash,
1103*61046927SAndroid Build Coastguard Worker                                           dxil_hashes);
1104*61046927SAndroid Build Coastguard Worker 
1105*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1106*61046927SAndroid Build Coastguard Worker }
1107*61046927SAndroid Build Coastguard Worker 
1108*61046927SAndroid Build Coastguard Worker VkFormat
dzn_graphics_pipeline_patch_vi_format(VkFormat format)1109*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_patch_vi_format(VkFormat format)
1110*61046927SAndroid Build Coastguard Worker {
1111*61046927SAndroid Build Coastguard Worker    switch (format) {
1112*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
1113*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
1114*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
1115*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
1116*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
1117*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
1118*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
1119*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_R32_UINT;
1120*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_R8G8B8A8_SSCALED:
1121*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_R8G8B8A8_SINT;
1122*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_R8G8B8A8_USCALED:
1123*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_R8G8B8A8_UINT;
1124*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_R16G16B16A16_USCALED:
1125*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_R16G16B16A16_UINT;
1126*61046927SAndroid Build Coastguard Worker    case VK_FORMAT_R16G16B16A16_SSCALED:
1127*61046927SAndroid Build Coastguard Worker       return VK_FORMAT_R16G16B16A16_SINT;
1128*61046927SAndroid Build Coastguard Worker    default:
1129*61046927SAndroid Build Coastguard Worker       return format;
1130*61046927SAndroid Build Coastguard Worker    }
1131*61046927SAndroid Build Coastguard Worker }
1132*61046927SAndroid Build Coastguard Worker 
1133*61046927SAndroid Build Coastguard Worker static VkResult
dzn_graphics_pipeline_translate_vi(struct dzn_graphics_pipeline * pipeline,const VkGraphicsPipelineCreateInfo * in,D3D12_INPUT_ELEMENT_DESC * inputs,enum pipe_format * vi_conversions)1134*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_translate_vi(struct dzn_graphics_pipeline *pipeline,
1135*61046927SAndroid Build Coastguard Worker                                    const VkGraphicsPipelineCreateInfo *in,
1136*61046927SAndroid Build Coastguard Worker                                    D3D12_INPUT_ELEMENT_DESC *inputs,
1137*61046927SAndroid Build Coastguard Worker                                    enum pipe_format *vi_conversions)
1138*61046927SAndroid Build Coastguard Worker {
1139*61046927SAndroid Build Coastguard Worker    const VkPipelineVertexInputStateCreateInfo *in_vi =
1140*61046927SAndroid Build Coastguard Worker       in->pVertexInputState;
1141*61046927SAndroid Build Coastguard Worker    const VkPipelineVertexInputDivisorStateCreateInfoEXT *divisors =
1142*61046927SAndroid Build Coastguard Worker       (const VkPipelineVertexInputDivisorStateCreateInfoEXT *)
1143*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(in_vi, PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
1144*61046927SAndroid Build Coastguard Worker 
1145*61046927SAndroid Build Coastguard Worker    if (!in_vi->vertexAttributeDescriptionCount)
1146*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1147*61046927SAndroid Build Coastguard Worker 
1148*61046927SAndroid Build Coastguard Worker    D3D12_INPUT_CLASSIFICATION slot_class[MAX_VBS];
1149*61046927SAndroid Build Coastguard Worker 
1150*61046927SAndroid Build Coastguard Worker    pipeline->vb.count = 0;
1151*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < in_vi->vertexBindingDescriptionCount; i++) {
1152*61046927SAndroid Build Coastguard Worker       const struct VkVertexInputBindingDescription *bdesc =
1153*61046927SAndroid Build Coastguard Worker          &in_vi->pVertexBindingDescriptions[i];
1154*61046927SAndroid Build Coastguard Worker 
1155*61046927SAndroid Build Coastguard Worker       pipeline->vb.count = MAX2(pipeline->vb.count, bdesc->binding + 1);
1156*61046927SAndroid Build Coastguard Worker       pipeline->vb.strides[bdesc->binding] = bdesc->stride;
1157*61046927SAndroid Build Coastguard Worker       if (bdesc->inputRate == VK_VERTEX_INPUT_RATE_INSTANCE) {
1158*61046927SAndroid Build Coastguard Worker          slot_class[bdesc->binding] = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
1159*61046927SAndroid Build Coastguard Worker       } else {
1160*61046927SAndroid Build Coastguard Worker          assert(bdesc->inputRate == VK_VERTEX_INPUT_RATE_VERTEX);
1161*61046927SAndroid Build Coastguard Worker          slot_class[bdesc->binding] = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
1162*61046927SAndroid Build Coastguard Worker       }
1163*61046927SAndroid Build Coastguard Worker    }
1164*61046927SAndroid Build Coastguard Worker 
1165*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < in_vi->vertexAttributeDescriptionCount; i++) {
1166*61046927SAndroid Build Coastguard Worker       const VkVertexInputAttributeDescription *attr =
1167*61046927SAndroid Build Coastguard Worker          &in_vi->pVertexAttributeDescriptions[i];
1168*61046927SAndroid Build Coastguard Worker       const VkVertexInputBindingDivisorDescriptionEXT *divisor = NULL;
1169*61046927SAndroid Build Coastguard Worker 
1170*61046927SAndroid Build Coastguard Worker       if (slot_class[attr->binding] == D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA &&
1171*61046927SAndroid Build Coastguard Worker           divisors) {
1172*61046927SAndroid Build Coastguard Worker          for (uint32_t d = 0; d < divisors->vertexBindingDivisorCount; d++) {
1173*61046927SAndroid Build Coastguard Worker             if (attr->binding == divisors->pVertexBindingDivisors[d].binding) {
1174*61046927SAndroid Build Coastguard Worker                divisor = &divisors->pVertexBindingDivisors[d];
1175*61046927SAndroid Build Coastguard Worker                break;
1176*61046927SAndroid Build Coastguard Worker             }
1177*61046927SAndroid Build Coastguard Worker          }
1178*61046927SAndroid Build Coastguard Worker       }
1179*61046927SAndroid Build Coastguard Worker 
1180*61046927SAndroid Build Coastguard Worker       VkFormat patched_format = dzn_graphics_pipeline_patch_vi_format(attr->format);
1181*61046927SAndroid Build Coastguard Worker       if (patched_format != attr->format)
1182*61046927SAndroid Build Coastguard Worker          vi_conversions[attr->location] = vk_format_to_pipe_format(attr->format);
1183*61046927SAndroid Build Coastguard Worker 
1184*61046927SAndroid Build Coastguard Worker       /* nir_to_dxil() name all vertex inputs as TEXCOORDx */
1185*61046927SAndroid Build Coastguard Worker       inputs[attr->location] = (D3D12_INPUT_ELEMENT_DESC) {
1186*61046927SAndroid Build Coastguard Worker          .SemanticName = "TEXCOORD",
1187*61046927SAndroid Build Coastguard Worker          .Format = dzn_buffer_get_dxgi_format(patched_format),
1188*61046927SAndroid Build Coastguard Worker          .InputSlot = attr->binding,
1189*61046927SAndroid Build Coastguard Worker          .InputSlotClass = slot_class[attr->binding],
1190*61046927SAndroid Build Coastguard Worker          .InstanceDataStepRate =
1191*61046927SAndroid Build Coastguard Worker             divisor ? divisor->divisor :
1192*61046927SAndroid Build Coastguard Worker             slot_class[attr->binding] == D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA ? 1 : 0,
1193*61046927SAndroid Build Coastguard Worker          .AlignedByteOffset = attr->offset,
1194*61046927SAndroid Build Coastguard Worker       };
1195*61046927SAndroid Build Coastguard Worker    }
1196*61046927SAndroid Build Coastguard Worker 
1197*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1198*61046927SAndroid Build Coastguard Worker }
1199*61046927SAndroid Build Coastguard Worker 
1200*61046927SAndroid Build Coastguard Worker static D3D12_PRIMITIVE_TOPOLOGY_TYPE
to_prim_topology_type(VkPrimitiveTopology in)1201*61046927SAndroid Build Coastguard Worker to_prim_topology_type(VkPrimitiveTopology in)
1202*61046927SAndroid Build Coastguard Worker {
1203*61046927SAndroid Build Coastguard Worker    switch (in) {
1204*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1205*61046927SAndroid Build Coastguard Worker       return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
1206*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1207*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
1208*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1209*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
1210*61046927SAndroid Build Coastguard Worker       return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
1211*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1212*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
1213*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
1214*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1215*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1216*61046927SAndroid Build Coastguard Worker       return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
1217*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
1218*61046927SAndroid Build Coastguard Worker       return D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
1219*61046927SAndroid Build Coastguard Worker    default: unreachable("Invalid primitive topology");
1220*61046927SAndroid Build Coastguard Worker    }
1221*61046927SAndroid Build Coastguard Worker }
1222*61046927SAndroid Build Coastguard Worker 
1223*61046927SAndroid Build Coastguard Worker static D3D12_PRIMITIVE_TOPOLOGY
to_prim_topology(VkPrimitiveTopology in,unsigned patch_control_points,bool support_triangle_fan)1224*61046927SAndroid Build Coastguard Worker to_prim_topology(VkPrimitiveTopology in, unsigned patch_control_points, bool support_triangle_fan)
1225*61046927SAndroid Build Coastguard Worker {
1226*61046927SAndroid Build Coastguard Worker    switch (in) {
1227*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
1228*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
1229*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
1230*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
1231*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ;
1232*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
1233*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
1234*61046927SAndroid Build Coastguard Worker    /* Triangle fans are emulated using an intermediate index buffer. */
1235*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return support_triangle_fan ?
1236*61046927SAndroid Build Coastguard Worker       D3D_PRIMITIVE_TOPOLOGY_TRIANGLEFAN : D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
1237*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ;
1238*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ;
1239*61046927SAndroid Build Coastguard Worker    case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
1240*61046927SAndroid Build Coastguard Worker       assert(patch_control_points);
1241*61046927SAndroid Build Coastguard Worker       return (D3D12_PRIMITIVE_TOPOLOGY)(D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + patch_control_points - 1);
1242*61046927SAndroid Build Coastguard Worker    default: unreachable("Invalid primitive topology");
1243*61046927SAndroid Build Coastguard Worker    }
1244*61046927SAndroid Build Coastguard Worker }
1245*61046927SAndroid Build Coastguard Worker 
1246*61046927SAndroid Build Coastguard Worker static VkResult
dzn_graphics_pipeline_translate_ia(struct dzn_device * device,struct dzn_graphics_pipeline * pipeline,D3D12_PIPELINE_STATE_STREAM_DESC * out,const VkGraphicsPipelineCreateInfo * in)1247*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_translate_ia(struct dzn_device *device,
1248*61046927SAndroid Build Coastguard Worker                                    struct dzn_graphics_pipeline *pipeline,
1249*61046927SAndroid Build Coastguard Worker                                    D3D12_PIPELINE_STATE_STREAM_DESC *out,
1250*61046927SAndroid Build Coastguard Worker                                    const VkGraphicsPipelineCreateInfo *in)
1251*61046927SAndroid Build Coastguard Worker {
1252*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev =
1253*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical, struct dzn_physical_device, vk);
1254*61046927SAndroid Build Coastguard Worker    const VkPipelineInputAssemblyStateCreateInfo *in_ia =
1255*61046927SAndroid Build Coastguard Worker       in->pInputAssemblyState;
1256*61046927SAndroid Build Coastguard Worker    bool has_tes = false;
1257*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < in->stageCount; i++) {
1258*61046927SAndroid Build Coastguard Worker       if (in->pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
1259*61046927SAndroid Build Coastguard Worker           in->pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
1260*61046927SAndroid Build Coastguard Worker          has_tes = true;
1261*61046927SAndroid Build Coastguard Worker          break;
1262*61046927SAndroid Build Coastguard Worker       }
1263*61046927SAndroid Build Coastguard Worker    }
1264*61046927SAndroid Build Coastguard Worker    const VkPipelineTessellationStateCreateInfo *in_tes =
1265*61046927SAndroid Build Coastguard Worker       has_tes ? in->pTessellationState : NULL;
1266*61046927SAndroid Build Coastguard Worker    VkResult ret = VK_SUCCESS;
1267*61046927SAndroid Build Coastguard Worker 
1268*61046927SAndroid Build Coastguard Worker    d3d12_gfx_pipeline_state_stream_new_desc(out, PRIMITIVE_TOPOLOGY, D3D12_PRIMITIVE_TOPOLOGY_TYPE, prim_top_type);
1269*61046927SAndroid Build Coastguard Worker    *prim_top_type = to_prim_topology_type(in_ia->topology);
1270*61046927SAndroid Build Coastguard Worker    pipeline->ia.triangle_fan = in_ia->topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN && !pdev->options15.TriangleFanSupported;
1271*61046927SAndroid Build Coastguard Worker    pipeline->ia.topology =
1272*61046927SAndroid Build Coastguard Worker       to_prim_topology(in_ia->topology, in_tes ? in_tes->patchControlPoints : 0,
1273*61046927SAndroid Build Coastguard Worker                        pdev->options15.TriangleFanSupported);
1274*61046927SAndroid Build Coastguard Worker 
1275*61046927SAndroid Build Coastguard Worker    if (in_ia->primitiveRestartEnable) {
1276*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(out, IB_STRIP_CUT_VALUE, D3D12_INDEX_BUFFER_STRIP_CUT_VALUE, ib_strip_cut);
1277*61046927SAndroid Build Coastguard Worker       pipeline->templates.desc_offsets.ib_strip_cut =
1278*61046927SAndroid Build Coastguard Worker          (uintptr_t)ib_strip_cut - (uintptr_t)out->pPipelineStateSubobjectStream;
1279*61046927SAndroid Build Coastguard Worker       *ib_strip_cut = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
1280*61046927SAndroid Build Coastguard Worker       ret = dzn_graphics_pipeline_prepare_for_variants(device, pipeline);
1281*61046927SAndroid Build Coastguard Worker    }
1282*61046927SAndroid Build Coastguard Worker 
1283*61046927SAndroid Build Coastguard Worker    return ret;
1284*61046927SAndroid Build Coastguard Worker }
1285*61046927SAndroid Build Coastguard Worker 
1286*61046927SAndroid Build Coastguard Worker static D3D12_FILL_MODE
translate_polygon_mode(VkPolygonMode in)1287*61046927SAndroid Build Coastguard Worker translate_polygon_mode(VkPolygonMode in)
1288*61046927SAndroid Build Coastguard Worker {
1289*61046927SAndroid Build Coastguard Worker    switch (in) {
1290*61046927SAndroid Build Coastguard Worker    case VK_POLYGON_MODE_FILL: return D3D12_FILL_MODE_SOLID;
1291*61046927SAndroid Build Coastguard Worker    case VK_POLYGON_MODE_LINE: return D3D12_FILL_MODE_WIREFRAME;
1292*61046927SAndroid Build Coastguard Worker    case VK_POLYGON_MODE_POINT:
1293*61046927SAndroid Build Coastguard Worker       /* This is handled elsewhere */
1294*61046927SAndroid Build Coastguard Worker       return D3D12_FILL_MODE_SOLID;
1295*61046927SAndroid Build Coastguard Worker    default: unreachable("Unsupported polygon mode");
1296*61046927SAndroid Build Coastguard Worker    }
1297*61046927SAndroid Build Coastguard Worker }
1298*61046927SAndroid Build Coastguard Worker 
1299*61046927SAndroid Build Coastguard Worker static D3D12_CULL_MODE
translate_cull_mode(VkCullModeFlags in)1300*61046927SAndroid Build Coastguard Worker translate_cull_mode(VkCullModeFlags in)
1301*61046927SAndroid Build Coastguard Worker {
1302*61046927SAndroid Build Coastguard Worker    switch (in) {
1303*61046927SAndroid Build Coastguard Worker    case VK_CULL_MODE_NONE: return D3D12_CULL_MODE_NONE;
1304*61046927SAndroid Build Coastguard Worker    case VK_CULL_MODE_FRONT_BIT: return D3D12_CULL_MODE_FRONT;
1305*61046927SAndroid Build Coastguard Worker    case VK_CULL_MODE_BACK_BIT: return D3D12_CULL_MODE_BACK;
1306*61046927SAndroid Build Coastguard Worker    /* Front+back face culling is equivalent to 'rasterization disabled' */
1307*61046927SAndroid Build Coastguard Worker    case VK_CULL_MODE_FRONT_AND_BACK: return D3D12_CULL_MODE_NONE;
1308*61046927SAndroid Build Coastguard Worker    default: unreachable("Unsupported cull mode");
1309*61046927SAndroid Build Coastguard Worker    }
1310*61046927SAndroid Build Coastguard Worker }
1311*61046927SAndroid Build Coastguard Worker 
1312*61046927SAndroid Build Coastguard Worker static int32_t
translate_depth_bias(double depth_bias)1313*61046927SAndroid Build Coastguard Worker translate_depth_bias(double depth_bias)
1314*61046927SAndroid Build Coastguard Worker {
1315*61046927SAndroid Build Coastguard Worker    if (depth_bias > INT32_MAX)
1316*61046927SAndroid Build Coastguard Worker       return INT32_MAX;
1317*61046927SAndroid Build Coastguard Worker    else if (depth_bias < INT32_MIN)
1318*61046927SAndroid Build Coastguard Worker       return INT32_MIN;
1319*61046927SAndroid Build Coastguard Worker 
1320*61046927SAndroid Build Coastguard Worker    return depth_bias;
1321*61046927SAndroid Build Coastguard Worker }
1322*61046927SAndroid Build Coastguard Worker 
1323*61046927SAndroid Build Coastguard Worker static void
dzn_graphics_pipeline_translate_rast(struct dzn_device * device,struct dzn_graphics_pipeline * pipeline,D3D12_PIPELINE_STATE_STREAM_DESC * out,const VkGraphicsPipelineCreateInfo * in)1324*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_translate_rast(struct dzn_device *device,
1325*61046927SAndroid Build Coastguard Worker                                      struct dzn_graphics_pipeline *pipeline,
1326*61046927SAndroid Build Coastguard Worker                                      D3D12_PIPELINE_STATE_STREAM_DESC *out,
1327*61046927SAndroid Build Coastguard Worker                                      const VkGraphicsPipelineCreateInfo *in)
1328*61046927SAndroid Build Coastguard Worker {
1329*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev = container_of(device->vk.physical, struct dzn_physical_device, vk);
1330*61046927SAndroid Build Coastguard Worker    const VkPipelineRasterizationStateCreateInfo *in_rast =
1331*61046927SAndroid Build Coastguard Worker       in->pRasterizationState;
1332*61046927SAndroid Build Coastguard Worker    const VkPipelineViewportStateCreateInfo *in_vp =
1333*61046927SAndroid Build Coastguard Worker       in_rast->rasterizerDiscardEnable ? NULL : in->pViewportState;
1334*61046927SAndroid Build Coastguard Worker    const VkPipelineMultisampleStateCreateInfo *in_ms =
1335*61046927SAndroid Build Coastguard Worker       in_rast->rasterizerDiscardEnable ? NULL : in->pMultisampleState;
1336*61046927SAndroid Build Coastguard Worker 
1337*61046927SAndroid Build Coastguard Worker    if (in_vp) {
1338*61046927SAndroid Build Coastguard Worker       pipeline->vp.count = in_vp->viewportCount;
1339*61046927SAndroid Build Coastguard Worker       if (in_vp->pViewports) {
1340*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; in_vp->pViewports && i < in_vp->viewportCount; i++)
1341*61046927SAndroid Build Coastguard Worker             dzn_translate_viewport(&pipeline->vp.desc[i], &in_vp->pViewports[i]);
1342*61046927SAndroid Build Coastguard Worker       }
1343*61046927SAndroid Build Coastguard Worker 
1344*61046927SAndroid Build Coastguard Worker       pipeline->scissor.count = in_vp->scissorCount;
1345*61046927SAndroid Build Coastguard Worker       if (in_vp->pScissors) {
1346*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; i < in_vp->scissorCount; i++)
1347*61046927SAndroid Build Coastguard Worker             dzn_translate_rect(&pipeline->scissor.desc[i], &in_vp->pScissors[i]);
1348*61046927SAndroid Build Coastguard Worker       }
1349*61046927SAndroid Build Coastguard Worker    }
1350*61046927SAndroid Build Coastguard Worker 
1351*61046927SAndroid Build Coastguard Worker    if (pdev->options19.NarrowQuadrilateralLinesSupported) {
1352*61046927SAndroid Build Coastguard Worker       assert(pdev->options16.DynamicDepthBiasSupported);
1353*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(out, RASTERIZER2, D3D12_RASTERIZER_DESC2, desc);
1354*61046927SAndroid Build Coastguard Worker       pipeline->templates.desc_offsets.rast =
1355*61046927SAndroid Build Coastguard Worker          (uintptr_t)desc - (uintptr_t)out->pPipelineStateSubobjectStream;
1356*61046927SAndroid Build Coastguard Worker       desc->DepthClipEnable = !in_rast->depthClampEnable;
1357*61046927SAndroid Build Coastguard Worker       desc->FillMode = translate_polygon_mode(in_rast->polygonMode);
1358*61046927SAndroid Build Coastguard Worker       desc->CullMode = translate_cull_mode(in_rast->cullMode);
1359*61046927SAndroid Build Coastguard Worker       desc->FrontCounterClockwise =
1360*61046927SAndroid Build Coastguard Worker          in_rast->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE;
1361*61046927SAndroid Build Coastguard Worker       if (in_rast->depthBiasEnable) {
1362*61046927SAndroid Build Coastguard Worker          desc->DepthBias = in_rast->depthBiasConstantFactor;
1363*61046927SAndroid Build Coastguard Worker          desc->SlopeScaledDepthBias = in_rast->depthBiasSlopeFactor;
1364*61046927SAndroid Build Coastguard Worker          desc->DepthBiasClamp = in_rast->depthBiasClamp;
1365*61046927SAndroid Build Coastguard Worker       }
1366*61046927SAndroid Build Coastguard Worker       desc->LineRasterizationMode = D3D12_LINE_RASTERIZATION_MODE_QUADRILATERAL_NARROW;
1367*61046927SAndroid Build Coastguard Worker    } else {
1368*61046927SAndroid Build Coastguard Worker       static_assert(sizeof(D3D12_RASTERIZER_DESC) == sizeof(D3D12_RASTERIZER_DESC1), "Casting between these");
1369*61046927SAndroid Build Coastguard Worker       D3D12_PIPELINE_STATE_SUBOBJECT_TYPE rast_type = pdev->options16.DynamicDepthBiasSupported ?
1370*61046927SAndroid Build Coastguard Worker          D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER1 :
1371*61046927SAndroid Build Coastguard Worker          D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER;
1372*61046927SAndroid Build Coastguard Worker       d3d12_pipeline_state_stream_new_desc(out, MAX_GFX_PIPELINE_STATE_STREAM_SIZE, rast_type, D3D12_RASTERIZER_DESC, desc);
1373*61046927SAndroid Build Coastguard Worker       pipeline->templates.desc_offsets.rast =
1374*61046927SAndroid Build Coastguard Worker          (uintptr_t)desc - (uintptr_t)out->pPipelineStateSubobjectStream;
1375*61046927SAndroid Build Coastguard Worker       desc->DepthClipEnable = !in_rast->depthClampEnable;
1376*61046927SAndroid Build Coastguard Worker       desc->FillMode = translate_polygon_mode(in_rast->polygonMode);
1377*61046927SAndroid Build Coastguard Worker       desc->CullMode = translate_cull_mode(in_rast->cullMode);
1378*61046927SAndroid Build Coastguard Worker       desc->FrontCounterClockwise =
1379*61046927SAndroid Build Coastguard Worker          in_rast->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE;
1380*61046927SAndroid Build Coastguard Worker       if (in_rast->depthBiasEnable) {
1381*61046927SAndroid Build Coastguard Worker          if (rast_type == D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER1)
1382*61046927SAndroid Build Coastguard Worker             ((D3D12_RASTERIZER_DESC1 *)desc)->DepthBias = in_rast->depthBiasConstantFactor;
1383*61046927SAndroid Build Coastguard Worker          else
1384*61046927SAndroid Build Coastguard Worker             desc->DepthBias = translate_depth_bias(in_rast->depthBiasConstantFactor);
1385*61046927SAndroid Build Coastguard Worker          desc->SlopeScaledDepthBias = in_rast->depthBiasSlopeFactor;
1386*61046927SAndroid Build Coastguard Worker          desc->DepthBiasClamp = in_rast->depthBiasClamp;
1387*61046927SAndroid Build Coastguard Worker       }
1388*61046927SAndroid Build Coastguard Worker 
1389*61046927SAndroid Build Coastguard Worker       /* The Vulkan conformance tests use different reference rasterizers for single-sampled
1390*61046927SAndroid Build Coastguard Worker        * and multi-sampled lines. The single-sampled lines can be bresenham lines, but multi-
1391*61046927SAndroid Build Coastguard Worker        * sampled need to be quadrilateral lines. This still isn't *quite* sufficient, because
1392*61046927SAndroid Build Coastguard Worker        * D3D only supports a line width of 1.4 (per spec), but Vulkan requires us to support
1393*61046927SAndroid Build Coastguard Worker        * 1.0 (and without claiming wide lines, that's all we can support).
1394*61046927SAndroid Build Coastguard Worker        */
1395*61046927SAndroid Build Coastguard Worker       if (in_ms && in_ms->rasterizationSamples > 1)
1396*61046927SAndroid Build Coastguard Worker          desc->MultisampleEnable = true;
1397*61046927SAndroid Build Coastguard Worker    }
1398*61046927SAndroid Build Coastguard Worker 
1399*61046927SAndroid Build Coastguard Worker    assert(in_rast->lineWidth == 1.0f);
1400*61046927SAndroid Build Coastguard Worker }
1401*61046927SAndroid Build Coastguard Worker 
1402*61046927SAndroid Build Coastguard Worker static void
dzn_graphics_pipeline_translate_ms(struct dzn_graphics_pipeline * pipeline,D3D12_PIPELINE_STATE_STREAM_DESC * out,const VkGraphicsPipelineCreateInfo * in)1403*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_translate_ms(struct dzn_graphics_pipeline *pipeline,
1404*61046927SAndroid Build Coastguard Worker                                    D3D12_PIPELINE_STATE_STREAM_DESC *out,
1405*61046927SAndroid Build Coastguard Worker                                    const VkGraphicsPipelineCreateInfo *in)
1406*61046927SAndroid Build Coastguard Worker {
1407*61046927SAndroid Build Coastguard Worker    const VkPipelineRasterizationStateCreateInfo *in_rast =
1408*61046927SAndroid Build Coastguard Worker       in->pRasterizationState;
1409*61046927SAndroid Build Coastguard Worker    const VkPipelineMultisampleStateCreateInfo *in_ms =
1410*61046927SAndroid Build Coastguard Worker       in_rast->rasterizerDiscardEnable ? NULL : in->pMultisampleState;
1411*61046927SAndroid Build Coastguard Worker 
1412*61046927SAndroid Build Coastguard Worker    if (!in_ms)
1413*61046927SAndroid Build Coastguard Worker       return;
1414*61046927SAndroid Build Coastguard Worker 
1415*61046927SAndroid Build Coastguard Worker    /* TODO: minSampleShading (use VRS), alphaToOneEnable */
1416*61046927SAndroid Build Coastguard Worker    d3d12_gfx_pipeline_state_stream_new_desc(out, SAMPLE_DESC, DXGI_SAMPLE_DESC, desc);
1417*61046927SAndroid Build Coastguard Worker    desc->Count = in_ms ? in_ms->rasterizationSamples : 1;
1418*61046927SAndroid Build Coastguard Worker    desc->Quality = 0;
1419*61046927SAndroid Build Coastguard Worker 
1420*61046927SAndroid Build Coastguard Worker    if (!in_ms->pSampleMask)
1421*61046927SAndroid Build Coastguard Worker       return;
1422*61046927SAndroid Build Coastguard Worker 
1423*61046927SAndroid Build Coastguard Worker    d3d12_gfx_pipeline_state_stream_new_desc(out, SAMPLE_MASK, UINT, mask);
1424*61046927SAndroid Build Coastguard Worker    *mask = *in_ms->pSampleMask;
1425*61046927SAndroid Build Coastguard Worker }
1426*61046927SAndroid Build Coastguard Worker 
1427*61046927SAndroid Build Coastguard Worker static D3D12_STENCIL_OP
translate_stencil_op(VkStencilOp in)1428*61046927SAndroid Build Coastguard Worker translate_stencil_op(VkStencilOp in)
1429*61046927SAndroid Build Coastguard Worker {
1430*61046927SAndroid Build Coastguard Worker    switch (in) {
1431*61046927SAndroid Build Coastguard Worker    case VK_STENCIL_OP_KEEP: return D3D12_STENCIL_OP_KEEP;
1432*61046927SAndroid Build Coastguard Worker    case VK_STENCIL_OP_ZERO: return D3D12_STENCIL_OP_ZERO;
1433*61046927SAndroid Build Coastguard Worker    case VK_STENCIL_OP_REPLACE: return D3D12_STENCIL_OP_REPLACE;
1434*61046927SAndroid Build Coastguard Worker    case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return D3D12_STENCIL_OP_INCR_SAT;
1435*61046927SAndroid Build Coastguard Worker    case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return D3D12_STENCIL_OP_DECR_SAT;
1436*61046927SAndroid Build Coastguard Worker    case VK_STENCIL_OP_INCREMENT_AND_WRAP: return D3D12_STENCIL_OP_INCR;
1437*61046927SAndroid Build Coastguard Worker    case VK_STENCIL_OP_DECREMENT_AND_WRAP: return D3D12_STENCIL_OP_DECR;
1438*61046927SAndroid Build Coastguard Worker    case VK_STENCIL_OP_INVERT: return D3D12_STENCIL_OP_INVERT;
1439*61046927SAndroid Build Coastguard Worker    default: unreachable("Invalid stencil op");
1440*61046927SAndroid Build Coastguard Worker    }
1441*61046927SAndroid Build Coastguard Worker }
1442*61046927SAndroid Build Coastguard Worker 
1443*61046927SAndroid Build Coastguard Worker static void
translate_stencil_test(struct dzn_graphics_pipeline * pipeline,D3D12_DEPTH_STENCIL_DESC2 * out,const VkGraphicsPipelineCreateInfo * in)1444*61046927SAndroid Build Coastguard Worker translate_stencil_test(struct dzn_graphics_pipeline *pipeline,
1445*61046927SAndroid Build Coastguard Worker                        D3D12_DEPTH_STENCIL_DESC2 *out,
1446*61046927SAndroid Build Coastguard Worker                        const VkGraphicsPipelineCreateInfo *in)
1447*61046927SAndroid Build Coastguard Worker {
1448*61046927SAndroid Build Coastguard Worker    const VkPipelineDepthStencilStateCreateInfo *in_zsa =
1449*61046927SAndroid Build Coastguard Worker       in->pDepthStencilState;
1450*61046927SAndroid Build Coastguard Worker 
1451*61046927SAndroid Build Coastguard Worker    bool front_test_uses_ref =
1452*61046927SAndroid Build Coastguard Worker       !(in->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT) &&
1453*61046927SAndroid Build Coastguard Worker       in_zsa->front.compareOp != VK_COMPARE_OP_NEVER &&
1454*61046927SAndroid Build Coastguard Worker       in_zsa->front.compareOp != VK_COMPARE_OP_ALWAYS &&
1455*61046927SAndroid Build Coastguard Worker       (pipeline->zsa.stencil_test.dynamic_compare_mask ||
1456*61046927SAndroid Build Coastguard Worker        in_zsa->front.compareMask != 0);
1457*61046927SAndroid Build Coastguard Worker    bool back_test_uses_ref =
1458*61046927SAndroid Build Coastguard Worker       !(in->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT) &&
1459*61046927SAndroid Build Coastguard Worker       in_zsa->back.compareOp != VK_COMPARE_OP_NEVER &&
1460*61046927SAndroid Build Coastguard Worker       in_zsa->back.compareOp != VK_COMPARE_OP_ALWAYS &&
1461*61046927SAndroid Build Coastguard Worker       (pipeline->zsa.stencil_test.dynamic_compare_mask ||
1462*61046927SAndroid Build Coastguard Worker        in_zsa->back.compareMask != 0);
1463*61046927SAndroid Build Coastguard Worker 
1464*61046927SAndroid Build Coastguard Worker    if (front_test_uses_ref && pipeline->zsa.stencil_test.dynamic_compare_mask)
1465*61046927SAndroid Build Coastguard Worker       pipeline->zsa.stencil_test.front.compare_mask = UINT32_MAX;
1466*61046927SAndroid Build Coastguard Worker    else if (front_test_uses_ref)
1467*61046927SAndroid Build Coastguard Worker       pipeline->zsa.stencil_test.front.compare_mask = in_zsa->front.compareMask;
1468*61046927SAndroid Build Coastguard Worker    else
1469*61046927SAndroid Build Coastguard Worker       pipeline->zsa.stencil_test.front.compare_mask = 0;
1470*61046927SAndroid Build Coastguard Worker 
1471*61046927SAndroid Build Coastguard Worker    if (back_test_uses_ref && pipeline->zsa.stencil_test.dynamic_compare_mask)
1472*61046927SAndroid Build Coastguard Worker       pipeline->zsa.stencil_test.back.compare_mask = UINT32_MAX;
1473*61046927SAndroid Build Coastguard Worker    else if (back_test_uses_ref)
1474*61046927SAndroid Build Coastguard Worker       pipeline->zsa.stencil_test.back.compare_mask = in_zsa->back.compareMask;
1475*61046927SAndroid Build Coastguard Worker    else
1476*61046927SAndroid Build Coastguard Worker       pipeline->zsa.stencil_test.back.compare_mask = 0;
1477*61046927SAndroid Build Coastguard Worker 
1478*61046927SAndroid Build Coastguard Worker    bool back_wr_uses_ref =
1479*61046927SAndroid Build Coastguard Worker       !(in->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT) &&
1480*61046927SAndroid Build Coastguard Worker       ((in_zsa->back.compareOp != VK_COMPARE_OP_ALWAYS &&
1481*61046927SAndroid Build Coastguard Worker         in_zsa->back.failOp == VK_STENCIL_OP_REPLACE) ||
1482*61046927SAndroid Build Coastguard Worker        (in_zsa->back.compareOp != VK_COMPARE_OP_NEVER &&
1483*61046927SAndroid Build Coastguard Worker         (!in_zsa->depthTestEnable || in_zsa->depthCompareOp != VK_COMPARE_OP_NEVER) &&
1484*61046927SAndroid Build Coastguard Worker         in_zsa->back.passOp == VK_STENCIL_OP_REPLACE) ||
1485*61046927SAndroid Build Coastguard Worker        (in_zsa->depthTestEnable &&
1486*61046927SAndroid Build Coastguard Worker         in_zsa->depthCompareOp != VK_COMPARE_OP_ALWAYS &&
1487*61046927SAndroid Build Coastguard Worker         in_zsa->back.depthFailOp == VK_STENCIL_OP_REPLACE));
1488*61046927SAndroid Build Coastguard Worker    bool front_wr_uses_ref =
1489*61046927SAndroid Build Coastguard Worker       !(in->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT) &&
1490*61046927SAndroid Build Coastguard Worker       ((in_zsa->front.compareOp != VK_COMPARE_OP_ALWAYS &&
1491*61046927SAndroid Build Coastguard Worker         in_zsa->front.failOp == VK_STENCIL_OP_REPLACE) ||
1492*61046927SAndroid Build Coastguard Worker        (in_zsa->front.compareOp != VK_COMPARE_OP_NEVER &&
1493*61046927SAndroid Build Coastguard Worker         (!in_zsa->depthTestEnable || in_zsa->depthCompareOp != VK_COMPARE_OP_NEVER) &&
1494*61046927SAndroid Build Coastguard Worker         in_zsa->front.passOp == VK_STENCIL_OP_REPLACE) ||
1495*61046927SAndroid Build Coastguard Worker        (in_zsa->depthTestEnable &&
1496*61046927SAndroid Build Coastguard Worker         in_zsa->depthCompareOp != VK_COMPARE_OP_ALWAYS &&
1497*61046927SAndroid Build Coastguard Worker         in_zsa->front.depthFailOp == VK_STENCIL_OP_REPLACE));
1498*61046927SAndroid Build Coastguard Worker 
1499*61046927SAndroid Build Coastguard Worker    pipeline->zsa.stencil_test.front.write_mask =
1500*61046927SAndroid Build Coastguard Worker       (pipeline->zsa.stencil_test.dynamic_write_mask ||
1501*61046927SAndroid Build Coastguard Worker        (in->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT)) ?
1502*61046927SAndroid Build Coastguard Worker       0 : in_zsa->front.writeMask;
1503*61046927SAndroid Build Coastguard Worker    pipeline->zsa.stencil_test.back.write_mask =
1504*61046927SAndroid Build Coastguard Worker       (pipeline->zsa.stencil_test.dynamic_write_mask ||
1505*61046927SAndroid Build Coastguard Worker        (in->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT)) ?
1506*61046927SAndroid Build Coastguard Worker       0 : in_zsa->back.writeMask;
1507*61046927SAndroid Build Coastguard Worker 
1508*61046927SAndroid Build Coastguard Worker    pipeline->zsa.stencil_test.front.uses_ref = front_test_uses_ref || front_wr_uses_ref;
1509*61046927SAndroid Build Coastguard Worker    pipeline->zsa.stencil_test.back.uses_ref = back_test_uses_ref || back_wr_uses_ref;
1510*61046927SAndroid Build Coastguard Worker 
1511*61046927SAndroid Build Coastguard Worker    pipeline->zsa.stencil_test.front.ref =
1512*61046927SAndroid Build Coastguard Worker       pipeline->zsa.stencil_test.dynamic_ref ? 0 : in_zsa->front.reference;
1513*61046927SAndroid Build Coastguard Worker    pipeline->zsa.stencil_test.back.ref =
1514*61046927SAndroid Build Coastguard Worker       pipeline->zsa.stencil_test.dynamic_ref ? 0 : in_zsa->back.reference;
1515*61046927SAndroid Build Coastguard Worker 
1516*61046927SAndroid Build Coastguard Worker    out->FrontFace.StencilReadMask = pipeline->zsa.stencil_test.front.compare_mask;
1517*61046927SAndroid Build Coastguard Worker    out->BackFace.StencilReadMask = pipeline->zsa.stencil_test.back.compare_mask;
1518*61046927SAndroid Build Coastguard Worker    out->FrontFace.StencilWriteMask = pipeline->zsa.stencil_test.front.write_mask;
1519*61046927SAndroid Build Coastguard Worker    out->BackFace.StencilWriteMask = pipeline->zsa.stencil_test.back.write_mask;
1520*61046927SAndroid Build Coastguard Worker }
1521*61046927SAndroid Build Coastguard Worker 
1522*61046927SAndroid Build Coastguard Worker static void
dzn_graphics_pipeline_translate_zsa(struct dzn_device * device,struct dzn_graphics_pipeline * pipeline,D3D12_PIPELINE_STATE_STREAM_DESC * out,const VkGraphicsPipelineCreateInfo * in)1523*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_translate_zsa(struct dzn_device *device,
1524*61046927SAndroid Build Coastguard Worker                                     struct dzn_graphics_pipeline *pipeline,
1525*61046927SAndroid Build Coastguard Worker                                     D3D12_PIPELINE_STATE_STREAM_DESC *out,
1526*61046927SAndroid Build Coastguard Worker                                     const VkGraphicsPipelineCreateInfo *in)
1527*61046927SAndroid Build Coastguard Worker {
1528*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev =
1529*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical, struct dzn_physical_device, vk);
1530*61046927SAndroid Build Coastguard Worker 
1531*61046927SAndroid Build Coastguard Worker    const VkPipelineRasterizationStateCreateInfo *in_rast =
1532*61046927SAndroid Build Coastguard Worker       in->pRasterizationState;
1533*61046927SAndroid Build Coastguard Worker    const VkPipelineDepthStencilStateCreateInfo *in_zsa =
1534*61046927SAndroid Build Coastguard Worker       in_rast->rasterizerDiscardEnable ? NULL : in->pDepthStencilState;
1535*61046927SAndroid Build Coastguard Worker    const VkPipelineRenderingCreateInfo *ri = vk_find_struct_const(in, PIPELINE_RENDERING_CREATE_INFO);
1536*61046927SAndroid Build Coastguard Worker 
1537*61046927SAndroid Build Coastguard Worker    if (!in_zsa ||
1538*61046927SAndroid Build Coastguard Worker        in_rast->cullMode == VK_CULL_MODE_FRONT_AND_BACK) {
1539*61046927SAndroid Build Coastguard Worker       /* Ensure depth is disabled if the rasterizer should be disabled / everything culled */
1540*61046927SAndroid Build Coastguard Worker       if (pdev->options14.IndependentFrontAndBackStencilRefMaskSupported) {
1541*61046927SAndroid Build Coastguard Worker          d3d12_gfx_pipeline_state_stream_new_desc(out, DEPTH_STENCIL2, D3D12_DEPTH_STENCIL_DESC2, stream_desc);
1542*61046927SAndroid Build Coastguard Worker          pipeline->templates.desc_offsets.ds = (uintptr_t)stream_desc - (uintptr_t)out->pPipelineStateSubobjectStream;
1543*61046927SAndroid Build Coastguard Worker          memset(stream_desc, 0, sizeof(*stream_desc));
1544*61046927SAndroid Build Coastguard Worker       } else {
1545*61046927SAndroid Build Coastguard Worker          d3d12_gfx_pipeline_state_stream_new_desc(out, DEPTH_STENCIL1, D3D12_DEPTH_STENCIL_DESC1, stream_desc);
1546*61046927SAndroid Build Coastguard Worker          pipeline->templates.desc_offsets.ds = (uintptr_t)stream_desc - (uintptr_t)out->pPipelineStateSubobjectStream;
1547*61046927SAndroid Build Coastguard Worker          memset(stream_desc, 0, sizeof(*stream_desc));
1548*61046927SAndroid Build Coastguard Worker       }
1549*61046927SAndroid Build Coastguard Worker       return;
1550*61046927SAndroid Build Coastguard Worker    }
1551*61046927SAndroid Build Coastguard Worker 
1552*61046927SAndroid Build Coastguard Worker    D3D12_DEPTH_STENCIL_DESC2 desc;
1553*61046927SAndroid Build Coastguard Worker    memset(&desc, 0, sizeof(desc));
1554*61046927SAndroid Build Coastguard Worker 
1555*61046927SAndroid Build Coastguard Worker    bool has_no_depth = ri && ri->depthAttachmentFormat == VK_FORMAT_UNDEFINED;
1556*61046927SAndroid Build Coastguard Worker    bool has_no_stencil = ri && ri->stencilAttachmentFormat == VK_FORMAT_UNDEFINED;
1557*61046927SAndroid Build Coastguard Worker 
1558*61046927SAndroid Build Coastguard Worker    desc.DepthEnable = !has_no_depth &&
1559*61046927SAndroid Build Coastguard Worker       (in_zsa->depthTestEnable || in_zsa->depthBoundsTestEnable);
1560*61046927SAndroid Build Coastguard Worker    if (desc.DepthEnable) {
1561*61046927SAndroid Build Coastguard Worker       desc.DepthWriteMask =
1562*61046927SAndroid Build Coastguard Worker          in_zsa->depthWriteEnable ?
1563*61046927SAndroid Build Coastguard Worker          D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
1564*61046927SAndroid Build Coastguard Worker       desc.DepthFunc =
1565*61046927SAndroid Build Coastguard Worker          in_zsa->depthTestEnable ?
1566*61046927SAndroid Build Coastguard Worker          dzn_translate_compare_op(in_zsa->depthCompareOp) :
1567*61046927SAndroid Build Coastguard Worker          D3D12_COMPARISON_FUNC_ALWAYS;
1568*61046927SAndroid Build Coastguard Worker    }
1569*61046927SAndroid Build Coastguard Worker    pipeline->zsa.depth_bounds.enable = in_zsa->depthBoundsTestEnable;
1570*61046927SAndroid Build Coastguard Worker    pipeline->zsa.depth_bounds.min = in_zsa->minDepthBounds;
1571*61046927SAndroid Build Coastguard Worker    pipeline->zsa.depth_bounds.max = in_zsa->maxDepthBounds;
1572*61046927SAndroid Build Coastguard Worker    desc.DepthBoundsTestEnable = in_zsa->depthBoundsTestEnable;
1573*61046927SAndroid Build Coastguard Worker    desc.StencilEnable = in_zsa->stencilTestEnable && !has_no_stencil;
1574*61046927SAndroid Build Coastguard Worker    if (desc.StencilEnable) {
1575*61046927SAndroid Build Coastguard Worker       desc.FrontFace.StencilFailOp = translate_stencil_op(in_zsa->front.failOp);
1576*61046927SAndroid Build Coastguard Worker       desc.FrontFace.StencilDepthFailOp = translate_stencil_op(in_zsa->front.depthFailOp);
1577*61046927SAndroid Build Coastguard Worker       desc.FrontFace.StencilPassOp = translate_stencil_op(in_zsa->front.passOp);
1578*61046927SAndroid Build Coastguard Worker       desc.FrontFace.StencilFunc = dzn_translate_compare_op(in_zsa->front.compareOp);
1579*61046927SAndroid Build Coastguard Worker       desc.BackFace.StencilFailOp = translate_stencil_op(in_zsa->back.failOp);
1580*61046927SAndroid Build Coastguard Worker       desc.BackFace.StencilDepthFailOp = translate_stencil_op(in_zsa->back.depthFailOp);
1581*61046927SAndroid Build Coastguard Worker       desc.BackFace.StencilPassOp = translate_stencil_op(in_zsa->back.passOp);
1582*61046927SAndroid Build Coastguard Worker       desc.BackFace.StencilFunc = dzn_translate_compare_op(in_zsa->back.compareOp);
1583*61046927SAndroid Build Coastguard Worker 
1584*61046927SAndroid Build Coastguard Worker       pipeline->zsa.stencil_test.enable = true;
1585*61046927SAndroid Build Coastguard Worker 
1586*61046927SAndroid Build Coastguard Worker       translate_stencil_test(pipeline, &desc, in);
1587*61046927SAndroid Build Coastguard Worker    }
1588*61046927SAndroid Build Coastguard Worker 
1589*61046927SAndroid Build Coastguard Worker    if (pdev->options14.IndependentFrontAndBackStencilRefMaskSupported) {
1590*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(out, DEPTH_STENCIL2, D3D12_DEPTH_STENCIL_DESC2, stream_desc);
1591*61046927SAndroid Build Coastguard Worker       pipeline->templates.desc_offsets.ds =
1592*61046927SAndroid Build Coastguard Worker          (uintptr_t)stream_desc - (uintptr_t)out->pPipelineStateSubobjectStream;
1593*61046927SAndroid Build Coastguard Worker       *stream_desc = desc;
1594*61046927SAndroid Build Coastguard Worker    } else {
1595*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(out, DEPTH_STENCIL1, D3D12_DEPTH_STENCIL_DESC1, stream_desc);
1596*61046927SAndroid Build Coastguard Worker       pipeline->templates.desc_offsets.ds =
1597*61046927SAndroid Build Coastguard Worker          (uintptr_t)stream_desc - (uintptr_t)out->pPipelineStateSubobjectStream;
1598*61046927SAndroid Build Coastguard Worker 
1599*61046927SAndroid Build Coastguard Worker       stream_desc->DepthEnable = desc.DepthEnable;
1600*61046927SAndroid Build Coastguard Worker       stream_desc->DepthWriteMask = desc.DepthWriteMask;
1601*61046927SAndroid Build Coastguard Worker       stream_desc->DepthFunc = desc.DepthFunc;
1602*61046927SAndroid Build Coastguard Worker       stream_desc->DepthBoundsTestEnable = desc.DepthBoundsTestEnable;
1603*61046927SAndroid Build Coastguard Worker       stream_desc->StencilEnable = desc.StencilEnable;
1604*61046927SAndroid Build Coastguard Worker       stream_desc->FrontFace.StencilFailOp = desc.FrontFace.StencilFailOp;
1605*61046927SAndroid Build Coastguard Worker       stream_desc->FrontFace.StencilDepthFailOp = desc.FrontFace.StencilDepthFailOp;
1606*61046927SAndroid Build Coastguard Worker       stream_desc->FrontFace.StencilPassOp = desc.FrontFace.StencilPassOp;
1607*61046927SAndroid Build Coastguard Worker       stream_desc->FrontFace.StencilFunc = desc.FrontFace.StencilFunc;
1608*61046927SAndroid Build Coastguard Worker       stream_desc->BackFace.StencilFailOp = desc.BackFace.StencilFailOp;
1609*61046927SAndroid Build Coastguard Worker       stream_desc->BackFace.StencilDepthFailOp = desc.BackFace.StencilDepthFailOp;
1610*61046927SAndroid Build Coastguard Worker       stream_desc->BackFace.StencilPassOp = desc.BackFace.StencilPassOp;
1611*61046927SAndroid Build Coastguard Worker       stream_desc->BackFace.StencilFunc = desc.BackFace.StencilFunc;
1612*61046927SAndroid Build Coastguard Worker 
1613*61046927SAndroid Build Coastguard Worker       /* No support for independent front/back, just pick front (if set, else back) */
1614*61046927SAndroid Build Coastguard Worker       stream_desc->StencilReadMask = desc.FrontFace.StencilReadMask ? desc.FrontFace.StencilReadMask : desc.BackFace.StencilReadMask;
1615*61046927SAndroid Build Coastguard Worker       stream_desc->StencilWriteMask = desc.FrontFace.StencilWriteMask ? desc.FrontFace.StencilWriteMask : desc.BackFace.StencilWriteMask;
1616*61046927SAndroid Build Coastguard Worker    }
1617*61046927SAndroid Build Coastguard Worker }
1618*61046927SAndroid Build Coastguard Worker 
1619*61046927SAndroid Build Coastguard Worker static D3D12_BLEND
translate_blend_factor(VkBlendFactor in,bool is_alpha,bool support_alpha_blend_factor)1620*61046927SAndroid Build Coastguard Worker translate_blend_factor(VkBlendFactor in, bool is_alpha, bool support_alpha_blend_factor)
1621*61046927SAndroid Build Coastguard Worker {
1622*61046927SAndroid Build Coastguard Worker    switch (in) {
1623*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ZERO: return D3D12_BLEND_ZERO;
1624*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ONE: return D3D12_BLEND_ONE;
1625*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_SRC_COLOR:
1626*61046927SAndroid Build Coastguard Worker       return is_alpha ? D3D12_BLEND_SRC_ALPHA : D3D12_BLEND_SRC_COLOR;
1627*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
1628*61046927SAndroid Build Coastguard Worker       return is_alpha ? D3D12_BLEND_INV_SRC_ALPHA : D3D12_BLEND_INV_SRC_COLOR;
1629*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_DST_COLOR:
1630*61046927SAndroid Build Coastguard Worker       return is_alpha ? D3D12_BLEND_DEST_ALPHA : D3D12_BLEND_DEST_COLOR;
1631*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
1632*61046927SAndroid Build Coastguard Worker       return is_alpha ? D3D12_BLEND_INV_DEST_ALPHA : D3D12_BLEND_INV_DEST_COLOR;
1633*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA;
1634*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA;
1635*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA;
1636*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA;
1637*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_CONSTANT_COLOR:
1638*61046927SAndroid Build Coastguard Worker       return is_alpha && support_alpha_blend_factor ? D3D12_BLEND_ALPHA_FACTOR : D3D12_BLEND_BLEND_FACTOR;
1639*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_CONSTANT_ALPHA:
1640*61046927SAndroid Build Coastguard Worker       return support_alpha_blend_factor ? D3D12_BLEND_ALPHA_FACTOR : D3D12_BLEND_BLEND_FACTOR;
1641*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
1642*61046927SAndroid Build Coastguard Worker       return is_alpha && support_alpha_blend_factor ? D3D12_BLEND_INV_ALPHA_FACTOR : D3D12_BLEND_INV_BLEND_FACTOR;
1643*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
1644*61046927SAndroid Build Coastguard Worker       return support_alpha_blend_factor ? D3D12_BLEND_INV_ALPHA_FACTOR : D3D12_BLEND_INV_BLEND_FACTOR;
1645*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_SRC1_COLOR:
1646*61046927SAndroid Build Coastguard Worker       return is_alpha ? D3D12_BLEND_SRC1_ALPHA : D3D12_BLEND_SRC1_COLOR;
1647*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
1648*61046927SAndroid Build Coastguard Worker       return is_alpha ? D3D12_BLEND_INV_SRC1_ALPHA : D3D12_BLEND_INV_SRC1_COLOR;
1649*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_SRC1_ALPHA: return D3D12_BLEND_SRC1_ALPHA;
1650*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: return D3D12_BLEND_INV_SRC1_ALPHA;
1651*61046927SAndroid Build Coastguard Worker    case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT;
1652*61046927SAndroid Build Coastguard Worker    default: unreachable("Invalid blend factor");
1653*61046927SAndroid Build Coastguard Worker    }
1654*61046927SAndroid Build Coastguard Worker }
1655*61046927SAndroid Build Coastguard Worker 
1656*61046927SAndroid Build Coastguard Worker static D3D12_BLEND_OP
translate_blend_op(VkBlendOp in)1657*61046927SAndroid Build Coastguard Worker translate_blend_op(VkBlendOp in)
1658*61046927SAndroid Build Coastguard Worker {
1659*61046927SAndroid Build Coastguard Worker    switch (in) {
1660*61046927SAndroid Build Coastguard Worker    case VK_BLEND_OP_ADD: return D3D12_BLEND_OP_ADD;
1661*61046927SAndroid Build Coastguard Worker    case VK_BLEND_OP_SUBTRACT: return D3D12_BLEND_OP_SUBTRACT;
1662*61046927SAndroid Build Coastguard Worker    case VK_BLEND_OP_REVERSE_SUBTRACT: return D3D12_BLEND_OP_REV_SUBTRACT;
1663*61046927SAndroid Build Coastguard Worker    case VK_BLEND_OP_MIN: return D3D12_BLEND_OP_MIN;
1664*61046927SAndroid Build Coastguard Worker    case VK_BLEND_OP_MAX: return D3D12_BLEND_OP_MAX;
1665*61046927SAndroid Build Coastguard Worker    default: unreachable("Invalid blend op");
1666*61046927SAndroid Build Coastguard Worker    }
1667*61046927SAndroid Build Coastguard Worker }
1668*61046927SAndroid Build Coastguard Worker 
1669*61046927SAndroid Build Coastguard Worker static D3D12_LOGIC_OP
translate_logic_op(VkLogicOp in)1670*61046927SAndroid Build Coastguard Worker translate_logic_op(VkLogicOp in)
1671*61046927SAndroid Build Coastguard Worker {
1672*61046927SAndroid Build Coastguard Worker    switch (in) {
1673*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_CLEAR: return D3D12_LOGIC_OP_CLEAR;
1674*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_AND: return D3D12_LOGIC_OP_AND;
1675*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_AND_REVERSE: return D3D12_LOGIC_OP_AND_REVERSE;
1676*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_COPY: return D3D12_LOGIC_OP_COPY;
1677*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_AND_INVERTED: return D3D12_LOGIC_OP_AND_INVERTED;
1678*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_NO_OP: return D3D12_LOGIC_OP_NOOP;
1679*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_XOR: return D3D12_LOGIC_OP_XOR;
1680*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_OR: return D3D12_LOGIC_OP_OR;
1681*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_NOR: return D3D12_LOGIC_OP_NOR;
1682*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_EQUIVALENT: return D3D12_LOGIC_OP_EQUIV;
1683*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_INVERT: return D3D12_LOGIC_OP_INVERT;
1684*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_OR_REVERSE: return D3D12_LOGIC_OP_OR_REVERSE;
1685*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_COPY_INVERTED: return D3D12_LOGIC_OP_COPY_INVERTED;
1686*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_OR_INVERTED: return D3D12_LOGIC_OP_OR_INVERTED;
1687*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_NAND: return D3D12_LOGIC_OP_NAND;
1688*61046927SAndroid Build Coastguard Worker    case VK_LOGIC_OP_SET: return D3D12_LOGIC_OP_SET;
1689*61046927SAndroid Build Coastguard Worker    default: unreachable("Invalid logic op");
1690*61046927SAndroid Build Coastguard Worker    }
1691*61046927SAndroid Build Coastguard Worker }
1692*61046927SAndroid Build Coastguard Worker 
1693*61046927SAndroid Build Coastguard Worker static void
dzn_graphics_pipeline_translate_blend(struct dzn_graphics_pipeline * pipeline,D3D12_PIPELINE_STATE_STREAM_DESC * out,const VkGraphicsPipelineCreateInfo * in)1694*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_translate_blend(struct dzn_graphics_pipeline *pipeline,
1695*61046927SAndroid Build Coastguard Worker                                       D3D12_PIPELINE_STATE_STREAM_DESC *out,
1696*61046927SAndroid Build Coastguard Worker                                       const VkGraphicsPipelineCreateInfo *in)
1697*61046927SAndroid Build Coastguard Worker {
1698*61046927SAndroid Build Coastguard Worker    const VkPipelineRasterizationStateCreateInfo *in_rast =
1699*61046927SAndroid Build Coastguard Worker       in->pRasterizationState;
1700*61046927SAndroid Build Coastguard Worker    const VkPipelineColorBlendStateCreateInfo *in_blend =
1701*61046927SAndroid Build Coastguard Worker       in_rast->rasterizerDiscardEnable ? NULL : in->pColorBlendState;
1702*61046927SAndroid Build Coastguard Worker    const VkPipelineMultisampleStateCreateInfo *in_ms =
1703*61046927SAndroid Build Coastguard Worker       in_rast->rasterizerDiscardEnable ? NULL : in->pMultisampleState;
1704*61046927SAndroid Build Coastguard Worker 
1705*61046927SAndroid Build Coastguard Worker    if (!in_blend || !in_ms)
1706*61046927SAndroid Build Coastguard Worker       return;
1707*61046927SAndroid Build Coastguard Worker 
1708*61046927SAndroid Build Coastguard Worker    struct dzn_device *device =
1709*61046927SAndroid Build Coastguard Worker       container_of(pipeline->base.base.device, struct dzn_device, vk);
1710*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev =
1711*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical, struct dzn_physical_device, vk);
1712*61046927SAndroid Build Coastguard Worker    bool support_alpha_blend_factor = pdev->options13.AlphaBlendFactorSupported;
1713*61046927SAndroid Build Coastguard Worker 
1714*61046927SAndroid Build Coastguard Worker    d3d12_gfx_pipeline_state_stream_new_desc(out, BLEND, D3D12_BLEND_DESC, desc);
1715*61046927SAndroid Build Coastguard Worker    D3D12_LOGIC_OP logicop =
1716*61046927SAndroid Build Coastguard Worker       in_blend->logicOpEnable ?
1717*61046927SAndroid Build Coastguard Worker       translate_logic_op(in_blend->logicOp) : D3D12_LOGIC_OP_NOOP;
1718*61046927SAndroid Build Coastguard Worker    desc->AlphaToCoverageEnable = in_ms->alphaToCoverageEnable;
1719*61046927SAndroid Build Coastguard Worker    memcpy(pipeline->blend.constants, in_blend->blendConstants,
1720*61046927SAndroid Build Coastguard Worker           sizeof(pipeline->blend.constants));
1721*61046927SAndroid Build Coastguard Worker 
1722*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < in_blend->attachmentCount; i++) {
1723*61046927SAndroid Build Coastguard Worker       if (i > 0 &&
1724*61046927SAndroid Build Coastguard Worker           memcmp(&in_blend->pAttachments[i - 1], &in_blend->pAttachments[i],
1725*61046927SAndroid Build Coastguard Worker                  sizeof(*in_blend->pAttachments)) != 0)
1726*61046927SAndroid Build Coastguard Worker          desc->IndependentBlendEnable = true;
1727*61046927SAndroid Build Coastguard Worker 
1728*61046927SAndroid Build Coastguard Worker       desc->RenderTarget[i].BlendEnable =
1729*61046927SAndroid Build Coastguard Worker          in_blend->pAttachments[i].blendEnable;
1730*61046927SAndroid Build Coastguard Worker       desc->RenderTarget[i].RenderTargetWriteMask =
1731*61046927SAndroid Build Coastguard Worker          in_blend->pAttachments[i].colorWriteMask;
1732*61046927SAndroid Build Coastguard Worker 
1733*61046927SAndroid Build Coastguard Worker       if (in_blend->logicOpEnable) {
1734*61046927SAndroid Build Coastguard Worker          desc->RenderTarget[i].LogicOpEnable = true;
1735*61046927SAndroid Build Coastguard Worker          desc->RenderTarget[i].LogicOp = logicop;
1736*61046927SAndroid Build Coastguard Worker       } else {
1737*61046927SAndroid Build Coastguard Worker          desc->RenderTarget[i].SrcBlend =
1738*61046927SAndroid Build Coastguard Worker             translate_blend_factor(in_blend->pAttachments[i].srcColorBlendFactor, false, support_alpha_blend_factor);
1739*61046927SAndroid Build Coastguard Worker          desc->RenderTarget[i].DestBlend =
1740*61046927SAndroid Build Coastguard Worker             translate_blend_factor(in_blend->pAttachments[i].dstColorBlendFactor, false, support_alpha_blend_factor);
1741*61046927SAndroid Build Coastguard Worker          desc->RenderTarget[i].BlendOp =
1742*61046927SAndroid Build Coastguard Worker             translate_blend_op(in_blend->pAttachments[i].colorBlendOp);
1743*61046927SAndroid Build Coastguard Worker          desc->RenderTarget[i].SrcBlendAlpha =
1744*61046927SAndroid Build Coastguard Worker             translate_blend_factor(in_blend->pAttachments[i].srcAlphaBlendFactor, true, support_alpha_blend_factor);
1745*61046927SAndroid Build Coastguard Worker          desc->RenderTarget[i].DestBlendAlpha =
1746*61046927SAndroid Build Coastguard Worker             translate_blend_factor(in_blend->pAttachments[i].dstAlphaBlendFactor, true, support_alpha_blend_factor);
1747*61046927SAndroid Build Coastguard Worker          desc->RenderTarget[i].BlendOpAlpha =
1748*61046927SAndroid Build Coastguard Worker             translate_blend_op(in_blend->pAttachments[i].alphaBlendOp);
1749*61046927SAndroid Build Coastguard Worker       }
1750*61046927SAndroid Build Coastguard Worker    }
1751*61046927SAndroid Build Coastguard Worker }
1752*61046927SAndroid Build Coastguard Worker 
1753*61046927SAndroid Build Coastguard Worker 
1754*61046927SAndroid Build Coastguard Worker static void
dzn_pipeline_init(struct dzn_pipeline * pipeline,struct dzn_device * device,VkPipelineBindPoint type,VkPipelineCreateFlags2KHR flags,struct dzn_pipeline_layout * layout,D3D12_PIPELINE_STATE_STREAM_DESC * stream_desc)1755*61046927SAndroid Build Coastguard Worker dzn_pipeline_init(struct dzn_pipeline *pipeline,
1756*61046927SAndroid Build Coastguard Worker                   struct dzn_device *device,
1757*61046927SAndroid Build Coastguard Worker                   VkPipelineBindPoint type,
1758*61046927SAndroid Build Coastguard Worker                   VkPipelineCreateFlags2KHR flags,
1759*61046927SAndroid Build Coastguard Worker                   struct dzn_pipeline_layout *layout,
1760*61046927SAndroid Build Coastguard Worker                   D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc)
1761*61046927SAndroid Build Coastguard Worker {
1762*61046927SAndroid Build Coastguard Worker    pipeline->type = type;
1763*61046927SAndroid Build Coastguard Worker    pipeline->flags = flags;
1764*61046927SAndroid Build Coastguard Worker    pipeline->root.sets_param_count = layout->root.sets_param_count;
1765*61046927SAndroid Build Coastguard Worker    pipeline->root.sysval_cbv_param_idx = layout->root.sysval_cbv_param_idx;
1766*61046927SAndroid Build Coastguard Worker    pipeline->root.push_constant_cbv_param_idx = layout->root.push_constant_cbv_param_idx;
1767*61046927SAndroid Build Coastguard Worker    pipeline->root.dynamic_buffer_bindless_param_idx = layout->root.dynamic_buffer_bindless_param_idx;
1768*61046927SAndroid Build Coastguard Worker    STATIC_ASSERT(sizeof(pipeline->root.type) == sizeof(layout->root.type));
1769*61046927SAndroid Build Coastguard Worker    memcpy(pipeline->root.type, layout->root.type, sizeof(pipeline->root.type));
1770*61046927SAndroid Build Coastguard Worker    pipeline->root.sig = layout->root.sig;
1771*61046927SAndroid Build Coastguard Worker    ID3D12RootSignature_AddRef(pipeline->root.sig);
1772*61046927SAndroid Build Coastguard Worker 
1773*61046927SAndroid Build Coastguard Worker    STATIC_ASSERT(sizeof(layout->desc_count) == sizeof(pipeline->desc_count));
1774*61046927SAndroid Build Coastguard Worker    memcpy(pipeline->desc_count, layout->desc_count, sizeof(pipeline->desc_count));
1775*61046927SAndroid Build Coastguard Worker 
1776*61046927SAndroid Build Coastguard Worker    STATIC_ASSERT(sizeof(layout->sets) == sizeof(pipeline->sets));
1777*61046927SAndroid Build Coastguard Worker    memcpy(pipeline->sets, layout->sets, sizeof(pipeline->sets));
1778*61046927SAndroid Build Coastguard Worker    pipeline->set_count = layout->set_count;
1779*61046927SAndroid Build Coastguard Worker    pipeline->dynamic_buffer_count = layout->dynamic_buffer_count;
1780*61046927SAndroid Build Coastguard Worker    vk_object_base_init(&device->vk, &pipeline->base, VK_OBJECT_TYPE_PIPELINE);
1781*61046927SAndroid Build Coastguard Worker 
1782*61046927SAndroid Build Coastguard Worker    ASSERTED uint32_t max_streamsz =
1783*61046927SAndroid Build Coastguard Worker       type == VK_PIPELINE_BIND_POINT_GRAPHICS ?
1784*61046927SAndroid Build Coastguard Worker       MAX_GFX_PIPELINE_STATE_STREAM_SIZE :
1785*61046927SAndroid Build Coastguard Worker       MAX_COMPUTE_PIPELINE_STATE_STREAM_SIZE;
1786*61046927SAndroid Build Coastguard Worker 
1787*61046927SAndroid Build Coastguard Worker    d3d12_pipeline_state_stream_new_desc_abbrev(stream_desc, max_streamsz, ROOT_SIGNATURE,
1788*61046927SAndroid Build Coastguard Worker                                                ID3D12RootSignature *, root_sig);
1789*61046927SAndroid Build Coastguard Worker    *root_sig = pipeline->root.sig;
1790*61046927SAndroid Build Coastguard Worker }
1791*61046927SAndroid Build Coastguard Worker 
1792*61046927SAndroid Build Coastguard Worker static void
dzn_pipeline_finish(struct dzn_pipeline * pipeline)1793*61046927SAndroid Build Coastguard Worker dzn_pipeline_finish(struct dzn_pipeline *pipeline)
1794*61046927SAndroid Build Coastguard Worker {
1795*61046927SAndroid Build Coastguard Worker    if (pipeline->state)
1796*61046927SAndroid Build Coastguard Worker       ID3D12PipelineState_Release(pipeline->state);
1797*61046927SAndroid Build Coastguard Worker    if (pipeline->root.sig)
1798*61046927SAndroid Build Coastguard Worker       ID3D12RootSignature_Release(pipeline->root.sig);
1799*61046927SAndroid Build Coastguard Worker 
1800*61046927SAndroid Build Coastguard Worker    vk_object_base_finish(&pipeline->base);
1801*61046927SAndroid Build Coastguard Worker }
1802*61046927SAndroid Build Coastguard Worker 
dzn_graphics_pipeline_delete_variant(struct hash_entry * he)1803*61046927SAndroid Build Coastguard Worker static void dzn_graphics_pipeline_delete_variant(struct hash_entry *he)
1804*61046927SAndroid Build Coastguard Worker {
1805*61046927SAndroid Build Coastguard Worker    struct dzn_graphics_pipeline_variant *variant = he->data;
1806*61046927SAndroid Build Coastguard Worker 
1807*61046927SAndroid Build Coastguard Worker    if (variant->state)
1808*61046927SAndroid Build Coastguard Worker       ID3D12PipelineState_Release(variant->state);
1809*61046927SAndroid Build Coastguard Worker }
1810*61046927SAndroid Build Coastguard Worker 
dzn_graphics_pipeline_delete_cmd_sig(struct hash_entry * he)1811*61046927SAndroid Build Coastguard Worker static void dzn_graphics_pipeline_delete_cmd_sig(struct hash_entry *he)
1812*61046927SAndroid Build Coastguard Worker {
1813*61046927SAndroid Build Coastguard Worker    ID3D12CommandSignature_Release((ID3D12CommandSignature *)he->data);
1814*61046927SAndroid Build Coastguard Worker }
1815*61046927SAndroid Build Coastguard Worker 
1816*61046927SAndroid Build Coastguard Worker static void
dzn_graphics_pipeline_cleanup_nir_shaders(struct dzn_graphics_pipeline * pipeline)1817*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_cleanup_nir_shaders(struct dzn_graphics_pipeline *pipeline)
1818*61046927SAndroid Build Coastguard Worker {
1819*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->templates.shaders); i++) {
1820*61046927SAndroid Build Coastguard Worker       ralloc_free(pipeline->templates.shaders[i].nir);
1821*61046927SAndroid Build Coastguard Worker       pipeline->templates.shaders[i].nir = NULL;
1822*61046927SAndroid Build Coastguard Worker    }
1823*61046927SAndroid Build Coastguard Worker }
1824*61046927SAndroid Build Coastguard Worker 
1825*61046927SAndroid Build Coastguard Worker static void
dzn_graphics_pipeline_cleanup_dxil_shaders(struct dzn_graphics_pipeline * pipeline)1826*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_cleanup_dxil_shaders(struct dzn_graphics_pipeline *pipeline)
1827*61046927SAndroid Build Coastguard Worker {
1828*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->templates.shaders); i++) {
1829*61046927SAndroid Build Coastguard Worker       if (pipeline->templates.shaders[i].bc) {
1830*61046927SAndroid Build Coastguard Worker          free((void *)pipeline->templates.shaders[i].bc->pShaderBytecode);
1831*61046927SAndroid Build Coastguard Worker          pipeline->templates.shaders[i].bc = NULL;
1832*61046927SAndroid Build Coastguard Worker       }
1833*61046927SAndroid Build Coastguard Worker    }
1834*61046927SAndroid Build Coastguard Worker }
1835*61046927SAndroid Build Coastguard Worker 
1836*61046927SAndroid Build Coastguard Worker static void
dzn_graphics_pipeline_destroy(struct dzn_graphics_pipeline * pipeline,const VkAllocationCallbacks * alloc)1837*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_destroy(struct dzn_graphics_pipeline *pipeline,
1838*61046927SAndroid Build Coastguard Worker                               const VkAllocationCallbacks *alloc)
1839*61046927SAndroid Build Coastguard Worker {
1840*61046927SAndroid Build Coastguard Worker    if (!pipeline)
1841*61046927SAndroid Build Coastguard Worker       return;
1842*61046927SAndroid Build Coastguard Worker 
1843*61046927SAndroid Build Coastguard Worker    _mesa_hash_table_destroy(pipeline->variants,
1844*61046927SAndroid Build Coastguard Worker                             dzn_graphics_pipeline_delete_variant);
1845*61046927SAndroid Build Coastguard Worker 
1846*61046927SAndroid Build Coastguard Worker    dzn_graphics_pipeline_cleanup_nir_shaders(pipeline);
1847*61046927SAndroid Build Coastguard Worker    dzn_graphics_pipeline_cleanup_dxil_shaders(pipeline);
1848*61046927SAndroid Build Coastguard Worker 
1849*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->indirect_cmd_sigs); i++) {
1850*61046927SAndroid Build Coastguard Worker       if (pipeline->indirect_cmd_sigs[i])
1851*61046927SAndroid Build Coastguard Worker          ID3D12CommandSignature_Release(pipeline->indirect_cmd_sigs[i]);
1852*61046927SAndroid Build Coastguard Worker    }
1853*61046927SAndroid Build Coastguard Worker    _mesa_hash_table_destroy(pipeline->custom_stride_cmd_sigs,
1854*61046927SAndroid Build Coastguard Worker                             dzn_graphics_pipeline_delete_cmd_sig);
1855*61046927SAndroid Build Coastguard Worker 
1856*61046927SAndroid Build Coastguard Worker    dzn_pipeline_finish(&pipeline->base);
1857*61046927SAndroid Build Coastguard Worker    vk_free2(&pipeline->base.base.device->alloc, alloc, pipeline);
1858*61046927SAndroid Build Coastguard Worker }
1859*61046927SAndroid Build Coastguard Worker 
1860*61046927SAndroid Build Coastguard Worker static VkResult
dzn_graphics_pipeline_create(struct dzn_device * device,VkPipelineCache cache,const VkGraphicsPipelineCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipeline * out)1861*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_create(struct dzn_device *device,
1862*61046927SAndroid Build Coastguard Worker                              VkPipelineCache cache,
1863*61046927SAndroid Build Coastguard Worker                              const VkGraphicsPipelineCreateInfo *pCreateInfo,
1864*61046927SAndroid Build Coastguard Worker                              const VkAllocationCallbacks *pAllocator,
1865*61046927SAndroid Build Coastguard Worker                              VkPipeline *out)
1866*61046927SAndroid Build Coastguard Worker {
1867*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev =
1868*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical, struct dzn_physical_device, vk);
1869*61046927SAndroid Build Coastguard Worker    const VkPipelineRenderingCreateInfo *ri = (const VkPipelineRenderingCreateInfo *)
1870*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo, PIPELINE_RENDERING_CREATE_INFO);
1871*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline_cache, pcache, cache);
1872*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_render_pass, pass, pCreateInfo->renderPass);
1873*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(dzn_pipeline_layout, layout, pCreateInfo->layout);
1874*61046927SAndroid Build Coastguard Worker    uint32_t color_count = 0;
1875*61046927SAndroid Build Coastguard Worker    VkFormat color_fmts[MAX_RTS] = { 0 };
1876*61046927SAndroid Build Coastguard Worker    VkFormat zs_fmt = VK_FORMAT_UNDEFINED;
1877*61046927SAndroid Build Coastguard Worker    VkResult ret;
1878*61046927SAndroid Build Coastguard Worker    HRESULT hres = 0;
1879*61046927SAndroid Build Coastguard Worker    D3D12_VIEW_INSTANCE_LOCATION vi_locs[D3D12_MAX_VIEW_INSTANCE_COUNT];
1880*61046927SAndroid Build Coastguard Worker 
1881*61046927SAndroid Build Coastguard Worker    struct dzn_graphics_pipeline *pipeline =
1882*61046927SAndroid Build Coastguard Worker       vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8,
1883*61046927SAndroid Build Coastguard Worker                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1884*61046927SAndroid Build Coastguard Worker    if (!pipeline)
1885*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1886*61046927SAndroid Build Coastguard Worker 
1887*61046927SAndroid Build Coastguard Worker    D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc = &pipeline->templates.stream_desc;
1888*61046927SAndroid Build Coastguard Worker    stream_desc->pPipelineStateSubobjectStream = pipeline->templates.stream_buf;
1889*61046927SAndroid Build Coastguard Worker 
1890*61046927SAndroid Build Coastguard Worker    dzn_pipeline_init(&pipeline->base, device,
1891*61046927SAndroid Build Coastguard Worker                      VK_PIPELINE_BIND_POINT_GRAPHICS,
1892*61046927SAndroid Build Coastguard Worker                      vk_graphics_pipeline_create_flags(pCreateInfo),
1893*61046927SAndroid Build Coastguard Worker                      layout, stream_desc);
1894*61046927SAndroid Build Coastguard Worker    D3D12_INPUT_ELEMENT_DESC attribs[MAX_VERTEX_GENERIC_ATTRIBS] = { 0 };
1895*61046927SAndroid Build Coastguard Worker    enum pipe_format vi_conversions[MAX_VERTEX_GENERIC_ATTRIBS] = { 0 };
1896*61046927SAndroid Build Coastguard Worker 
1897*61046927SAndroid Build Coastguard Worker    ret = dzn_graphics_pipeline_translate_vi(pipeline, pCreateInfo,
1898*61046927SAndroid Build Coastguard Worker                                             attribs, vi_conversions);
1899*61046927SAndroid Build Coastguard Worker    if (ret != VK_SUCCESS)
1900*61046927SAndroid Build Coastguard Worker       goto out;
1901*61046927SAndroid Build Coastguard Worker 
1902*61046927SAndroid Build Coastguard Worker    d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, FLAGS, D3D12_PIPELINE_STATE_FLAGS, flags);
1903*61046927SAndroid Build Coastguard Worker    *flags = D3D12_PIPELINE_STATE_FLAG_NONE;
1904*61046927SAndroid Build Coastguard Worker 
1905*61046927SAndroid Build Coastguard Worker    if (pCreateInfo->pDynamicState) {
1906*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < pCreateInfo->pDynamicState->dynamicStateCount; i++) {
1907*61046927SAndroid Build Coastguard Worker          switch (pCreateInfo->pDynamicState->pDynamicStates[i]) {
1908*61046927SAndroid Build Coastguard Worker          case VK_DYNAMIC_STATE_VIEWPORT:
1909*61046927SAndroid Build Coastguard Worker             pipeline->vp.dynamic = true;
1910*61046927SAndroid Build Coastguard Worker             break;
1911*61046927SAndroid Build Coastguard Worker          case VK_DYNAMIC_STATE_SCISSOR:
1912*61046927SAndroid Build Coastguard Worker             pipeline->scissor.dynamic = true;
1913*61046927SAndroid Build Coastguard Worker             break;
1914*61046927SAndroid Build Coastguard Worker          case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
1915*61046927SAndroid Build Coastguard Worker             pipeline->zsa.stencil_test.dynamic_ref = true;
1916*61046927SAndroid Build Coastguard Worker             break;
1917*61046927SAndroid Build Coastguard Worker          case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
1918*61046927SAndroid Build Coastguard Worker             pipeline->zsa.stencil_test.dynamic_compare_mask = true;
1919*61046927SAndroid Build Coastguard Worker             ret = dzn_graphics_pipeline_prepare_for_variants(device, pipeline);
1920*61046927SAndroid Build Coastguard Worker             if (ret)
1921*61046927SAndroid Build Coastguard Worker                goto out;
1922*61046927SAndroid Build Coastguard Worker             break;
1923*61046927SAndroid Build Coastguard Worker          case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
1924*61046927SAndroid Build Coastguard Worker             pipeline->zsa.stencil_test.dynamic_write_mask = true;
1925*61046927SAndroid Build Coastguard Worker             ret = dzn_graphics_pipeline_prepare_for_variants(device, pipeline);
1926*61046927SAndroid Build Coastguard Worker             if (ret)
1927*61046927SAndroid Build Coastguard Worker                goto out;
1928*61046927SAndroid Build Coastguard Worker             break;
1929*61046927SAndroid Build Coastguard Worker          case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
1930*61046927SAndroid Build Coastguard Worker             pipeline->blend.dynamic_constants = true;
1931*61046927SAndroid Build Coastguard Worker             break;
1932*61046927SAndroid Build Coastguard Worker          case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
1933*61046927SAndroid Build Coastguard Worker             pipeline->zsa.depth_bounds.dynamic = true;
1934*61046927SAndroid Build Coastguard Worker             break;
1935*61046927SAndroid Build Coastguard Worker          case VK_DYNAMIC_STATE_DEPTH_BIAS:
1936*61046927SAndroid Build Coastguard Worker             pipeline->zsa.dynamic_depth_bias = true;
1937*61046927SAndroid Build Coastguard Worker             if (pdev->options16.DynamicDepthBiasSupported) {
1938*61046927SAndroid Build Coastguard Worker                *flags |= D3D12_PIPELINE_STATE_FLAG_DYNAMIC_DEPTH_BIAS;
1939*61046927SAndroid Build Coastguard Worker             } else {
1940*61046927SAndroid Build Coastguard Worker                ret = dzn_graphics_pipeline_prepare_for_variants(device, pipeline);
1941*61046927SAndroid Build Coastguard Worker                if (ret)
1942*61046927SAndroid Build Coastguard Worker                   goto out;
1943*61046927SAndroid Build Coastguard Worker             }
1944*61046927SAndroid Build Coastguard Worker             break;
1945*61046927SAndroid Build Coastguard Worker          case VK_DYNAMIC_STATE_LINE_WIDTH:
1946*61046927SAndroid Build Coastguard Worker             /* Nothing to do since we just support lineWidth = 1. */
1947*61046927SAndroid Build Coastguard Worker             break;
1948*61046927SAndroid Build Coastguard Worker          default: unreachable("Unsupported dynamic state");
1949*61046927SAndroid Build Coastguard Worker          }
1950*61046927SAndroid Build Coastguard Worker       }
1951*61046927SAndroid Build Coastguard Worker    }
1952*61046927SAndroid Build Coastguard Worker 
1953*61046927SAndroid Build Coastguard Worker    ret = dzn_graphics_pipeline_translate_ia(device, pipeline, stream_desc, pCreateInfo);
1954*61046927SAndroid Build Coastguard Worker    if (ret)
1955*61046927SAndroid Build Coastguard Worker       goto out;
1956*61046927SAndroid Build Coastguard Worker 
1957*61046927SAndroid Build Coastguard Worker    dzn_graphics_pipeline_translate_rast(device, pipeline, stream_desc, pCreateInfo);
1958*61046927SAndroid Build Coastguard Worker    dzn_graphics_pipeline_translate_ms(pipeline, stream_desc, pCreateInfo);
1959*61046927SAndroid Build Coastguard Worker    dzn_graphics_pipeline_translate_zsa(device, pipeline, stream_desc, pCreateInfo);
1960*61046927SAndroid Build Coastguard Worker    dzn_graphics_pipeline_translate_blend(pipeline, stream_desc, pCreateInfo);
1961*61046927SAndroid Build Coastguard Worker 
1962*61046927SAndroid Build Coastguard Worker    unsigned view_mask = 0;
1963*61046927SAndroid Build Coastguard Worker    if (pass) {
1964*61046927SAndroid Build Coastguard Worker       const struct vk_subpass *subpass = &pass->subpasses[pCreateInfo->subpass];
1965*61046927SAndroid Build Coastguard Worker       color_count = subpass->color_count;
1966*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < subpass->color_count; i++) {
1967*61046927SAndroid Build Coastguard Worker          uint32_t idx = subpass->color_attachments[i].attachment;
1968*61046927SAndroid Build Coastguard Worker 
1969*61046927SAndroid Build Coastguard Worker          if (idx == VK_ATTACHMENT_UNUSED) continue;
1970*61046927SAndroid Build Coastguard Worker 
1971*61046927SAndroid Build Coastguard Worker          const struct vk_render_pass_attachment *attachment =
1972*61046927SAndroid Build Coastguard Worker             &pass->attachments[idx];
1973*61046927SAndroid Build Coastguard Worker 
1974*61046927SAndroid Build Coastguard Worker          color_fmts[i] = attachment->format;
1975*61046927SAndroid Build Coastguard Worker       }
1976*61046927SAndroid Build Coastguard Worker 
1977*61046927SAndroid Build Coastguard Worker       if (subpass->depth_stencil_attachment &&
1978*61046927SAndroid Build Coastguard Worker           subpass->depth_stencil_attachment->attachment != VK_ATTACHMENT_UNUSED) {
1979*61046927SAndroid Build Coastguard Worker          const struct vk_render_pass_attachment *attachment =
1980*61046927SAndroid Build Coastguard Worker             &pass->attachments[subpass->depth_stencil_attachment->attachment];
1981*61046927SAndroid Build Coastguard Worker 
1982*61046927SAndroid Build Coastguard Worker          zs_fmt = attachment->format;
1983*61046927SAndroid Build Coastguard Worker       }
1984*61046927SAndroid Build Coastguard Worker 
1985*61046927SAndroid Build Coastguard Worker       view_mask = subpass->view_mask;
1986*61046927SAndroid Build Coastguard Worker    } else if (ri) {
1987*61046927SAndroid Build Coastguard Worker       color_count = ri->colorAttachmentCount;
1988*61046927SAndroid Build Coastguard Worker       memcpy(color_fmts, ri->pColorAttachmentFormats,
1989*61046927SAndroid Build Coastguard Worker              sizeof(color_fmts[0]) * color_count);
1990*61046927SAndroid Build Coastguard Worker       if (ri->depthAttachmentFormat != VK_FORMAT_UNDEFINED)
1991*61046927SAndroid Build Coastguard Worker          zs_fmt = ri->depthAttachmentFormat;
1992*61046927SAndroid Build Coastguard Worker       else if (ri->stencilAttachmentFormat != VK_FORMAT_UNDEFINED)
1993*61046927SAndroid Build Coastguard Worker          zs_fmt = ri->stencilAttachmentFormat;
1994*61046927SAndroid Build Coastguard Worker 
1995*61046927SAndroid Build Coastguard Worker       view_mask = ri->viewMask;
1996*61046927SAndroid Build Coastguard Worker    }
1997*61046927SAndroid Build Coastguard Worker 
1998*61046927SAndroid Build Coastguard Worker    if (color_count > 0) {
1999*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, RENDER_TARGET_FORMATS, struct D3D12_RT_FORMAT_ARRAY, rts);
2000*61046927SAndroid Build Coastguard Worker       rts->NumRenderTargets = color_count;
2001*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < color_count; i++) {
2002*61046927SAndroid Build Coastguard Worker          rts->RTFormats[i] =
2003*61046927SAndroid Build Coastguard Worker             dzn_image_get_dxgi_format(pdev, color_fmts[i],
2004*61046927SAndroid Build Coastguard Worker                                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
2005*61046927SAndroid Build Coastguard Worker                                       VK_IMAGE_ASPECT_COLOR_BIT);
2006*61046927SAndroid Build Coastguard Worker       }
2007*61046927SAndroid Build Coastguard Worker    }
2008*61046927SAndroid Build Coastguard Worker 
2009*61046927SAndroid Build Coastguard Worker    if (zs_fmt != VK_FORMAT_UNDEFINED) {
2010*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, DEPTH_STENCIL_FORMAT, DXGI_FORMAT, ds_fmt);
2011*61046927SAndroid Build Coastguard Worker       *ds_fmt =
2012*61046927SAndroid Build Coastguard Worker          dzn_image_get_dxgi_format(pdev, zs_fmt,
2013*61046927SAndroid Build Coastguard Worker                                    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
2014*61046927SAndroid Build Coastguard Worker                                    VK_IMAGE_ASPECT_DEPTH_BIT |
2015*61046927SAndroid Build Coastguard Worker                                    VK_IMAGE_ASPECT_STENCIL_BIT);
2016*61046927SAndroid Build Coastguard Worker       pipeline->zsa.ds_fmt = *ds_fmt;
2017*61046927SAndroid Build Coastguard Worker    }
2018*61046927SAndroid Build Coastguard Worker 
2019*61046927SAndroid Build Coastguard Worker    pipeline->multiview.view_mask = MAX2(view_mask, 1);
2020*61046927SAndroid Build Coastguard Worker    if (view_mask != 0 && /* Is multiview */
2021*61046927SAndroid Build Coastguard Worker        view_mask != 1 && /* Is non-trivially multiview */
2022*61046927SAndroid Build Coastguard Worker        (view_mask & ~((1 << D3D12_MAX_VIEW_INSTANCE_COUNT) - 1)) == 0 && /* Uses only views 0 thru 3 */
2023*61046927SAndroid Build Coastguard Worker        pdev->options3.ViewInstancingTier > D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED /* Actually supported */) {
2024*61046927SAndroid Build Coastguard Worker       d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, VIEW_INSTANCING, D3D12_VIEW_INSTANCING_DESC, vi);
2025*61046927SAndroid Build Coastguard Worker       vi->pViewInstanceLocations = vi_locs;
2026*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < D3D12_MAX_VIEW_INSTANCE_COUNT; ++i) {
2027*61046927SAndroid Build Coastguard Worker          vi_locs[i].RenderTargetArrayIndex = i;
2028*61046927SAndroid Build Coastguard Worker          vi_locs[i].ViewportArrayIndex = 0;
2029*61046927SAndroid Build Coastguard Worker          if (view_mask & (1 << i))
2030*61046927SAndroid Build Coastguard Worker             vi->ViewInstanceCount = i + 1;
2031*61046927SAndroid Build Coastguard Worker       }
2032*61046927SAndroid Build Coastguard Worker       vi->Flags = D3D12_VIEW_INSTANCING_FLAG_ENABLE_VIEW_INSTANCE_MASKING;
2033*61046927SAndroid Build Coastguard Worker       pipeline->multiview.native_view_instancing = true;
2034*61046927SAndroid Build Coastguard Worker    }
2035*61046927SAndroid Build Coastguard Worker 
2036*61046927SAndroid Build Coastguard Worker    ret = dzn_graphics_pipeline_compile_shaders(device, pipeline, pcache,
2037*61046927SAndroid Build Coastguard Worker                                                layout, stream_desc,
2038*61046927SAndroid Build Coastguard Worker                                                attribs, vi_conversions,
2039*61046927SAndroid Build Coastguard Worker                                                pCreateInfo);
2040*61046927SAndroid Build Coastguard Worker    if (ret != VK_SUCCESS)
2041*61046927SAndroid Build Coastguard Worker       goto out;
2042*61046927SAndroid Build Coastguard Worker 
2043*61046927SAndroid Build Coastguard Worker    /* If we have no position output from a pre-rasterizer stage, we need to make sure that
2044*61046927SAndroid Build Coastguard Worker     * depth is disabled, to fully disable the rasterizer. We can only know this after compiling
2045*61046927SAndroid Build Coastguard Worker     * or loading the shaders.
2046*61046927SAndroid Build Coastguard Worker     */
2047*61046927SAndroid Build Coastguard Worker    if (pipeline->rast_disabled_from_missing_position) {
2048*61046927SAndroid Build Coastguard Worker       if (pdev->options14.IndependentFrontAndBackStencilRefMaskSupported) {
2049*61046927SAndroid Build Coastguard Worker          D3D12_DEPTH_STENCIL_DESC2 *ds = dzn_graphics_pipeline_get_desc(pipeline, pipeline->templates.stream_buf, ds);
2050*61046927SAndroid Build Coastguard Worker          if (ds)
2051*61046927SAndroid Build Coastguard Worker             ds->DepthEnable = ds->StencilEnable = false;
2052*61046927SAndroid Build Coastguard Worker       } else {
2053*61046927SAndroid Build Coastguard Worker          D3D12_DEPTH_STENCIL_DESC1 *ds = dzn_graphics_pipeline_get_desc(pipeline, pipeline->templates.stream_buf, ds);
2054*61046927SAndroid Build Coastguard Worker          if (ds)
2055*61046927SAndroid Build Coastguard Worker             ds->DepthEnable = ds->StencilEnable = false;
2056*61046927SAndroid Build Coastguard Worker       }
2057*61046927SAndroid Build Coastguard Worker    }
2058*61046927SAndroid Build Coastguard Worker 
2059*61046927SAndroid Build Coastguard Worker    if (!pipeline->variants) {
2060*61046927SAndroid Build Coastguard Worker       hres = ID3D12Device4_CreatePipelineState(device->dev, stream_desc,
2061*61046927SAndroid Build Coastguard Worker                                                &IID_ID3D12PipelineState,
2062*61046927SAndroid Build Coastguard Worker                                                (void **)&pipeline->base.state);
2063*61046927SAndroid Build Coastguard Worker       if (FAILED(hres)) {
2064*61046927SAndroid Build Coastguard Worker          ret = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2065*61046927SAndroid Build Coastguard Worker          goto out;
2066*61046927SAndroid Build Coastguard Worker       }
2067*61046927SAndroid Build Coastguard Worker 
2068*61046927SAndroid Build Coastguard Worker       dzn_graphics_pipeline_cleanup_dxil_shaders(pipeline);
2069*61046927SAndroid Build Coastguard Worker    }
2070*61046927SAndroid Build Coastguard Worker 
2071*61046927SAndroid Build Coastguard Worker    dzn_graphics_pipeline_cleanup_nir_shaders(pipeline);
2072*61046927SAndroid Build Coastguard Worker    ret = VK_SUCCESS;
2073*61046927SAndroid Build Coastguard Worker 
2074*61046927SAndroid Build Coastguard Worker out:
2075*61046927SAndroid Build Coastguard Worker    if (ret != VK_SUCCESS)
2076*61046927SAndroid Build Coastguard Worker       dzn_graphics_pipeline_destroy(pipeline, pAllocator);
2077*61046927SAndroid Build Coastguard Worker    else
2078*61046927SAndroid Build Coastguard Worker       *out = dzn_graphics_pipeline_to_handle(pipeline);
2079*61046927SAndroid Build Coastguard Worker 
2080*61046927SAndroid Build Coastguard Worker    return ret;
2081*61046927SAndroid Build Coastguard Worker }
2082*61046927SAndroid Build Coastguard Worker 
2083*61046927SAndroid Build Coastguard Worker static void
mask_key_for_stencil_state(struct dzn_physical_device * pdev,struct dzn_graphics_pipeline * pipeline,const struct dzn_graphics_pipeline_variant_key * key,struct dzn_graphics_pipeline_variant_key * masked_key)2084*61046927SAndroid Build Coastguard Worker mask_key_for_stencil_state(struct dzn_physical_device *pdev,
2085*61046927SAndroid Build Coastguard Worker                            struct dzn_graphics_pipeline *pipeline,
2086*61046927SAndroid Build Coastguard Worker                            const struct dzn_graphics_pipeline_variant_key *key,
2087*61046927SAndroid Build Coastguard Worker                            struct dzn_graphics_pipeline_variant_key *masked_key)
2088*61046927SAndroid Build Coastguard Worker {
2089*61046927SAndroid Build Coastguard Worker    if (pdev->options14.IndependentFrontAndBackStencilRefMaskSupported) {
2090*61046927SAndroid Build Coastguard Worker       const D3D12_DEPTH_STENCIL_DESC2 *ds_templ =
2091*61046927SAndroid Build Coastguard Worker          dzn_graphics_pipeline_get_desc_template(pipeline, ds);
2092*61046927SAndroid Build Coastguard Worker       if (ds_templ && ds_templ->StencilEnable) {
2093*61046927SAndroid Build Coastguard Worker          if (ds_templ->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2094*61046927SAndroid Build Coastguard Worker              ds_templ->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS)
2095*61046927SAndroid Build Coastguard Worker             masked_key->stencil_test.front.compare_mask = key->stencil_test.front.compare_mask;
2096*61046927SAndroid Build Coastguard Worker          if (ds_templ->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2097*61046927SAndroid Build Coastguard Worker              ds_templ->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS)
2098*61046927SAndroid Build Coastguard Worker             masked_key->stencil_test.back.compare_mask = key->stencil_test.back.compare_mask;
2099*61046927SAndroid Build Coastguard Worker          if (pipeline->zsa.stencil_test.dynamic_write_mask) {
2100*61046927SAndroid Build Coastguard Worker             masked_key->stencil_test.front.write_mask = key->stencil_test.front.write_mask;
2101*61046927SAndroid Build Coastguard Worker             masked_key->stencil_test.back.write_mask = key->stencil_test.back.write_mask;
2102*61046927SAndroid Build Coastguard Worker          }
2103*61046927SAndroid Build Coastguard Worker       }
2104*61046927SAndroid Build Coastguard Worker    } else {
2105*61046927SAndroid Build Coastguard Worker       const D3D12_DEPTH_STENCIL_DESC1 *ds_templ =
2106*61046927SAndroid Build Coastguard Worker          dzn_graphics_pipeline_get_desc_template(pipeline, ds);
2107*61046927SAndroid Build Coastguard Worker       if (ds_templ && ds_templ->StencilEnable) {
2108*61046927SAndroid Build Coastguard Worker          if (ds_templ->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2109*61046927SAndroid Build Coastguard Worker              ds_templ->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS)
2110*61046927SAndroid Build Coastguard Worker             masked_key->stencil_test.front.compare_mask = key->stencil_test.front.compare_mask;
2111*61046927SAndroid Build Coastguard Worker          if (ds_templ->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2112*61046927SAndroid Build Coastguard Worker              ds_templ->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS)
2113*61046927SAndroid Build Coastguard Worker             masked_key->stencil_test.back.compare_mask = key->stencil_test.back.compare_mask;
2114*61046927SAndroid Build Coastguard Worker          if (pipeline->zsa.stencil_test.dynamic_write_mask) {
2115*61046927SAndroid Build Coastguard Worker             masked_key->stencil_test.front.write_mask = key->stencil_test.front.write_mask;
2116*61046927SAndroid Build Coastguard Worker             masked_key->stencil_test.back.write_mask = key->stencil_test.back.write_mask;
2117*61046927SAndroid Build Coastguard Worker          }
2118*61046927SAndroid Build Coastguard Worker       }
2119*61046927SAndroid Build Coastguard Worker    }
2120*61046927SAndroid Build Coastguard Worker }
2121*61046927SAndroid Build Coastguard Worker 
2122*61046927SAndroid Build Coastguard Worker static void
update_stencil_state(struct dzn_physical_device * pdev,struct dzn_graphics_pipeline * pipeline,uintptr_t * stream_buf,const struct dzn_graphics_pipeline_variant_key * masked_key)2123*61046927SAndroid Build Coastguard Worker update_stencil_state(struct dzn_physical_device *pdev,
2124*61046927SAndroid Build Coastguard Worker                      struct dzn_graphics_pipeline *pipeline,
2125*61046927SAndroid Build Coastguard Worker                      uintptr_t *stream_buf,
2126*61046927SAndroid Build Coastguard Worker                      const struct dzn_graphics_pipeline_variant_key *masked_key)
2127*61046927SAndroid Build Coastguard Worker {
2128*61046927SAndroid Build Coastguard Worker    if (pdev->options14.IndependentFrontAndBackStencilRefMaskSupported) {
2129*61046927SAndroid Build Coastguard Worker       D3D12_DEPTH_STENCIL_DESC2 *ds =
2130*61046927SAndroid Build Coastguard Worker          dzn_graphics_pipeline_get_desc(pipeline, stream_buf, ds);
2131*61046927SAndroid Build Coastguard Worker       if (ds && ds->StencilEnable) {
2132*61046927SAndroid Build Coastguard Worker          if (pipeline->zsa.stencil_test.dynamic_compare_mask) {
2133*61046927SAndroid Build Coastguard Worker             if (ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2134*61046927SAndroid Build Coastguard Worker                   ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS) {
2135*61046927SAndroid Build Coastguard Worker                ds->FrontFace.StencilReadMask = masked_key->stencil_test.front.compare_mask;
2136*61046927SAndroid Build Coastguard Worker             }
2137*61046927SAndroid Build Coastguard Worker 
2138*61046927SAndroid Build Coastguard Worker             if (ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2139*61046927SAndroid Build Coastguard Worker                   ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS) {
2140*61046927SAndroid Build Coastguard Worker                ds->BackFace.StencilReadMask = masked_key->stencil_test.back.compare_mask;
2141*61046927SAndroid Build Coastguard Worker             }
2142*61046927SAndroid Build Coastguard Worker          }
2143*61046927SAndroid Build Coastguard Worker 
2144*61046927SAndroid Build Coastguard Worker          if (pipeline->zsa.stencil_test.dynamic_write_mask) {
2145*61046927SAndroid Build Coastguard Worker             ds->FrontFace.StencilWriteMask = masked_key->stencil_test.front.write_mask;
2146*61046927SAndroid Build Coastguard Worker             ds->BackFace.StencilWriteMask = masked_key->stencil_test.back.write_mask;
2147*61046927SAndroid Build Coastguard Worker          }
2148*61046927SAndroid Build Coastguard Worker       }
2149*61046927SAndroid Build Coastguard Worker    } else {
2150*61046927SAndroid Build Coastguard Worker       D3D12_DEPTH_STENCIL_DESC1 *ds =
2151*61046927SAndroid Build Coastguard Worker          dzn_graphics_pipeline_get_desc(pipeline, stream_buf, ds);
2152*61046927SAndroid Build Coastguard Worker       if (ds && ds->StencilEnable) {
2153*61046927SAndroid Build Coastguard Worker          if (pipeline->zsa.stencil_test.dynamic_compare_mask) {
2154*61046927SAndroid Build Coastguard Worker             if (ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2155*61046927SAndroid Build Coastguard Worker                   ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS) {
2156*61046927SAndroid Build Coastguard Worker                ds->StencilReadMask = masked_key->stencil_test.front.compare_mask;
2157*61046927SAndroid Build Coastguard Worker             }
2158*61046927SAndroid Build Coastguard Worker 
2159*61046927SAndroid Build Coastguard Worker             if (ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2160*61046927SAndroid Build Coastguard Worker                   ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS) {
2161*61046927SAndroid Build Coastguard Worker                ds->StencilReadMask = masked_key->stencil_test.back.compare_mask;
2162*61046927SAndroid Build Coastguard Worker             }
2163*61046927SAndroid Build Coastguard Worker 
2164*61046927SAndroid Build Coastguard Worker             if (ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2165*61046927SAndroid Build Coastguard Worker                   ds->FrontFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS &&
2166*61046927SAndroid Build Coastguard Worker                   ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_NEVER &&
2167*61046927SAndroid Build Coastguard Worker                   ds->BackFace.StencilFunc != D3D12_COMPARISON_FUNC_ALWAYS)
2168*61046927SAndroid Build Coastguard Worker                assert(masked_key->stencil_test.front.compare_mask == masked_key->stencil_test.back.compare_mask);
2169*61046927SAndroid Build Coastguard Worker          }
2170*61046927SAndroid Build Coastguard Worker 
2171*61046927SAndroid Build Coastguard Worker          if (pipeline->zsa.stencil_test.dynamic_write_mask) {
2172*61046927SAndroid Build Coastguard Worker             assert(!masked_key->stencil_test.front.write_mask ||
2173*61046927SAndroid Build Coastguard Worker                      !masked_key->stencil_test.back.write_mask ||
2174*61046927SAndroid Build Coastguard Worker                      masked_key->stencil_test.front.write_mask == masked_key->stencil_test.back.write_mask);
2175*61046927SAndroid Build Coastguard Worker             ds->StencilWriteMask =
2176*61046927SAndroid Build Coastguard Worker                masked_key->stencil_test.front.write_mask |
2177*61046927SAndroid Build Coastguard Worker                masked_key->stencil_test.back.write_mask;
2178*61046927SAndroid Build Coastguard Worker          }
2179*61046927SAndroid Build Coastguard Worker       }
2180*61046927SAndroid Build Coastguard Worker    }
2181*61046927SAndroid Build Coastguard Worker }
2182*61046927SAndroid Build Coastguard Worker 
2183*61046927SAndroid Build Coastguard Worker ID3D12PipelineState *
dzn_graphics_pipeline_get_state(struct dzn_graphics_pipeline * pipeline,const struct dzn_graphics_pipeline_variant_key * key)2184*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_get_state(struct dzn_graphics_pipeline *pipeline,
2185*61046927SAndroid Build Coastguard Worker                                 const struct dzn_graphics_pipeline_variant_key *key)
2186*61046927SAndroid Build Coastguard Worker {
2187*61046927SAndroid Build Coastguard Worker    if (!pipeline->variants)
2188*61046927SAndroid Build Coastguard Worker       return pipeline->base.state;
2189*61046927SAndroid Build Coastguard Worker 
2190*61046927SAndroid Build Coastguard Worker    struct dzn_device *device =
2191*61046927SAndroid Build Coastguard Worker       container_of(pipeline->base.base.device, struct dzn_device, vk);
2192*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev =
2193*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical, struct dzn_physical_device, vk);
2194*61046927SAndroid Build Coastguard Worker 
2195*61046927SAndroid Build Coastguard Worker    struct dzn_graphics_pipeline_variant_key masked_key = { 0 };
2196*61046927SAndroid Build Coastguard Worker 
2197*61046927SAndroid Build Coastguard Worker    if (dzn_graphics_pipeline_get_desc_template(pipeline, ib_strip_cut))
2198*61046927SAndroid Build Coastguard Worker       masked_key.ib_strip_cut = key->ib_strip_cut;
2199*61046927SAndroid Build Coastguard Worker 
2200*61046927SAndroid Build Coastguard Worker    if (!pdev->options16.DynamicDepthBiasSupported &&
2201*61046927SAndroid Build Coastguard Worker        dzn_graphics_pipeline_get_desc_template(pipeline, rast) &&
2202*61046927SAndroid Build Coastguard Worker        pipeline->zsa.dynamic_depth_bias)
2203*61046927SAndroid Build Coastguard Worker       masked_key.depth_bias = key->depth_bias;
2204*61046927SAndroid Build Coastguard Worker 
2205*61046927SAndroid Build Coastguard Worker    mask_key_for_stencil_state(pdev, pipeline, key, &masked_key);
2206*61046927SAndroid Build Coastguard Worker 
2207*61046927SAndroid Build Coastguard Worker    struct hash_entry *he =
2208*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_search(pipeline->variants, &masked_key);
2209*61046927SAndroid Build Coastguard Worker 
2210*61046927SAndroid Build Coastguard Worker    struct dzn_graphics_pipeline_variant *variant;
2211*61046927SAndroid Build Coastguard Worker 
2212*61046927SAndroid Build Coastguard Worker    if (!he) {
2213*61046927SAndroid Build Coastguard Worker       variant = rzalloc(pipeline->variants, struct dzn_graphics_pipeline_variant);
2214*61046927SAndroid Build Coastguard Worker       variant->key = masked_key;
2215*61046927SAndroid Build Coastguard Worker 
2216*61046927SAndroid Build Coastguard Worker       uintptr_t stream_buf[MAX_GFX_PIPELINE_STATE_STREAM_SIZE / sizeof(uintptr_t)];
2217*61046927SAndroid Build Coastguard Worker       D3D12_PIPELINE_STATE_STREAM_DESC stream_desc = {
2218*61046927SAndroid Build Coastguard Worker          .SizeInBytes = pipeline->templates.stream_desc.SizeInBytes,
2219*61046927SAndroid Build Coastguard Worker          .pPipelineStateSubobjectStream = stream_buf,
2220*61046927SAndroid Build Coastguard Worker       };
2221*61046927SAndroid Build Coastguard Worker 
2222*61046927SAndroid Build Coastguard Worker       memcpy(stream_buf, pipeline->templates.stream_buf, stream_desc.SizeInBytes);
2223*61046927SAndroid Build Coastguard Worker 
2224*61046927SAndroid Build Coastguard Worker       D3D12_INDEX_BUFFER_STRIP_CUT_VALUE *ib_strip_cut =
2225*61046927SAndroid Build Coastguard Worker          dzn_graphics_pipeline_get_desc(pipeline, stream_buf, ib_strip_cut);
2226*61046927SAndroid Build Coastguard Worker       if (ib_strip_cut)
2227*61046927SAndroid Build Coastguard Worker          *ib_strip_cut = masked_key.ib_strip_cut;
2228*61046927SAndroid Build Coastguard Worker 
2229*61046927SAndroid Build Coastguard Worker       D3D12_RASTERIZER_DESC *rast =
2230*61046927SAndroid Build Coastguard Worker          dzn_graphics_pipeline_get_desc(pipeline, stream_buf, rast);
2231*61046927SAndroid Build Coastguard Worker       if (!pdev->options16.DynamicDepthBiasSupported && rast && pipeline->zsa.dynamic_depth_bias) {
2232*61046927SAndroid Build Coastguard Worker          rast->DepthBias = translate_depth_bias(masked_key.depth_bias.constant_factor);
2233*61046927SAndroid Build Coastguard Worker          rast->DepthBiasClamp = masked_key.depth_bias.clamp;
2234*61046927SAndroid Build Coastguard Worker          rast->SlopeScaledDepthBias = masked_key.depth_bias.slope_factor;
2235*61046927SAndroid Build Coastguard Worker       }
2236*61046927SAndroid Build Coastguard Worker 
2237*61046927SAndroid Build Coastguard Worker       update_stencil_state(pdev, pipeline, stream_buf, &masked_key);
2238*61046927SAndroid Build Coastguard Worker 
2239*61046927SAndroid Build Coastguard Worker       ASSERTED HRESULT hres = ID3D12Device4_CreatePipelineState(device->dev, &stream_desc,
2240*61046927SAndroid Build Coastguard Worker                                                                 &IID_ID3D12PipelineState,
2241*61046927SAndroid Build Coastguard Worker                                                                 (void**)(&variant->state));
2242*61046927SAndroid Build Coastguard Worker       assert(!FAILED(hres));
2243*61046927SAndroid Build Coastguard Worker       he = _mesa_hash_table_insert(pipeline->variants, &variant->key, variant);
2244*61046927SAndroid Build Coastguard Worker       assert(he);
2245*61046927SAndroid Build Coastguard Worker    } else {
2246*61046927SAndroid Build Coastguard Worker       variant = he->data;
2247*61046927SAndroid Build Coastguard Worker    }
2248*61046927SAndroid Build Coastguard Worker 
2249*61046927SAndroid Build Coastguard Worker    if (variant->state)
2250*61046927SAndroid Build Coastguard Worker       ID3D12PipelineState_AddRef(variant->state);
2251*61046927SAndroid Build Coastguard Worker 
2252*61046927SAndroid Build Coastguard Worker    if (pipeline->base.state)
2253*61046927SAndroid Build Coastguard Worker       ID3D12PipelineState_Release(pipeline->base.state);
2254*61046927SAndroid Build Coastguard Worker 
2255*61046927SAndroid Build Coastguard Worker    pipeline->base.state = variant->state;
2256*61046927SAndroid Build Coastguard Worker    return variant->state;
2257*61046927SAndroid Build Coastguard Worker }
2258*61046927SAndroid Build Coastguard Worker 
2259*61046927SAndroid Build Coastguard Worker #define DZN_INDIRECT_CMD_SIG_MAX_ARGS 4
2260*61046927SAndroid Build Coastguard Worker 
2261*61046927SAndroid Build Coastguard Worker ID3D12CommandSignature *
dzn_graphics_pipeline_get_indirect_cmd_sig(struct dzn_graphics_pipeline * pipeline,struct dzn_indirect_draw_cmd_sig_key key)2262*61046927SAndroid Build Coastguard Worker dzn_graphics_pipeline_get_indirect_cmd_sig(struct dzn_graphics_pipeline *pipeline,
2263*61046927SAndroid Build Coastguard Worker                                            struct dzn_indirect_draw_cmd_sig_key key)
2264*61046927SAndroid Build Coastguard Worker {
2265*61046927SAndroid Build Coastguard Worker    assert(key.value < DZN_NUM_INDIRECT_DRAW_CMD_SIGS);
2266*61046927SAndroid Build Coastguard Worker 
2267*61046927SAndroid Build Coastguard Worker    struct dzn_device *device = container_of(pipeline->base.base.device, struct dzn_device, vk);
2268*61046927SAndroid Build Coastguard Worker 
2269*61046927SAndroid Build Coastguard Worker    uint32_t cmd_arg_count = 0;
2270*61046927SAndroid Build Coastguard Worker    D3D12_INDIRECT_ARGUMENT_DESC cmd_args[DZN_INDIRECT_CMD_SIG_MAX_ARGS];
2271*61046927SAndroid Build Coastguard Worker    uint32_t stride = 0;
2272*61046927SAndroid Build Coastguard Worker 
2273*61046927SAndroid Build Coastguard Worker    if (key.triangle_fan) {
2274*61046927SAndroid Build Coastguard Worker       assert(key.indexed);
2275*61046927SAndroid Build Coastguard Worker       cmd_args[cmd_arg_count++] = (D3D12_INDIRECT_ARGUMENT_DESC) {
2276*61046927SAndroid Build Coastguard Worker          .Type = D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW,
2277*61046927SAndroid Build Coastguard Worker       };
2278*61046927SAndroid Build Coastguard Worker       stride += sizeof(D3D12_INDEX_BUFFER_VIEW);
2279*61046927SAndroid Build Coastguard Worker    }
2280*61046927SAndroid Build Coastguard Worker 
2281*61046927SAndroid Build Coastguard Worker    if (key.draw_params) {
2282*61046927SAndroid Build Coastguard Worker       cmd_args[cmd_arg_count++] = (D3D12_INDIRECT_ARGUMENT_DESC){
2283*61046927SAndroid Build Coastguard Worker          .Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
2284*61046927SAndroid Build Coastguard Worker          .Constant = {
2285*61046927SAndroid Build Coastguard Worker             .RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx,
2286*61046927SAndroid Build Coastguard Worker             .DestOffsetIn32BitValues = offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex) / 4,
2287*61046927SAndroid Build Coastguard Worker             .Num32BitValuesToSet = 2,
2288*61046927SAndroid Build Coastguard Worker          },
2289*61046927SAndroid Build Coastguard Worker       };
2290*61046927SAndroid Build Coastguard Worker       stride += sizeof(uint32_t) * 2;
2291*61046927SAndroid Build Coastguard Worker    }
2292*61046927SAndroid Build Coastguard Worker 
2293*61046927SAndroid Build Coastguard Worker    if (key.draw_id) {
2294*61046927SAndroid Build Coastguard Worker       struct dzn_physical_device *pdev = container_of(device->vk.physical, struct dzn_physical_device, vk);
2295*61046927SAndroid Build Coastguard Worker       if (pdev->options21.ExecuteIndirectTier >= D3D12_EXECUTE_INDIRECT_TIER_1_1) {
2296*61046927SAndroid Build Coastguard Worker          cmd_args[cmd_arg_count++] = (D3D12_INDIRECT_ARGUMENT_DESC){
2297*61046927SAndroid Build Coastguard Worker             .Type = D3D12_INDIRECT_ARGUMENT_TYPE_INCREMENTING_CONSTANT,
2298*61046927SAndroid Build Coastguard Worker             .IncrementingConstant = {
2299*61046927SAndroid Build Coastguard Worker                .RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx,
2300*61046927SAndroid Build Coastguard Worker                .DestOffsetIn32BitValues = offsetof(struct dxil_spirv_vertex_runtime_data, draw_id) / 4,
2301*61046927SAndroid Build Coastguard Worker             },
2302*61046927SAndroid Build Coastguard Worker          };
2303*61046927SAndroid Build Coastguard Worker       } else {
2304*61046927SAndroid Build Coastguard Worker          cmd_args[cmd_arg_count++] = (D3D12_INDIRECT_ARGUMENT_DESC){
2305*61046927SAndroid Build Coastguard Worker             .Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
2306*61046927SAndroid Build Coastguard Worker             .Constant = {
2307*61046927SAndroid Build Coastguard Worker                .RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx,
2308*61046927SAndroid Build Coastguard Worker                .DestOffsetIn32BitValues = offsetof(struct dxil_spirv_vertex_runtime_data, draw_id) / 4,
2309*61046927SAndroid Build Coastguard Worker                .Num32BitValuesToSet = 1,
2310*61046927SAndroid Build Coastguard Worker             },
2311*61046927SAndroid Build Coastguard Worker          };
2312*61046927SAndroid Build Coastguard Worker          stride += sizeof(uint32_t);
2313*61046927SAndroid Build Coastguard Worker       }
2314*61046927SAndroid Build Coastguard Worker    }
2315*61046927SAndroid Build Coastguard Worker 
2316*61046927SAndroid Build Coastguard Worker    cmd_args[cmd_arg_count++] = (D3D12_INDIRECT_ARGUMENT_DESC) {
2317*61046927SAndroid Build Coastguard Worker       .Type = key.indexed ?
2318*61046927SAndroid Build Coastguard Worker               D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED :
2319*61046927SAndroid Build Coastguard Worker               D3D12_INDIRECT_ARGUMENT_TYPE_DRAW,
2320*61046927SAndroid Build Coastguard Worker    };
2321*61046927SAndroid Build Coastguard Worker    stride += key.indexed ? sizeof(D3D12_DRAW_INDEXED_ARGUMENTS) :
2322*61046927SAndroid Build Coastguard Worker                            sizeof(D3D12_DRAW_ARGUMENTS);
2323*61046927SAndroid Build Coastguard Worker 
2324*61046927SAndroid Build Coastguard Worker    assert(cmd_arg_count <= ARRAY_SIZE(cmd_args));
2325*61046927SAndroid Build Coastguard Worker    assert(offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex) == 0);
2326*61046927SAndroid Build Coastguard Worker    ID3D12CommandSignature *cmdsig = NULL;
2327*61046927SAndroid Build Coastguard Worker 
2328*61046927SAndroid Build Coastguard Worker    if (key.custom_stride == 0 || key.custom_stride == stride)
2329*61046927SAndroid Build Coastguard Worker       cmdsig = pipeline->indirect_cmd_sigs[key.value];
2330*61046927SAndroid Build Coastguard Worker    else {
2331*61046927SAndroid Build Coastguard Worker       if (!pipeline->custom_stride_cmd_sigs) {
2332*61046927SAndroid Build Coastguard Worker          pipeline->custom_stride_cmd_sigs =
2333*61046927SAndroid Build Coastguard Worker             _mesa_hash_table_create(NULL, gfx_pipeline_cmd_signature_key_hash, gfx_pipeline_cmd_signature_key_equal);
2334*61046927SAndroid Build Coastguard Worker       }
2335*61046927SAndroid Build Coastguard Worker       struct hash_entry *entry = _mesa_hash_table_search(pipeline->custom_stride_cmd_sigs, &key);
2336*61046927SAndroid Build Coastguard Worker       if (entry)
2337*61046927SAndroid Build Coastguard Worker          cmdsig = entry->data;
2338*61046927SAndroid Build Coastguard Worker    }
2339*61046927SAndroid Build Coastguard Worker 
2340*61046927SAndroid Build Coastguard Worker    if (cmdsig)
2341*61046927SAndroid Build Coastguard Worker       return cmdsig;
2342*61046927SAndroid Build Coastguard Worker 
2343*61046927SAndroid Build Coastguard Worker    D3D12_COMMAND_SIGNATURE_DESC cmd_sig_desc = {
2344*61046927SAndroid Build Coastguard Worker       .ByteStride = key.custom_stride ? key.custom_stride : stride,
2345*61046927SAndroid Build Coastguard Worker       .NumArgumentDescs = cmd_arg_count,
2346*61046927SAndroid Build Coastguard Worker       .pArgumentDescs = cmd_args,
2347*61046927SAndroid Build Coastguard Worker    };
2348*61046927SAndroid Build Coastguard Worker    /* A root signature should be specified iff root params are changing */
2349*61046927SAndroid Build Coastguard Worker    ID3D12RootSignature *root_sig = key.draw_id || key.draw_params ?
2350*61046927SAndroid Build Coastguard Worker       pipeline->base.root.sig : NULL;
2351*61046927SAndroid Build Coastguard Worker    HRESULT hres =
2352*61046927SAndroid Build Coastguard Worker       ID3D12Device1_CreateCommandSignature(device->dev, &cmd_sig_desc,
2353*61046927SAndroid Build Coastguard Worker                                            root_sig,
2354*61046927SAndroid Build Coastguard Worker                                            &IID_ID3D12CommandSignature,
2355*61046927SAndroid Build Coastguard Worker                                            (void **)&cmdsig);
2356*61046927SAndroid Build Coastguard Worker    if (FAILED(hres))
2357*61046927SAndroid Build Coastguard Worker       return NULL;
2358*61046927SAndroid Build Coastguard Worker 
2359*61046927SAndroid Build Coastguard Worker    if (key.custom_stride == 0 || key.custom_stride == stride)
2360*61046927SAndroid Build Coastguard Worker       pipeline->indirect_cmd_sigs[key.value] = cmdsig;
2361*61046927SAndroid Build Coastguard Worker    else
2362*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_insert(pipeline->custom_stride_cmd_sigs, &key, cmdsig);
2363*61046927SAndroid Build Coastguard Worker    return cmdsig;
2364*61046927SAndroid Build Coastguard Worker }
2365*61046927SAndroid Build Coastguard Worker 
2366*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateGraphicsPipelines(VkDevice dev,VkPipelineCache pipelineCache,uint32_t count,const VkGraphicsPipelineCreateInfo * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipelines)2367*61046927SAndroid Build Coastguard Worker dzn_CreateGraphicsPipelines(VkDevice dev,
2368*61046927SAndroid Build Coastguard Worker                             VkPipelineCache pipelineCache,
2369*61046927SAndroid Build Coastguard Worker                             uint32_t count,
2370*61046927SAndroid Build Coastguard Worker                             const VkGraphicsPipelineCreateInfo *pCreateInfos,
2371*61046927SAndroid Build Coastguard Worker                             const VkAllocationCallbacks *pAllocator,
2372*61046927SAndroid Build Coastguard Worker                             VkPipeline *pPipelines)
2373*61046927SAndroid Build Coastguard Worker {
2374*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(dzn_device, device, dev);
2375*61046927SAndroid Build Coastguard Worker    VkResult result = VK_SUCCESS;
2376*61046927SAndroid Build Coastguard Worker 
2377*61046927SAndroid Build Coastguard Worker    unsigned i;
2378*61046927SAndroid Build Coastguard Worker    for (i = 0; i < count; i++) {
2379*61046927SAndroid Build Coastguard Worker       result = dzn_graphics_pipeline_create(device,
2380*61046927SAndroid Build Coastguard Worker                                             pipelineCache,
2381*61046927SAndroid Build Coastguard Worker                                             &pCreateInfos[i],
2382*61046927SAndroid Build Coastguard Worker                                             pAllocator,
2383*61046927SAndroid Build Coastguard Worker                                             &pPipelines[i]);
2384*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
2385*61046927SAndroid Build Coastguard Worker          pPipelines[i] = VK_NULL_HANDLE;
2386*61046927SAndroid Build Coastguard Worker 
2387*61046927SAndroid Build Coastguard Worker          /* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED_EX as it
2388*61046927SAndroid Build Coastguard Worker           * is not obvious what error should be report upon 2 different failures.
2389*61046927SAndroid Build Coastguard Worker           */
2390*61046927SAndroid Build Coastguard Worker          if (result != VK_PIPELINE_COMPILE_REQUIRED)
2391*61046927SAndroid Build Coastguard Worker             break;
2392*61046927SAndroid Build Coastguard Worker 
2393*61046927SAndroid Build Coastguard Worker          if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT)
2394*61046927SAndroid Build Coastguard Worker             break;
2395*61046927SAndroid Build Coastguard Worker       }
2396*61046927SAndroid Build Coastguard Worker    }
2397*61046927SAndroid Build Coastguard Worker 
2398*61046927SAndroid Build Coastguard Worker    for (; i < count; i++)
2399*61046927SAndroid Build Coastguard Worker       pPipelines[i] = VK_NULL_HANDLE;
2400*61046927SAndroid Build Coastguard Worker 
2401*61046927SAndroid Build Coastguard Worker    return result;
2402*61046927SAndroid Build Coastguard Worker }
2403*61046927SAndroid Build Coastguard Worker 
2404*61046927SAndroid Build Coastguard Worker static void
dzn_compute_pipeline_destroy(struct dzn_compute_pipeline * pipeline,const VkAllocationCallbacks * alloc)2405*61046927SAndroid Build Coastguard Worker dzn_compute_pipeline_destroy(struct dzn_compute_pipeline *pipeline,
2406*61046927SAndroid Build Coastguard Worker                              const VkAllocationCallbacks *alloc)
2407*61046927SAndroid Build Coastguard Worker {
2408*61046927SAndroid Build Coastguard Worker    if (!pipeline)
2409*61046927SAndroid Build Coastguard Worker       return;
2410*61046927SAndroid Build Coastguard Worker 
2411*61046927SAndroid Build Coastguard Worker    if (pipeline->indirect_cmd_sig)
2412*61046927SAndroid Build Coastguard Worker       ID3D12CommandSignature_Release(pipeline->indirect_cmd_sig);
2413*61046927SAndroid Build Coastguard Worker 
2414*61046927SAndroid Build Coastguard Worker    dzn_pipeline_finish(&pipeline->base);
2415*61046927SAndroid Build Coastguard Worker    vk_free2(&pipeline->base.base.device->alloc, alloc, pipeline);
2416*61046927SAndroid Build Coastguard Worker }
2417*61046927SAndroid Build Coastguard Worker 
2418*61046927SAndroid Build Coastguard Worker static VkResult
dzn_pipeline_cache_lookup_compute_pipeline(struct vk_pipeline_cache * cache,uint8_t * pipeline_hash,D3D12_PIPELINE_STATE_STREAM_DESC * stream_desc,D3D12_SHADER_BYTECODE * dxil,bool * cache_hit)2419*61046927SAndroid Build Coastguard Worker dzn_pipeline_cache_lookup_compute_pipeline(struct vk_pipeline_cache *cache,
2420*61046927SAndroid Build Coastguard Worker                                            uint8_t *pipeline_hash,
2421*61046927SAndroid Build Coastguard Worker                                            D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc,
2422*61046927SAndroid Build Coastguard Worker                                            D3D12_SHADER_BYTECODE *dxil,
2423*61046927SAndroid Build Coastguard Worker                                            bool *cache_hit)
2424*61046927SAndroid Build Coastguard Worker {
2425*61046927SAndroid Build Coastguard Worker    *cache_hit = false;
2426*61046927SAndroid Build Coastguard Worker 
2427*61046927SAndroid Build Coastguard Worker    if (!cache)
2428*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
2429*61046927SAndroid Build Coastguard Worker 
2430*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_object *cache_obj = NULL;
2431*61046927SAndroid Build Coastguard Worker 
2432*61046927SAndroid Build Coastguard Worker    cache_obj =
2433*61046927SAndroid Build Coastguard Worker       vk_pipeline_cache_lookup_object(cache, pipeline_hash, SHA1_DIGEST_LENGTH,
2434*61046927SAndroid Build Coastguard Worker                                       &dzn_cached_blob_ops,
2435*61046927SAndroid Build Coastguard Worker                                       NULL);
2436*61046927SAndroid Build Coastguard Worker    if (!cache_obj)
2437*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
2438*61046927SAndroid Build Coastguard Worker 
2439*61046927SAndroid Build Coastguard Worker    struct dzn_cached_blob *cached_blob =
2440*61046927SAndroid Build Coastguard Worker       container_of(cache_obj, struct dzn_cached_blob, base);
2441*61046927SAndroid Build Coastguard Worker 
2442*61046927SAndroid Build Coastguard Worker    assert(cached_blob->size == SHA1_DIGEST_LENGTH);
2443*61046927SAndroid Build Coastguard Worker 
2444*61046927SAndroid Build Coastguard Worker    const uint8_t *dxil_hash = cached_blob->data;
2445*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage;
2446*61046927SAndroid Build Coastguard Worker 
2447*61046927SAndroid Build Coastguard Worker    VkResult ret =
2448*61046927SAndroid Build Coastguard Worker       dzn_pipeline_cache_lookup_dxil_shader(cache, dxil_hash, &stage, dxil);
2449*61046927SAndroid Build Coastguard Worker 
2450*61046927SAndroid Build Coastguard Worker    if (ret != VK_SUCCESS || stage == MESA_SHADER_NONE)
2451*61046927SAndroid Build Coastguard Worker       goto out;
2452*61046927SAndroid Build Coastguard Worker 
2453*61046927SAndroid Build Coastguard Worker    assert(stage == MESA_SHADER_COMPUTE);
2454*61046927SAndroid Build Coastguard Worker 
2455*61046927SAndroid Build Coastguard Worker    d3d12_compute_pipeline_state_stream_new_desc(stream_desc, CS, D3D12_SHADER_BYTECODE, slot);
2456*61046927SAndroid Build Coastguard Worker    *slot = *dxil;
2457*61046927SAndroid Build Coastguard Worker    *cache_hit = true;
2458*61046927SAndroid Build Coastguard Worker 
2459*61046927SAndroid Build Coastguard Worker out:
2460*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_unref(cache->base.device, cache_obj);
2461*61046927SAndroid Build Coastguard Worker    return ret;
2462*61046927SAndroid Build Coastguard Worker }
2463*61046927SAndroid Build Coastguard Worker 
2464*61046927SAndroid Build Coastguard Worker static void
dzn_pipeline_cache_add_compute_pipeline(struct vk_pipeline_cache * cache,uint8_t * pipeline_hash,uint8_t * dxil_hash)2465*61046927SAndroid Build Coastguard Worker dzn_pipeline_cache_add_compute_pipeline(struct vk_pipeline_cache *cache,
2466*61046927SAndroid Build Coastguard Worker                                         uint8_t *pipeline_hash,
2467*61046927SAndroid Build Coastguard Worker                                         uint8_t *dxil_hash)
2468*61046927SAndroid Build Coastguard Worker {
2469*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_object *cache_obj =
2470*61046927SAndroid Build Coastguard Worker       dzn_cached_blob_create(cache->base.device, pipeline_hash, NULL, SHA1_DIGEST_LENGTH);
2471*61046927SAndroid Build Coastguard Worker    if (!cache_obj)
2472*61046927SAndroid Build Coastguard Worker       return;
2473*61046927SAndroid Build Coastguard Worker 
2474*61046927SAndroid Build Coastguard Worker    struct dzn_cached_blob *cached_blob =
2475*61046927SAndroid Build Coastguard Worker       container_of(cache_obj, struct dzn_cached_blob, base);
2476*61046927SAndroid Build Coastguard Worker 
2477*61046927SAndroid Build Coastguard Worker    memcpy((void *)cached_blob->data, dxil_hash, SHA1_DIGEST_LENGTH);
2478*61046927SAndroid Build Coastguard Worker 
2479*61046927SAndroid Build Coastguard Worker    cache_obj = vk_pipeline_cache_add_object(cache, cache_obj);
2480*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_unref(cache->base.device, cache_obj);
2481*61046927SAndroid Build Coastguard Worker }
2482*61046927SAndroid Build Coastguard Worker 
2483*61046927SAndroid Build Coastguard Worker static VkResult
dzn_compute_pipeline_compile_shader(struct dzn_device * device,struct dzn_compute_pipeline * pipeline,struct vk_pipeline_cache * cache,const struct dzn_pipeline_layout * layout,D3D12_PIPELINE_STATE_STREAM_DESC * stream_desc,D3D12_SHADER_BYTECODE * shader,const VkComputePipelineCreateInfo * info)2484*61046927SAndroid Build Coastguard Worker dzn_compute_pipeline_compile_shader(struct dzn_device *device,
2485*61046927SAndroid Build Coastguard Worker                                     struct dzn_compute_pipeline *pipeline,
2486*61046927SAndroid Build Coastguard Worker                                     struct vk_pipeline_cache *cache,
2487*61046927SAndroid Build Coastguard Worker                                     const struct dzn_pipeline_layout *layout,
2488*61046927SAndroid Build Coastguard Worker                                     D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc,
2489*61046927SAndroid Build Coastguard Worker                                     D3D12_SHADER_BYTECODE *shader,
2490*61046927SAndroid Build Coastguard Worker                                     const VkComputePipelineCreateInfo *info)
2491*61046927SAndroid Build Coastguard Worker {
2492*61046927SAndroid Build Coastguard Worker    struct dzn_physical_device *pdev =
2493*61046927SAndroid Build Coastguard Worker       container_of(device->vk.physical, struct dzn_physical_device, vk);
2494*61046927SAndroid Build Coastguard Worker    uint8_t spirv_hash[SHA1_DIGEST_LENGTH], pipeline_hash[SHA1_DIGEST_LENGTH], nir_hash[SHA1_DIGEST_LENGTH];
2495*61046927SAndroid Build Coastguard Worker    VkResult ret = VK_SUCCESS;
2496*61046927SAndroid Build Coastguard Worker    nir_shader *nir = NULL;
2497*61046927SAndroid Build Coastguard Worker 
2498*61046927SAndroid Build Coastguard Worker    if (cache) {
2499*61046927SAndroid Build Coastguard Worker       struct mesa_sha1 pipeline_hash_ctx;
2500*61046927SAndroid Build Coastguard Worker 
2501*61046927SAndroid Build Coastguard Worker       _mesa_sha1_init(&pipeline_hash_ctx);
2502*61046927SAndroid Build Coastguard Worker       vk_pipeline_hash_shader_stage(pipeline->base.flags, &info->stage, NULL, spirv_hash);
2503*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, &device->bindless, sizeof(device->bindless));
2504*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, spirv_hash, sizeof(spirv_hash));
2505*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&pipeline_hash_ctx, layout->stages[MESA_SHADER_COMPUTE].hash,
2506*61046927SAndroid Build Coastguard Worker                         sizeof(layout->stages[MESA_SHADER_COMPUTE].hash));
2507*61046927SAndroid Build Coastguard Worker       _mesa_sha1_final(&pipeline_hash_ctx, pipeline_hash);
2508*61046927SAndroid Build Coastguard Worker 
2509*61046927SAndroid Build Coastguard Worker       bool cache_hit = false;
2510*61046927SAndroid Build Coastguard Worker       ret = dzn_pipeline_cache_lookup_compute_pipeline(cache, pipeline_hash,
2511*61046927SAndroid Build Coastguard Worker                                                        stream_desc, shader,
2512*61046927SAndroid Build Coastguard Worker                                                        &cache_hit);
2513*61046927SAndroid Build Coastguard Worker       if (ret != VK_SUCCESS || cache_hit)
2514*61046927SAndroid Build Coastguard Worker          goto out;
2515*61046927SAndroid Build Coastguard Worker    }
2516*61046927SAndroid Build Coastguard Worker 
2517*61046927SAndroid Build Coastguard Worker    if (cache) {
2518*61046927SAndroid Build Coastguard Worker       struct mesa_sha1 nir_hash_ctx;
2519*61046927SAndroid Build Coastguard Worker       _mesa_sha1_init(&nir_hash_ctx);
2520*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&nir_hash_ctx, &device->bindless, sizeof(device->bindless));
2521*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&nir_hash_ctx, spirv_hash, sizeof(spirv_hash));
2522*61046927SAndroid Build Coastguard Worker       _mesa_sha1_final(&nir_hash_ctx, nir_hash);
2523*61046927SAndroid Build Coastguard Worker    }
2524*61046927SAndroid Build Coastguard Worker    nir_shader_compiler_options nir_opts;
2525*61046927SAndroid Build Coastguard Worker    const unsigned supported_bit_sizes = 16 | 32 | 64;
2526*61046927SAndroid Build Coastguard Worker    dxil_get_nir_compiler_options(&nir_opts, dzn_get_shader_model(pdev), supported_bit_sizes, supported_bit_sizes);
2527*61046927SAndroid Build Coastguard Worker    struct dzn_nir_options options = {
2528*61046927SAndroid Build Coastguard Worker       .nir_opts = &nir_opts,
2529*61046927SAndroid Build Coastguard Worker    };
2530*61046927SAndroid Build Coastguard Worker    struct dxil_spirv_metadata metadata = { 0 };
2531*61046927SAndroid Build Coastguard Worker    ret = dzn_pipeline_get_nir_shader(device, layout, cache, nir_hash,
2532*61046927SAndroid Build Coastguard Worker                                      pipeline->base.flags, &info->stage,
2533*61046927SAndroid Build Coastguard Worker                                      MESA_SHADER_COMPUTE,
2534*61046927SAndroid Build Coastguard Worker                                      &options, &metadata, &nir);
2535*61046927SAndroid Build Coastguard Worker    if (ret != VK_SUCCESS)
2536*61046927SAndroid Build Coastguard Worker       return ret;
2537*61046927SAndroid Build Coastguard Worker 
2538*61046927SAndroid Build Coastguard Worker    uint8_t bindings_hash[SHA1_DIGEST_LENGTH], dxil_hash[SHA1_DIGEST_LENGTH];
2539*61046927SAndroid Build Coastguard Worker 
2540*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, adjust_var_bindings, device, layout, cache ? bindings_hash : NULL);
2541*61046927SAndroid Build Coastguard Worker 
2542*61046927SAndroid Build Coastguard Worker    if (cache) {
2543*61046927SAndroid Build Coastguard Worker       struct mesa_sha1 dxil_hash_ctx;
2544*61046927SAndroid Build Coastguard Worker 
2545*61046927SAndroid Build Coastguard Worker       _mesa_sha1_init(&dxil_hash_ctx);
2546*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&dxil_hash_ctx, nir_hash, sizeof(nir_hash));
2547*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&dxil_hash_ctx, spirv_hash, sizeof(spirv_hash));
2548*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&dxil_hash_ctx, bindings_hash, sizeof(bindings_hash));
2549*61046927SAndroid Build Coastguard Worker       _mesa_sha1_final(&dxil_hash_ctx, dxil_hash);
2550*61046927SAndroid Build Coastguard Worker 
2551*61046927SAndroid Build Coastguard Worker       gl_shader_stage stage;
2552*61046927SAndroid Build Coastguard Worker 
2553*61046927SAndroid Build Coastguard Worker       ret = dzn_pipeline_cache_lookup_dxil_shader(cache, dxil_hash, &stage, shader);
2554*61046927SAndroid Build Coastguard Worker       if (ret != VK_SUCCESS)
2555*61046927SAndroid Build Coastguard Worker          goto out;
2556*61046927SAndroid Build Coastguard Worker 
2557*61046927SAndroid Build Coastguard Worker       if (stage != MESA_SHADER_NONE) {
2558*61046927SAndroid Build Coastguard Worker          assert(stage == MESA_SHADER_COMPUTE);
2559*61046927SAndroid Build Coastguard Worker          d3d12_compute_pipeline_state_stream_new_desc(stream_desc, CS, D3D12_SHADER_BYTECODE, cs);
2560*61046927SAndroid Build Coastguard Worker          *cs = *shader;
2561*61046927SAndroid Build Coastguard Worker          dzn_pipeline_cache_add_compute_pipeline(cache, pipeline_hash, dxil_hash);
2562*61046927SAndroid Build Coastguard Worker          goto out;
2563*61046927SAndroid Build Coastguard Worker       }
2564*61046927SAndroid Build Coastguard Worker    }
2565*61046927SAndroid Build Coastguard Worker 
2566*61046927SAndroid Build Coastguard Worker    ret = dzn_pipeline_compile_shader(device, nir, 0, shader);
2567*61046927SAndroid Build Coastguard Worker    if (ret != VK_SUCCESS)
2568*61046927SAndroid Build Coastguard Worker       goto out;
2569*61046927SAndroid Build Coastguard Worker 
2570*61046927SAndroid Build Coastguard Worker    d3d12_compute_pipeline_state_stream_new_desc(stream_desc, CS, D3D12_SHADER_BYTECODE, cs);
2571*61046927SAndroid Build Coastguard Worker    *cs = *shader;
2572*61046927SAndroid Build Coastguard Worker 
2573*61046927SAndroid Build Coastguard Worker    if (cache) {
2574*61046927SAndroid Build Coastguard Worker       dzn_pipeline_cache_add_dxil_shader(cache, dxil_hash, MESA_SHADER_COMPUTE, shader);
2575*61046927SAndroid Build Coastguard Worker       dzn_pipeline_cache_add_compute_pipeline(cache, pipeline_hash, dxil_hash);
2576*61046927SAndroid Build Coastguard Worker    }
2577*61046927SAndroid Build Coastguard Worker 
2578*61046927SAndroid Build Coastguard Worker out:
2579*61046927SAndroid Build Coastguard Worker    ralloc_free(nir);
2580*61046927SAndroid Build Coastguard Worker    return ret;
2581*61046927SAndroid Build Coastguard Worker }
2582*61046927SAndroid Build Coastguard Worker 
2583*61046927SAndroid Build Coastguard Worker static VkResult
dzn_compute_pipeline_create(struct dzn_device * device,VkPipelineCache cache,const VkComputePipelineCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipeline * out)2584*61046927SAndroid Build Coastguard Worker dzn_compute_pipeline_create(struct dzn_device *device,
2585*61046927SAndroid Build Coastguard Worker                             VkPipelineCache cache,
2586*61046927SAndroid Build Coastguard Worker                             const VkComputePipelineCreateInfo *pCreateInfo,
2587*61046927SAndroid Build Coastguard Worker                             const VkAllocationCallbacks *pAllocator,
2588*61046927SAndroid Build Coastguard Worker                             VkPipeline *out)
2589*61046927SAndroid Build Coastguard Worker {
2590*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(dzn_pipeline_layout, layout, pCreateInfo->layout);
2591*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline_cache, pcache, cache);
2592*61046927SAndroid Build Coastguard Worker 
2593*61046927SAndroid Build Coastguard Worker    struct dzn_compute_pipeline *pipeline =
2594*61046927SAndroid Build Coastguard Worker       vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8,
2595*61046927SAndroid Build Coastguard Worker                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2596*61046927SAndroid Build Coastguard Worker    if (!pipeline)
2597*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2598*61046927SAndroid Build Coastguard Worker 
2599*61046927SAndroid Build Coastguard Worker    uintptr_t state_buf[MAX_COMPUTE_PIPELINE_STATE_STREAM_SIZE / sizeof(uintptr_t)];
2600*61046927SAndroid Build Coastguard Worker    D3D12_PIPELINE_STATE_STREAM_DESC stream_desc = {
2601*61046927SAndroid Build Coastguard Worker       .pPipelineStateSubobjectStream = state_buf,
2602*61046927SAndroid Build Coastguard Worker    };
2603*61046927SAndroid Build Coastguard Worker 
2604*61046927SAndroid Build Coastguard Worker    dzn_pipeline_init(&pipeline->base, device,
2605*61046927SAndroid Build Coastguard Worker                      VK_PIPELINE_BIND_POINT_COMPUTE,
2606*61046927SAndroid Build Coastguard Worker                      vk_compute_pipeline_create_flags(pCreateInfo),
2607*61046927SAndroid Build Coastguard Worker                      layout, &stream_desc);
2608*61046927SAndroid Build Coastguard Worker 
2609*61046927SAndroid Build Coastguard Worker    D3D12_SHADER_BYTECODE shader = { 0 };
2610*61046927SAndroid Build Coastguard Worker    VkResult ret =
2611*61046927SAndroid Build Coastguard Worker       dzn_compute_pipeline_compile_shader(device, pipeline, pcache, layout,
2612*61046927SAndroid Build Coastguard Worker                                           &stream_desc, &shader, pCreateInfo);
2613*61046927SAndroid Build Coastguard Worker    if (ret != VK_SUCCESS)
2614*61046927SAndroid Build Coastguard Worker       goto out;
2615*61046927SAndroid Build Coastguard Worker 
2616*61046927SAndroid Build Coastguard Worker    if (FAILED(ID3D12Device4_CreatePipelineState(device->dev, &stream_desc,
2617*61046927SAndroid Build Coastguard Worker                                                 &IID_ID3D12PipelineState,
2618*61046927SAndroid Build Coastguard Worker                                                 (void **)&pipeline->base.state)))
2619*61046927SAndroid Build Coastguard Worker       ret = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2620*61046927SAndroid Build Coastguard Worker 
2621*61046927SAndroid Build Coastguard Worker out:
2622*61046927SAndroid Build Coastguard Worker    free((void *)shader.pShaderBytecode);
2623*61046927SAndroid Build Coastguard Worker    if (ret != VK_SUCCESS)
2624*61046927SAndroid Build Coastguard Worker       dzn_compute_pipeline_destroy(pipeline, pAllocator);
2625*61046927SAndroid Build Coastguard Worker    else
2626*61046927SAndroid Build Coastguard Worker       *out = dzn_compute_pipeline_to_handle(pipeline);
2627*61046927SAndroid Build Coastguard Worker 
2628*61046927SAndroid Build Coastguard Worker    return ret;
2629*61046927SAndroid Build Coastguard Worker }
2630*61046927SAndroid Build Coastguard Worker 
2631*61046927SAndroid Build Coastguard Worker ID3D12CommandSignature *
dzn_compute_pipeline_get_indirect_cmd_sig(struct dzn_compute_pipeline * pipeline)2632*61046927SAndroid Build Coastguard Worker dzn_compute_pipeline_get_indirect_cmd_sig(struct dzn_compute_pipeline *pipeline)
2633*61046927SAndroid Build Coastguard Worker {
2634*61046927SAndroid Build Coastguard Worker    if (pipeline->indirect_cmd_sig)
2635*61046927SAndroid Build Coastguard Worker       return pipeline->indirect_cmd_sig;
2636*61046927SAndroid Build Coastguard Worker 
2637*61046927SAndroid Build Coastguard Worker    struct dzn_device *device =
2638*61046927SAndroid Build Coastguard Worker       container_of(pipeline->base.base.device, struct dzn_device, vk);
2639*61046927SAndroid Build Coastguard Worker 
2640*61046927SAndroid Build Coastguard Worker    D3D12_INDIRECT_ARGUMENT_DESC indirect_dispatch_args[] = {
2641*61046927SAndroid Build Coastguard Worker       {
2642*61046927SAndroid Build Coastguard Worker          .Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT,
2643*61046927SAndroid Build Coastguard Worker          .Constant = {
2644*61046927SAndroid Build Coastguard Worker             .RootParameterIndex = pipeline->base.root.sysval_cbv_param_idx,
2645*61046927SAndroid Build Coastguard Worker             .DestOffsetIn32BitValues = 0,
2646*61046927SAndroid Build Coastguard Worker             .Num32BitValuesToSet = 3,
2647*61046927SAndroid Build Coastguard Worker          },
2648*61046927SAndroid Build Coastguard Worker       },
2649*61046927SAndroid Build Coastguard Worker       {
2650*61046927SAndroid Build Coastguard Worker          .Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,
2651*61046927SAndroid Build Coastguard Worker       },
2652*61046927SAndroid Build Coastguard Worker    };
2653*61046927SAndroid Build Coastguard Worker 
2654*61046927SAndroid Build Coastguard Worker    D3D12_COMMAND_SIGNATURE_DESC indirect_dispatch_desc = {
2655*61046927SAndroid Build Coastguard Worker       .ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS) * 2,
2656*61046927SAndroid Build Coastguard Worker       .NumArgumentDescs = ARRAY_SIZE(indirect_dispatch_args),
2657*61046927SAndroid Build Coastguard Worker       .pArgumentDescs = indirect_dispatch_args,
2658*61046927SAndroid Build Coastguard Worker    };
2659*61046927SAndroid Build Coastguard Worker 
2660*61046927SAndroid Build Coastguard Worker    HRESULT hres =
2661*61046927SAndroid Build Coastguard Worker       ID3D12Device1_CreateCommandSignature(device->dev, &indirect_dispatch_desc,
2662*61046927SAndroid Build Coastguard Worker                                            pipeline->base.root.sig,
2663*61046927SAndroid Build Coastguard Worker                                            &IID_ID3D12CommandSignature,
2664*61046927SAndroid Build Coastguard Worker                                            (void **)&pipeline->indirect_cmd_sig);
2665*61046927SAndroid Build Coastguard Worker    if (FAILED(hres))
2666*61046927SAndroid Build Coastguard Worker       return NULL;
2667*61046927SAndroid Build Coastguard Worker 
2668*61046927SAndroid Build Coastguard Worker    return pipeline->indirect_cmd_sig;
2669*61046927SAndroid Build Coastguard Worker }
2670*61046927SAndroid Build Coastguard Worker 
2671*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateComputePipelines(VkDevice dev,VkPipelineCache pipelineCache,uint32_t count,const VkComputePipelineCreateInfo * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipelines)2672*61046927SAndroid Build Coastguard Worker dzn_CreateComputePipelines(VkDevice dev,
2673*61046927SAndroid Build Coastguard Worker                            VkPipelineCache pipelineCache,
2674*61046927SAndroid Build Coastguard Worker                            uint32_t count,
2675*61046927SAndroid Build Coastguard Worker                            const VkComputePipelineCreateInfo *pCreateInfos,
2676*61046927SAndroid Build Coastguard Worker                            const VkAllocationCallbacks *pAllocator,
2677*61046927SAndroid Build Coastguard Worker                            VkPipeline *pPipelines)
2678*61046927SAndroid Build Coastguard Worker {
2679*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(dzn_device, device, dev);
2680*61046927SAndroid Build Coastguard Worker    VkResult result = VK_SUCCESS;
2681*61046927SAndroid Build Coastguard Worker 
2682*61046927SAndroid Build Coastguard Worker    unsigned i;
2683*61046927SAndroid Build Coastguard Worker    for (i = 0; i < count; i++) {
2684*61046927SAndroid Build Coastguard Worker       result = dzn_compute_pipeline_create(device,
2685*61046927SAndroid Build Coastguard Worker                                            pipelineCache,
2686*61046927SAndroid Build Coastguard Worker                                            &pCreateInfos[i],
2687*61046927SAndroid Build Coastguard Worker                                            pAllocator,
2688*61046927SAndroid Build Coastguard Worker                                            &pPipelines[i]);
2689*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
2690*61046927SAndroid Build Coastguard Worker          pPipelines[i] = VK_NULL_HANDLE;
2691*61046927SAndroid Build Coastguard Worker 
2692*61046927SAndroid Build Coastguard Worker          /* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED_EX as it
2693*61046927SAndroid Build Coastguard Worker           * is not obvious what error should be report upon 2 different failures.
2694*61046927SAndroid Build Coastguard Worker           */
2695*61046927SAndroid Build Coastguard Worker          if (result != VK_PIPELINE_COMPILE_REQUIRED)
2696*61046927SAndroid Build Coastguard Worker             break;
2697*61046927SAndroid Build Coastguard Worker 
2698*61046927SAndroid Build Coastguard Worker          if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT)
2699*61046927SAndroid Build Coastguard Worker             break;
2700*61046927SAndroid Build Coastguard Worker       }
2701*61046927SAndroid Build Coastguard Worker    }
2702*61046927SAndroid Build Coastguard Worker 
2703*61046927SAndroid Build Coastguard Worker    for (; i < count; i++)
2704*61046927SAndroid Build Coastguard Worker       pPipelines[i] = VK_NULL_HANDLE;
2705*61046927SAndroid Build Coastguard Worker 
2706*61046927SAndroid Build Coastguard Worker    return result;
2707*61046927SAndroid Build Coastguard Worker }
2708*61046927SAndroid Build Coastguard Worker 
2709*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
dzn_DestroyPipeline(VkDevice device,VkPipeline pipeline,const VkAllocationCallbacks * pAllocator)2710*61046927SAndroid Build Coastguard Worker dzn_DestroyPipeline(VkDevice device,
2711*61046927SAndroid Build Coastguard Worker                     VkPipeline pipeline,
2712*61046927SAndroid Build Coastguard Worker                     const VkAllocationCallbacks *pAllocator)
2713*61046927SAndroid Build Coastguard Worker {
2714*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(dzn_pipeline, pipe, pipeline);
2715*61046927SAndroid Build Coastguard Worker 
2716*61046927SAndroid Build Coastguard Worker    if (!pipe)
2717*61046927SAndroid Build Coastguard Worker       return;
2718*61046927SAndroid Build Coastguard Worker 
2719*61046927SAndroid Build Coastguard Worker    if (pipe->type == VK_PIPELINE_BIND_POINT_GRAPHICS) {
2720*61046927SAndroid Build Coastguard Worker       struct dzn_graphics_pipeline *gfx = container_of(pipe, struct dzn_graphics_pipeline, base);
2721*61046927SAndroid Build Coastguard Worker       dzn_graphics_pipeline_destroy(gfx, pAllocator);
2722*61046927SAndroid Build Coastguard Worker    } else {
2723*61046927SAndroid Build Coastguard Worker       assert(pipe->type == VK_PIPELINE_BIND_POINT_COMPUTE);
2724*61046927SAndroid Build Coastguard Worker       struct dzn_compute_pipeline *compute = container_of(pipe, struct dzn_compute_pipeline, base);
2725*61046927SAndroid Build Coastguard Worker       dzn_compute_pipeline_destroy(compute, pAllocator);
2726*61046927SAndroid Build Coastguard Worker    }
2727*61046927SAndroid Build Coastguard Worker }
2728