1bf215546Sopenharmony_ci#include "vk_graphics_state.h"
2bf215546Sopenharmony_ci
3bf215546Sopenharmony_ci#include "vk_alloc.h"
4bf215546Sopenharmony_ci#include "vk_command_buffer.h"
5bf215546Sopenharmony_ci#include "vk_common_entrypoints.h"
6bf215546Sopenharmony_ci#include "vk_device.h"
7bf215546Sopenharmony_ci#include "vk_log.h"
8bf215546Sopenharmony_ci#include "vk_render_pass.h"
9bf215546Sopenharmony_ci#include "vk_standard_sample_locations.h"
10bf215546Sopenharmony_ci#include "vk_util.h"
11bf215546Sopenharmony_ci
12bf215546Sopenharmony_ci#include <assert.h>
13bf215546Sopenharmony_ci
14bf215546Sopenharmony_cienum mesa_vk_graphics_state_groups {
15bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_VERTEX_INPUT_BIT            = (1 << 0),
16bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_INPUT_ASSEMBLY_BIT          = (1 << 1),
17bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_TESSELLATION_BIT            = (1 << 2),
18bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_VIEWPORT_BIT                = (1 << 3),
19bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_DISCARD_RECTANGLES_BIT      = (1 << 4),
20bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_RASTERIZATION_BIT           = (1 << 5),
21bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_FRAGMENT_SHADING_RATE_BIT   = (1 << 6),
22bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_MULTISAMPLE_BIT             = (1 << 7),
23bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_DEPTH_STENCIL_BIT           = (1 << 8),
24bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_COLOR_BLEND_BIT             = (1 << 9),
25bf215546Sopenharmony_ci   MESA_VK_GRAPHICS_STATE_RENDER_PASS_BIT             = (1 << 10),
26bf215546Sopenharmony_ci};
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_cistatic void
29bf215546Sopenharmony_ciclear_all_dynamic_state(BITSET_WORD *dynamic)
30bf215546Sopenharmony_ci{
31bf215546Sopenharmony_ci   /* Clear the whole array so there are no undefined bits at the top */
32bf215546Sopenharmony_ci   memset(dynamic, 0, sizeof(*dynamic) *
33bf215546Sopenharmony_ci          BITSET_WORDS(MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX));
34bf215546Sopenharmony_ci}
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_cistatic void
37bf215546Sopenharmony_ciget_dynamic_state_groups(BITSET_WORD *dynamic,
38bf215546Sopenharmony_ci                         enum mesa_vk_graphics_state_groups groups)
39bf215546Sopenharmony_ci{
40bf215546Sopenharmony_ci   clear_all_dynamic_state(dynamic);
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_VERTEX_INPUT_BIT) {
43bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_VI);
44bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_VI_BINDING_STRIDES);
45bf215546Sopenharmony_ci   }
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_INPUT_ASSEMBLY_BIT) {
48bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_IA_PRIMITIVE_TOPOLOGY);
49bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_IA_PRIMITIVE_RESTART_ENABLE);
50bf215546Sopenharmony_ci   }
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_TESSELLATION_BIT)
53bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_TS_PATCH_CONTROL_POINTS);
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_VIEWPORT_BIT) {
56bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_VP_VIEWPORT_COUNT);
57bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_VP_VIEWPORTS);
58bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_VP_SCISSOR_COUNT);
59bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_VP_SCISSORS);
60bf215546Sopenharmony_ci   }
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_DISCARD_RECTANGLES_BIT)
63bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DR_RECTANGLES);
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_RASTERIZATION_BIT) {
66bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_RS_RASTERIZER_DISCARD_ENABLE);
67bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_RS_CULL_MODE);
68bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_RS_FRONT_FACE);
69bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_ENABLE);
70bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_FACTORS);
71bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_RS_LINE_WIDTH);
72bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_RS_LINE_STIPPLE);
73bf215546Sopenharmony_ci   }
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_FRAGMENT_SHADING_RATE_BIT)
76bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_FSR);
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_MULTISAMPLE_BIT)
79bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_MS_SAMPLE_LOCATIONS);
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_DEPTH_STENCIL_BIT) {
82bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_TEST_ENABLE);
83bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_WRITE_ENABLE);
84bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_COMPARE_OP);
85bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE);
86bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_BOUNDS);
87bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE);
88bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_OP);
89bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK);
90bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK);
91bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE);
92bf215546Sopenharmony_ci   }
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   if (groups & MESA_VK_GRAPHICS_STATE_COLOR_BLEND_BIT) {
95bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_CB_LOGIC_OP);
96bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES);
97bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS);
98bf215546Sopenharmony_ci   }
99bf215546Sopenharmony_ci}
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_cistatic enum mesa_vk_graphics_state_groups
102bf215546Sopenharmony_cifully_dynamic_state_groups(const BITSET_WORD *dynamic)
103bf215546Sopenharmony_ci{
104bf215546Sopenharmony_ci   enum mesa_vk_graphics_state_groups groups = 0;
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   if (BITSET_TEST(dynamic, MESA_VK_DYNAMIC_VI))
107bf215546Sopenharmony_ci      groups |= MESA_VK_GRAPHICS_STATE_VERTEX_INPUT_BIT;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   if (BITSET_TEST(dynamic, MESA_VK_DYNAMIC_IA_PRIMITIVE_TOPOLOGY) &&
110bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_IA_PRIMITIVE_RESTART_ENABLE))
111bf215546Sopenharmony_ci      groups |= MESA_VK_GRAPHICS_STATE_INPUT_ASSEMBLY_BIT;
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   if (BITSET_TEST(dynamic, MESA_VK_DYNAMIC_FSR))
114bf215546Sopenharmony_ci      groups |= MESA_VK_GRAPHICS_STATE_FRAGMENT_SHADING_RATE_BIT;
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   if (BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_TEST_ENABLE) &&
117bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_WRITE_ENABLE) &&
118bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_COMPARE_OP) &&
119bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE) &&
120bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_BOUNDS) &&
121bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE) &&
122bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_OP) &&
123bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) &&
124bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) &&
125bf215546Sopenharmony_ci       BITSET_TEST(dynamic, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE))
126bf215546Sopenharmony_ci      groups |= MESA_VK_GRAPHICS_STATE_DEPTH_STENCIL_BIT;
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   return groups;
129bf215546Sopenharmony_ci}
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_cistatic void
132bf215546Sopenharmony_civalidate_dynamic_state_groups(const BITSET_WORD *dynamic,
133bf215546Sopenharmony_ci                              enum mesa_vk_graphics_state_groups groups)
134bf215546Sopenharmony_ci{
135bf215546Sopenharmony_ci#ifndef NDEBUG
136bf215546Sopenharmony_ci   BITSET_DECLARE(all_dynamic, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX);
137bf215546Sopenharmony_ci   get_dynamic_state_groups(all_dynamic, groups);
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci   for (uint32_t w = 0; w < ARRAY_SIZE(all_dynamic); w++)
140bf215546Sopenharmony_ci      assert(!(dynamic[w] & ~all_dynamic[w]));
141bf215546Sopenharmony_ci#endif
142bf215546Sopenharmony_ci}
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_civoid
145bf215546Sopenharmony_civk_get_dynamic_graphics_states(BITSET_WORD *dynamic,
146bf215546Sopenharmony_ci                               const VkPipelineDynamicStateCreateInfo *info)
147bf215546Sopenharmony_ci{
148bf215546Sopenharmony_ci   clear_all_dynamic_state(dynamic);
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   /* From the Vulkan 1.3.218 spec:
151bf215546Sopenharmony_ci    *
152bf215546Sopenharmony_ci    *    "pDynamicState is a pointer to a VkPipelineDynamicStateCreateInfo
153bf215546Sopenharmony_ci    *    structure defining which properties of the pipeline state object are
154bf215546Sopenharmony_ci    *    dynamic and can be changed independently of the pipeline state. This
155bf215546Sopenharmony_ci    *    can be NULL, which means no state in the pipeline is considered
156bf215546Sopenharmony_ci    *    dynamic."
157bf215546Sopenharmony_ci    */
158bf215546Sopenharmony_ci   if (info == NULL)
159bf215546Sopenharmony_ci      return;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci#define CASE(VK, MESA) \
162bf215546Sopenharmony_ci   case VK_DYNAMIC_STATE_##VK: \
163bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_##MESA); \
164bf215546Sopenharmony_ci      break;
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci#define CASE2(VK, MESA1, MESA2) \
167bf215546Sopenharmony_ci   case VK_DYNAMIC_STATE_##VK: \
168bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_##MESA1); \
169bf215546Sopenharmony_ci      BITSET_SET(dynamic, MESA_VK_DYNAMIC_##MESA2); \
170bf215546Sopenharmony_ci      break;
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci   for (uint32_t i = 0; i < info->dynamicStateCount; i++) {
173bf215546Sopenharmony_ci      switch (info->pDynamicStates[i]) {
174bf215546Sopenharmony_ci      CASE2(VERTEX_INPUT_EXT,             VI, VI_BINDING_STRIDES)
175bf215546Sopenharmony_ci      CASE( VERTEX_INPUT_BINDING_STRIDE,  VI_BINDING_STRIDES)
176bf215546Sopenharmony_ci      CASE( VIEWPORT,                     VP_VIEWPORTS)
177bf215546Sopenharmony_ci      CASE( SCISSOR,                      VP_SCISSORS)
178bf215546Sopenharmony_ci      CASE( LINE_WIDTH,                   RS_LINE_WIDTH)
179bf215546Sopenharmony_ci      CASE( DEPTH_BIAS,                   RS_DEPTH_BIAS_FACTORS)
180bf215546Sopenharmony_ci      CASE( BLEND_CONSTANTS,              CB_BLEND_CONSTANTS)
181bf215546Sopenharmony_ci      CASE( DEPTH_BOUNDS,                 DS_DEPTH_BOUNDS_TEST_BOUNDS)
182bf215546Sopenharmony_ci      CASE( STENCIL_COMPARE_MASK,         DS_STENCIL_COMPARE_MASK)
183bf215546Sopenharmony_ci      CASE( STENCIL_WRITE_MASK,           DS_STENCIL_WRITE_MASK)
184bf215546Sopenharmony_ci      CASE( STENCIL_REFERENCE,            DS_STENCIL_REFERENCE)
185bf215546Sopenharmony_ci      CASE( CULL_MODE,                    RS_CULL_MODE)
186bf215546Sopenharmony_ci      CASE( FRONT_FACE,                   RS_FRONT_FACE)
187bf215546Sopenharmony_ci      CASE( PRIMITIVE_TOPOLOGY,           IA_PRIMITIVE_TOPOLOGY)
188bf215546Sopenharmony_ci      CASE2(VIEWPORT_WITH_COUNT,          VP_VIEWPORT_COUNT, VP_VIEWPORTS)
189bf215546Sopenharmony_ci      CASE2(SCISSOR_WITH_COUNT,           VP_SCISSOR_COUNT, VP_SCISSORS)
190bf215546Sopenharmony_ci      CASE( DEPTH_TEST_ENABLE,            DS_DEPTH_TEST_ENABLE)
191bf215546Sopenharmony_ci      CASE( DEPTH_WRITE_ENABLE,           DS_DEPTH_WRITE_ENABLE)
192bf215546Sopenharmony_ci      CASE( DEPTH_COMPARE_OP,             DS_DEPTH_COMPARE_OP)
193bf215546Sopenharmony_ci      CASE( DEPTH_BOUNDS_TEST_ENABLE,     DS_DEPTH_BOUNDS_TEST_ENABLE)
194bf215546Sopenharmony_ci      CASE( STENCIL_TEST_ENABLE,          DS_STENCIL_TEST_ENABLE)
195bf215546Sopenharmony_ci      CASE( STENCIL_OP,                   DS_STENCIL_OP)
196bf215546Sopenharmony_ci      CASE( RASTERIZER_DISCARD_ENABLE,    RS_RASTERIZER_DISCARD_ENABLE)
197bf215546Sopenharmony_ci      CASE( DEPTH_BIAS_ENABLE,            RS_DEPTH_BIAS_ENABLE)
198bf215546Sopenharmony_ci      CASE( PRIMITIVE_RESTART_ENABLE,     IA_PRIMITIVE_RESTART_ENABLE)
199bf215546Sopenharmony_ci      CASE( DISCARD_RECTANGLE_EXT,        DR_RECTANGLES)
200bf215546Sopenharmony_ci      CASE( SAMPLE_LOCATIONS_EXT,         MS_SAMPLE_LOCATIONS)
201bf215546Sopenharmony_ci      CASE( FRAGMENT_SHADING_RATE_KHR,    FSR)
202bf215546Sopenharmony_ci      CASE( LINE_STIPPLE_EXT,             RS_LINE_STIPPLE)
203bf215546Sopenharmony_ci      CASE( PATCH_CONTROL_POINTS_EXT,     TS_PATCH_CONTROL_POINTS)
204bf215546Sopenharmony_ci      CASE( LOGIC_OP_EXT,                 CB_LOGIC_OP)
205bf215546Sopenharmony_ci      CASE( COLOR_WRITE_ENABLE_EXT,       CB_COLOR_WRITE_ENABLES)
206bf215546Sopenharmony_ci      default:
207bf215546Sopenharmony_ci         unreachable("Unsupported dynamic graphics state");
208bf215546Sopenharmony_ci      }
209bf215546Sopenharmony_ci   }
210bf215546Sopenharmony_ci}
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci#define IS_DYNAMIC(STATE) \
213bf215546Sopenharmony_ci   BITSET_TEST(dynamic, MESA_VK_DYNAMIC_##STATE)
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci#define IS_NEEDED(STATE) \
216bf215546Sopenharmony_ci   BITSET_TEST(needed, MESA_VK_DYNAMIC_##STATE)
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_cistatic void
219bf215546Sopenharmony_civk_vertex_input_state_init(struct vk_vertex_input_state *vi,
220bf215546Sopenharmony_ci                           const BITSET_WORD *dynamic,
221bf215546Sopenharmony_ci                           const VkPipelineVertexInputStateCreateInfo *vi_info)
222bf215546Sopenharmony_ci{
223bf215546Sopenharmony_ci   assert(!IS_DYNAMIC(VI));
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   memset(vi, 0, sizeof(*vi));
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   for (uint32_t i = 0; i < vi_info->vertexBindingDescriptionCount; i++) {
228bf215546Sopenharmony_ci      const VkVertexInputBindingDescription *desc =
229bf215546Sopenharmony_ci         &vi_info->pVertexBindingDescriptions[i];
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci      assert(desc->binding < MESA_VK_MAX_VERTEX_BINDINGS);
232bf215546Sopenharmony_ci      assert(desc->stride <= MESA_VK_MAX_VERTEX_BINDING_STRIDE);
233bf215546Sopenharmony_ci      assert(desc->inputRate <= 1);
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci      const uint32_t b = desc->binding;
236bf215546Sopenharmony_ci      vi->bindings_valid |= BITFIELD_BIT(b);
237bf215546Sopenharmony_ci      vi->bindings[b].stride = desc->stride;
238bf215546Sopenharmony_ci      vi->bindings[b].input_rate = desc->inputRate;
239bf215546Sopenharmony_ci      vi->bindings[b].divisor = 1;
240bf215546Sopenharmony_ci   }
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci   for (uint32_t i = 0; i < vi_info->vertexAttributeDescriptionCount; i++) {
243bf215546Sopenharmony_ci      const VkVertexInputAttributeDescription *desc =
244bf215546Sopenharmony_ci         &vi_info->pVertexAttributeDescriptions[i];
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci      assert(desc->location < MESA_VK_MAX_VERTEX_ATTRIBUTES);
247bf215546Sopenharmony_ci      assert(desc->binding < MESA_VK_MAX_VERTEX_BINDINGS);
248bf215546Sopenharmony_ci      assert(vi->bindings_valid & BITFIELD_BIT(desc->binding));
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci      const uint32_t a = desc->location;
251bf215546Sopenharmony_ci      vi->attributes_valid |= BITFIELD_BIT(a);
252bf215546Sopenharmony_ci      vi->attributes[a].binding = desc->binding;
253bf215546Sopenharmony_ci      vi->attributes[a].format = desc->format;
254bf215546Sopenharmony_ci      vi->attributes[a].offset = desc->offset;
255bf215546Sopenharmony_ci   }
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   const VkPipelineVertexInputDivisorStateCreateInfoEXT *vi_div_state =
258bf215546Sopenharmony_ci      vk_find_struct_const(vi_info->pNext,
259bf215546Sopenharmony_ci                           PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
260bf215546Sopenharmony_ci   if (vi_div_state) {
261bf215546Sopenharmony_ci      for (uint32_t i = 0; i < vi_div_state->vertexBindingDivisorCount; i++) {
262bf215546Sopenharmony_ci         const VkVertexInputBindingDivisorDescriptionEXT *desc =
263bf215546Sopenharmony_ci            &vi_div_state->pVertexBindingDivisors[i];
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci         assert(desc->binding < MESA_VK_MAX_VERTEX_BINDINGS);
266bf215546Sopenharmony_ci         assert(vi->bindings_valid & BITFIELD_BIT(desc->binding));
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci         const uint32_t b = desc->binding;
269bf215546Sopenharmony_ci         vi->bindings[b].divisor = desc->divisor;
270bf215546Sopenharmony_ci      }
271bf215546Sopenharmony_ci   }
272bf215546Sopenharmony_ci}
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_cistatic void
275bf215546Sopenharmony_civk_dynamic_graphics_state_init_vi(struct vk_dynamic_graphics_state *dst,
276bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
277bf215546Sopenharmony_ci                                  const struct vk_vertex_input_state *vi)
278bf215546Sopenharmony_ci{
279bf215546Sopenharmony_ci   if (IS_NEEDED(VI))
280bf215546Sopenharmony_ci      *dst->vi = *vi;
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   if (IS_NEEDED(VI_BINDING_STRIDES)) {
283bf215546Sopenharmony_ci      for (uint32_t b = 0; b < MESA_VK_MAX_VERTEX_BINDINGS; b++) {
284bf215546Sopenharmony_ci         if (vi->bindings_valid & BITFIELD_BIT(b))
285bf215546Sopenharmony_ci            dst->vi_binding_strides[b] = vi->bindings[b].stride;
286bf215546Sopenharmony_ci         else
287bf215546Sopenharmony_ci            dst->vi_binding_strides[b] = 0;
288bf215546Sopenharmony_ci      }
289bf215546Sopenharmony_ci   }
290bf215546Sopenharmony_ci}
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_cistatic void
293bf215546Sopenharmony_civk_input_assembly_state_init(struct vk_input_assembly_state *ia,
294bf215546Sopenharmony_ci                             const BITSET_WORD *dynamic,
295bf215546Sopenharmony_ci                             const VkPipelineInputAssemblyStateCreateInfo *ia_info)
296bf215546Sopenharmony_ci{
297bf215546Sopenharmony_ci   if (IS_DYNAMIC(IA_PRIMITIVE_TOPOLOGY)) {
298bf215546Sopenharmony_ci      ia->primitive_topology = -1;
299bf215546Sopenharmony_ci   } else {
300bf215546Sopenharmony_ci      assert(ia_info->topology <= UINT8_MAX);
301bf215546Sopenharmony_ci      ia->primitive_topology = ia_info->topology;
302bf215546Sopenharmony_ci   }
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci   ia->primitive_restart_enable = ia_info->primitiveRestartEnable;
305bf215546Sopenharmony_ci}
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_cistatic void
308bf215546Sopenharmony_civk_dynamic_graphics_state_init_ia(struct vk_dynamic_graphics_state *dst,
309bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
310bf215546Sopenharmony_ci                                  const struct vk_input_assembly_state *ia)
311bf215546Sopenharmony_ci{
312bf215546Sopenharmony_ci   dst->ia = *ia;
313bf215546Sopenharmony_ci}
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_cistatic void
316bf215546Sopenharmony_civk_tessellation_state_init(struct vk_tessellation_state *ts,
317bf215546Sopenharmony_ci                           const BITSET_WORD *dynamic,
318bf215546Sopenharmony_ci                           const VkPipelineTessellationStateCreateInfo *ts_info)
319bf215546Sopenharmony_ci{
320bf215546Sopenharmony_ci   if (IS_DYNAMIC(TS_PATCH_CONTROL_POINTS)) {
321bf215546Sopenharmony_ci      ts->patch_control_points = 0;
322bf215546Sopenharmony_ci   } else {
323bf215546Sopenharmony_ci      assert(ts_info->patchControlPoints <= UINT8_MAX);
324bf215546Sopenharmony_ci      ts->patch_control_points = ts_info->patchControlPoints;
325bf215546Sopenharmony_ci   }
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci   const VkPipelineTessellationDomainOriginStateCreateInfo *ts_do_info =
328bf215546Sopenharmony_ci      vk_find_struct_const(ts_info->pNext,
329bf215546Sopenharmony_ci                           PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO);
330bf215546Sopenharmony_ci   if (ts_do_info != NULL) {
331bf215546Sopenharmony_ci      assert(ts_do_info->domainOrigin <= UINT8_MAX);
332bf215546Sopenharmony_ci      ts->domain_origin = ts_do_info->domainOrigin;
333bf215546Sopenharmony_ci   } else {
334bf215546Sopenharmony_ci      ts->domain_origin = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
335bf215546Sopenharmony_ci   }
336bf215546Sopenharmony_ci}
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_cistatic void
339bf215546Sopenharmony_civk_dynamic_graphics_state_init_ts(struct vk_dynamic_graphics_state *dst,
340bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
341bf215546Sopenharmony_ci                                  const struct vk_tessellation_state *ts)
342bf215546Sopenharmony_ci{
343bf215546Sopenharmony_ci   dst->ts.patch_control_points = ts->patch_control_points;
344bf215546Sopenharmony_ci}
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_cistatic void
347bf215546Sopenharmony_civk_viewport_state_init(struct vk_viewport_state *vp,
348bf215546Sopenharmony_ci                       const BITSET_WORD *dynamic,
349bf215546Sopenharmony_ci                       const VkPipelineViewportStateCreateInfo *vp_info)
350bf215546Sopenharmony_ci{
351bf215546Sopenharmony_ci   memset(vp, 0, sizeof(*vp));
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci   if (!IS_DYNAMIC(VP_VIEWPORT_COUNT)) {
354bf215546Sopenharmony_ci      assert(vp_info->viewportCount <= MESA_VK_MAX_VIEWPORTS);
355bf215546Sopenharmony_ci      vp->viewport_count = vp_info->viewportCount;
356bf215546Sopenharmony_ci   }
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci   if (!IS_DYNAMIC(VP_VIEWPORTS)) {
359bf215546Sopenharmony_ci      assert(!IS_DYNAMIC(VP_VIEWPORT_COUNT));
360bf215546Sopenharmony_ci      typed_memcpy(vp->viewports, vp_info->pViewports,
361bf215546Sopenharmony_ci                   vp_info->viewportCount);
362bf215546Sopenharmony_ci   }
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci   if (!IS_DYNAMIC(VP_SCISSOR_COUNT)) {
365bf215546Sopenharmony_ci      assert(vp_info->scissorCount <= MESA_VK_MAX_SCISSORS);
366bf215546Sopenharmony_ci      vp->scissor_count = vp_info->scissorCount;
367bf215546Sopenharmony_ci   }
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci   if (!IS_DYNAMIC(VP_SCISSORS)) {
370bf215546Sopenharmony_ci      assert(!IS_DYNAMIC(VP_SCISSOR_COUNT));
371bf215546Sopenharmony_ci      typed_memcpy(vp->scissors, vp_info->pScissors,
372bf215546Sopenharmony_ci                   vp_info->scissorCount);
373bf215546Sopenharmony_ci   }
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   const VkPipelineViewportDepthClipControlCreateInfoEXT *vp_dcc_info =
376bf215546Sopenharmony_ci      vk_find_struct_const(vp_info->pNext,
377bf215546Sopenharmony_ci                           PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT);
378bf215546Sopenharmony_ci   if (vp_dcc_info != NULL)
379bf215546Sopenharmony_ci      vp->negative_one_to_one = vp_dcc_info->negativeOneToOne;
380bf215546Sopenharmony_ci}
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_cistatic void
383bf215546Sopenharmony_civk_dynamic_graphics_state_init_vp(struct vk_dynamic_graphics_state *dst,
384bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
385bf215546Sopenharmony_ci                                  const struct vk_viewport_state *vp)
386bf215546Sopenharmony_ci{
387bf215546Sopenharmony_ci   dst->vp.viewport_count = vp->viewport_count;
388bf215546Sopenharmony_ci   if (IS_NEEDED(VP_VIEWPORTS))
389bf215546Sopenharmony_ci      typed_memcpy(dst->vp.viewports, vp->viewports, vp->viewport_count);
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci   dst->vp.scissor_count = vp->scissor_count;
392bf215546Sopenharmony_ci   if (IS_NEEDED(VP_SCISSORS))
393bf215546Sopenharmony_ci      typed_memcpy(dst->vp.scissors, vp->scissors, vp->scissor_count);
394bf215546Sopenharmony_ci}
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_cistatic void
397bf215546Sopenharmony_civk_discard_rectangles_state_init(struct vk_discard_rectangles_state *dr,
398bf215546Sopenharmony_ci                                 const BITSET_WORD *dynamic,
399bf215546Sopenharmony_ci                                 const VkPipelineDiscardRectangleStateCreateInfoEXT *dr_info)
400bf215546Sopenharmony_ci{
401bf215546Sopenharmony_ci   memset(dr, 0, sizeof(*dr));
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci   if (dr_info == NULL)
404bf215546Sopenharmony_ci      return;
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci   dr->mode = dr_info->discardRectangleMode;
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci   if (!IS_DYNAMIC(DR_RECTANGLES)) {
409bf215546Sopenharmony_ci      assert(dr_info->discardRectangleCount <= MESA_VK_MAX_DISCARD_RECTANGLES);
410bf215546Sopenharmony_ci      dr->rectangle_count = dr_info->discardRectangleCount;
411bf215546Sopenharmony_ci      typed_memcpy(dr->rectangles, dr_info->pDiscardRectangles,
412bf215546Sopenharmony_ci                   dr_info->discardRectangleCount);
413bf215546Sopenharmony_ci   }
414bf215546Sopenharmony_ci}
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_cistatic void
417bf215546Sopenharmony_civk_dynamic_graphics_state_init_dr(struct vk_dynamic_graphics_state *dst,
418bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
419bf215546Sopenharmony_ci                                  const struct vk_discard_rectangles_state *dr)
420bf215546Sopenharmony_ci{
421bf215546Sopenharmony_ci   dst->dr.rectangle_count = dr->rectangle_count;
422bf215546Sopenharmony_ci   typed_memcpy(dst->dr.rectangles, dr->rectangles, dr->rectangle_count);
423bf215546Sopenharmony_ci}
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_cistatic void
426bf215546Sopenharmony_civk_rasterization_state_init(struct vk_rasterization_state *rs,
427bf215546Sopenharmony_ci                            const BITSET_WORD *dynamic,
428bf215546Sopenharmony_ci                            const VkPipelineRasterizationStateCreateInfo *rs_info)
429bf215546Sopenharmony_ci{
430bf215546Sopenharmony_ci   *rs = (struct vk_rasterization_state) {
431bf215546Sopenharmony_ci      .rasterizer_discard_enable = false,
432bf215546Sopenharmony_ci      .conservative_mode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT,
433bf215546Sopenharmony_ci      .rasterization_order_amd = VK_RASTERIZATION_ORDER_STRICT_AMD,
434bf215546Sopenharmony_ci      .provoking_vertex = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT,
435bf215546Sopenharmony_ci      .line.mode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT,
436bf215546Sopenharmony_ci   };
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci   if (!IS_DYNAMIC(RS_RASTERIZER_DISCARD_ENABLE))
439bf215546Sopenharmony_ci      rs->rasterizer_discard_enable = rs_info->rasterizerDiscardEnable;
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci   /* From the Vulkan 1.3.218 spec:
442bf215546Sopenharmony_ci    *
443bf215546Sopenharmony_ci    *    "If VkPipelineRasterizationDepthClipStateCreateInfoEXT is present in
444bf215546Sopenharmony_ci    *    the graphics pipeline state then depth clipping is disabled if
445bf215546Sopenharmony_ci    *    VkPipelineRasterizationDepthClipStateCreateInfoEXT::depthClipEnable
446bf215546Sopenharmony_ci    *    is VK_FALSE. Otherwise, if
447bf215546Sopenharmony_ci    *    VkPipelineRasterizationDepthClipStateCreateInfoEXT is not present,
448bf215546Sopenharmony_ci    *    depth clipping is disabled when
449bf215546Sopenharmony_ci    *    VkPipelineRasterizationStateCreateInfo::depthClampEnable is VK_TRUE.
450bf215546Sopenharmony_ci    */
451bf215546Sopenharmony_ci   rs->depth_clamp_enable = rs_info->depthClampEnable;
452bf215546Sopenharmony_ci   rs->depth_clip_enable = !rs_info->depthClampEnable;
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci   rs->polygon_mode = rs_info->polygonMode;
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci   rs->cull_mode = rs_info->cullMode;
457bf215546Sopenharmony_ci   rs->front_face = rs_info->frontFace;
458bf215546Sopenharmony_ci   rs->depth_bias.enable = rs_info->depthBiasEnable;
459bf215546Sopenharmony_ci   if ((rs_info->depthBiasEnable || IS_DYNAMIC(RS_DEPTH_BIAS_ENABLE)) &&
460bf215546Sopenharmony_ci       !IS_DYNAMIC(RS_DEPTH_BIAS_FACTORS)) {
461bf215546Sopenharmony_ci      rs->depth_bias.constant = rs_info->depthBiasConstantFactor;
462bf215546Sopenharmony_ci      rs->depth_bias.clamp = rs_info->depthBiasClamp;
463bf215546Sopenharmony_ci      rs->depth_bias.slope = rs_info->depthBiasSlopeFactor;
464bf215546Sopenharmony_ci   }
465bf215546Sopenharmony_ci   rs->line.width = rs_info->lineWidth;
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci   vk_foreach_struct_const(ext, rs_info->pNext) {
468bf215546Sopenharmony_ci      switch (ext->sType) {
469bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT: {
470bf215546Sopenharmony_ci         const VkPipelineRasterizationConservativeStateCreateInfoEXT *rcs_info =
471bf215546Sopenharmony_ci            (const VkPipelineRasterizationConservativeStateCreateInfoEXT *)ext;
472bf215546Sopenharmony_ci         rs->conservative_mode = rcs_info->conservativeRasterizationMode;
473bf215546Sopenharmony_ci         break;
474bf215546Sopenharmony_ci      }
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT: {
477bf215546Sopenharmony_ci         const VkPipelineRasterizationDepthClipStateCreateInfoEXT *rdc_info =
478bf215546Sopenharmony_ci            (const VkPipelineRasterizationDepthClipStateCreateInfoEXT *)ext;
479bf215546Sopenharmony_ci         rs->depth_clip_enable = rdc_info->depthClipEnable;
480bf215546Sopenharmony_ci         break;
481bf215546Sopenharmony_ci      }
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT: {
484bf215546Sopenharmony_ci         const VkPipelineRasterizationLineStateCreateInfoEXT *rl_info =
485bf215546Sopenharmony_ci            (const VkPipelineRasterizationLineStateCreateInfoEXT *)ext;
486bf215546Sopenharmony_ci         rs->line.mode = rl_info->lineRasterizationMode;
487bf215546Sopenharmony_ci         rs->line.stipple.enable = rl_info->stippledLineEnable;
488bf215546Sopenharmony_ci         if (rs->line.stipple.enable && !IS_DYNAMIC(RS_LINE_STIPPLE)) {
489bf215546Sopenharmony_ci            rs->line.stipple.factor = rl_info->lineStippleFactor;
490bf215546Sopenharmony_ci            rs->line.stipple.pattern = rl_info->lineStipplePattern;
491bf215546Sopenharmony_ci         }
492bf215546Sopenharmony_ci         break;
493bf215546Sopenharmony_ci      }
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT: {
496bf215546Sopenharmony_ci         const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *rpv_info =
497bf215546Sopenharmony_ci            (const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *)ext;
498bf215546Sopenharmony_ci         rs->provoking_vertex = rpv_info->provokingVertexMode;
499bf215546Sopenharmony_ci         break;
500bf215546Sopenharmony_ci      }
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD: {
503bf215546Sopenharmony_ci         const VkPipelineRasterizationStateRasterizationOrderAMD *rro_info =
504bf215546Sopenharmony_ci            (const VkPipelineRasterizationStateRasterizationOrderAMD *)ext;
505bf215546Sopenharmony_ci         rs->rasterization_order_amd = rro_info->rasterizationOrder;
506bf215546Sopenharmony_ci         break;
507bf215546Sopenharmony_ci      }
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT: {
510bf215546Sopenharmony_ci         const VkPipelineRasterizationStateStreamCreateInfoEXT *rss_info =
511bf215546Sopenharmony_ci            (const VkPipelineRasterizationStateStreamCreateInfoEXT *)ext;
512bf215546Sopenharmony_ci         rs->rasterization_stream = rss_info->rasterizationStream;
513bf215546Sopenharmony_ci         break;
514bf215546Sopenharmony_ci      }
515bf215546Sopenharmony_ci
516bf215546Sopenharmony_ci      default:
517bf215546Sopenharmony_ci         break;
518bf215546Sopenharmony_ci      }
519bf215546Sopenharmony_ci   }
520bf215546Sopenharmony_ci}
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_cistatic void
523bf215546Sopenharmony_civk_dynamic_graphics_state_init_rs(struct vk_dynamic_graphics_state *dst,
524bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
525bf215546Sopenharmony_ci                                  const struct vk_rasterization_state *rs)
526bf215546Sopenharmony_ci{
527bf215546Sopenharmony_ci   dst->rs.rasterizer_discard_enable = rs->rasterizer_discard_enable;
528bf215546Sopenharmony_ci   dst->rs.cull_mode = rs->cull_mode;
529bf215546Sopenharmony_ci   dst->rs.front_face = rs->front_face;
530bf215546Sopenharmony_ci   dst->rs.depth_bias.enable = rs->depth_bias.enable;
531bf215546Sopenharmony_ci   dst->rs.depth_bias.constant = rs->depth_bias.constant;
532bf215546Sopenharmony_ci   dst->rs.depth_bias.clamp = rs->depth_bias.clamp;
533bf215546Sopenharmony_ci   dst->rs.depth_bias.slope = rs->depth_bias.slope;
534bf215546Sopenharmony_ci   dst->rs.line.width = rs->line.width;
535bf215546Sopenharmony_ci   dst->rs.line.stipple.factor = rs->line.stipple.factor;
536bf215546Sopenharmony_ci   dst->rs.line.stipple.pattern = rs->line.stipple.pattern;
537bf215546Sopenharmony_ci}
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_cistatic void
540bf215546Sopenharmony_civk_fragment_shading_rate_state_init(
541bf215546Sopenharmony_ci   struct vk_fragment_shading_rate_state *fsr,
542bf215546Sopenharmony_ci   const BITSET_WORD *dynamic,
543bf215546Sopenharmony_ci   const VkPipelineFragmentShadingRateStateCreateInfoKHR *fsr_info)
544bf215546Sopenharmony_ci{
545bf215546Sopenharmony_ci   if (fsr_info != NULL) {
546bf215546Sopenharmony_ci      fsr->fragment_size = fsr_info->fragmentSize;
547bf215546Sopenharmony_ci      fsr->combiner_ops[0] = fsr_info->combinerOps[0];
548bf215546Sopenharmony_ci      fsr->combiner_ops[1] = fsr_info->combinerOps[1];
549bf215546Sopenharmony_ci   } else {
550bf215546Sopenharmony_ci      fsr->fragment_size = (VkExtent2D) { 1, 1 };
551bf215546Sopenharmony_ci      fsr->combiner_ops[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR;
552bf215546Sopenharmony_ci      fsr->combiner_ops[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR;
553bf215546Sopenharmony_ci   }
554bf215546Sopenharmony_ci}
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_cistatic void
557bf215546Sopenharmony_civk_dynamic_graphics_state_init_fsr(
558bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dst,
559bf215546Sopenharmony_ci   const BITSET_WORD *needed,
560bf215546Sopenharmony_ci   const struct vk_fragment_shading_rate_state *fsr)
561bf215546Sopenharmony_ci{
562bf215546Sopenharmony_ci   dst->fsr = *fsr;
563bf215546Sopenharmony_ci}
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_cistatic void
566bf215546Sopenharmony_civk_sample_locations_state_init(struct vk_sample_locations_state *sl,
567bf215546Sopenharmony_ci                               const VkSampleLocationsInfoEXT *sl_info)
568bf215546Sopenharmony_ci{
569bf215546Sopenharmony_ci   sl->per_pixel = sl_info->sampleLocationsPerPixel;
570bf215546Sopenharmony_ci   sl->grid_size = sl_info->sampleLocationGridSize;
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci   /* From the Vulkan 1.3.218 spec:
573bf215546Sopenharmony_ci    *
574bf215546Sopenharmony_ci    *    VUID-VkSampleLocationsInfoEXT-sampleLocationsCount-01527
575bf215546Sopenharmony_ci    *
576bf215546Sopenharmony_ci    *    "sampleLocationsCount must equal sampleLocationsPerPixel *
577bf215546Sopenharmony_ci    *    sampleLocationGridSize.width * sampleLocationGridSize.height"
578bf215546Sopenharmony_ci    */
579bf215546Sopenharmony_ci   assert(sl_info->sampleLocationsCount ==
580bf215546Sopenharmony_ci          sl_info->sampleLocationsPerPixel *
581bf215546Sopenharmony_ci          sl_info->sampleLocationGridSize.width *
582bf215546Sopenharmony_ci          sl_info->sampleLocationGridSize.height);
583bf215546Sopenharmony_ci
584bf215546Sopenharmony_ci   assert(sl_info->sampleLocationsCount <= MESA_VK_MAX_SAMPLE_LOCATIONS);
585bf215546Sopenharmony_ci   typed_memcpy(sl->locations, sl_info->pSampleLocations,
586bf215546Sopenharmony_ci                sl_info->sampleLocationsCount);
587bf215546Sopenharmony_ci}
588bf215546Sopenharmony_ci
589bf215546Sopenharmony_cistatic void
590bf215546Sopenharmony_civk_multisample_state_init(struct vk_multisample_state *ms,
591bf215546Sopenharmony_ci                          const BITSET_WORD *dynamic,
592bf215546Sopenharmony_ci                          const VkPipelineMultisampleStateCreateInfo *ms_info)
593bf215546Sopenharmony_ci{
594bf215546Sopenharmony_ci   ms->rasterization_samples = ms_info->rasterizationSamples;
595bf215546Sopenharmony_ci   ms->sample_shading_enable = ms_info->sampleShadingEnable;
596bf215546Sopenharmony_ci   ms->min_sample_shading = ms_info->minSampleShading;
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   /* From the Vulkan 1.3.218 spec:
599bf215546Sopenharmony_ci    *
600bf215546Sopenharmony_ci    *    "If pSampleMask is NULL, it is treated as if the mask has all bits
601bf215546Sopenharmony_ci    *    set to 1."
602bf215546Sopenharmony_ci    */
603bf215546Sopenharmony_ci   ms->sample_mask = ms_info->pSampleMask ? *ms_info->pSampleMask : ~0;
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   ms->alpha_to_coverage_enable = ms_info->alphaToCoverageEnable;
606bf215546Sopenharmony_ci   ms->alpha_to_one_enable = ms_info->alphaToOneEnable;
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci   /* These get filled in by vk_multisample_sample_locations_state_init() */
609bf215546Sopenharmony_ci   ms->sample_locations_enable = false;
610bf215546Sopenharmony_ci   ms->sample_locations = NULL;
611bf215546Sopenharmony_ci}
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_cistatic bool
614bf215546Sopenharmony_cineeds_sample_locations_state(
615bf215546Sopenharmony_ci   const BITSET_WORD *dynamic,
616bf215546Sopenharmony_ci   const VkPipelineSampleLocationsStateCreateInfoEXT *sl_info)
617bf215546Sopenharmony_ci{
618bf215546Sopenharmony_ci   return !IS_DYNAMIC(MS_SAMPLE_LOCATIONS) &&
619bf215546Sopenharmony_ci          sl_info != NULL && sl_info->sampleLocationsEnable;
620bf215546Sopenharmony_ci}
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_cistatic void
623bf215546Sopenharmony_civk_multisample_sample_locations_state_init(
624bf215546Sopenharmony_ci   struct vk_multisample_state *ms,
625bf215546Sopenharmony_ci   struct vk_sample_locations_state *sl,
626bf215546Sopenharmony_ci   const BITSET_WORD *dynamic,
627bf215546Sopenharmony_ci   const VkPipelineMultisampleStateCreateInfo *ms_info,
628bf215546Sopenharmony_ci   const VkPipelineSampleLocationsStateCreateInfoEXT *sl_info)
629bf215546Sopenharmony_ci{
630bf215546Sopenharmony_ci   ms->sample_locations_enable =
631bf215546Sopenharmony_ci      sl_info != NULL && sl_info->sampleLocationsEnable;
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci   assert(ms->sample_locations == NULL);
634bf215546Sopenharmony_ci   if (!IS_DYNAMIC(MS_SAMPLE_LOCATIONS)) {
635bf215546Sopenharmony_ci      if (ms->sample_locations_enable) {
636bf215546Sopenharmony_ci         vk_sample_locations_state_init(sl, &sl_info->sampleLocationsInfo);
637bf215546Sopenharmony_ci         ms->sample_locations = sl;
638bf215546Sopenharmony_ci      } else {
639bf215546Sopenharmony_ci         /* Otherwise, pre-populate with the standard sample locations.  If
640bf215546Sopenharmony_ci          * the driver doesn't support standard sample locations, it probably
641bf215546Sopenharmony_ci          * doesn't support custom locations either and can completely ignore
642bf215546Sopenharmony_ci          * this state.
643bf215546Sopenharmony_ci          */
644bf215546Sopenharmony_ci         ms->sample_locations =
645bf215546Sopenharmony_ci            vk_standard_sample_locations_state(ms_info->rasterizationSamples);
646bf215546Sopenharmony_ci      }
647bf215546Sopenharmony_ci   }
648bf215546Sopenharmony_ci}
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_cistatic void
651bf215546Sopenharmony_civk_dynamic_graphics_state_init_ms(struct vk_dynamic_graphics_state *dst,
652bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
653bf215546Sopenharmony_ci                                  const struct vk_multisample_state *ms)
654bf215546Sopenharmony_ci{
655bf215546Sopenharmony_ci   if (IS_NEEDED(MS_SAMPLE_LOCATIONS))
656bf215546Sopenharmony_ci      *dst->ms.sample_locations = *ms->sample_locations;
657bf215546Sopenharmony_ci}
658bf215546Sopenharmony_ci
659bf215546Sopenharmony_cistatic void
660bf215546Sopenharmony_civk_stencil_test_face_state_init(struct vk_stencil_test_face_state *face,
661bf215546Sopenharmony_ci                                const VkStencilOpState *info)
662bf215546Sopenharmony_ci{
663bf215546Sopenharmony_ci   face->op.fail = info->failOp;
664bf215546Sopenharmony_ci   face->op.pass = info->passOp;
665bf215546Sopenharmony_ci   face->op.depth_fail = info->depthFailOp;
666bf215546Sopenharmony_ci   face->op.compare = info->compareOp;
667bf215546Sopenharmony_ci   face->compare_mask = info->compareMask;
668bf215546Sopenharmony_ci   face->write_mask = info->writeMask;
669bf215546Sopenharmony_ci   face->reference = info->reference;
670bf215546Sopenharmony_ci}
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_cistatic void
673bf215546Sopenharmony_civk_depth_stencil_state_init(struct vk_depth_stencil_state *ds,
674bf215546Sopenharmony_ci                            const BITSET_WORD *dynamic,
675bf215546Sopenharmony_ci                            const VkPipelineDepthStencilStateCreateInfo *ds_info)
676bf215546Sopenharmony_ci{
677bf215546Sopenharmony_ci   memset(ds, 0, sizeof(*ds));
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci   ds->depth.test_enable = ds_info->depthTestEnable;
680bf215546Sopenharmony_ci   ds->depth.write_enable = ds_info->depthWriteEnable;
681bf215546Sopenharmony_ci   ds->depth.compare_op = ds_info->depthCompareOp;
682bf215546Sopenharmony_ci   ds->depth.bounds_test.enable = ds_info->depthBoundsTestEnable;
683bf215546Sopenharmony_ci   ds->depth.bounds_test.min = ds_info->minDepthBounds;
684bf215546Sopenharmony_ci   ds->depth.bounds_test.max = ds_info->maxDepthBounds;
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci   ds->stencil.test_enable = ds_info->stencilTestEnable;
687bf215546Sopenharmony_ci   ds->stencil.write_enable = true;
688bf215546Sopenharmony_ci   vk_stencil_test_face_state_init(&ds->stencil.front, &ds_info->front);
689bf215546Sopenharmony_ci   vk_stencil_test_face_state_init(&ds->stencil.back, &ds_info->back);
690bf215546Sopenharmony_ci}
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_cistatic void
693bf215546Sopenharmony_civk_dynamic_graphics_state_init_ds(struct vk_dynamic_graphics_state *dst,
694bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
695bf215546Sopenharmony_ci                                  const struct vk_depth_stencil_state *ds)
696bf215546Sopenharmony_ci{
697bf215546Sopenharmony_ci   dst->ds = *ds;
698bf215546Sopenharmony_ci}
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_cistatic bool
701bf215546Sopenharmony_cioptimize_stencil_face(struct vk_stencil_test_face_state *face,
702bf215546Sopenharmony_ci                      VkCompareOp depthCompareOp,
703bf215546Sopenharmony_ci                      bool consider_write_mask)
704bf215546Sopenharmony_ci{
705bf215546Sopenharmony_ci   /* If compareOp is ALWAYS then the stencil test will never fail and failOp
706bf215546Sopenharmony_ci    * will never happen.  Set failOp to KEEP in this case.
707bf215546Sopenharmony_ci    */
708bf215546Sopenharmony_ci   if (face->op.compare == VK_COMPARE_OP_ALWAYS)
709bf215546Sopenharmony_ci      face->op.fail = VK_STENCIL_OP_KEEP;
710bf215546Sopenharmony_ci
711bf215546Sopenharmony_ci   /* If compareOp is NEVER or depthCompareOp is NEVER then one of the depth
712bf215546Sopenharmony_ci    * or stencil tests will fail and passOp will never happen.
713bf215546Sopenharmony_ci    */
714bf215546Sopenharmony_ci   if (face->op.compare == VK_COMPARE_OP_NEVER ||
715bf215546Sopenharmony_ci       depthCompareOp == VK_COMPARE_OP_NEVER)
716bf215546Sopenharmony_ci      face->op.pass = VK_STENCIL_OP_KEEP;
717bf215546Sopenharmony_ci
718bf215546Sopenharmony_ci   /* If compareOp is NEVER or depthCompareOp is ALWAYS then either the
719bf215546Sopenharmony_ci    * stencil test will fail or the depth test will pass.  In either case,
720bf215546Sopenharmony_ci    * depthFailOp will never happen.
721bf215546Sopenharmony_ci    */
722bf215546Sopenharmony_ci   if (face->op.compare == VK_COMPARE_OP_NEVER ||
723bf215546Sopenharmony_ci       depthCompareOp == VK_COMPARE_OP_ALWAYS)
724bf215546Sopenharmony_ci      face->op.depth_fail = VK_STENCIL_OP_KEEP;
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_ci   /* If the write mask is zero, nothing will be written to the stencil buffer
727bf215546Sopenharmony_ci    * so it's as if all operations are KEEP.
728bf215546Sopenharmony_ci    */
729bf215546Sopenharmony_ci   if (consider_write_mask && face->write_mask == 0) {
730bf215546Sopenharmony_ci      face->op.pass = VK_STENCIL_OP_KEEP;
731bf215546Sopenharmony_ci      face->op.fail = VK_STENCIL_OP_KEEP;
732bf215546Sopenharmony_ci      face->op.depth_fail = VK_STENCIL_OP_KEEP;
733bf215546Sopenharmony_ci   }
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci   return face->op.fail != VK_STENCIL_OP_KEEP ||
736bf215546Sopenharmony_ci          face->op.depth_fail != VK_STENCIL_OP_KEEP ||
737bf215546Sopenharmony_ci          face->op.pass != VK_STENCIL_OP_KEEP;
738bf215546Sopenharmony_ci}
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_civoid
741bf215546Sopenharmony_civk_optimize_depth_stencil_state(struct vk_depth_stencil_state *ds,
742bf215546Sopenharmony_ci                                VkImageAspectFlags ds_aspects,
743bf215546Sopenharmony_ci                                bool consider_write_mask)
744bf215546Sopenharmony_ci{
745bf215546Sopenharmony_ci   /* stencil.write_enable is a dummy right now that should always be true */
746bf215546Sopenharmony_ci   assert(ds->stencil.write_enable);
747bf215546Sopenharmony_ci
748bf215546Sopenharmony_ci   /* From the Vulkan 1.3.221 spec:
749bf215546Sopenharmony_ci    *
750bf215546Sopenharmony_ci    *    "If there is no depth attachment then the depth test is skipped."
751bf215546Sopenharmony_ci    */
752bf215546Sopenharmony_ci   if (!(ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT))
753bf215546Sopenharmony_ci      ds->depth.test_enable = false;
754bf215546Sopenharmony_ci
755bf215546Sopenharmony_ci   /* From the Vulkan 1.3.221 spec:
756bf215546Sopenharmony_ci    *
757bf215546Sopenharmony_ci    *    "...or if there is no stencil attachment, the coverage mask is
758bf215546Sopenharmony_ci    *    unmodified by this operation."
759bf215546Sopenharmony_ci    */
760bf215546Sopenharmony_ci   if (!(ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT))
761bf215546Sopenharmony_ci      ds->stencil.test_enable = false;
762bf215546Sopenharmony_ci
763bf215546Sopenharmony_ci   /* If the depth test is disabled, we won't be writing anything. Make sure we
764bf215546Sopenharmony_ci    * treat the test as always passing later on as well.
765bf215546Sopenharmony_ci    */
766bf215546Sopenharmony_ci   if (!ds->depth.test_enable) {
767bf215546Sopenharmony_ci      ds->depth.write_enable = false;
768bf215546Sopenharmony_ci      ds->depth.compare_op = VK_COMPARE_OP_ALWAYS;
769bf215546Sopenharmony_ci   }
770bf215546Sopenharmony_ci
771bf215546Sopenharmony_ci   /* If the stencil test is disabled, we won't be writing anything. Make sure
772bf215546Sopenharmony_ci    * we treat the test as always passing later on as well.
773bf215546Sopenharmony_ci    */
774bf215546Sopenharmony_ci   if (!ds->stencil.test_enable) {
775bf215546Sopenharmony_ci      ds->stencil.write_enable = false;
776bf215546Sopenharmony_ci      ds->stencil.front.op.compare = VK_COMPARE_OP_ALWAYS;
777bf215546Sopenharmony_ci      ds->stencil.back.op.compare = VK_COMPARE_OP_ALWAYS;
778bf215546Sopenharmony_ci   }
779bf215546Sopenharmony_ci
780bf215546Sopenharmony_ci   /* If the stencil test is enabled and always fails, then we will never get
781bf215546Sopenharmony_ci    * to the depth test so we can just disable the depth test entirely.
782bf215546Sopenharmony_ci    */
783bf215546Sopenharmony_ci   if (ds->stencil.test_enable &&
784bf215546Sopenharmony_ci       ds->stencil.front.op.compare == VK_COMPARE_OP_NEVER &&
785bf215546Sopenharmony_ci       ds->stencil.back.op.compare == VK_COMPARE_OP_NEVER) {
786bf215546Sopenharmony_ci      ds->depth.test_enable = false;
787bf215546Sopenharmony_ci      ds->depth.write_enable = false;
788bf215546Sopenharmony_ci   }
789bf215546Sopenharmony_ci
790bf215546Sopenharmony_ci   /* If depthCompareOp is EQUAL then the value we would be writing to the
791bf215546Sopenharmony_ci    * depth buffer is the same as the value that's already there so there's no
792bf215546Sopenharmony_ci    * point in writing it.
793bf215546Sopenharmony_ci    */
794bf215546Sopenharmony_ci   if (ds->depth.compare_op == VK_COMPARE_OP_EQUAL)
795bf215546Sopenharmony_ci      ds->depth.write_enable = false;
796bf215546Sopenharmony_ci
797bf215546Sopenharmony_ci   /* If the stencil ops are such that we don't actually ever modify the
798bf215546Sopenharmony_ci    * stencil buffer, we should disable writes.
799bf215546Sopenharmony_ci    */
800bf215546Sopenharmony_ci   if (!optimize_stencil_face(&ds->stencil.front, ds->depth.compare_op,
801bf215546Sopenharmony_ci                              consider_write_mask) &&
802bf215546Sopenharmony_ci       !optimize_stencil_face(&ds->stencil.back, ds->depth.compare_op,
803bf215546Sopenharmony_ci                              consider_write_mask))
804bf215546Sopenharmony_ci      ds->stencil.write_enable = false;
805bf215546Sopenharmony_ci
806bf215546Sopenharmony_ci   /* If the depth test always passes and we never write out depth, that's the
807bf215546Sopenharmony_ci    * same as if the depth test is disabled entirely.
808bf215546Sopenharmony_ci    */
809bf215546Sopenharmony_ci   if (ds->depth.compare_op == VK_COMPARE_OP_ALWAYS && !ds->depth.write_enable)
810bf215546Sopenharmony_ci      ds->depth.test_enable = false;
811bf215546Sopenharmony_ci
812bf215546Sopenharmony_ci   /* If the stencil test always passes and we never write out stencil, that's
813bf215546Sopenharmony_ci    * the same as if the stencil test is disabled entirely.
814bf215546Sopenharmony_ci    */
815bf215546Sopenharmony_ci   if (ds->stencil.front.op.compare == VK_COMPARE_OP_ALWAYS &&
816bf215546Sopenharmony_ci       ds->stencil.back.op.compare == VK_COMPARE_OP_ALWAYS &&
817bf215546Sopenharmony_ci       !ds->stencil.write_enable)
818bf215546Sopenharmony_ci      ds->stencil.test_enable = false;
819bf215546Sopenharmony_ci}
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_cistatic void
822bf215546Sopenharmony_civk_color_blend_state_init(struct vk_color_blend_state *cb,
823bf215546Sopenharmony_ci                          const BITSET_WORD *dynamic,
824bf215546Sopenharmony_ci                          const VkPipelineColorBlendStateCreateInfo *cb_info)
825bf215546Sopenharmony_ci{
826bf215546Sopenharmony_ci   memset(cb, 0, sizeof(*cb));
827bf215546Sopenharmony_ci
828bf215546Sopenharmony_ci   cb->logic_op_enable = cb_info->logicOpEnable;
829bf215546Sopenharmony_ci   cb->logic_op = cb_info->logicOp;
830bf215546Sopenharmony_ci
831bf215546Sopenharmony_ci   assert(cb_info->attachmentCount <= MESA_VK_MAX_COLOR_ATTACHMENTS);
832bf215546Sopenharmony_ci   cb->attachment_count = cb_info->attachmentCount;
833bf215546Sopenharmony_ci   for (uint32_t a = 0; a < cb_info->attachmentCount; a++) {
834bf215546Sopenharmony_ci      const VkPipelineColorBlendAttachmentState *att =
835bf215546Sopenharmony_ci         &cb_info->pAttachments[a];
836bf215546Sopenharmony_ci
837bf215546Sopenharmony_ci      cb->attachments[a] = (struct vk_color_blend_attachment_state) {
838bf215546Sopenharmony_ci         .blend_enable = att->blendEnable,
839bf215546Sopenharmony_ci         .src_color_blend_factor = att->srcColorBlendFactor,
840bf215546Sopenharmony_ci         .dst_color_blend_factor = att->dstColorBlendFactor,
841bf215546Sopenharmony_ci         .src_alpha_blend_factor = att->srcAlphaBlendFactor,
842bf215546Sopenharmony_ci         .dst_alpha_blend_factor = att->dstAlphaBlendFactor,
843bf215546Sopenharmony_ci         .write_mask = att->colorWriteMask,
844bf215546Sopenharmony_ci         .color_blend_op = att->colorBlendOp,
845bf215546Sopenharmony_ci         .alpha_blend_op = att->alphaBlendOp,
846bf215546Sopenharmony_ci      };
847bf215546Sopenharmony_ci   }
848bf215546Sopenharmony_ci
849bf215546Sopenharmony_ci   for (uint32_t i = 0; i < 4; i++)
850bf215546Sopenharmony_ci      cb->blend_constants[i] = cb_info->blendConstants[i];
851bf215546Sopenharmony_ci
852bf215546Sopenharmony_ci   const VkPipelineColorWriteCreateInfoEXT *cw_info =
853bf215546Sopenharmony_ci      vk_find_struct_const(cb_info->pNext, PIPELINE_COLOR_WRITE_CREATE_INFO_EXT);
854bf215546Sopenharmony_ci   if (cw_info != NULL) {
855bf215546Sopenharmony_ci      assert(cb_info->attachmentCount == cw_info->attachmentCount);
856bf215546Sopenharmony_ci      for (uint32_t a = 0; a < cw_info->attachmentCount; a++) {
857bf215546Sopenharmony_ci         if (cw_info->pColorWriteEnables[a])
858bf215546Sopenharmony_ci            cb->color_write_enables |= BITFIELD_BIT(a);
859bf215546Sopenharmony_ci      }
860bf215546Sopenharmony_ci   } else {
861bf215546Sopenharmony_ci      cb->color_write_enables = BITFIELD_MASK(cb_info->attachmentCount);
862bf215546Sopenharmony_ci   }
863bf215546Sopenharmony_ci}
864bf215546Sopenharmony_ci
865bf215546Sopenharmony_cistatic void
866bf215546Sopenharmony_civk_dynamic_graphics_state_init_cb(struct vk_dynamic_graphics_state *dst,
867bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
868bf215546Sopenharmony_ci                                  const struct vk_color_blend_state *cb)
869bf215546Sopenharmony_ci{
870bf215546Sopenharmony_ci   dst->cb.logic_op = cb->logic_op;
871bf215546Sopenharmony_ci   dst->cb.color_write_enables = cb->color_write_enables;
872bf215546Sopenharmony_ci
873bf215546Sopenharmony_ci   if (IS_NEEDED(CB_BLEND_CONSTANTS))
874bf215546Sopenharmony_ci      typed_memcpy(dst->cb.blend_constants, cb->blend_constants, 4);
875bf215546Sopenharmony_ci}
876bf215546Sopenharmony_ci
877bf215546Sopenharmony_cistatic bool
878bf215546Sopenharmony_civk_render_pass_state_is_complete(const struct vk_render_pass_state *rp)
879bf215546Sopenharmony_ci{
880bf215546Sopenharmony_ci   return rp->attachment_aspects != VK_IMAGE_ASPECT_METADATA_BIT;
881bf215546Sopenharmony_ci}
882bf215546Sopenharmony_ci
883bf215546Sopenharmony_cistatic void
884bf215546Sopenharmony_civk_render_pass_state_init(struct vk_render_pass_state *rp,
885bf215546Sopenharmony_ci                          const struct vk_render_pass_state *old_rp,
886bf215546Sopenharmony_ci                          const VkGraphicsPipelineCreateInfo *info,
887bf215546Sopenharmony_ci                          const struct vk_subpass_info *sp_info,
888bf215546Sopenharmony_ci                          VkGraphicsPipelineLibraryFlagsEXT lib)
889bf215546Sopenharmony_ci{
890bf215546Sopenharmony_ci   /* If we already have render pass state and it has attachment info, then
891bf215546Sopenharmony_ci    * it's complete and we don't need a new one.
892bf215546Sopenharmony_ci    */
893bf215546Sopenharmony_ci   if (old_rp != NULL && vk_render_pass_state_is_complete(old_rp)) {
894bf215546Sopenharmony_ci      *rp = *old_rp;
895bf215546Sopenharmony_ci      return;
896bf215546Sopenharmony_ci   }
897bf215546Sopenharmony_ci
898bf215546Sopenharmony_ci   *rp = (struct vk_render_pass_state) {
899bf215546Sopenharmony_ci      .render_pass = info->renderPass,
900bf215546Sopenharmony_ci      .subpass = info->subpass,
901bf215546Sopenharmony_ci      .depth_attachment_format = VK_FORMAT_UNDEFINED,
902bf215546Sopenharmony_ci      .stencil_attachment_format = VK_FORMAT_UNDEFINED,
903bf215546Sopenharmony_ci   };
904bf215546Sopenharmony_ci
905bf215546Sopenharmony_ci   if (info->renderPass != VK_NULL_HANDLE && sp_info != NULL) {
906bf215546Sopenharmony_ci      rp->attachment_aspects = sp_info->attachment_aspects;
907bf215546Sopenharmony_ci      rp->view_mask = sp_info->view_mask;
908bf215546Sopenharmony_ci      return;
909bf215546Sopenharmony_ci   }
910bf215546Sopenharmony_ci
911bf215546Sopenharmony_ci   const VkPipelineRenderingCreateInfo *r_info =
912bf215546Sopenharmony_ci      vk_get_pipeline_rendering_create_info(info);
913bf215546Sopenharmony_ci
914bf215546Sopenharmony_ci   if (r_info == NULL)
915bf215546Sopenharmony_ci      return;
916bf215546Sopenharmony_ci
917bf215546Sopenharmony_ci   rp->view_mask = r_info->viewMask;
918bf215546Sopenharmony_ci
919bf215546Sopenharmony_ci   /* From the Vulkan 1.3.218 spec description of pre-rasterization state:
920bf215546Sopenharmony_ci    *
921bf215546Sopenharmony_ci    *    "Fragment shader state is defined by:
922bf215546Sopenharmony_ci    *    ...
923bf215546Sopenharmony_ci    *     * VkRenderPass and subpass parameter
924bf215546Sopenharmony_ci    *     * The viewMask parameter of VkPipelineRenderingCreateInfo (formats
925bf215546Sopenharmony_ci    *       are ignored)"
926bf215546Sopenharmony_ci    *
927bf215546Sopenharmony_ci    * The description of fragment shader state contains identical text.
928bf215546Sopenharmony_ci    *
929bf215546Sopenharmony_ci    * If we have a render pass then we have full information.  Even if we're
930bf215546Sopenharmony_ci    * dynamic-rendering-only, the presence of a render pass means the
931bf215546Sopenharmony_ci    * rendering info came from a vk_render_pass and is therefore complete.
932bf215546Sopenharmony_ci    * Otherwise, all we can grab is the view mask and we have to leave the
933bf215546Sopenharmony_ci    * rest for later.
934bf215546Sopenharmony_ci    */
935bf215546Sopenharmony_ci   if (info->renderPass == VK_NULL_HANDLE &&
936bf215546Sopenharmony_ci       !(lib & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT)) {
937bf215546Sopenharmony_ci      rp->attachment_aspects = VK_IMAGE_ASPECT_METADATA_BIT;
938bf215546Sopenharmony_ci      return;
939bf215546Sopenharmony_ci   }
940bf215546Sopenharmony_ci
941bf215546Sopenharmony_ci   assert(r_info->colorAttachmentCount <= MESA_VK_MAX_COLOR_ATTACHMENTS);
942bf215546Sopenharmony_ci   rp->color_attachment_count = r_info->colorAttachmentCount;
943bf215546Sopenharmony_ci   for (uint32_t i = 0; i < r_info->colorAttachmentCount; i++) {
944bf215546Sopenharmony_ci      rp->color_attachment_formats[i] = r_info->pColorAttachmentFormats[i];
945bf215546Sopenharmony_ci      if (r_info->pColorAttachmentFormats[i] != VK_FORMAT_UNDEFINED)
946bf215546Sopenharmony_ci         rp->attachment_aspects |= VK_IMAGE_ASPECT_COLOR_BIT;
947bf215546Sopenharmony_ci   }
948bf215546Sopenharmony_ci
949bf215546Sopenharmony_ci   rp->depth_attachment_format = r_info->depthAttachmentFormat;
950bf215546Sopenharmony_ci   if (r_info->depthAttachmentFormat != VK_FORMAT_UNDEFINED)
951bf215546Sopenharmony_ci      rp->attachment_aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
952bf215546Sopenharmony_ci
953bf215546Sopenharmony_ci   rp->stencil_attachment_format = r_info->stencilAttachmentFormat;
954bf215546Sopenharmony_ci   if (r_info->stencilAttachmentFormat != VK_FORMAT_UNDEFINED)
955bf215546Sopenharmony_ci      rp->attachment_aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
956bf215546Sopenharmony_ci
957bf215546Sopenharmony_ci   const VkRenderingSelfDependencyInfoMESA *rsd_info =
958bf215546Sopenharmony_ci      vk_find_struct_const(r_info->pNext, RENDERING_SELF_DEPENDENCY_INFO_MESA);
959bf215546Sopenharmony_ci   if (rsd_info != NULL) {
960bf215546Sopenharmony_ci      STATIC_ASSERT(sizeof(rp->color_self_dependencies) * 8 >=
961bf215546Sopenharmony_ci                    MESA_VK_MAX_COLOR_ATTACHMENTS);
962bf215546Sopenharmony_ci      rp->color_self_dependencies = rsd_info->colorSelfDependencies;
963bf215546Sopenharmony_ci      rp->depth_self_dependency = rsd_info->depthSelfDependency;
964bf215546Sopenharmony_ci      rp->stencil_self_dependency = rsd_info->stencilSelfDependency;
965bf215546Sopenharmony_ci   }
966bf215546Sopenharmony_ci}
967bf215546Sopenharmony_ci
968bf215546Sopenharmony_cistatic void
969bf215546Sopenharmony_civk_dynamic_graphics_state_init_rp(struct vk_dynamic_graphics_state *dst,
970bf215546Sopenharmony_ci                                  const BITSET_WORD *needed,
971bf215546Sopenharmony_ci                                  const struct vk_render_pass_state *rp)
972bf215546Sopenharmony_ci{ }
973bf215546Sopenharmony_ci
974bf215546Sopenharmony_ci#define FOREACH_STATE_GROUP(f)                           \
975bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_VERTEX_INPUT_BIT,            \
976bf215546Sopenharmony_ci     vk_vertex_input_state, vi);                         \
977bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_INPUT_ASSEMBLY_BIT,          \
978bf215546Sopenharmony_ci     vk_input_assembly_state, ia);                       \
979bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_TESSELLATION_BIT,            \
980bf215546Sopenharmony_ci     vk_tessellation_state, ts);                         \
981bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_VIEWPORT_BIT,                \
982bf215546Sopenharmony_ci     vk_viewport_state, vp);                             \
983bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_DISCARD_RECTANGLES_BIT,      \
984bf215546Sopenharmony_ci     vk_discard_rectangles_state, dr);                   \
985bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_RASTERIZATION_BIT,           \
986bf215546Sopenharmony_ci     vk_rasterization_state, rs);                        \
987bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_FRAGMENT_SHADING_RATE_BIT,   \
988bf215546Sopenharmony_ci     vk_fragment_shading_rate_state, fsr);               \
989bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_MULTISAMPLE_BIT,             \
990bf215546Sopenharmony_ci     vk_multisample_state, ms);                          \
991bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_DEPTH_STENCIL_BIT,           \
992bf215546Sopenharmony_ci     vk_depth_stencil_state, ds);                        \
993bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_COLOR_BLEND_BIT,             \
994bf215546Sopenharmony_ci     vk_color_blend_state, cb);                          \
995bf215546Sopenharmony_ci   f(MESA_VK_GRAPHICS_STATE_RENDER_PASS_BIT,             \
996bf215546Sopenharmony_ci     vk_render_pass_state, rp);
997bf215546Sopenharmony_ci
998bf215546Sopenharmony_cistatic enum mesa_vk_graphics_state_groups
999bf215546Sopenharmony_civk_graphics_pipeline_state_groups(const struct vk_graphics_pipeline_state *state)
1000bf215546Sopenharmony_ci{
1001bf215546Sopenharmony_ci   /* For now, we just validate dynamic state */
1002bf215546Sopenharmony_ci   enum mesa_vk_graphics_state_groups groups = 0;
1003bf215546Sopenharmony_ci
1004bf215546Sopenharmony_ci#define FILL_HAS(STATE, type, s) \
1005bf215546Sopenharmony_ci   if (state->s != NULL) groups |= STATE
1006bf215546Sopenharmony_ci
1007bf215546Sopenharmony_ci   FOREACH_STATE_GROUP(FILL_HAS)
1008bf215546Sopenharmony_ci
1009bf215546Sopenharmony_ci#undef FILL_HAS
1010bf215546Sopenharmony_ci
1011bf215546Sopenharmony_ci   return groups | fully_dynamic_state_groups(state->dynamic);
1012bf215546Sopenharmony_ci}
1013bf215546Sopenharmony_ci
1014bf215546Sopenharmony_cistatic void
1015bf215546Sopenharmony_civk_graphics_pipeline_state_validate(const struct vk_graphics_pipeline_state *state)
1016bf215546Sopenharmony_ci{
1017bf215546Sopenharmony_ci#ifndef NDEBUG
1018bf215546Sopenharmony_ci   /* For now, we just validate dynamic state */
1019bf215546Sopenharmony_ci   enum mesa_vk_graphics_state_groups groups =
1020bf215546Sopenharmony_ci      vk_graphics_pipeline_state_groups(state);
1021bf215546Sopenharmony_ci   validate_dynamic_state_groups(state->dynamic, groups);
1022bf215546Sopenharmony_ci#endif
1023bf215546Sopenharmony_ci}
1024bf215546Sopenharmony_ci
1025bf215546Sopenharmony_cistatic bool
1026bf215546Sopenharmony_cimay_have_rasterization(const struct vk_graphics_pipeline_state *state,
1027bf215546Sopenharmony_ci                       const BITSET_WORD *dynamic,
1028bf215546Sopenharmony_ci                       const VkGraphicsPipelineCreateInfo *info)
1029bf215546Sopenharmony_ci{
1030bf215546Sopenharmony_ci   if (state->rs) {
1031bf215546Sopenharmony_ci      /* We default rasterizer_discard_enable to false when dynamic */
1032bf215546Sopenharmony_ci      return !state->rs->rasterizer_discard_enable;
1033bf215546Sopenharmony_ci   } else {
1034bf215546Sopenharmony_ci      return IS_DYNAMIC(RS_RASTERIZER_DISCARD_ENABLE) ||
1035bf215546Sopenharmony_ci             !info->pRasterizationState->rasterizerDiscardEnable;
1036bf215546Sopenharmony_ci   }
1037bf215546Sopenharmony_ci}
1038bf215546Sopenharmony_ci
1039bf215546Sopenharmony_ciVkResult
1040bf215546Sopenharmony_civk_graphics_pipeline_state_fill(const struct vk_device *device,
1041bf215546Sopenharmony_ci                                struct vk_graphics_pipeline_state *state,
1042bf215546Sopenharmony_ci                                const VkGraphicsPipelineCreateInfo *info,
1043bf215546Sopenharmony_ci                                const struct vk_subpass_info *sp_info,
1044bf215546Sopenharmony_ci                                struct vk_graphics_pipeline_all_state *all,
1045bf215546Sopenharmony_ci                                const VkAllocationCallbacks *alloc,
1046bf215546Sopenharmony_ci                                VkSystemAllocationScope scope,
1047bf215546Sopenharmony_ci                                void **alloc_ptr_out)
1048bf215546Sopenharmony_ci{
1049bf215546Sopenharmony_ci   vk_graphics_pipeline_state_validate(state);
1050bf215546Sopenharmony_ci
1051bf215546Sopenharmony_ci   BITSET_DECLARE(dynamic, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX);
1052bf215546Sopenharmony_ci   vk_get_dynamic_graphics_states(dynamic, info->pDynamicState);
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_ci   for (uint32_t i = 0; i < info->stageCount; i++)
1055bf215546Sopenharmony_ci      state->shader_stages |= info->pStages[i].stage;
1056bf215546Sopenharmony_ci
1057bf215546Sopenharmony_ci   /* In case we return early */
1058bf215546Sopenharmony_ci   if (alloc_ptr_out != NULL)
1059bf215546Sopenharmony_ci      *alloc_ptr_out = NULL;
1060bf215546Sopenharmony_ci
1061bf215546Sopenharmony_ci   /*
1062bf215546Sopenharmony_ci    * First, figure out which library-level shader/state groups we need
1063bf215546Sopenharmony_ci    */
1064bf215546Sopenharmony_ci
1065bf215546Sopenharmony_ci   VkGraphicsPipelineLibraryFlagsEXT lib;
1066bf215546Sopenharmony_ci   if (info->flags & VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) {
1067bf215546Sopenharmony_ci      const VkGraphicsPipelineLibraryCreateInfoEXT *gfx_lib_info =
1068bf215546Sopenharmony_ci         vk_find_struct_const(info->pNext, GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT);
1069bf215546Sopenharmony_ci      lib = gfx_lib_info->flags;
1070bf215546Sopenharmony_ci   } else {
1071bf215546Sopenharmony_ci      /* We're building a complete pipeline.  From the Vulkan 1.3.218 spec:
1072bf215546Sopenharmony_ci       *
1073bf215546Sopenharmony_ci       *    "A complete graphics pipeline always includes pre-rasterization
1074bf215546Sopenharmony_ci       *    shader state, with other subsets included depending on that state.
1075bf215546Sopenharmony_ci       *    If the pre-rasterization shader state includes a vertex shader,
1076bf215546Sopenharmony_ci       *    then vertex input state is included in a complete graphics
1077bf215546Sopenharmony_ci       *    pipeline. If the value of
1078bf215546Sopenharmony_ci       *    VkPipelineRasterizationStateCreateInfo::rasterizerDiscardEnable in
1079bf215546Sopenharmony_ci       *    the pre-rasterization shader state is VK_FALSE or the
1080bf215546Sopenharmony_ci       *    VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE dynamic state is
1081bf215546Sopenharmony_ci       *    enabled fragment shader state and fragment output interface state
1082bf215546Sopenharmony_ci       *    is included in a complete graphics pipeline."
1083bf215546Sopenharmony_ci       */
1084bf215546Sopenharmony_ci      lib = VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
1085bf215546Sopenharmony_ci
1086bf215546Sopenharmony_ci      if (state->shader_stages & VK_SHADER_STAGE_VERTEX_BIT)
1087bf215546Sopenharmony_ci         lib |= VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT;
1088bf215546Sopenharmony_ci
1089bf215546Sopenharmony_ci      if (may_have_rasterization(state, dynamic, info)) {
1090bf215546Sopenharmony_ci         lib |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
1091bf215546Sopenharmony_ci         lib |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
1092bf215546Sopenharmony_ci      }
1093bf215546Sopenharmony_ci   }
1094bf215546Sopenharmony_ci
1095bf215546Sopenharmony_ci   /*
1096bf215546Sopenharmony_ci    * Next, turn those into individual states.  Among other things, this
1097bf215546Sopenharmony_ci    * de-duplicates things like FSR and multisample state which appear in
1098bf215546Sopenharmony_ci    * multiple library groups.
1099bf215546Sopenharmony_ci    */
1100bf215546Sopenharmony_ci
1101bf215546Sopenharmony_ci   enum mesa_vk_graphics_state_groups needs = 0;
1102bf215546Sopenharmony_ci   if (lib & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) {
1103bf215546Sopenharmony_ci      needs |= MESA_VK_GRAPHICS_STATE_VERTEX_INPUT_BIT;
1104bf215546Sopenharmony_ci      needs |= MESA_VK_GRAPHICS_STATE_INPUT_ASSEMBLY_BIT;
1105bf215546Sopenharmony_ci   }
1106bf215546Sopenharmony_ci
1107bf215546Sopenharmony_ci   /* Other stuff potentially depends on this so gather it early */
1108bf215546Sopenharmony_ci   struct vk_render_pass_state rp;
1109bf215546Sopenharmony_ci   if (lib & (VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT |
1110bf215546Sopenharmony_ci              VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT |
1111bf215546Sopenharmony_ci              VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT)) {
1112bf215546Sopenharmony_ci      vk_render_pass_state_init(&rp, state->rp, info, sp_info, lib);
1113bf215546Sopenharmony_ci
1114bf215546Sopenharmony_ci      needs |= MESA_VK_GRAPHICS_STATE_RENDER_PASS_BIT;
1115bf215546Sopenharmony_ci
1116bf215546Sopenharmony_ci      /* If the old state was incomplete but the new one isn't, set state->rp
1117bf215546Sopenharmony_ci       * to NULL so it gets replaced with the new version.
1118bf215546Sopenharmony_ci       */
1119bf215546Sopenharmony_ci      if (state->rp != NULL &&
1120bf215546Sopenharmony_ci          !vk_render_pass_state_is_complete(state->rp) &&
1121bf215546Sopenharmony_ci          vk_render_pass_state_is_complete(&rp))
1122bf215546Sopenharmony_ci         state->rp = NULL;
1123bf215546Sopenharmony_ci   }
1124bf215546Sopenharmony_ci
1125bf215546Sopenharmony_ci   if (lib & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) {
1126bf215546Sopenharmony_ci      /* From the Vulkan 1.3.218 spec:
1127bf215546Sopenharmony_ci       *
1128bf215546Sopenharmony_ci       *    VUID-VkGraphicsPipelineCreateInfo-stage-02096
1129bf215546Sopenharmony_ci       *
1130bf215546Sopenharmony_ci       *    "If the pipeline is being created with pre-rasterization shader
1131bf215546Sopenharmony_ci       *    state the stage member of one element of pStages must be either
1132bf215546Sopenharmony_ci       *    VK_SHADER_STAGE_VERTEX_BIT or VK_SHADER_STAGE_MESH_BIT_NV"
1133bf215546Sopenharmony_ci       */
1134bf215546Sopenharmony_ci      assert(state->shader_stages & (VK_SHADER_STAGE_VERTEX_BIT |
1135bf215546Sopenharmony_ci                                     VK_SHADER_STAGE_MESH_BIT_NV));
1136bf215546Sopenharmony_ci
1137bf215546Sopenharmony_ci      if (state->shader_stages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
1138bf215546Sopenharmony_ci                                  VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
1139bf215546Sopenharmony_ci         needs |= MESA_VK_GRAPHICS_STATE_TESSELLATION_BIT;
1140bf215546Sopenharmony_ci
1141bf215546Sopenharmony_ci      if (may_have_rasterization(state, dynamic, info))
1142bf215546Sopenharmony_ci         needs |= MESA_VK_GRAPHICS_STATE_VIEWPORT_BIT;
1143bf215546Sopenharmony_ci
1144bf215546Sopenharmony_ci      needs |= MESA_VK_GRAPHICS_STATE_DISCARD_RECTANGLES_BIT;
1145bf215546Sopenharmony_ci      needs |= MESA_VK_GRAPHICS_STATE_RASTERIZATION_BIT;
1146bf215546Sopenharmony_ci      needs |= MESA_VK_GRAPHICS_STATE_FRAGMENT_SHADING_RATE_BIT;
1147bf215546Sopenharmony_ci   }
1148bf215546Sopenharmony_ci
1149bf215546Sopenharmony_ci   if (lib & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) {
1150bf215546Sopenharmony_ci      needs |= MESA_VK_GRAPHICS_STATE_FRAGMENT_SHADING_RATE_BIT;
1151bf215546Sopenharmony_ci
1152bf215546Sopenharmony_ci      /* From the Vulkan 1.3.218 spec:
1153bf215546Sopenharmony_ci       *
1154bf215546Sopenharmony_ci       *    "Fragment shader state is defined by:
1155bf215546Sopenharmony_ci       *    ...
1156bf215546Sopenharmony_ci       *     - VkPipelineMultisampleStateCreateInfo if sample shading is
1157bf215546Sopenharmony_ci       *       enabled or renderpass is not VK_NULL_HANDLE"
1158bf215546Sopenharmony_ci       *
1159bf215546Sopenharmony_ci       * and
1160bf215546Sopenharmony_ci       *
1161bf215546Sopenharmony_ci       *    VUID-VkGraphicsPipelineCreateInfo-pMultisampleState-06629
1162bf215546Sopenharmony_ci       *
1163bf215546Sopenharmony_ci       *    "If the pipeline is being created with fragment shader state
1164bf215546Sopenharmony_ci       *    pMultisampleState must be NULL or a valid pointer to a valid
1165bf215546Sopenharmony_ci       *    VkPipelineMultisampleStateCreateInfo structure"
1166bf215546Sopenharmony_ci       *
1167bf215546Sopenharmony_ci       * so we can reliably detect when to include it based on the
1168bf215546Sopenharmony_ci       * pMultisampleState pointer.
1169bf215546Sopenharmony_ci       */
1170bf215546Sopenharmony_ci      if (info->pMultisampleState != NULL)
1171bf215546Sopenharmony_ci         needs |= MESA_VK_GRAPHICS_STATE_MULTISAMPLE_BIT;
1172bf215546Sopenharmony_ci
1173bf215546Sopenharmony_ci      /* From the Vulkan 1.3.218 spec:
1174bf215546Sopenharmony_ci       *
1175bf215546Sopenharmony_ci       *    VUID-VkGraphicsPipelineCreateInfo-renderPass-06043
1176bf215546Sopenharmony_ci       *
1177bf215546Sopenharmony_ci       *    "If renderPass is not VK_NULL_HANDLE, the pipeline is being
1178bf215546Sopenharmony_ci       *    created with fragment shader state, and subpass uses a
1179bf215546Sopenharmony_ci       *    depth/stencil attachment, pDepthStencilState must be a valid
1180bf215546Sopenharmony_ci       *    pointer to a valid VkPipelineDepthStencilStateCreateInfo
1181bf215546Sopenharmony_ci       *    structure"
1182bf215546Sopenharmony_ci       *
1183bf215546Sopenharmony_ci       *    VUID-VkGraphicsPipelineCreateInfo-renderPass-06053
1184bf215546Sopenharmony_ci       *
1185bf215546Sopenharmony_ci       *    "If renderPass is VK_NULL_HANDLE, the pipeline is being created
1186bf215546Sopenharmony_ci       *    with fragment shader state and fragment output interface state,
1187bf215546Sopenharmony_ci       *    and either of VkPipelineRenderingCreateInfo::depthAttachmentFormat
1188bf215546Sopenharmony_ci       *    or VkPipelineRenderingCreateInfo::stencilAttachmentFormat are not
1189bf215546Sopenharmony_ci       *    VK_FORMAT_UNDEFINED, pDepthStencilState must be a valid pointer to
1190bf215546Sopenharmony_ci       *    a valid VkPipelineDepthStencilStateCreateInfo structure"
1191bf215546Sopenharmony_ci       *
1192bf215546Sopenharmony_ci       *    VUID-VkGraphicsPipelineCreateInfo-renderPass-06590
1193bf215546Sopenharmony_ci       *
1194bf215546Sopenharmony_ci       *    "If renderPass is VK_NULL_HANDLE and the pipeline is being created
1195bf215546Sopenharmony_ci       *    with fragment shader state but not fragment output interface
1196bf215546Sopenharmony_ci       *    state, pDepthStencilState must be a valid pointer to a valid
1197bf215546Sopenharmony_ci       *    VkPipelineDepthStencilStateCreateInfo structure"
1198bf215546Sopenharmony_ci       *
1199bf215546Sopenharmony_ci       * In the first case, we'll have a real set of aspects in rp.  In the
1200bf215546Sopenharmony_ci       * second case, where we have both fragment shader and fragment output
1201bf215546Sopenharmony_ci       * state, we will also have a valid set of aspects.  In the third case
1202bf215546Sopenharmony_ci       * where we only have fragment shader state and no render pass, the
1203bf215546Sopenharmony_ci       * vk_render_pass_state will be incomplete.
1204bf215546Sopenharmony_ci       */
1205bf215546Sopenharmony_ci      if ((rp.attachment_aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
1206bf215546Sopenharmony_ci                                    VK_IMAGE_ASPECT_STENCIL_BIT)) ||
1207bf215546Sopenharmony_ci          !vk_render_pass_state_is_complete(&rp))
1208bf215546Sopenharmony_ci         needs |= MESA_VK_GRAPHICS_STATE_DEPTH_STENCIL_BIT;
1209bf215546Sopenharmony_ci   }
1210bf215546Sopenharmony_ci
1211bf215546Sopenharmony_ci   if (lib & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) {
1212bf215546Sopenharmony_ci      if (rp.attachment_aspects & (VK_IMAGE_ASPECT_COLOR_BIT))
1213bf215546Sopenharmony_ci         needs |= MESA_VK_GRAPHICS_STATE_COLOR_BLEND_BIT;
1214bf215546Sopenharmony_ci
1215bf215546Sopenharmony_ci      needs |= MESA_VK_GRAPHICS_STATE_MULTISAMPLE_BIT;
1216bf215546Sopenharmony_ci   }
1217bf215546Sopenharmony_ci
1218bf215546Sopenharmony_ci   /*
1219bf215546Sopenharmony_ci    * Next, Filter off any states we already have.
1220bf215546Sopenharmony_ci    */
1221bf215546Sopenharmony_ci
1222bf215546Sopenharmony_ci#define FILTER_NEEDS(STATE, type, s) \
1223bf215546Sopenharmony_ci   if (state->s != NULL) needs &= ~STATE
1224bf215546Sopenharmony_ci
1225bf215546Sopenharmony_ci   FOREACH_STATE_GROUP(FILTER_NEEDS)
1226bf215546Sopenharmony_ci
1227bf215546Sopenharmony_ci#undef FILTER_NEEDS
1228bf215546Sopenharmony_ci
1229bf215546Sopenharmony_ci   /* Filter dynamic state down to just what we're adding */
1230bf215546Sopenharmony_ci   BITSET_DECLARE(dynamic_filter, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX);
1231bf215546Sopenharmony_ci   get_dynamic_state_groups(dynamic_filter, needs);
1232bf215546Sopenharmony_ci   BITSET_AND(dynamic, dynamic, dynamic_filter);
1233bf215546Sopenharmony_ci
1234bf215546Sopenharmony_ci   /* And add it in */
1235bf215546Sopenharmony_ci   BITSET_OR(state->dynamic, state->dynamic, dynamic);
1236bf215546Sopenharmony_ci
1237bf215546Sopenharmony_ci   /*
1238bf215546Sopenharmony_ci    * If a state is fully dynamic, we don't need to even allocate them.  Do
1239bf215546Sopenharmony_ci    * this after we've filtered dynamic state because we still want them to
1240bf215546Sopenharmony_ci    * show up in the dynamic state but don't want the actual state.
1241bf215546Sopenharmony_ci    */
1242bf215546Sopenharmony_ci   needs &= ~fully_dynamic_state_groups(state->dynamic);
1243bf215546Sopenharmony_ci
1244bf215546Sopenharmony_ci   /* If we don't need to set up any new states, bail early */
1245bf215546Sopenharmony_ci   if (needs == 0)
1246bf215546Sopenharmony_ci      return VK_SUCCESS;
1247bf215546Sopenharmony_ci
1248bf215546Sopenharmony_ci   /*
1249bf215546Sopenharmony_ci    * Now, ensure that we have space for each of the states we're going to
1250bf215546Sopenharmony_ci    * fill.  If all != NULL, we'll pull from that.  Otherwise, we need to
1251bf215546Sopenharmony_ci    * allocate memory.
1252bf215546Sopenharmony_ci    */
1253bf215546Sopenharmony_ci
1254bf215546Sopenharmony_ci   VK_MULTIALLOC(ma);
1255bf215546Sopenharmony_ci
1256bf215546Sopenharmony_ci#define ENSURE_STATE_IF_NEEDED(STATE, type, s) \
1257bf215546Sopenharmony_ci   struct type *new_##s = NULL; \
1258bf215546Sopenharmony_ci   if (needs & STATE) { \
1259bf215546Sopenharmony_ci      if (all == NULL) { \
1260bf215546Sopenharmony_ci         vk_multialloc_add(&ma, &new_##s, struct type, 1); \
1261bf215546Sopenharmony_ci      } else { \
1262bf215546Sopenharmony_ci         new_##s = &all->s; \
1263bf215546Sopenharmony_ci      } \
1264bf215546Sopenharmony_ci   }
1265bf215546Sopenharmony_ci
1266bf215546Sopenharmony_ci   FOREACH_STATE_GROUP(ENSURE_STATE_IF_NEEDED)
1267bf215546Sopenharmony_ci
1268bf215546Sopenharmony_ci#undef ENSURE_STATE_IF_NEEDED
1269bf215546Sopenharmony_ci
1270bf215546Sopenharmony_ci   /* Sample locations are a bit special.  We don't want to waste the memory
1271bf215546Sopenharmony_ci    * for 64 floats if we don't need to.  Also, we set up standard sample
1272bf215546Sopenharmony_ci    * locations if no user-provided sample locations are available.
1273bf215546Sopenharmony_ci    */
1274bf215546Sopenharmony_ci   const VkPipelineSampleLocationsStateCreateInfoEXT *sl_info = NULL;
1275bf215546Sopenharmony_ci   struct vk_sample_locations_state *new_sl = NULL;
1276bf215546Sopenharmony_ci   if (needs & MESA_VK_GRAPHICS_STATE_MULTISAMPLE_BIT) {
1277bf215546Sopenharmony_ci      sl_info = vk_find_struct_const(info->pMultisampleState->pNext,
1278bf215546Sopenharmony_ci                                     PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT);
1279bf215546Sopenharmony_ci      if (needs_sample_locations_state(dynamic, sl_info)) {
1280bf215546Sopenharmony_ci         if (all == NULL) {
1281bf215546Sopenharmony_ci            vk_multialloc_add(&ma, &new_sl, struct vk_sample_locations_state, 1);
1282bf215546Sopenharmony_ci         } else {
1283bf215546Sopenharmony_ci            new_sl = &all->ms_sample_locations;
1284bf215546Sopenharmony_ci         }
1285bf215546Sopenharmony_ci      }
1286bf215546Sopenharmony_ci   }
1287bf215546Sopenharmony_ci
1288bf215546Sopenharmony_ci   /*
1289bf215546Sopenharmony_ci    * Allocate memory, if needed
1290bf215546Sopenharmony_ci    */
1291bf215546Sopenharmony_ci
1292bf215546Sopenharmony_ci   if (ma.size > 0) {
1293bf215546Sopenharmony_ci      assert(all == NULL);
1294bf215546Sopenharmony_ci      *alloc_ptr_out = vk_multialloc_alloc2(&ma, &device->alloc, alloc, scope);
1295bf215546Sopenharmony_ci      if (*alloc_ptr_out == NULL)
1296bf215546Sopenharmony_ci         return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1297bf215546Sopenharmony_ci   }
1298bf215546Sopenharmony_ci
1299bf215546Sopenharmony_ci   /*
1300bf215546Sopenharmony_ci    * Create aliases for various input infos so we can use or FOREACH macro
1301bf215546Sopenharmony_ci    */
1302bf215546Sopenharmony_ci
1303bf215546Sopenharmony_ci#define INFO_ALIAS(_State, s) \
1304bf215546Sopenharmony_ci   const VkPipeline##_State##StateCreateInfo *s##_info = info->p##_State##State
1305bf215546Sopenharmony_ci
1306bf215546Sopenharmony_ci   INFO_ALIAS(VertexInput, vi);
1307bf215546Sopenharmony_ci   INFO_ALIAS(InputAssembly, ia);
1308bf215546Sopenharmony_ci   INFO_ALIAS(Tessellation, ts);
1309bf215546Sopenharmony_ci   INFO_ALIAS(Viewport, vp);
1310bf215546Sopenharmony_ci   INFO_ALIAS(Rasterization, rs);
1311bf215546Sopenharmony_ci   INFO_ALIAS(Multisample, ms);
1312bf215546Sopenharmony_ci   INFO_ALIAS(DepthStencil, ds);
1313bf215546Sopenharmony_ci   INFO_ALIAS(ColorBlend, cb);
1314bf215546Sopenharmony_ci
1315bf215546Sopenharmony_ci#undef INFO_ALIAS
1316bf215546Sopenharmony_ci
1317bf215546Sopenharmony_ci   const VkPipelineDiscardRectangleStateCreateInfoEXT *dr_info =
1318bf215546Sopenharmony_ci      vk_find_struct_const(info->pNext, PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT);
1319bf215546Sopenharmony_ci
1320bf215546Sopenharmony_ci   const VkPipelineFragmentShadingRateStateCreateInfoKHR *fsr_info =
1321bf215546Sopenharmony_ci      vk_find_struct_const(info->pNext, PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR);
1322bf215546Sopenharmony_ci
1323bf215546Sopenharmony_ci   /*
1324bf215546Sopenharmony_ci    * Finally, fill out all the states
1325bf215546Sopenharmony_ci    */
1326bf215546Sopenharmony_ci
1327bf215546Sopenharmony_ci#define INIT_STATE_IF_NEEDED(STATE, type, s) \
1328bf215546Sopenharmony_ci   if (needs & STATE) { \
1329bf215546Sopenharmony_ci      type##_init(new_##s, dynamic, s##_info); \
1330bf215546Sopenharmony_ci      state->s = new_##s; \
1331bf215546Sopenharmony_ci   }
1332bf215546Sopenharmony_ci
1333bf215546Sopenharmony_ci   /* render pass state is special and we just copy it */
1334bf215546Sopenharmony_ci#define vk_render_pass_state_init(s, d, i) *s = rp
1335bf215546Sopenharmony_ci
1336bf215546Sopenharmony_ci   FOREACH_STATE_GROUP(INIT_STATE_IF_NEEDED)
1337bf215546Sopenharmony_ci
1338bf215546Sopenharmony_ci#undef vk_render_pass_state_init
1339bf215546Sopenharmony_ci#undef INIT_STATE_IF_NEEDED
1340bf215546Sopenharmony_ci
1341bf215546Sopenharmony_ci   if (needs & MESA_VK_GRAPHICS_STATE_MULTISAMPLE_BIT) {
1342bf215546Sopenharmony_ci       vk_multisample_sample_locations_state_init(new_ms, new_sl, dynamic,
1343bf215546Sopenharmony_ci                                                  ms_info, sl_info);
1344bf215546Sopenharmony_ci   }
1345bf215546Sopenharmony_ci
1346bf215546Sopenharmony_ci   return VK_SUCCESS;
1347bf215546Sopenharmony_ci}
1348bf215546Sopenharmony_ci
1349bf215546Sopenharmony_ci#undef IS_DYNAMIC
1350bf215546Sopenharmony_ci#undef IS_NEEDED
1351bf215546Sopenharmony_ci
1352bf215546Sopenharmony_civoid
1353bf215546Sopenharmony_civk_graphics_pipeline_state_merge(struct vk_graphics_pipeline_state *dst,
1354bf215546Sopenharmony_ci                                 const struct vk_graphics_pipeline_state *src)
1355bf215546Sopenharmony_ci{
1356bf215546Sopenharmony_ci   vk_graphics_pipeline_state_validate(dst);
1357bf215546Sopenharmony_ci   vk_graphics_pipeline_state_validate(src);
1358bf215546Sopenharmony_ci
1359bf215546Sopenharmony_ci   BITSET_OR(dst->dynamic, dst->dynamic, src->dynamic);
1360bf215546Sopenharmony_ci
1361bf215546Sopenharmony_ci   dst->shader_stages |= src->shader_stages;
1362bf215546Sopenharmony_ci
1363bf215546Sopenharmony_ci   /* Render pass state needs special care because a render pass state may be
1364bf215546Sopenharmony_ci    * incomplete (view mask only).  See vk_render_pass_state_init().
1365bf215546Sopenharmony_ci    */
1366bf215546Sopenharmony_ci   if (dst->rp != NULL && src->rp != NULL &&
1367bf215546Sopenharmony_ci       !vk_render_pass_state_is_complete(dst->rp) &&
1368bf215546Sopenharmony_ci       vk_render_pass_state_is_complete(src->rp))
1369bf215546Sopenharmony_ci      dst->rp = src->rp;
1370bf215546Sopenharmony_ci
1371bf215546Sopenharmony_ci#define MERGE(STATE, type, state) \
1372bf215546Sopenharmony_ci   if (dst->state == NULL && src->state != NULL) dst->state = src->state;
1373bf215546Sopenharmony_ci
1374bf215546Sopenharmony_ci   FOREACH_STATE_GROUP(MERGE)
1375bf215546Sopenharmony_ci
1376bf215546Sopenharmony_ci#undef MERGE
1377bf215546Sopenharmony_ci}
1378bf215546Sopenharmony_ci
1379bf215546Sopenharmony_ciconst struct vk_dynamic_graphics_state vk_default_dynamic_graphics_state = {
1380bf215546Sopenharmony_ci   .rs = {
1381bf215546Sopenharmony_ci      .line = {
1382bf215546Sopenharmony_ci         .width = 1.0f,
1383bf215546Sopenharmony_ci      },
1384bf215546Sopenharmony_ci   },
1385bf215546Sopenharmony_ci   .fsr = {
1386bf215546Sopenharmony_ci      .fragment_size = {1u, 1u},
1387bf215546Sopenharmony_ci      .combiner_ops = {
1388bf215546Sopenharmony_ci         VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
1389bf215546Sopenharmony_ci         VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
1390bf215546Sopenharmony_ci      },
1391bf215546Sopenharmony_ci   },
1392bf215546Sopenharmony_ci   .ds = {
1393bf215546Sopenharmony_ci      .depth = {
1394bf215546Sopenharmony_ci         .bounds_test = {
1395bf215546Sopenharmony_ci            .min = 0.0f,
1396bf215546Sopenharmony_ci            .max = 1.0f,
1397bf215546Sopenharmony_ci         },
1398bf215546Sopenharmony_ci      },
1399bf215546Sopenharmony_ci      .stencil = {
1400bf215546Sopenharmony_ci         .write_enable = true,
1401bf215546Sopenharmony_ci         .front = {
1402bf215546Sopenharmony_ci            .compare_mask = -1,
1403bf215546Sopenharmony_ci            .write_mask = -1,
1404bf215546Sopenharmony_ci         },
1405bf215546Sopenharmony_ci         .back = {
1406bf215546Sopenharmony_ci            .compare_mask = -1,
1407bf215546Sopenharmony_ci            .write_mask = -1,
1408bf215546Sopenharmony_ci         },
1409bf215546Sopenharmony_ci      },
1410bf215546Sopenharmony_ci   },
1411bf215546Sopenharmony_ci   .cb = {
1412bf215546Sopenharmony_ci      .color_write_enables = 0xffffffffu,
1413bf215546Sopenharmony_ci   },
1414bf215546Sopenharmony_ci};
1415bf215546Sopenharmony_ci
1416bf215546Sopenharmony_civoid
1417bf215546Sopenharmony_civk_dynamic_graphics_state_init(struct vk_dynamic_graphics_state *dyn)
1418bf215546Sopenharmony_ci{
1419bf215546Sopenharmony_ci   *dyn = vk_default_dynamic_graphics_state;
1420bf215546Sopenharmony_ci}
1421bf215546Sopenharmony_ci
1422bf215546Sopenharmony_civoid
1423bf215546Sopenharmony_civk_dynamic_graphics_state_clear(struct vk_dynamic_graphics_state *dyn)
1424bf215546Sopenharmony_ci{
1425bf215546Sopenharmony_ci   struct vk_vertex_input_state *vi = dyn->vi;
1426bf215546Sopenharmony_ci   struct vk_sample_locations_state *sl = dyn->ms.sample_locations;
1427bf215546Sopenharmony_ci
1428bf215546Sopenharmony_ci   *dyn = vk_default_dynamic_graphics_state;
1429bf215546Sopenharmony_ci
1430bf215546Sopenharmony_ci   if (vi != NULL) {
1431bf215546Sopenharmony_ci      memset(vi, 0, sizeof(*vi));
1432bf215546Sopenharmony_ci      dyn->vi = vi;
1433bf215546Sopenharmony_ci   }
1434bf215546Sopenharmony_ci
1435bf215546Sopenharmony_ci   if (sl != NULL) {
1436bf215546Sopenharmony_ci      memset(sl, 0, sizeof(*sl));
1437bf215546Sopenharmony_ci      dyn->ms.sample_locations = sl;
1438bf215546Sopenharmony_ci   }
1439bf215546Sopenharmony_ci}
1440bf215546Sopenharmony_ci
1441bf215546Sopenharmony_civoid
1442bf215546Sopenharmony_civk_dynamic_graphics_state_fill(struct vk_dynamic_graphics_state *dyn,
1443bf215546Sopenharmony_ci                               const struct vk_graphics_pipeline_state *p)
1444bf215546Sopenharmony_ci{
1445bf215546Sopenharmony_ci   /* This funciton (and the individual vk_dynamic_graphics_state_init_*
1446bf215546Sopenharmony_ci    * functions it calls) are a bit sloppy.  Instead of checking every single
1447bf215546Sopenharmony_ci    * bit, we just copy everything and set the bits the right way at the end
1448bf215546Sopenharmony_ci    * based on what groups we actually had.
1449bf215546Sopenharmony_ci    */
1450bf215546Sopenharmony_ci   enum mesa_vk_graphics_state_groups groups = 0;
1451bf215546Sopenharmony_ci
1452bf215546Sopenharmony_ci   BITSET_DECLARE(needed, MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX);
1453bf215546Sopenharmony_ci   BITSET_COPY(needed, p->dynamic);
1454bf215546Sopenharmony_ci   BITSET_NOT(needed);
1455bf215546Sopenharmony_ci
1456bf215546Sopenharmony_ci   /* We only want to copy these if the driver has filled out the relevant
1457bf215546Sopenharmony_ci    * pointer in the dynamic state struct.  If not, they don't support them
1458bf215546Sopenharmony_ci    * as dynamic state and we should leave them alone.
1459bf215546Sopenharmony_ci    */
1460bf215546Sopenharmony_ci   if (dyn->vi == NULL)
1461bf215546Sopenharmony_ci      BITSET_CLEAR(needed, MESA_VK_DYNAMIC_VI);
1462bf215546Sopenharmony_ci   if (dyn->ms.sample_locations == NULL)
1463bf215546Sopenharmony_ci      BITSET_CLEAR(needed, MESA_VK_DYNAMIC_MS_SAMPLE_LOCATIONS);
1464bf215546Sopenharmony_ci
1465bf215546Sopenharmony_ci#define INIT_DYNAMIC_STATE(STATE, type, s) \
1466bf215546Sopenharmony_ci   if (p->s != NULL) { \
1467bf215546Sopenharmony_ci      vk_dynamic_graphics_state_init_##s(dyn, needed, p->s); \
1468bf215546Sopenharmony_ci      groups |= STATE; \
1469bf215546Sopenharmony_ci   }
1470bf215546Sopenharmony_ci
1471bf215546Sopenharmony_ci   FOREACH_STATE_GROUP(INIT_DYNAMIC_STATE);
1472bf215546Sopenharmony_ci
1473bf215546Sopenharmony_ci#undef INIT_DYNAMIC_STATE
1474bf215546Sopenharmony_ci
1475bf215546Sopenharmony_ci   /* Mask off all but the groups we actually found */
1476bf215546Sopenharmony_ci   get_dynamic_state_groups(dyn->set, groups);
1477bf215546Sopenharmony_ci   BITSET_AND(dyn->set, dyn->set, needed);
1478bf215546Sopenharmony_ci}
1479bf215546Sopenharmony_ci
1480bf215546Sopenharmony_ci#define SET_DYN_VALUE(dst, STATE, state, value) do {        \
1481bf215546Sopenharmony_ci   if (!BITSET_TEST((dst)->set, MESA_VK_DYNAMIC_##STATE) || \
1482bf215546Sopenharmony_ci       (dst)->state != (value)) {                           \
1483bf215546Sopenharmony_ci      (dst)->state = (value);                               \
1484bf215546Sopenharmony_ci      assert((dst)->state == (value));                      \
1485bf215546Sopenharmony_ci      BITSET_SET(dst->set, MESA_VK_DYNAMIC_##STATE);        \
1486bf215546Sopenharmony_ci      BITSET_SET(dst->dirty, MESA_VK_DYNAMIC_##STATE);      \
1487bf215546Sopenharmony_ci   }                                                        \
1488bf215546Sopenharmony_ci} while(0)
1489bf215546Sopenharmony_ci
1490bf215546Sopenharmony_ci#define SET_DYN_BOOL(dst, STATE, state, value) \
1491bf215546Sopenharmony_ci   SET_DYN_VALUE(dst, STATE, state, (bool)value);
1492bf215546Sopenharmony_ci
1493bf215546Sopenharmony_ci#define SET_DYN_ARRAY(dst, STATE, state, start, count, src) do {  \
1494bf215546Sopenharmony_ci   assert(start + count <= ARRAY_SIZE((dst)->state));             \
1495bf215546Sopenharmony_ci   STATIC_ASSERT(sizeof(*(dst)->state) == sizeof(*(src)));        \
1496bf215546Sopenharmony_ci   const size_t __state_size = sizeof(*(dst)->state) * (count);   \
1497bf215546Sopenharmony_ci   if (!BITSET_TEST((dst)->set, MESA_VK_DYNAMIC_##STATE) ||       \
1498bf215546Sopenharmony_ci       memcmp((dst)->state + start, src, __state_size)) {         \
1499bf215546Sopenharmony_ci      memcpy((dst)->state + start, src, __state_size);            \
1500bf215546Sopenharmony_ci      BITSET_SET(dst->set, MESA_VK_DYNAMIC_##STATE);              \
1501bf215546Sopenharmony_ci      BITSET_SET(dst->dirty, MESA_VK_DYNAMIC_##STATE);            \
1502bf215546Sopenharmony_ci   }                                                              \
1503bf215546Sopenharmony_ci} while(0)
1504bf215546Sopenharmony_ci
1505bf215546Sopenharmony_civoid
1506bf215546Sopenharmony_civk_dynamic_graphics_state_copy(struct vk_dynamic_graphics_state *dst,
1507bf215546Sopenharmony_ci                               const struct vk_dynamic_graphics_state *src)
1508bf215546Sopenharmony_ci{
1509bf215546Sopenharmony_ci#define IS_SET_IN_SRC(STATE) \
1510bf215546Sopenharmony_ci   BITSET_TEST(src->set, MESA_VK_DYNAMIC_##STATE)
1511bf215546Sopenharmony_ci
1512bf215546Sopenharmony_ci#define COPY_MEMBER(STATE, state) \
1513bf215546Sopenharmony_ci   SET_DYN_VALUE(dst, STATE, state, src->state)
1514bf215546Sopenharmony_ci
1515bf215546Sopenharmony_ci#define COPY_ARRAY(STATE, state, count) \
1516bf215546Sopenharmony_ci   SET_DYN_ARRAY(dst, STATE, state, 0, count, src->state)
1517bf215546Sopenharmony_ci
1518bf215546Sopenharmony_ci#define COPY_IF_SET(STATE, state) \
1519bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(STATE)) SET_DYN_VALUE(dst, STATE, state, src->state)
1520bf215546Sopenharmony_ci
1521bf215546Sopenharmony_ci   assert((dst->vi != NULL) == (src->vi != NULL));
1522bf215546Sopenharmony_ci   if (dst->vi != NULL && IS_SET_IN_SRC(VI)) {
1523bf215546Sopenharmony_ci      COPY_MEMBER(VI, vi->bindings_valid);
1524bf215546Sopenharmony_ci      u_foreach_bit(b, src->vi->bindings_valid) {
1525bf215546Sopenharmony_ci         COPY_MEMBER(VI, vi->bindings[b].stride);
1526bf215546Sopenharmony_ci         COPY_MEMBER(VI, vi->bindings[b].input_rate);
1527bf215546Sopenharmony_ci         COPY_MEMBER(VI, vi->bindings[b].divisor);
1528bf215546Sopenharmony_ci      }
1529bf215546Sopenharmony_ci      COPY_MEMBER(VI, vi->attributes_valid);
1530bf215546Sopenharmony_ci      u_foreach_bit(a, src->vi->attributes_valid) {
1531bf215546Sopenharmony_ci         COPY_MEMBER(VI, vi->attributes[a].binding);
1532bf215546Sopenharmony_ci         COPY_MEMBER(VI, vi->attributes[a].format);
1533bf215546Sopenharmony_ci         COPY_MEMBER(VI, vi->attributes[a].offset);
1534bf215546Sopenharmony_ci      }
1535bf215546Sopenharmony_ci   }
1536bf215546Sopenharmony_ci
1537bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(VI_BINDING_STRIDES)) {
1538bf215546Sopenharmony_ci      COPY_ARRAY(VI_BINDING_STRIDES, vi_binding_strides,
1539bf215546Sopenharmony_ci                 MESA_VK_MAX_VERTEX_BINDINGS);
1540bf215546Sopenharmony_ci   }
1541bf215546Sopenharmony_ci
1542bf215546Sopenharmony_ci   COPY_IF_SET(IA_PRIMITIVE_TOPOLOGY, ia.primitive_topology);
1543bf215546Sopenharmony_ci   COPY_IF_SET(IA_PRIMITIVE_RESTART_ENABLE, ia.primitive_restart_enable);
1544bf215546Sopenharmony_ci   COPY_IF_SET(TS_PATCH_CONTROL_POINTS, ts.patch_control_points);
1545bf215546Sopenharmony_ci
1546bf215546Sopenharmony_ci   COPY_IF_SET(VP_VIEWPORT_COUNT, vp.viewport_count);
1547bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(VP_VIEWPORTS)) {
1548bf215546Sopenharmony_ci      assert(IS_SET_IN_SRC(VP_VIEWPORT_COUNT));
1549bf215546Sopenharmony_ci      COPY_ARRAY(VP_VIEWPORTS, vp.viewports, src->vp.viewport_count);
1550bf215546Sopenharmony_ci   }
1551bf215546Sopenharmony_ci
1552bf215546Sopenharmony_ci   COPY_IF_SET(VP_SCISSOR_COUNT, vp.scissor_count);
1553bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(VP_SCISSORS)) {
1554bf215546Sopenharmony_ci      assert(IS_SET_IN_SRC(VP_SCISSOR_COUNT));
1555bf215546Sopenharmony_ci      COPY_ARRAY(VP_SCISSORS, vp.scissors, src->vp.scissor_count);
1556bf215546Sopenharmony_ci   }
1557bf215546Sopenharmony_ci
1558bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(DR_RECTANGLES)) {
1559bf215546Sopenharmony_ci      COPY_MEMBER(DR_RECTANGLES, dr.rectangle_count);
1560bf215546Sopenharmony_ci      COPY_ARRAY(DR_RECTANGLES, dr.rectangles, src->dr.rectangle_count);
1561bf215546Sopenharmony_ci   }
1562bf215546Sopenharmony_ci
1563bf215546Sopenharmony_ci   COPY_IF_SET(RS_RASTERIZER_DISCARD_ENABLE, rs.rasterizer_discard_enable);
1564bf215546Sopenharmony_ci   COPY_IF_SET(RS_CULL_MODE, rs.cull_mode);
1565bf215546Sopenharmony_ci   COPY_IF_SET(RS_FRONT_FACE, rs.front_face);
1566bf215546Sopenharmony_ci   COPY_IF_SET(RS_DEPTH_BIAS_ENABLE, rs.depth_bias.enable);
1567bf215546Sopenharmony_ci   COPY_IF_SET(RS_DEPTH_BIAS_FACTORS, rs.depth_bias.constant);
1568bf215546Sopenharmony_ci   COPY_IF_SET(RS_DEPTH_BIAS_FACTORS, rs.depth_bias.clamp);
1569bf215546Sopenharmony_ci   COPY_IF_SET(RS_DEPTH_BIAS_FACTORS, rs.depth_bias.slope);
1570bf215546Sopenharmony_ci   COPY_IF_SET(RS_LINE_WIDTH, rs.line.width);
1571bf215546Sopenharmony_ci   COPY_IF_SET(RS_LINE_STIPPLE, rs.line.stipple.factor);
1572bf215546Sopenharmony_ci   COPY_IF_SET(RS_LINE_STIPPLE, rs.line.stipple.pattern);
1573bf215546Sopenharmony_ci
1574bf215546Sopenharmony_ci   COPY_IF_SET(FSR, fsr.fragment_size.width);
1575bf215546Sopenharmony_ci   COPY_IF_SET(FSR, fsr.fragment_size.height);
1576bf215546Sopenharmony_ci   COPY_IF_SET(FSR, fsr.combiner_ops[0]);
1577bf215546Sopenharmony_ci   COPY_IF_SET(FSR, fsr.combiner_ops[1]);
1578bf215546Sopenharmony_ci
1579bf215546Sopenharmony_ci   assert((dst->ms.sample_locations == NULL) ==
1580bf215546Sopenharmony_ci          (src->ms.sample_locations == NULL));
1581bf215546Sopenharmony_ci   if (dst->ms.sample_locations != NULL &&
1582bf215546Sopenharmony_ci       IS_SET_IN_SRC(MS_SAMPLE_LOCATIONS)) {
1583bf215546Sopenharmony_ci      COPY_MEMBER(MS_SAMPLE_LOCATIONS, ms.sample_locations->per_pixel);
1584bf215546Sopenharmony_ci      COPY_MEMBER(MS_SAMPLE_LOCATIONS, ms.sample_locations->grid_size.width);
1585bf215546Sopenharmony_ci      COPY_MEMBER(MS_SAMPLE_LOCATIONS, ms.sample_locations->grid_size.height);
1586bf215546Sopenharmony_ci      const uint32_t sl_count = src->ms.sample_locations->per_pixel *
1587bf215546Sopenharmony_ci                                src->ms.sample_locations->grid_size.width *
1588bf215546Sopenharmony_ci                                src->ms.sample_locations->grid_size.height;
1589bf215546Sopenharmony_ci      COPY_ARRAY(MS_SAMPLE_LOCATIONS, ms.sample_locations->locations, sl_count);
1590bf215546Sopenharmony_ci   }
1591bf215546Sopenharmony_ci
1592bf215546Sopenharmony_ci   COPY_IF_SET(DS_DEPTH_TEST_ENABLE, ds.depth.test_enable);
1593bf215546Sopenharmony_ci   COPY_IF_SET(DS_DEPTH_WRITE_ENABLE, ds.depth.write_enable);
1594bf215546Sopenharmony_ci   COPY_IF_SET(DS_DEPTH_COMPARE_OP, ds.depth.compare_op);
1595bf215546Sopenharmony_ci   COPY_IF_SET(DS_DEPTH_BOUNDS_TEST_ENABLE, ds.depth.bounds_test.enable);
1596bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(DS_DEPTH_BOUNDS_TEST_BOUNDS)) {
1597bf215546Sopenharmony_ci      COPY_MEMBER(DS_DEPTH_BOUNDS_TEST_BOUNDS, ds.depth.bounds_test.min);
1598bf215546Sopenharmony_ci      COPY_MEMBER(DS_DEPTH_BOUNDS_TEST_BOUNDS, ds.depth.bounds_test.max);
1599bf215546Sopenharmony_ci   }
1600bf215546Sopenharmony_ci
1601bf215546Sopenharmony_ci   COPY_IF_SET(DS_STENCIL_TEST_ENABLE, ds.stencil.test_enable);
1602bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(DS_STENCIL_OP)) {
1603bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_OP, ds.stencil.front.op.fail);
1604bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_OP, ds.stencil.front.op.pass);
1605bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_OP, ds.stencil.front.op.depth_fail);
1606bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_OP, ds.stencil.front.op.compare);
1607bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_OP, ds.stencil.back.op.fail);
1608bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_OP, ds.stencil.back.op.pass);
1609bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_OP, ds.stencil.back.op.depth_fail);
1610bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_OP, ds.stencil.back.op.compare);
1611bf215546Sopenharmony_ci   }
1612bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(DS_STENCIL_COMPARE_MASK)) {
1613bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_COMPARE_MASK, ds.stencil.front.compare_mask);
1614bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_COMPARE_MASK, ds.stencil.back.compare_mask);
1615bf215546Sopenharmony_ci   }
1616bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(DS_STENCIL_WRITE_MASK)) {
1617bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_WRITE_MASK, ds.stencil.front.write_mask);
1618bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_WRITE_MASK, ds.stencil.back.write_mask);
1619bf215546Sopenharmony_ci   }
1620bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(DS_STENCIL_REFERENCE)) {
1621bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_REFERENCE, ds.stencil.front.reference);
1622bf215546Sopenharmony_ci      COPY_MEMBER(DS_STENCIL_REFERENCE, ds.stencil.back.reference);
1623bf215546Sopenharmony_ci   }
1624bf215546Sopenharmony_ci
1625bf215546Sopenharmony_ci   COPY_IF_SET(CB_LOGIC_OP, cb.logic_op);
1626bf215546Sopenharmony_ci   COPY_IF_SET(CB_COLOR_WRITE_ENABLES, cb.color_write_enables);
1627bf215546Sopenharmony_ci   if (IS_SET_IN_SRC(CB_BLEND_CONSTANTS))
1628bf215546Sopenharmony_ci      COPY_ARRAY(CB_BLEND_CONSTANTS, cb.blend_constants, 4);
1629bf215546Sopenharmony_ci
1630bf215546Sopenharmony_ci#undef IS_SET_IN_SRC
1631bf215546Sopenharmony_ci#undef MARK_DIRTY
1632bf215546Sopenharmony_ci#undef COPY_MEMBER
1633bf215546Sopenharmony_ci#undef COPY_ARRAY
1634bf215546Sopenharmony_ci#undef COPY_IF_SET
1635bf215546Sopenharmony_ci
1636bf215546Sopenharmony_ci   for (uint32_t w = 0; w < ARRAY_SIZE(dst->dirty); w++) {
1637bf215546Sopenharmony_ci      /* If it's in the source but isn't set in the destination at all, mark
1638bf215546Sopenharmony_ci       * it dirty.  It's possible that the default values just happen to equal
1639bf215546Sopenharmony_ci       * the value from src.
1640bf215546Sopenharmony_ci       */
1641bf215546Sopenharmony_ci      dst->dirty[w] |= src->set[w] & ~dst->set[w];
1642bf215546Sopenharmony_ci
1643bf215546Sopenharmony_ci      /* Everything that was in the source is now in the destination */
1644bf215546Sopenharmony_ci      dst->set[w] |= src->set[w];
1645bf215546Sopenharmony_ci   }
1646bf215546Sopenharmony_ci}
1647bf215546Sopenharmony_ci
1648bf215546Sopenharmony_civoid
1649bf215546Sopenharmony_civk_cmd_set_dynamic_graphics_state(struct vk_command_buffer *cmd,
1650bf215546Sopenharmony_ci                                  const struct vk_dynamic_graphics_state *state)
1651bf215546Sopenharmony_ci{
1652bf215546Sopenharmony_ci   vk_dynamic_graphics_state_copy(&cmd->dynamic_graphics_state, state);
1653bf215546Sopenharmony_ci}
1654bf215546Sopenharmony_ci
1655bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1656bf215546Sopenharmony_civk_common_CmdSetVertexInputEXT(VkCommandBuffer commandBuffer,
1657bf215546Sopenharmony_ci   uint32_t vertexBindingDescriptionCount,
1658bf215546Sopenharmony_ci   const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions,
1659bf215546Sopenharmony_ci   uint32_t vertexAttributeDescriptionCount,
1660bf215546Sopenharmony_ci   const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions)
1661bf215546Sopenharmony_ci{
1662bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1663bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1664bf215546Sopenharmony_ci
1665bf215546Sopenharmony_ci   uint32_t bindings_valid = 0;
1666bf215546Sopenharmony_ci   for (uint32_t i = 0; i < vertexBindingDescriptionCount; i++) {
1667bf215546Sopenharmony_ci      const VkVertexInputBindingDescription2EXT *desc =
1668bf215546Sopenharmony_ci         &pVertexBindingDescriptions[i];
1669bf215546Sopenharmony_ci
1670bf215546Sopenharmony_ci      assert(desc->binding < MESA_VK_MAX_VERTEX_BINDINGS);
1671bf215546Sopenharmony_ci      assert(desc->stride <= MESA_VK_MAX_VERTEX_BINDING_STRIDE);
1672bf215546Sopenharmony_ci      assert(desc->inputRate <= UINT8_MAX);
1673bf215546Sopenharmony_ci
1674bf215546Sopenharmony_ci      const uint32_t b = desc->binding;
1675bf215546Sopenharmony_ci      bindings_valid |= BITFIELD_BIT(b);
1676bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, VI, vi->bindings[b].stride, desc->stride);
1677bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, VI, vi->bindings[b].input_rate, desc->inputRate);
1678bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, VI, vi->bindings[b].divisor, desc->divisor);
1679bf215546Sopenharmony_ci
1680bf215546Sopenharmony_ci      /* Also set bindings_strides in case a driver is keying off that */
1681bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, VI_BINDING_STRIDES,
1682bf215546Sopenharmony_ci                    vi_binding_strides[b], desc->stride);
1683bf215546Sopenharmony_ci   }
1684bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, VI, vi->bindings_valid, bindings_valid);
1685bf215546Sopenharmony_ci
1686bf215546Sopenharmony_ci   uint32_t attributes_valid = 0;
1687bf215546Sopenharmony_ci   for (uint32_t i = 0; i < vertexAttributeDescriptionCount; i++) {
1688bf215546Sopenharmony_ci      const VkVertexInputAttributeDescription2EXT *desc =
1689bf215546Sopenharmony_ci         &pVertexAttributeDescriptions[i];
1690bf215546Sopenharmony_ci
1691bf215546Sopenharmony_ci      assert(desc->location < MESA_VK_MAX_VERTEX_ATTRIBUTES);
1692bf215546Sopenharmony_ci      assert(desc->binding < MESA_VK_MAX_VERTEX_BINDINGS);
1693bf215546Sopenharmony_ci      assert(bindings_valid & BITFIELD_BIT(desc->binding));
1694bf215546Sopenharmony_ci
1695bf215546Sopenharmony_ci      const uint32_t a = desc->location;
1696bf215546Sopenharmony_ci      attributes_valid |= BITFIELD_BIT(a);
1697bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, VI, vi->attributes[a].binding, desc->binding);
1698bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, VI, vi->attributes[a].format, desc->format);
1699bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, VI, vi->attributes[a].offset, desc->offset);
1700bf215546Sopenharmony_ci   }
1701bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, VI, vi->attributes_valid, attributes_valid);
1702bf215546Sopenharmony_ci}
1703bf215546Sopenharmony_ci
1704bf215546Sopenharmony_civoid
1705bf215546Sopenharmony_civk_cmd_set_vertex_binding_strides(struct vk_command_buffer *cmd,
1706bf215546Sopenharmony_ci                                  uint32_t first_binding,
1707bf215546Sopenharmony_ci                                  uint32_t binding_count,
1708bf215546Sopenharmony_ci                                  const VkDeviceSize *strides)
1709bf215546Sopenharmony_ci{
1710bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1711bf215546Sopenharmony_ci
1712bf215546Sopenharmony_ci   for (uint32_t i = 0; i < binding_count; i++) {
1713bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, VI_BINDING_STRIDES,
1714bf215546Sopenharmony_ci                    vi_binding_strides[first_binding + i], strides[i]);
1715bf215546Sopenharmony_ci   }
1716bf215546Sopenharmony_ci}
1717bf215546Sopenharmony_ci
1718bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1719bf215546Sopenharmony_civk_common_CmdSetPrimitiveTopology(VkCommandBuffer commandBuffer,
1720bf215546Sopenharmony_ci                                  VkPrimitiveTopology primitiveTopology)
1721bf215546Sopenharmony_ci{
1722bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1723bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1724bf215546Sopenharmony_ci
1725bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, IA_PRIMITIVE_TOPOLOGY,
1726bf215546Sopenharmony_ci                 ia.primitive_topology, primitiveTopology);
1727bf215546Sopenharmony_ci}
1728bf215546Sopenharmony_ci
1729bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1730bf215546Sopenharmony_civk_common_CmdSetPrimitiveRestartEnable(VkCommandBuffer commandBuffer,
1731bf215546Sopenharmony_ci                                       VkBool32 primitiveRestartEnable)
1732bf215546Sopenharmony_ci{
1733bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1734bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1735bf215546Sopenharmony_ci
1736bf215546Sopenharmony_ci   SET_DYN_BOOL(dyn, IA_PRIMITIVE_RESTART_ENABLE,
1737bf215546Sopenharmony_ci                ia.primitive_restart_enable, primitiveRestartEnable);
1738bf215546Sopenharmony_ci}
1739bf215546Sopenharmony_ci
1740bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1741bf215546Sopenharmony_civk_common_CmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer,
1742bf215546Sopenharmony_ci                                      uint32_t patchControlPoints)
1743bf215546Sopenharmony_ci{
1744bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1745bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1746bf215546Sopenharmony_ci
1747bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, TS_PATCH_CONTROL_POINTS,
1748bf215546Sopenharmony_ci                 ts.patch_control_points, patchControlPoints);
1749bf215546Sopenharmony_ci}
1750bf215546Sopenharmony_ci
1751bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1752bf215546Sopenharmony_civk_common_CmdSetViewport(VkCommandBuffer commandBuffer,
1753bf215546Sopenharmony_ci                         uint32_t firstViewport,
1754bf215546Sopenharmony_ci                         uint32_t viewportCount,
1755bf215546Sopenharmony_ci                         const VkViewport *pViewports)
1756bf215546Sopenharmony_ci{
1757bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1758bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1759bf215546Sopenharmony_ci
1760bf215546Sopenharmony_ci   SET_DYN_ARRAY(dyn, VP_VIEWPORTS, vp.viewports,
1761bf215546Sopenharmony_ci                 firstViewport, viewportCount, pViewports);
1762bf215546Sopenharmony_ci}
1763bf215546Sopenharmony_ci
1764bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1765bf215546Sopenharmony_civk_common_CmdSetViewportWithCount(VkCommandBuffer commandBuffer,
1766bf215546Sopenharmony_ci                                  uint32_t viewportCount,
1767bf215546Sopenharmony_ci                                  const VkViewport *pViewports)
1768bf215546Sopenharmony_ci{
1769bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1770bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1771bf215546Sopenharmony_ci
1772bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, VP_VIEWPORT_COUNT, vp.viewport_count, viewportCount);
1773bf215546Sopenharmony_ci   SET_DYN_ARRAY(dyn, VP_VIEWPORTS, vp.viewports, 0, viewportCount, pViewports);
1774bf215546Sopenharmony_ci}
1775bf215546Sopenharmony_ci
1776bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1777bf215546Sopenharmony_civk_common_CmdSetScissor(VkCommandBuffer commandBuffer,
1778bf215546Sopenharmony_ci                        uint32_t firstScissor,
1779bf215546Sopenharmony_ci                        uint32_t scissorCount,
1780bf215546Sopenharmony_ci                        const VkRect2D *pScissors)
1781bf215546Sopenharmony_ci{
1782bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1783bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1784bf215546Sopenharmony_ci
1785bf215546Sopenharmony_ci   SET_DYN_ARRAY(dyn, VP_SCISSORS, vp.scissors,
1786bf215546Sopenharmony_ci                 firstScissor, scissorCount, pScissors);
1787bf215546Sopenharmony_ci}
1788bf215546Sopenharmony_ci
1789bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1790bf215546Sopenharmony_civk_common_CmdSetScissorWithCount(VkCommandBuffer commandBuffer,
1791bf215546Sopenharmony_ci                                 uint32_t scissorCount,
1792bf215546Sopenharmony_ci                                 const VkRect2D *pScissors)
1793bf215546Sopenharmony_ci{
1794bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1795bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1796bf215546Sopenharmony_ci
1797bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, VP_SCISSOR_COUNT, vp.scissor_count, scissorCount);
1798bf215546Sopenharmony_ci   SET_DYN_ARRAY(dyn, VP_SCISSORS, vp.scissors, 0, scissorCount, pScissors);
1799bf215546Sopenharmony_ci}
1800bf215546Sopenharmony_ci
1801bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1802bf215546Sopenharmony_civk_common_CmdSetDiscardRectangleEXT(VkCommandBuffer commandBuffer,
1803bf215546Sopenharmony_ci                                    uint32_t firstDiscardRectangle,
1804bf215546Sopenharmony_ci                                    uint32_t discardRectangleCount,
1805bf215546Sopenharmony_ci                                    const VkRect2D *pDiscardRectangles)
1806bf215546Sopenharmony_ci{
1807bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1808bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1809bf215546Sopenharmony_ci
1810bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, DR_RECTANGLES, dr.rectangle_count, discardRectangleCount);
1811bf215546Sopenharmony_ci   SET_DYN_ARRAY(dyn, DR_RECTANGLES, dr.rectangles, firstDiscardRectangle,
1812bf215546Sopenharmony_ci                 discardRectangleCount, pDiscardRectangles);
1813bf215546Sopenharmony_ci}
1814bf215546Sopenharmony_ci
1815bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1816bf215546Sopenharmony_civk_common_CmdSetRasterizerDiscardEnableEXT(VkCommandBuffer commandBuffer,
1817bf215546Sopenharmony_ci                                           VkBool32 rasterizerDiscardEnable)
1818bf215546Sopenharmony_ci{
1819bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1820bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1821bf215546Sopenharmony_ci
1822bf215546Sopenharmony_ci   SET_DYN_BOOL(dyn, RS_RASTERIZER_DISCARD_ENABLE,
1823bf215546Sopenharmony_ci                rs.rasterizer_discard_enable, rasterizerDiscardEnable);
1824bf215546Sopenharmony_ci}
1825bf215546Sopenharmony_ci
1826bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1827bf215546Sopenharmony_civk_common_CmdSetCullMode(VkCommandBuffer commandBuffer,
1828bf215546Sopenharmony_ci                         VkCullModeFlags cullMode)
1829bf215546Sopenharmony_ci{
1830bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1831bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1832bf215546Sopenharmony_ci
1833bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, RS_CULL_MODE, rs.cull_mode, cullMode);
1834bf215546Sopenharmony_ci}
1835bf215546Sopenharmony_ci
1836bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1837bf215546Sopenharmony_civk_common_CmdSetFrontFace(VkCommandBuffer commandBuffer,
1838bf215546Sopenharmony_ci                          VkFrontFace frontFace)
1839bf215546Sopenharmony_ci{
1840bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1841bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1842bf215546Sopenharmony_ci
1843bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, RS_FRONT_FACE, rs.front_face, frontFace);
1844bf215546Sopenharmony_ci}
1845bf215546Sopenharmony_ci
1846bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1847bf215546Sopenharmony_civk_common_CmdSetDepthBiasEnable(VkCommandBuffer commandBuffer,
1848bf215546Sopenharmony_ci                                VkBool32 depthBiasEnable)
1849bf215546Sopenharmony_ci{
1850bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1851bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1852bf215546Sopenharmony_ci
1853bf215546Sopenharmony_ci   SET_DYN_BOOL(dyn, RS_DEPTH_BIAS_ENABLE,
1854bf215546Sopenharmony_ci                rs.depth_bias.enable, depthBiasEnable);
1855bf215546Sopenharmony_ci}
1856bf215546Sopenharmony_ci
1857bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1858bf215546Sopenharmony_civk_common_CmdSetDepthBias(VkCommandBuffer commandBuffer,
1859bf215546Sopenharmony_ci                          float depthBiasConstantFactor,
1860bf215546Sopenharmony_ci                          float depthBiasClamp,
1861bf215546Sopenharmony_ci                          float depthBiasSlopeFactor)
1862bf215546Sopenharmony_ci{
1863bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1864bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1865bf215546Sopenharmony_ci
1866bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, RS_DEPTH_BIAS_FACTORS,
1867bf215546Sopenharmony_ci                 rs.depth_bias.constant, depthBiasConstantFactor);
1868bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, RS_DEPTH_BIAS_FACTORS,
1869bf215546Sopenharmony_ci                 rs.depth_bias.clamp, depthBiasClamp);
1870bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, RS_DEPTH_BIAS_FACTORS,
1871bf215546Sopenharmony_ci                 rs.depth_bias.slope, depthBiasSlopeFactor);
1872bf215546Sopenharmony_ci}
1873bf215546Sopenharmony_ci
1874bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1875bf215546Sopenharmony_civk_common_CmdSetLineWidth(VkCommandBuffer commandBuffer,
1876bf215546Sopenharmony_ci                          float lineWidth)
1877bf215546Sopenharmony_ci{
1878bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1879bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1880bf215546Sopenharmony_ci
1881bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, RS_LINE_WIDTH, rs.line.width, lineWidth);
1882bf215546Sopenharmony_ci}
1883bf215546Sopenharmony_ci
1884bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1885bf215546Sopenharmony_civk_common_CmdSetLineStippleEXT(VkCommandBuffer commandBuffer,
1886bf215546Sopenharmony_ci                               uint32_t lineStippleFactor,
1887bf215546Sopenharmony_ci                               uint16_t lineStipplePattern)
1888bf215546Sopenharmony_ci{
1889bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1890bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1891bf215546Sopenharmony_ci
1892bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, RS_LINE_STIPPLE,
1893bf215546Sopenharmony_ci                 rs.line.stipple.factor, lineStippleFactor);
1894bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, RS_LINE_STIPPLE,
1895bf215546Sopenharmony_ci                 rs.line.stipple.pattern, lineStipplePattern);
1896bf215546Sopenharmony_ci}
1897bf215546Sopenharmony_ci
1898bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1899bf215546Sopenharmony_civk_common_CmdSetFragmentShadingRateKHR(VkCommandBuffer commandBuffer,
1900bf215546Sopenharmony_ci   const VkExtent2D *pFragmentSize,
1901bf215546Sopenharmony_ci   const VkFragmentShadingRateCombinerOpKHR combinerOps[2])
1902bf215546Sopenharmony_ci{
1903bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1904bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1905bf215546Sopenharmony_ci
1906bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, FSR, fsr.fragment_size.width, pFragmentSize->width);
1907bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, FSR, fsr.fragment_size.height, pFragmentSize->height);
1908bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, FSR, fsr.combiner_ops[0], combinerOps[0]);
1909bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, FSR, fsr.combiner_ops[1], combinerOps[1]);
1910bf215546Sopenharmony_ci}
1911bf215546Sopenharmony_ci
1912bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1913bf215546Sopenharmony_civk_common_CmdSetSampleLocationsEXT(VkCommandBuffer commandBuffer,
1914bf215546Sopenharmony_ci                                   const VkSampleLocationsInfoEXT *pSampleLocationsInfo)
1915bf215546Sopenharmony_ci{
1916bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1917bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1918bf215546Sopenharmony_ci
1919bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, MS_SAMPLE_LOCATIONS,
1920bf215546Sopenharmony_ci                 ms.sample_locations->per_pixel,
1921bf215546Sopenharmony_ci                 pSampleLocationsInfo->sampleLocationsPerPixel);
1922bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, MS_SAMPLE_LOCATIONS,
1923bf215546Sopenharmony_ci                 ms.sample_locations->grid_size.width,
1924bf215546Sopenharmony_ci                 pSampleLocationsInfo->sampleLocationGridSize.width);
1925bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, MS_SAMPLE_LOCATIONS,
1926bf215546Sopenharmony_ci                 ms.sample_locations->grid_size.height,
1927bf215546Sopenharmony_ci                 pSampleLocationsInfo->sampleLocationGridSize.height);
1928bf215546Sopenharmony_ci
1929bf215546Sopenharmony_ci   assert(pSampleLocationsInfo->sampleLocationsCount ==
1930bf215546Sopenharmony_ci          pSampleLocationsInfo->sampleLocationsPerPixel *
1931bf215546Sopenharmony_ci          pSampleLocationsInfo->sampleLocationGridSize.width *
1932bf215546Sopenharmony_ci          pSampleLocationsInfo->sampleLocationGridSize.height);
1933bf215546Sopenharmony_ci
1934bf215546Sopenharmony_ci   assert(pSampleLocationsInfo->sampleLocationsCount <=
1935bf215546Sopenharmony_ci          MESA_VK_MAX_SAMPLE_LOCATIONS);
1936bf215546Sopenharmony_ci
1937bf215546Sopenharmony_ci   SET_DYN_ARRAY(dyn, MS_SAMPLE_LOCATIONS,
1938bf215546Sopenharmony_ci                 ms.sample_locations->locations,
1939bf215546Sopenharmony_ci                 0, pSampleLocationsInfo->sampleLocationsCount,
1940bf215546Sopenharmony_ci                 pSampleLocationsInfo->pSampleLocations);
1941bf215546Sopenharmony_ci}
1942bf215546Sopenharmony_ci
1943bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1944bf215546Sopenharmony_civk_common_CmdSetDepthTestEnable(VkCommandBuffer commandBuffer,
1945bf215546Sopenharmony_ci                                VkBool32 depthTestEnable)
1946bf215546Sopenharmony_ci{
1947bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1948bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1949bf215546Sopenharmony_ci
1950bf215546Sopenharmony_ci   SET_DYN_BOOL(dyn, DS_DEPTH_TEST_ENABLE,
1951bf215546Sopenharmony_ci                ds.depth.test_enable, depthTestEnable);
1952bf215546Sopenharmony_ci}
1953bf215546Sopenharmony_ci
1954bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1955bf215546Sopenharmony_civk_common_CmdSetDepthWriteEnable(VkCommandBuffer commandBuffer,
1956bf215546Sopenharmony_ci                                VkBool32 depthWriteEnable)
1957bf215546Sopenharmony_ci{
1958bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1959bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1960bf215546Sopenharmony_ci
1961bf215546Sopenharmony_ci   SET_DYN_BOOL(dyn, DS_DEPTH_WRITE_ENABLE,
1962bf215546Sopenharmony_ci                ds.depth.write_enable, depthWriteEnable);
1963bf215546Sopenharmony_ci}
1964bf215546Sopenharmony_ci
1965bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1966bf215546Sopenharmony_civk_common_CmdSetDepthCompareOp(VkCommandBuffer commandBuffer,
1967bf215546Sopenharmony_ci                               VkCompareOp depthCompareOp)
1968bf215546Sopenharmony_ci{
1969bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1970bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1971bf215546Sopenharmony_ci
1972bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, DS_DEPTH_COMPARE_OP, ds.depth.compare_op,
1973bf215546Sopenharmony_ci                 depthCompareOp);
1974bf215546Sopenharmony_ci}
1975bf215546Sopenharmony_ci
1976bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1977bf215546Sopenharmony_civk_common_CmdSetDepthBoundsTestEnable(VkCommandBuffer commandBuffer,
1978bf215546Sopenharmony_ci                                      VkBool32 depthBoundsTestEnable)
1979bf215546Sopenharmony_ci{
1980bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1981bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1982bf215546Sopenharmony_ci
1983bf215546Sopenharmony_ci   SET_DYN_BOOL(dyn, DS_DEPTH_BOUNDS_TEST_ENABLE,
1984bf215546Sopenharmony_ci                ds.depth.bounds_test.enable, depthBoundsTestEnable);
1985bf215546Sopenharmony_ci}
1986bf215546Sopenharmony_ci
1987bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1988bf215546Sopenharmony_civk_common_CmdSetDepthBounds(VkCommandBuffer commandBuffer,
1989bf215546Sopenharmony_ci                            float minDepthBounds,
1990bf215546Sopenharmony_ci                            float maxDepthBounds)
1991bf215546Sopenharmony_ci{
1992bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
1993bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
1994bf215546Sopenharmony_ci
1995bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, DS_DEPTH_BOUNDS_TEST_BOUNDS,
1996bf215546Sopenharmony_ci                 ds.depth.bounds_test.min, minDepthBounds);
1997bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, DS_DEPTH_BOUNDS_TEST_BOUNDS,
1998bf215546Sopenharmony_ci                 ds.depth.bounds_test.max, maxDepthBounds);
1999bf215546Sopenharmony_ci}
2000bf215546Sopenharmony_ci
2001bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2002bf215546Sopenharmony_civk_common_CmdSetStencilTestEnable(VkCommandBuffer commandBuffer,
2003bf215546Sopenharmony_ci                                  VkBool32 stencilTestEnable)
2004bf215546Sopenharmony_ci{
2005bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
2006bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
2007bf215546Sopenharmony_ci
2008bf215546Sopenharmony_ci   SET_DYN_BOOL(dyn, DS_STENCIL_TEST_ENABLE,
2009bf215546Sopenharmony_ci                ds.stencil.test_enable, stencilTestEnable);
2010bf215546Sopenharmony_ci}
2011bf215546Sopenharmony_ci
2012bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2013bf215546Sopenharmony_civk_common_CmdSetStencilOp(VkCommandBuffer commandBuffer,
2014bf215546Sopenharmony_ci                          VkStencilFaceFlags faceMask,
2015bf215546Sopenharmony_ci                          VkStencilOp failOp,
2016bf215546Sopenharmony_ci                          VkStencilOp passOp,
2017bf215546Sopenharmony_ci                          VkStencilOp depthFailOp,
2018bf215546Sopenharmony_ci                          VkCompareOp compareOp)
2019bf215546Sopenharmony_ci{
2020bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
2021bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
2022bf215546Sopenharmony_ci
2023bf215546Sopenharmony_ci   if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
2024bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.front.op.fail, failOp);
2025bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.front.op.pass, passOp);
2026bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.front.op.depth_fail, depthFailOp);
2027bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.front.op.compare, compareOp);
2028bf215546Sopenharmony_ci   }
2029bf215546Sopenharmony_ci
2030bf215546Sopenharmony_ci   if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
2031bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.back.op.fail, failOp);
2032bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.back.op.pass, passOp);
2033bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.back.op.depth_fail, depthFailOp);
2034bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.back.op.compare, compareOp);
2035bf215546Sopenharmony_ci   }
2036bf215546Sopenharmony_ci}
2037bf215546Sopenharmony_ci
2038bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2039bf215546Sopenharmony_civk_common_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
2040bf215546Sopenharmony_ci                                   VkStencilFaceFlags faceMask,
2041bf215546Sopenharmony_ci                                   uint32_t compareMask)
2042bf215546Sopenharmony_ci{
2043bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
2044bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
2045bf215546Sopenharmony_ci
2046bf215546Sopenharmony_ci   /* We assume 8-bit stencil always */
2047bf215546Sopenharmony_ci   STATIC_ASSERT(sizeof(dyn->ds.stencil.front.write_mask) == 1);
2048bf215546Sopenharmony_ci
2049bf215546Sopenharmony_ci   if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
2050bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_COMPARE_MASK,
2051bf215546Sopenharmony_ci                    ds.stencil.front.compare_mask, (uint8_t)compareMask);
2052bf215546Sopenharmony_ci   }
2053bf215546Sopenharmony_ci   if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
2054bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_COMPARE_MASK,
2055bf215546Sopenharmony_ci                    ds.stencil.back.compare_mask, (uint8_t)compareMask);
2056bf215546Sopenharmony_ci   }
2057bf215546Sopenharmony_ci}
2058bf215546Sopenharmony_ci
2059bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2060bf215546Sopenharmony_civk_common_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
2061bf215546Sopenharmony_ci                                 VkStencilFaceFlags faceMask,
2062bf215546Sopenharmony_ci                                 uint32_t writeMask)
2063bf215546Sopenharmony_ci{
2064bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
2065bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
2066bf215546Sopenharmony_ci
2067bf215546Sopenharmony_ci   /* We assume 8-bit stencil always */
2068bf215546Sopenharmony_ci   STATIC_ASSERT(sizeof(dyn->ds.stencil.front.write_mask) == 1);
2069bf215546Sopenharmony_ci
2070bf215546Sopenharmony_ci   if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
2071bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_WRITE_MASK,
2072bf215546Sopenharmony_ci                    ds.stencil.front.write_mask, (uint8_t)writeMask);
2073bf215546Sopenharmony_ci   }
2074bf215546Sopenharmony_ci   if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
2075bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_WRITE_MASK,
2076bf215546Sopenharmony_ci                    ds.stencil.back.write_mask, (uint8_t)writeMask);
2077bf215546Sopenharmony_ci   }
2078bf215546Sopenharmony_ci}
2079bf215546Sopenharmony_ci
2080bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2081bf215546Sopenharmony_civk_common_CmdSetStencilReference(VkCommandBuffer commandBuffer,
2082bf215546Sopenharmony_ci                                 VkStencilFaceFlags faceMask,
2083bf215546Sopenharmony_ci                                 uint32_t reference)
2084bf215546Sopenharmony_ci{
2085bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
2086bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
2087bf215546Sopenharmony_ci
2088bf215546Sopenharmony_ci   /* We assume 8-bit stencil always */
2089bf215546Sopenharmony_ci   STATIC_ASSERT(sizeof(dyn->ds.stencil.front.write_mask) == 1);
2090bf215546Sopenharmony_ci
2091bf215546Sopenharmony_ci   if (faceMask & VK_STENCIL_FACE_FRONT_BIT) {
2092bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_REFERENCE,
2093bf215546Sopenharmony_ci                    ds.stencil.front.reference, (uint8_t)reference);
2094bf215546Sopenharmony_ci   }
2095bf215546Sopenharmony_ci   if (faceMask & VK_STENCIL_FACE_BACK_BIT) {
2096bf215546Sopenharmony_ci      SET_DYN_VALUE(dyn, DS_STENCIL_REFERENCE,
2097bf215546Sopenharmony_ci                    ds.stencil.back.reference, (uint8_t)reference);
2098bf215546Sopenharmony_ci   }
2099bf215546Sopenharmony_ci}
2100bf215546Sopenharmony_ci
2101bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2102bf215546Sopenharmony_civk_common_CmdSetLogicOpEXT(VkCommandBuffer commandBuffer,
2103bf215546Sopenharmony_ci                           VkLogicOp logicOp)
2104bf215546Sopenharmony_ci{
2105bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
2106bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
2107bf215546Sopenharmony_ci
2108bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, CB_LOGIC_OP, cb.logic_op, logicOp);
2109bf215546Sopenharmony_ci}
2110bf215546Sopenharmony_ci
2111bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2112bf215546Sopenharmony_civk_common_CmdSetColorWriteEnableEXT(VkCommandBuffer commandBuffer,
2113bf215546Sopenharmony_ci                                    uint32_t attachmentCount,
2114bf215546Sopenharmony_ci                                    const VkBool32 *pColorWriteEnables)
2115bf215546Sopenharmony_ci{
2116bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
2117bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
2118bf215546Sopenharmony_ci
2119bf215546Sopenharmony_ci   assert(attachmentCount <= MESA_VK_MAX_COLOR_ATTACHMENTS);
2120bf215546Sopenharmony_ci
2121bf215546Sopenharmony_ci   uint8_t color_write_enables = 0;
2122bf215546Sopenharmony_ci   for (uint32_t a = 0; a < attachmentCount; a++) {
2123bf215546Sopenharmony_ci      if (pColorWriteEnables[a])
2124bf215546Sopenharmony_ci         color_write_enables |= BITFIELD_BIT(a);
2125bf215546Sopenharmony_ci   }
2126bf215546Sopenharmony_ci
2127bf215546Sopenharmony_ci   SET_DYN_VALUE(dyn, CB_COLOR_WRITE_ENABLES,
2128bf215546Sopenharmony_ci                 cb.color_write_enables, color_write_enables);
2129bf215546Sopenharmony_ci}
2130bf215546Sopenharmony_ci
2131bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2132bf215546Sopenharmony_civk_common_CmdSetBlendConstants(VkCommandBuffer commandBuffer,
2133bf215546Sopenharmony_ci                               const float  blendConstants[4])
2134bf215546Sopenharmony_ci{
2135bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer);
2136bf215546Sopenharmony_ci   struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state;
2137bf215546Sopenharmony_ci
2138bf215546Sopenharmony_ci   SET_DYN_ARRAY(dyn, CB_BLEND_CONSTANTS, cb.blend_constants,
2139bf215546Sopenharmony_ci                 0, 4, blendConstants);
2140bf215546Sopenharmony_ci}
2141