1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2021 Raspberry Pi Ltd
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "v3dv_private.h"
25bf215546Sopenharmony_ci#include "broadcom/common/v3d_macros.h"
26bf215546Sopenharmony_ci#include "broadcom/cle/v3dx_pack.h"
27bf215546Sopenharmony_ci#include "broadcom/compiler/v3d_compiler.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_cistatic uint8_t
30bf215546Sopenharmony_ciblend_factor(VkBlendFactor factor, bool dst_alpha_one, bool *needs_constants)
31bf215546Sopenharmony_ci{
32bf215546Sopenharmony_ci   switch (factor) {
33bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ZERO:
34bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ONE:
35bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_SRC_COLOR:
36bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
37bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_DST_COLOR:
38bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
39bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_SRC_ALPHA:
40bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
41bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE:
42bf215546Sopenharmony_ci      return factor;
43bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_CONSTANT_COLOR:
44bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
45bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_CONSTANT_ALPHA:
46bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
47bf215546Sopenharmony_ci      *needs_constants = true;
48bf215546Sopenharmony_ci      return factor;
49bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_DST_ALPHA:
50bf215546Sopenharmony_ci      return dst_alpha_one ? V3D_BLEND_FACTOR_ONE :
51bf215546Sopenharmony_ci                             V3D_BLEND_FACTOR_DST_ALPHA;
52bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
53bf215546Sopenharmony_ci      return dst_alpha_one ? V3D_BLEND_FACTOR_ZERO :
54bf215546Sopenharmony_ci                             V3D_BLEND_FACTOR_INV_DST_ALPHA;
55bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_SRC1_COLOR:
56bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
57bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_SRC1_ALPHA:
58bf215546Sopenharmony_ci   case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
59bf215546Sopenharmony_ci      assert(!"Invalid blend factor: dual source blending not supported.");
60bf215546Sopenharmony_ci   default:
61bf215546Sopenharmony_ci      assert(!"Unknown blend factor.");
62bf215546Sopenharmony_ci   }
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   /* Should be handled by the switch, added to avoid a "end of non-void
65bf215546Sopenharmony_ci    * function" error
66bf215546Sopenharmony_ci    */
67bf215546Sopenharmony_ci   unreachable("Unknown blend factor.");
68bf215546Sopenharmony_ci}
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_cistatic void
71bf215546Sopenharmony_cipack_blend(struct v3dv_pipeline *pipeline,
72bf215546Sopenharmony_ci           const VkPipelineColorBlendStateCreateInfo *cb_info)
73bf215546Sopenharmony_ci{
74bf215546Sopenharmony_ci   /* By default, we are not enabling blending and all color channel writes are
75bf215546Sopenharmony_ci    * enabled. Color write enables are independent of whether blending is
76bf215546Sopenharmony_ci    * enabled or not.
77bf215546Sopenharmony_ci    *
78bf215546Sopenharmony_ci    * Vulkan specifies color write masks so that bits set correspond to
79bf215546Sopenharmony_ci    * enabled channels. Our hardware does it the other way around.
80bf215546Sopenharmony_ci    */
81bf215546Sopenharmony_ci   pipeline->blend.enables = 0;
82bf215546Sopenharmony_ci   pipeline->blend.color_write_masks = 0; /* All channels enabled */
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   if (!cb_info)
85bf215546Sopenharmony_ci      return;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   assert(pipeline->subpass);
88bf215546Sopenharmony_ci   if (pipeline->subpass->color_count == 0)
89bf215546Sopenharmony_ci      return;
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   assert(pipeline->subpass->color_count == cb_info->attachmentCount);
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   pipeline->blend.needs_color_constants = false;
94bf215546Sopenharmony_ci   uint32_t color_write_masks = 0;
95bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pipeline->subpass->color_count; i++) {
96bf215546Sopenharmony_ci      const VkPipelineColorBlendAttachmentState *b_state =
97bf215546Sopenharmony_ci         &cb_info->pAttachments[i];
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci      uint32_t attachment_idx =
100bf215546Sopenharmony_ci         pipeline->subpass->color_attachments[i].attachment;
101bf215546Sopenharmony_ci      if (attachment_idx == VK_ATTACHMENT_UNUSED)
102bf215546Sopenharmony_ci         continue;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci      color_write_masks |= (~b_state->colorWriteMask & 0xf) << (4 * i);
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci      if (!b_state->blendEnable)
107bf215546Sopenharmony_ci         continue;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci      VkAttachmentDescription2 *desc =
110bf215546Sopenharmony_ci         &pipeline->pass->attachments[attachment_idx].desc;
111bf215546Sopenharmony_ci      const struct v3dv_format *format = v3dX(get_format)(desc->format);
112bf215546Sopenharmony_ci      bool dst_alpha_one = (format->swizzle[3] == PIPE_SWIZZLE_1);
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci      uint8_t rt_mask = 1 << i;
115bf215546Sopenharmony_ci      pipeline->blend.enables |= rt_mask;
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci      v3dvx_pack(pipeline->blend.cfg[i], BLEND_CFG, config) {
118bf215546Sopenharmony_ci         config.render_target_mask = rt_mask;
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci         config.color_blend_mode = b_state->colorBlendOp;
121bf215546Sopenharmony_ci         config.color_blend_dst_factor =
122bf215546Sopenharmony_ci            blend_factor(b_state->dstColorBlendFactor, dst_alpha_one,
123bf215546Sopenharmony_ci                         &pipeline->blend.needs_color_constants);
124bf215546Sopenharmony_ci         config.color_blend_src_factor =
125bf215546Sopenharmony_ci            blend_factor(b_state->srcColorBlendFactor, dst_alpha_one,
126bf215546Sopenharmony_ci                         &pipeline->blend.needs_color_constants);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci         config.alpha_blend_mode = b_state->alphaBlendOp;
129bf215546Sopenharmony_ci         config.alpha_blend_dst_factor =
130bf215546Sopenharmony_ci            blend_factor(b_state->dstAlphaBlendFactor, dst_alpha_one,
131bf215546Sopenharmony_ci                         &pipeline->blend.needs_color_constants);
132bf215546Sopenharmony_ci         config.alpha_blend_src_factor =
133bf215546Sopenharmony_ci            blend_factor(b_state->srcAlphaBlendFactor, dst_alpha_one,
134bf215546Sopenharmony_ci                         &pipeline->blend.needs_color_constants);
135bf215546Sopenharmony_ci      }
136bf215546Sopenharmony_ci   }
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   pipeline->blend.color_write_masks = color_write_masks;
139bf215546Sopenharmony_ci}
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci/* This requires that pack_blend() had been called before so we can set
142bf215546Sopenharmony_ci * the overall blend enable bit in the CFG_BITS packet.
143bf215546Sopenharmony_ci */
144bf215546Sopenharmony_cistatic void
145bf215546Sopenharmony_cipack_cfg_bits(struct v3dv_pipeline *pipeline,
146bf215546Sopenharmony_ci              const VkPipelineDepthStencilStateCreateInfo *ds_info,
147bf215546Sopenharmony_ci              const VkPipelineRasterizationStateCreateInfo *rs_info,
148bf215546Sopenharmony_ci              const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *pv_info,
149bf215546Sopenharmony_ci              const VkPipelineRasterizationLineStateCreateInfoEXT *ls_info,
150bf215546Sopenharmony_ci              const VkPipelineMultisampleStateCreateInfo *ms_info)
151bf215546Sopenharmony_ci{
152bf215546Sopenharmony_ci   assert(sizeof(pipeline->cfg_bits) == cl_packet_length(CFG_BITS));
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci   pipeline->msaa =
155bf215546Sopenharmony_ci      ms_info && ms_info->rasterizationSamples > VK_SAMPLE_COUNT_1_BIT;
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   v3dvx_pack(pipeline->cfg_bits, CFG_BITS, config) {
158bf215546Sopenharmony_ci      config.enable_forward_facing_primitive =
159bf215546Sopenharmony_ci         rs_info ? !(rs_info->cullMode & VK_CULL_MODE_FRONT_BIT) : false;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci      config.enable_reverse_facing_primitive =
162bf215546Sopenharmony_ci         rs_info ? !(rs_info->cullMode & VK_CULL_MODE_BACK_BIT) : false;
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci      /* Seems like the hardware is backwards regarding this setting... */
165bf215546Sopenharmony_ci      config.clockwise_primitives =
166bf215546Sopenharmony_ci         rs_info ? rs_info->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE : false;
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci      config.enable_depth_offset = rs_info ? rs_info->depthBiasEnable: false;
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci      /* This is required to pass line rasterization tests in CTS while
171bf215546Sopenharmony_ci       * exposing, at least, a minimum of 4-bits of subpixel precision
172bf215546Sopenharmony_ci       * (the minimum requirement).
173bf215546Sopenharmony_ci       */
174bf215546Sopenharmony_ci      if (ls_info &&
175bf215546Sopenharmony_ci          ls_info->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT)
176bf215546Sopenharmony_ci         config.line_rasterization = V3D_LINE_RASTERIZATION_DIAMOND_EXIT;
177bf215546Sopenharmony_ci      else
178bf215546Sopenharmony_ci         config.line_rasterization = V3D_LINE_RASTERIZATION_PERP_END_CAPS;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci      if (rs_info && rs_info->polygonMode != VK_POLYGON_MODE_FILL) {
181bf215546Sopenharmony_ci         config.direct3d_wireframe_triangles_mode = true;
182bf215546Sopenharmony_ci         config.direct3d_point_fill_mode =
183bf215546Sopenharmony_ci            rs_info->polygonMode == VK_POLYGON_MODE_POINT;
184bf215546Sopenharmony_ci      }
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci      /* diamond-exit rasterization does not suport oversample */
187bf215546Sopenharmony_ci      config.rasterizer_oversample_mode =
188bf215546Sopenharmony_ci         (config.line_rasterization == V3D_LINE_RASTERIZATION_PERP_END_CAPS &&
189bf215546Sopenharmony_ci          pipeline->msaa) ? 1 : 0;
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci      /* From the Vulkan spec:
192bf215546Sopenharmony_ci       *
193bf215546Sopenharmony_ci       *   "Provoking Vertex:
194bf215546Sopenharmony_ci       *
195bf215546Sopenharmony_ci       *       The vertex in a primitive from which flat shaded attribute
196bf215546Sopenharmony_ci       *       values are taken. This is generally the “first” vertex in the
197bf215546Sopenharmony_ci       *       primitive, and depends on the primitive topology."
198bf215546Sopenharmony_ci       *
199bf215546Sopenharmony_ci       * First vertex is the Direct3D style for provoking vertex. OpenGL uses
200bf215546Sopenharmony_ci       * the last vertex by default.
201bf215546Sopenharmony_ci       */
202bf215546Sopenharmony_ci      if (pv_info) {
203bf215546Sopenharmony_ci         config.direct3d_provoking_vertex =
204bf215546Sopenharmony_ci            pv_info->provokingVertexMode ==
205bf215546Sopenharmony_ci               VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
206bf215546Sopenharmony_ci      } else {
207bf215546Sopenharmony_ci         config.direct3d_provoking_vertex = true;
208bf215546Sopenharmony_ci      }
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci      config.blend_enable = pipeline->blend.enables != 0;
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci      /* Disable depth/stencil if we don't have a D/S attachment */
213bf215546Sopenharmony_ci      bool has_ds_attachment =
214bf215546Sopenharmony_ci         pipeline->subpass->ds_attachment.attachment != VK_ATTACHMENT_UNUSED;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci      if (ds_info && ds_info->depthTestEnable && has_ds_attachment) {
217bf215546Sopenharmony_ci         config.z_updates_enable = ds_info->depthWriteEnable;
218bf215546Sopenharmony_ci         config.depth_test_function = ds_info->depthCompareOp;
219bf215546Sopenharmony_ci      } else {
220bf215546Sopenharmony_ci         config.depth_test_function = VK_COMPARE_OP_ALWAYS;
221bf215546Sopenharmony_ci      }
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci      /* EZ state will be updated at draw time based on bound pipeline state */
224bf215546Sopenharmony_ci      config.early_z_updates_enable = false;
225bf215546Sopenharmony_ci      config.early_z_enable = false;
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci      config.stencil_enable =
228bf215546Sopenharmony_ci         ds_info ? ds_info->stencilTestEnable && has_ds_attachment: false;
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci      pipeline->z_updates_enable = config.z_updates_enable;
231bf215546Sopenharmony_ci   };
232bf215546Sopenharmony_ci}
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_cistatic uint32_t
235bf215546Sopenharmony_citranslate_stencil_op(enum pipe_stencil_op op)
236bf215546Sopenharmony_ci{
237bf215546Sopenharmony_ci   switch (op) {
238bf215546Sopenharmony_ci   case VK_STENCIL_OP_KEEP:
239bf215546Sopenharmony_ci      return V3D_STENCIL_OP_KEEP;
240bf215546Sopenharmony_ci   case VK_STENCIL_OP_ZERO:
241bf215546Sopenharmony_ci      return V3D_STENCIL_OP_ZERO;
242bf215546Sopenharmony_ci   case VK_STENCIL_OP_REPLACE:
243bf215546Sopenharmony_ci      return V3D_STENCIL_OP_REPLACE;
244bf215546Sopenharmony_ci   case VK_STENCIL_OP_INCREMENT_AND_CLAMP:
245bf215546Sopenharmony_ci      return V3D_STENCIL_OP_INCR;
246bf215546Sopenharmony_ci   case VK_STENCIL_OP_DECREMENT_AND_CLAMP:
247bf215546Sopenharmony_ci      return V3D_STENCIL_OP_DECR;
248bf215546Sopenharmony_ci   case VK_STENCIL_OP_INVERT:
249bf215546Sopenharmony_ci      return V3D_STENCIL_OP_INVERT;
250bf215546Sopenharmony_ci   case VK_STENCIL_OP_INCREMENT_AND_WRAP:
251bf215546Sopenharmony_ci      return V3D_STENCIL_OP_INCWRAP;
252bf215546Sopenharmony_ci   case VK_STENCIL_OP_DECREMENT_AND_WRAP:
253bf215546Sopenharmony_ci      return V3D_STENCIL_OP_DECWRAP;
254bf215546Sopenharmony_ci   default:
255bf215546Sopenharmony_ci      unreachable("bad stencil op");
256bf215546Sopenharmony_ci   }
257bf215546Sopenharmony_ci}
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_cistatic void
260bf215546Sopenharmony_cipack_single_stencil_cfg(struct v3dv_pipeline *pipeline,
261bf215546Sopenharmony_ci                        uint8_t *stencil_cfg,
262bf215546Sopenharmony_ci                        bool is_front,
263bf215546Sopenharmony_ci                        bool is_back,
264bf215546Sopenharmony_ci                        const VkStencilOpState *stencil_state)
265bf215546Sopenharmony_ci{
266bf215546Sopenharmony_ci   /* From the Vulkan spec:
267bf215546Sopenharmony_ci    *
268bf215546Sopenharmony_ci    *   "Reference is an integer reference value that is used in the unsigned
269bf215546Sopenharmony_ci    *    stencil comparison. The reference value used by stencil comparison
270bf215546Sopenharmony_ci    *    must be within the range [0,2^s-1] , where s is the number of bits in
271bf215546Sopenharmony_ci    *    the stencil framebuffer attachment, otherwise the reference value is
272bf215546Sopenharmony_ci    *    considered undefined."
273bf215546Sopenharmony_ci    *
274bf215546Sopenharmony_ci    * In our case, 's' is always 8, so we clamp to that to prevent our packing
275bf215546Sopenharmony_ci    * functions to assert in debug mode if they see larger values.
276bf215546Sopenharmony_ci    *
277bf215546Sopenharmony_ci    * If we have dynamic state we need to make sure we set the corresponding
278bf215546Sopenharmony_ci    * state bits to 0, since cl_emit_with_prepacked ORs the new value with
279bf215546Sopenharmony_ci    * the old.
280bf215546Sopenharmony_ci    */
281bf215546Sopenharmony_ci   const uint8_t write_mask =
282bf215546Sopenharmony_ci      pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK ?
283bf215546Sopenharmony_ci         0 : stencil_state->writeMask & 0xff;
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   const uint8_t compare_mask =
286bf215546Sopenharmony_ci      pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK ?
287bf215546Sopenharmony_ci         0 : stencil_state->compareMask & 0xff;
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci   const uint8_t reference =
290bf215546Sopenharmony_ci      pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK ?
291bf215546Sopenharmony_ci         0 : stencil_state->reference & 0xff;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   v3dvx_pack(stencil_cfg, STENCIL_CFG, config) {
294bf215546Sopenharmony_ci      config.front_config = is_front;
295bf215546Sopenharmony_ci      config.back_config = is_back;
296bf215546Sopenharmony_ci      config.stencil_write_mask = write_mask;
297bf215546Sopenharmony_ci      config.stencil_test_mask = compare_mask;
298bf215546Sopenharmony_ci      config.stencil_test_function = stencil_state->compareOp;
299bf215546Sopenharmony_ci      config.stencil_pass_op = translate_stencil_op(stencil_state->passOp);
300bf215546Sopenharmony_ci      config.depth_test_fail_op = translate_stencil_op(stencil_state->depthFailOp);
301bf215546Sopenharmony_ci      config.stencil_test_fail_op = translate_stencil_op(stencil_state->failOp);
302bf215546Sopenharmony_ci      config.stencil_ref_value = reference;
303bf215546Sopenharmony_ci   }
304bf215546Sopenharmony_ci}
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_cistatic void
307bf215546Sopenharmony_cipack_stencil_cfg(struct v3dv_pipeline *pipeline,
308bf215546Sopenharmony_ci                 const VkPipelineDepthStencilStateCreateInfo *ds_info)
309bf215546Sopenharmony_ci{
310bf215546Sopenharmony_ci   assert(sizeof(pipeline->stencil_cfg) == 2 * cl_packet_length(STENCIL_CFG));
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_ci   if (!ds_info || !ds_info->stencilTestEnable)
313bf215546Sopenharmony_ci      return;
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   if (pipeline->subpass->ds_attachment.attachment == VK_ATTACHMENT_UNUSED)
316bf215546Sopenharmony_ci      return;
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci   const uint32_t dynamic_stencil_states = V3DV_DYNAMIC_STENCIL_COMPARE_MASK |
319bf215546Sopenharmony_ci                                           V3DV_DYNAMIC_STENCIL_WRITE_MASK |
320bf215546Sopenharmony_ci                                           V3DV_DYNAMIC_STENCIL_REFERENCE;
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci   /* If front != back or we have dynamic stencil state we can't emit a single
324bf215546Sopenharmony_ci    * packet for both faces.
325bf215546Sopenharmony_ci    */
326bf215546Sopenharmony_ci   bool needs_front_and_back = false;
327bf215546Sopenharmony_ci   if ((pipeline->dynamic_state.mask & dynamic_stencil_states) ||
328bf215546Sopenharmony_ci       memcmp(&ds_info->front, &ds_info->back, sizeof(ds_info->front)))
329bf215546Sopenharmony_ci      needs_front_and_back = true;
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   /* If the front and back configurations are the same we can emit both with
332bf215546Sopenharmony_ci    * a single packet.
333bf215546Sopenharmony_ci    */
334bf215546Sopenharmony_ci   pipeline->emit_stencil_cfg[0] = true;
335bf215546Sopenharmony_ci   if (!needs_front_and_back) {
336bf215546Sopenharmony_ci      pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[0],
337bf215546Sopenharmony_ci                              true, true, &ds_info->front);
338bf215546Sopenharmony_ci   } else {
339bf215546Sopenharmony_ci      pipeline->emit_stencil_cfg[1] = true;
340bf215546Sopenharmony_ci      pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[0],
341bf215546Sopenharmony_ci                              true, false, &ds_info->front);
342bf215546Sopenharmony_ci      pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[1],
343bf215546Sopenharmony_ci                              false, true, &ds_info->back);
344bf215546Sopenharmony_ci   }
345bf215546Sopenharmony_ci}
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_civoid
348bf215546Sopenharmony_civ3dX(pipeline_pack_state)(struct v3dv_pipeline *pipeline,
349bf215546Sopenharmony_ci                          const VkPipelineColorBlendStateCreateInfo *cb_info,
350bf215546Sopenharmony_ci                          const VkPipelineDepthStencilStateCreateInfo *ds_info,
351bf215546Sopenharmony_ci                          const VkPipelineRasterizationStateCreateInfo *rs_info,
352bf215546Sopenharmony_ci                          const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *pv_info,
353bf215546Sopenharmony_ci                          const VkPipelineRasterizationLineStateCreateInfoEXT *ls_info,
354bf215546Sopenharmony_ci                          const VkPipelineMultisampleStateCreateInfo *ms_info)
355bf215546Sopenharmony_ci{
356bf215546Sopenharmony_ci   pack_blend(pipeline, cb_info);
357bf215546Sopenharmony_ci   pack_cfg_bits(pipeline, ds_info, rs_info, pv_info, ls_info, ms_info);
358bf215546Sopenharmony_ci   pack_stencil_cfg(pipeline, ds_info);
359bf215546Sopenharmony_ci}
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_cistatic void
362bf215546Sopenharmony_cipack_shader_state_record(struct v3dv_pipeline *pipeline)
363bf215546Sopenharmony_ci{
364bf215546Sopenharmony_ci   assert(sizeof(pipeline->shader_state_record) ==
365bf215546Sopenharmony_ci          cl_packet_length(GL_SHADER_STATE_RECORD));
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   struct v3d_fs_prog_data *prog_data_fs =
368bf215546Sopenharmony_ci      pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT]->prog_data.fs;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   struct v3d_vs_prog_data *prog_data_vs =
371bf215546Sopenharmony_ci      pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX]->prog_data.vs;
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci   struct v3d_vs_prog_data *prog_data_vs_bin =
374bf215546Sopenharmony_ci      pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX_BIN]->prog_data.vs;
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci   /* Note: we are not packing addresses, as we need the job (see
378bf215546Sopenharmony_ci    * cl_pack_emit_reloc). Additionally uniforms can't be filled up at this
379bf215546Sopenharmony_ci    * point as they depend on dynamic info that can be set after create the
380bf215546Sopenharmony_ci    * pipeline (like viewport), . Would need to be filled later, so we are
381bf215546Sopenharmony_ci    * doing a partial prepacking.
382bf215546Sopenharmony_ci    */
383bf215546Sopenharmony_ci   v3dvx_pack(pipeline->shader_state_record, GL_SHADER_STATE_RECORD, shader) {
384bf215546Sopenharmony_ci      shader.enable_clipping = true;
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci      if (!pipeline->has_gs) {
387bf215546Sopenharmony_ci         shader.point_size_in_shaded_vertex_data =
388bf215546Sopenharmony_ci            pipeline->topology == PIPE_PRIM_POINTS;
389bf215546Sopenharmony_ci      } else {
390bf215546Sopenharmony_ci         struct v3d_gs_prog_data *prog_data_gs =
391bf215546Sopenharmony_ci            pipeline->shared_data->variants[BROADCOM_SHADER_GEOMETRY]->prog_data.gs;
392bf215546Sopenharmony_ci         shader.point_size_in_shaded_vertex_data = prog_data_gs->writes_psiz;
393bf215546Sopenharmony_ci      }
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci      /* Must be set if the shader modifies Z, discards, or modifies
396bf215546Sopenharmony_ci       * the sample mask.  For any of these cases, the fragment
397bf215546Sopenharmony_ci       * shader needs to write the Z value (even just discards).
398bf215546Sopenharmony_ci       */
399bf215546Sopenharmony_ci      shader.fragment_shader_does_z_writes = prog_data_fs->writes_z;
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci      /* Set if the EZ test must be disabled (due to shader side
402bf215546Sopenharmony_ci       * effects and the early_z flag not being present in the
403bf215546Sopenharmony_ci       * shader).
404bf215546Sopenharmony_ci       */
405bf215546Sopenharmony_ci      shader.turn_off_early_z_test = prog_data_fs->disable_ez;
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci      shader.fragment_shader_uses_real_pixel_centre_w_in_addition_to_centroid_w2 =
408bf215546Sopenharmony_ci         prog_data_fs->uses_center_w;
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci      /* The description for gl_SampleID states that if a fragment shader reads
411bf215546Sopenharmony_ci       * it, then we should automatically activate per-sample shading. However,
412bf215546Sopenharmony_ci       * the Vulkan spec also states that if a framebuffer has no attachments:
413bf215546Sopenharmony_ci       *
414bf215546Sopenharmony_ci       *    "The subpass continues to use the width, height, and layers of the
415bf215546Sopenharmony_ci       *     framebuffer to define the dimensions of the rendering area, and the
416bf215546Sopenharmony_ci       *     rasterizationSamples from each pipeline’s
417bf215546Sopenharmony_ci       *     VkPipelineMultisampleStateCreateInfo to define the number of
418bf215546Sopenharmony_ci       *     samples used in rasterization multisample rasterization."
419bf215546Sopenharmony_ci       *
420bf215546Sopenharmony_ci       * So in this scenario, if the pipeline doesn't enable multiple samples
421bf215546Sopenharmony_ci       * but the fragment shader accesses gl_SampleID we would be requested
422bf215546Sopenharmony_ci       * to do per-sample shading in single sample rasterization mode, which
423bf215546Sopenharmony_ci       * is pointless, so just disable it in that case.
424bf215546Sopenharmony_ci       */
425bf215546Sopenharmony_ci      shader.enable_sample_rate_shading =
426bf215546Sopenharmony_ci         pipeline->sample_rate_shading ||
427bf215546Sopenharmony_ci         (pipeline->msaa && prog_data_fs->force_per_sample_msaa);
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci      shader.any_shader_reads_hardware_written_primitive_id = false;
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci      shader.do_scoreboard_wait_on_first_thread_switch =
432bf215546Sopenharmony_ci         prog_data_fs->lock_scoreboard_on_first_thrsw;
433bf215546Sopenharmony_ci      shader.disable_implicit_point_line_varyings =
434bf215546Sopenharmony_ci         !prog_data_fs->uses_implicit_point_line_varyings;
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci      shader.number_of_varyings_in_fragment_shader =
437bf215546Sopenharmony_ci         prog_data_fs->num_inputs;
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci      shader.coordinate_shader_propagate_nans = true;
440bf215546Sopenharmony_ci      shader.vertex_shader_propagate_nans = true;
441bf215546Sopenharmony_ci      shader.fragment_shader_propagate_nans = true;
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci      /* Note: see previous note about adresses */
444bf215546Sopenharmony_ci      /* shader.coordinate_shader_code_address */
445bf215546Sopenharmony_ci      /* shader.vertex_shader_code_address */
446bf215546Sopenharmony_ci      /* shader.fragment_shader_code_address */
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci      /* FIXME: Use combined input/output size flag in the common case (also
449bf215546Sopenharmony_ci       * on v3d, see v3dx_draw).
450bf215546Sopenharmony_ci       */
451bf215546Sopenharmony_ci      shader.coordinate_shader_has_separate_input_and_output_vpm_blocks =
452bf215546Sopenharmony_ci         prog_data_vs_bin->separate_segments;
453bf215546Sopenharmony_ci      shader.vertex_shader_has_separate_input_and_output_vpm_blocks =
454bf215546Sopenharmony_ci         prog_data_vs->separate_segments;
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci      shader.coordinate_shader_input_vpm_segment_size =
457bf215546Sopenharmony_ci         prog_data_vs_bin->separate_segments ?
458bf215546Sopenharmony_ci         prog_data_vs_bin->vpm_input_size : 1;
459bf215546Sopenharmony_ci      shader.vertex_shader_input_vpm_segment_size =
460bf215546Sopenharmony_ci         prog_data_vs->separate_segments ?
461bf215546Sopenharmony_ci         prog_data_vs->vpm_input_size : 1;
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci      shader.coordinate_shader_output_vpm_segment_size =
464bf215546Sopenharmony_ci         prog_data_vs_bin->vpm_output_size;
465bf215546Sopenharmony_ci      shader.vertex_shader_output_vpm_segment_size =
466bf215546Sopenharmony_ci         prog_data_vs->vpm_output_size;
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci      /* Note: see previous note about adresses */
469bf215546Sopenharmony_ci      /* shader.coordinate_shader_uniforms_address */
470bf215546Sopenharmony_ci      /* shader.vertex_shader_uniforms_address */
471bf215546Sopenharmony_ci      /* shader.fragment_shader_uniforms_address */
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci      shader.min_coord_shader_input_segments_required_in_play =
474bf215546Sopenharmony_ci         pipeline->vpm_cfg_bin.As;
475bf215546Sopenharmony_ci      shader.min_vertex_shader_input_segments_required_in_play =
476bf215546Sopenharmony_ci         pipeline->vpm_cfg.As;
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci      shader.min_coord_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size =
479bf215546Sopenharmony_ci         pipeline->vpm_cfg_bin.Ve;
480bf215546Sopenharmony_ci      shader.min_vertex_shader_output_segments_required_in_play_in_addition_to_vcm_cache_size =
481bf215546Sopenharmony_ci         pipeline->vpm_cfg.Ve;
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci      shader.coordinate_shader_4_way_threadable =
484bf215546Sopenharmony_ci         prog_data_vs_bin->base.threads == 4;
485bf215546Sopenharmony_ci      shader.vertex_shader_4_way_threadable =
486bf215546Sopenharmony_ci         prog_data_vs->base.threads == 4;
487bf215546Sopenharmony_ci      shader.fragment_shader_4_way_threadable =
488bf215546Sopenharmony_ci         prog_data_fs->base.threads == 4;
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci      shader.coordinate_shader_start_in_final_thread_section =
491bf215546Sopenharmony_ci         prog_data_vs_bin->base.single_seg;
492bf215546Sopenharmony_ci      shader.vertex_shader_start_in_final_thread_section =
493bf215546Sopenharmony_ci         prog_data_vs->base.single_seg;
494bf215546Sopenharmony_ci      shader.fragment_shader_start_in_final_thread_section =
495bf215546Sopenharmony_ci         prog_data_fs->base.single_seg;
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci      shader.vertex_id_read_by_coordinate_shader =
498bf215546Sopenharmony_ci         prog_data_vs_bin->uses_vid;
499bf215546Sopenharmony_ci      shader.base_instance_id_read_by_coordinate_shader =
500bf215546Sopenharmony_ci         prog_data_vs_bin->uses_biid;
501bf215546Sopenharmony_ci      shader.instance_id_read_by_coordinate_shader =
502bf215546Sopenharmony_ci         prog_data_vs_bin->uses_iid;
503bf215546Sopenharmony_ci      shader.vertex_id_read_by_vertex_shader =
504bf215546Sopenharmony_ci         prog_data_vs->uses_vid;
505bf215546Sopenharmony_ci      shader.base_instance_id_read_by_vertex_shader =
506bf215546Sopenharmony_ci         prog_data_vs->uses_biid;
507bf215546Sopenharmony_ci      shader.instance_id_read_by_vertex_shader =
508bf215546Sopenharmony_ci         prog_data_vs->uses_iid;
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci      /* Note: see previous note about adresses */
511bf215546Sopenharmony_ci      /* shader.address_of_default_attribute_values */
512bf215546Sopenharmony_ci   }
513bf215546Sopenharmony_ci}
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_cistatic void
516bf215546Sopenharmony_cipack_vcm_cache_size(struct v3dv_pipeline *pipeline)
517bf215546Sopenharmony_ci{
518bf215546Sopenharmony_ci   assert(sizeof(pipeline->vcm_cache_size) ==
519bf215546Sopenharmony_ci          cl_packet_length(VCM_CACHE_SIZE));
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci   v3dvx_pack(pipeline->vcm_cache_size, VCM_CACHE_SIZE, vcm) {
522bf215546Sopenharmony_ci      vcm.number_of_16_vertex_batches_for_binning = pipeline->vpm_cfg_bin.Vc;
523bf215546Sopenharmony_ci      vcm.number_of_16_vertex_batches_for_rendering = pipeline->vpm_cfg.Vc;
524bf215546Sopenharmony_ci   }
525bf215546Sopenharmony_ci}
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ci/* As defined on the GL_SHADER_STATE_ATTRIBUTE_RECORD */
528bf215546Sopenharmony_cistatic uint8_t
529bf215546Sopenharmony_ciget_attr_type(const struct util_format_description *desc)
530bf215546Sopenharmony_ci{
531bf215546Sopenharmony_ci   uint32_t r_size = desc->channel[0].size;
532bf215546Sopenharmony_ci   uint8_t attr_type = ATTRIBUTE_FLOAT;
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci   switch (desc->channel[0].type) {
535bf215546Sopenharmony_ci   case UTIL_FORMAT_TYPE_FLOAT:
536bf215546Sopenharmony_ci      if (r_size == 32) {
537bf215546Sopenharmony_ci         attr_type = ATTRIBUTE_FLOAT;
538bf215546Sopenharmony_ci      } else {
539bf215546Sopenharmony_ci         assert(r_size == 16);
540bf215546Sopenharmony_ci         attr_type = ATTRIBUTE_HALF_FLOAT;
541bf215546Sopenharmony_ci      }
542bf215546Sopenharmony_ci      break;
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ci   case UTIL_FORMAT_TYPE_SIGNED:
545bf215546Sopenharmony_ci   case UTIL_FORMAT_TYPE_UNSIGNED:
546bf215546Sopenharmony_ci      switch (r_size) {
547bf215546Sopenharmony_ci      case 32:
548bf215546Sopenharmony_ci         attr_type = ATTRIBUTE_INT;
549bf215546Sopenharmony_ci         break;
550bf215546Sopenharmony_ci      case 16:
551bf215546Sopenharmony_ci         attr_type = ATTRIBUTE_SHORT;
552bf215546Sopenharmony_ci         break;
553bf215546Sopenharmony_ci      case 10:
554bf215546Sopenharmony_ci         attr_type = ATTRIBUTE_INT2_10_10_10;
555bf215546Sopenharmony_ci         break;
556bf215546Sopenharmony_ci      case 8:
557bf215546Sopenharmony_ci         attr_type = ATTRIBUTE_BYTE;
558bf215546Sopenharmony_ci         break;
559bf215546Sopenharmony_ci      default:
560bf215546Sopenharmony_ci         fprintf(stderr,
561bf215546Sopenharmony_ci                 "format %s unsupported\n",
562bf215546Sopenharmony_ci                 desc->name);
563bf215546Sopenharmony_ci         attr_type = ATTRIBUTE_BYTE;
564bf215546Sopenharmony_ci         abort();
565bf215546Sopenharmony_ci      }
566bf215546Sopenharmony_ci      break;
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ci   default:
569bf215546Sopenharmony_ci      fprintf(stderr,
570bf215546Sopenharmony_ci              "format %s unsupported\n",
571bf215546Sopenharmony_ci              desc->name);
572bf215546Sopenharmony_ci      abort();
573bf215546Sopenharmony_ci   }
574bf215546Sopenharmony_ci
575bf215546Sopenharmony_ci   return attr_type;
576bf215546Sopenharmony_ci}
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_cistatic void
579bf215546Sopenharmony_cipack_shader_state_attribute_record(struct v3dv_pipeline *pipeline,
580bf215546Sopenharmony_ci                                   uint32_t index,
581bf215546Sopenharmony_ci                                   const VkVertexInputAttributeDescription *vi_desc)
582bf215546Sopenharmony_ci{
583bf215546Sopenharmony_ci   const uint32_t packet_length =
584bf215546Sopenharmony_ci      cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD);
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci   const struct util_format_description *desc =
587bf215546Sopenharmony_ci      vk_format_description(vi_desc->format);
588bf215546Sopenharmony_ci
589bf215546Sopenharmony_ci   uint32_t binding = vi_desc->binding;
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci   v3dvx_pack(&pipeline->vertex_attrs[index * packet_length],
592bf215546Sopenharmony_ci             GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) {
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_ci      /* vec_size == 0 means 4 */
595bf215546Sopenharmony_ci      attr.vec_size = desc->nr_channels & 3;
596bf215546Sopenharmony_ci      attr.signed_int_type = (desc->channel[0].type ==
597bf215546Sopenharmony_ci                              UTIL_FORMAT_TYPE_SIGNED);
598bf215546Sopenharmony_ci      attr.normalized_int_type = desc->channel[0].normalized;
599bf215546Sopenharmony_ci      attr.read_as_int_uint = desc->channel[0].pure_integer;
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci      attr.instance_divisor = MIN2(pipeline->vb[binding].instance_divisor,
602bf215546Sopenharmony_ci                                   0xffff);
603bf215546Sopenharmony_ci      attr.stride = pipeline->vb[binding].stride;
604bf215546Sopenharmony_ci      attr.type = get_attr_type(desc);
605bf215546Sopenharmony_ci   }
606bf215546Sopenharmony_ci}
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_civoid
609bf215546Sopenharmony_civ3dX(pipeline_pack_compile_state)(struct v3dv_pipeline *pipeline,
610bf215546Sopenharmony_ci                                  const VkPipelineVertexInputStateCreateInfo *vi_info,
611bf215546Sopenharmony_ci                                  const VkPipelineVertexInputDivisorStateCreateInfoEXT *vd_info)
612bf215546Sopenharmony_ci{
613bf215546Sopenharmony_ci   pack_shader_state_record(pipeline);
614bf215546Sopenharmony_ci   pack_vcm_cache_size(pipeline);
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci   pipeline->vb_count = vi_info->vertexBindingDescriptionCount;
617bf215546Sopenharmony_ci   for (uint32_t i = 0; i < vi_info->vertexBindingDescriptionCount; i++) {
618bf215546Sopenharmony_ci      const VkVertexInputBindingDescription *desc =
619bf215546Sopenharmony_ci         &vi_info->pVertexBindingDescriptions[i];
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci      pipeline->vb[desc->binding].stride = desc->stride;
622bf215546Sopenharmony_ci      pipeline->vb[desc->binding].instance_divisor = desc->inputRate;
623bf215546Sopenharmony_ci   }
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci   if (vd_info) {
626bf215546Sopenharmony_ci      for (uint32_t i = 0; i < vd_info->vertexBindingDivisorCount; i++) {
627bf215546Sopenharmony_ci         const VkVertexInputBindingDivisorDescriptionEXT *desc =
628bf215546Sopenharmony_ci            &vd_info->pVertexBindingDivisors[i];
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci         pipeline->vb[desc->binding].instance_divisor = desc->divisor;
631bf215546Sopenharmony_ci      }
632bf215546Sopenharmony_ci   }
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci   pipeline->va_count = 0;
635bf215546Sopenharmony_ci   struct v3d_vs_prog_data *prog_data_vs =
636bf215546Sopenharmony_ci      pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX]->prog_data.vs;
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci   for (uint32_t i = 0; i < vi_info->vertexAttributeDescriptionCount; i++) {
639bf215546Sopenharmony_ci      const VkVertexInputAttributeDescription *desc =
640bf215546Sopenharmony_ci         &vi_info->pVertexAttributeDescriptions[i];
641bf215546Sopenharmony_ci      uint32_t location = desc->location + VERT_ATTRIB_GENERIC0;
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ci      /* We use a custom driver_location_map instead of
644bf215546Sopenharmony_ci       * nir_find_variable_with_location because if we were able to get the
645bf215546Sopenharmony_ci       * shader variant from the cache, we would not have the nir shader
646bf215546Sopenharmony_ci       * available.
647bf215546Sopenharmony_ci       */
648bf215546Sopenharmony_ci      uint32_t driver_location =
649bf215546Sopenharmony_ci         prog_data_vs->driver_location_map[location];
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci      if (driver_location != -1) {
652bf215546Sopenharmony_ci         assert(driver_location < MAX_VERTEX_ATTRIBS);
653bf215546Sopenharmony_ci         pipeline->va[driver_location].offset = desc->offset;
654bf215546Sopenharmony_ci         pipeline->va[driver_location].binding = desc->binding;
655bf215546Sopenharmony_ci         pipeline->va[driver_location].vk_format = desc->format;
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci         pack_shader_state_attribute_record(pipeline, driver_location, desc);
658bf215546Sopenharmony_ci
659bf215546Sopenharmony_ci         pipeline->va_count++;
660bf215546Sopenharmony_ci      }
661bf215546Sopenharmony_ci   }
662bf215546Sopenharmony_ci}
663