1Graphics state 2============== 3 4The Mesa Vulkan runtime provides helpers for managing the numerous pieces 5of graphics state associated with a ``VkPipeline`` or set dynamically on a 6command buffer. No such helpers are provided for compute or ray-tracing 7because they have little or no state besides the shaders themselves. 8 9 10Pipeline state 11-------------- 12 13All (possibly dynamic) Vulkan graphics pipeline state is encapsulated into 14a single :cpp:struct:`vk_graphics_pipeline_state` structure which contains 15pointers to sub-structures for each of the different state categories. 16Unlike :cpp:type:`VkGraphicsPipelineCreateInfo`, the pointers in 17:cpp:struct:`vk_graphics_pipeline_state` are guaranteed to be either be 18NULL or point to valid and properly populated memory. 19 20When creating a pipeline, the 21:cpp:func:`vk_graphics_pipeline_state_fill()` function can be used to 22gather all of the state from the core structures as well as various `pNext` 23chains into a single state structure. Whenever an extension struct is 24missing, a reasonable default value is provided whenever possible. 25 26 27:cpp:func:`vk_graphics_pipeline_state_fill()` automatically handles both 28the render pass and dynamic rendering. For drivers which use 29:cpp:struct:`vk_render_pass`, the :cpp:struct:`vk_render_pass_state` 30structure will be populated as if for dynamic rendering, regardless of 31which path is used. Drivers which use their own render pass structure 32should parse the render pass, if available, and pass a 33:cpp:struct:`vk_subpass_info` into 34:cpp:func:`vk_graphics_pipeline_state_fill()` with the relevant information 35from the specified subpass. If a render pass is available, 36:cpp:struct:`vk_render_pass_state` will be populated with the 37:cpp:type:`VkRenderPass` handle and subpass index as well as the 38information from the :cpp:struct:`vk_render_pass_state`. If dynamic 39rendering is used or the driver does not provide a 40:cpp:struct:`vk_subpass_info` structure, :cpp:struct:`vk_render_pass_state` 41structure will be populated for dynamic rendering, including color, depth, 42and stencil attachment formats. 43 44.. doxygenstruct:: vk_subpass_info 45 :members: 46 47The usual flow for creating a full graphics pipeline (not library) looks 48like this: 49 50.. code-block:: c 51 52 struct vk_graphics_pipeline_state state = { }; 53 struct vk_graphics_pipeline_all_state all; 54 vk_graphics_pipeline_state_fill(&device->vk, &state, pCreateInfo, 55 NULL, &all, NULL, 0, NULL); 56 57 /* Emit stuff using the state in `state` */ 58 59The :cpp:struct:`vk_graphics_pipeline_all_state` structure exists to allow 60the state to sit on the stack instead of requiring a heap allocation. This 61is useful if you intend to use the state right away and don't need to store 62it. For pipeline libraries, it's likely more useful to use the dynamically 63allocated version and store the dynamically allocated memory in the 64library pipeline. 65 66.. code-block:: c 67 68 /* Assuming we have a vk_graphics_pipeline_state in pipeline */ 69 memset(&pipeline->state, 0, sizeof(pipeline->state)); 70 71 for (uint32_t i = 0; i < lib_info->libraryCount; i++) { 72 VK_FROM_HANDLE(drv_graphics_pipeline_library, lib, lib_info->pLibraries[i]); 73 vk_graphics_pipeline_state_merge(&pipeline->state, &lib->state); 74 } 75 76 /* This assumes you have a void **state_mem in pipeline */ 77 result = vk_graphics_pipeline_state_fill(&device->vk, &pipeline->state, 78 pCreateInfo, NULL, NULL, pAllocator, 79 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, 80 &pipeline->state_mem); 81 if (result != VK_SUCCESS) 82 return result; 83 84State from dependent libraries can be merged together using 85:cpp:func:`vk_graphics_pipeline_state_merge`. 86:cpp:func:`vk_graphics_pipeline_state_fill` will then only attempt to 87populate missing fields. You can also merge dependent pipeline libraries 88together but store the final state on the stack for immediate consumption: 89 90.. code-block:: c 91 92 struct vk_graphics_pipeline_state state = { }; 93 94 for (uint32_t i = 0; i < lib_info->libraryCount; i++) { 95 VK_FROM_HANDLE(drv_graphics_pipeline_library, lib, lib_info->pLibraries[i]); 96 vk_graphics_pipeline_state_merge(&state, &lib->state); 97 } 98 99 struct vk_graphics_pipeline_all_state all; 100 vk_graphics_pipeline_state_fill(&device->vk, &state, pCreateInfo, 101 NULL, &all, NULL, 0, NULL); 102 103.. doxygenfunction:: vk_graphics_pipeline_state_fill 104 105.. doxygenfunction:: vk_graphics_pipeline_state_merge 106 107 108Dynamic state 109------------- 110 111All dynamic states in Vulkan, regardless of which API version or extension 112introduced them, are represented by the 113:cpp:enum:`mesa_vk_dynamic_graphics_state` enum. This corresponds to the 114:cpp:type:`VkDynamicState` enum in the Vulkan API only it's compact (has no 115holes due to extension namespacing) and a bit better organized. Each 116enumerant is named with the name of the state group to which the dynamic 117state belongs as well as the name of the dynamic state itself. The fact 118that it's compact allows us to use to index bitsets. 119 120.. doxygenfunction:: vk_get_dynamic_graphics_states 121 122We also provide a :cpp:struct:`vk_dynamic_graphics_state` structure which 123contains all the dynamic graphics states, regardless of which API version 124or extension introduced them. This structure can be populated from a 125:cpp:struct:`vk_graphics_pipeline_state` via 126:cpp:func:`vk_dynamic_graphics_state_init`. 127 128.. doxygenfunction:: vk_dynamic_graphics_state_init 129.. doxygenfunction:: vk_dynamic_graphics_state_copy 130 131There is also a :cpp:struct:`vk_dynamic_graphics_state` embedded in 132:cpp:struct:`vk_command_buffer`. Should you choose to use them, we provide 133common implementations for all ``vkCmdSet*()`` functions. Two additional 134functions are provided for the driver to call in ``CmdBindPipeline()`` and 135``CmdBindVertexBuffers2()``: 136 137.. doxygenfunction:: vk_cmd_set_dynamic_graphics_state 138.. doxygenfunction:: vk_cmd_set_vertex_binding_strides 139 140To use the dynamic state framework, you will need the following in your 141pipeline structure: 142 143.. code-block:: c 144 145 struct drv_graphics_pipeline { 146 .... 147 struct vk_vertex_input_state vi_state; 148 struct vk_sample_locations_state sl_state; 149 struct vk_dynamic_graphics_state dynamic; 150 ... 151 }; 152 153Then, in your pipeline create function, 154 155.. code-block:: c 156 157 memset(&pipeline->dynamic, 0, sizeof(pipeline->dynamic)); 158 pipeline->dynamic->vi = &pipeline->vi_state; 159 pipeline->dynamic->ms.sample_locations = &pipeline->sl_state; 160 vk_dynamic_graphics_state_init(&pipeline->dynamic, &state); 161 162In your implementation of ``vkCmdBindPipeline()``, 163 164.. code-block:: c 165 166 vk_cmd_set_dynamic_graphics_state(&cmd->vk, &pipeline->dynamic_state); 167 168And, finally, at ``vkCmdDraw*()`` time, the code to emit dynamic state into 169your hardware command buffer will look something like this: 170 171.. code-block:: c 172 173 static void 174 emit_dynamic_state(struct drv_cmd_buffer *cmd) 175 { 176 struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state; 177 178 if (!vk_dynamic_graphics_state_any_dirty(dyn)) 179 return; 180 181 if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORTS) | 182 BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORT_COUNT)) { 183 /* Re-emit viewports */ 184 } 185 186 if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSORS) | 187 BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSOR_COUNT)) { 188 /* Re-emit scissors */ 189 } 190 191 /* etc... */ 192 193 vk_dynamic_graphics_state_clear_dirty(dyn); 194 } 195 196Any states used by the currently bound pipeline and attachments are always 197valid in ``vk_command_buffer::dynamic_graphics_state`` so you can always 198use a state even if it isn't dirty on this particular draw. 199 200.. doxygenfunction:: vk_dynamic_graphics_state_dirty_all 201.. doxygenfunction:: vk_dynamic_graphics_state_clear_dirty 202.. doxygenfunction:: vk_dynamic_graphics_state_any_dirty 203 204 205Depth stencil state optimization 206-------------------------------- 207 208.. doxygenfunction:: vk_optimize_depth_stencil_state 209 210 211Reference 212--------- 213 214.. doxygenstruct:: vk_graphics_pipeline_state 215 :members: 216 217.. doxygenstruct:: vk_vertex_binding_state 218 :members: 219 220.. doxygenstruct:: vk_vertex_attribute_state 221 :members: 222 223.. doxygenstruct:: vk_vertex_input_state 224 :members: 225 226.. doxygenstruct:: vk_input_assembly_state 227 :members: 228 229.. doxygenstruct:: vk_tessellation_state 230 :members: 231 232.. doxygenstruct:: vk_viewport_state 233 :members: 234 235.. doxygenstruct:: vk_discard_rectangles_state 236 :members: 237 238.. doxygenstruct:: vk_rasterization_state 239 :members: 240 241.. doxygenstruct:: vk_fragment_shading_rate_state 242 :members: 243 244.. doxygenstruct:: vk_sample_locations_state 245 :members: 246 247.. doxygenstruct:: vk_multisample_state 248 :members: 249 250.. doxygenstruct:: vk_stencil_test_face_state 251 :members: 252 253.. doxygenstruct:: vk_depth_stencil_state 254 :members: 255 256.. doxygenstruct:: vk_color_blend_state 257 :members: 258 259.. doxygenstruct:: vk_render_pass_state 260 :members: 261 262.. doxygenenum:: mesa_vk_dynamic_graphics_state 263 264.. doxygenstruct:: vk_dynamic_graphics_state 265 :members: 266