From 4ad149a8fc7974d9a6633557337ec2a866303072 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Thu, 30 Jun 2022 22:35:44 -0500 Subject: [PATCH] vulkan: Add a common implementation of vkCmdSet* Reviewed-by: Lionel Landwerlin Part-of: --- docs/vulkan/graphics-state.rst | 74 +++- src/vulkan/runtime/vk_command_buffer.c | 2 + src/vulkan/runtime/vk_command_buffer.h | 4 +- src/vulkan/runtime/vk_graphics_state.c | 496 +++++++++++++++++++++++++ src/vulkan/runtime/vk_graphics_state.h | 33 +- 5 files changed, 606 insertions(+), 3 deletions(-) diff --git a/docs/vulkan/graphics-state.rst b/docs/vulkan/graphics-state.rst index 278a5985031..5f88fa24790 100644 --- a/docs/vulkan/graphics-state.rst +++ b/docs/vulkan/graphics-state.rst @@ -104,9 +104,81 @@ or extension introduced them. This structure can be populated from a :cpp:func:`vk_dynamic_graphics_state_init`. .. doxygenfunction:: vk_dynamic_graphics_state_init - .. doxygenfunction:: vk_dynamic_graphics_state_copy +There is also a :cpp:struct:`vk_dynamic_graphics_state` embedded in +:cpp:struct:`vk_command_buffer`. Should you choose to use them, we provide +common implementations for all ``vkCmdSet*()`` functions. Two additional +functions are provided for the driver to call in ``CmdBindPipeline()`` and +``CmdBindVertexBuffers2()``: + +.. doxygenfunction:: vk_cmd_set_dynamic_graphics_state +.. doxygenfunction:: vk_cmd_set_vertex_binding_strides + +To use the dynamic state framework, you will need the following in your +pipeline structure: + +.. code-block:: c + + struct drv_graphics_pipeline { + .... + struct vk_vertex_input_state vi_state; + struct vk_sample_locations_state sl_state; + struct vk_dynamic_graphics_state dynamic; + ... + }; + +Then, in your pipeline create function, + +.. code-block:: c + + memset(&pipeline->dynamic, 0, sizeof(pipeline->dynamic)); + pipeline->dynamic->vi = &pipeline->vi_state; + pipeline->dynamic->ms.sample_locations = &pipeline->sl_state; + vk_dynamic_graphics_state_init(&pipeline->dynamic, &state); + +In your implementation of ``vkCmdBindPipeline()``, + +.. code-block:: c + + vk_cmd_set_dynamic_graphics_state(&cmd->vk, &pipeline->dynamic_state); + +And, finally, at ``vkCmdDraw*()`` time, the code to emit dynamic state into +your hardware command buffer will look something like this: + +.. code-block:: c + + static void + emit_dynamic_state(struct drv_cmd_buffer *cmd) + { + struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state; + + if (!vk_dynamic_graphics_state_any_dirty(dyn)) + return; + + if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORTS) | + BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORT_COUNT)) { + /* Re-emit viewports */ + } + + if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSORS) | + BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSOR_COUNT)) { + /* Re-emit scissors */ + } + + /* etc... */ + + vk_dynamic_graphics_state_clear_dirty(dyn); + } + +Any states used by the currently bound pipeline and attachments are always +valid in ``vk_command_buffer::dynamic_graphics_state`` so you can always +use a state even if it isn't dirty on this particular draw. + +.. doxygenfunction:: vk_dynamic_graphics_state_dirty_all +.. doxygenfunction:: vk_dynamic_graphics_state_clear_dirty +.. doxygenfunction:: vk_dynamic_graphics_state_any_dirty + Reference --------- diff --git a/src/vulkan/runtime/vk_command_buffer.c b/src/vulkan/runtime/vk_command_buffer.c index 477562ee8fb..d50a7480806 100644 --- a/src/vulkan/runtime/vk_command_buffer.c +++ b/src/vulkan/runtime/vk_command_buffer.c @@ -38,6 +38,7 @@ vk_command_buffer_init(struct vk_command_buffer *command_buffer, command_buffer->pool = pool; command_buffer->level = level; + vk_dynamic_graphics_state_init(&command_buffer->dynamic_graphics_state); vk_cmd_queue_init(&command_buffer->cmd_queue, &pool->alloc); util_dynarray_init(&command_buffer->labels, NULL); command_buffer->region_begin = true; @@ -50,6 +51,7 @@ vk_command_buffer_init(struct vk_command_buffer *command_buffer, void vk_command_buffer_reset(struct vk_command_buffer *command_buffer) { + vk_dynamic_graphics_state_clear(&command_buffer->dynamic_graphics_state); vk_command_buffer_reset_render_pass(command_buffer); vk_cmd_queue_reset(&command_buffer->cmd_queue); util_dynarray_clear(&command_buffer->labels); diff --git a/src/vulkan/runtime/vk_command_buffer.h b/src/vulkan/runtime/vk_command_buffer.h index e910bef67f2..2d1184a8c04 100644 --- a/src/vulkan/runtime/vk_command_buffer.h +++ b/src/vulkan/runtime/vk_command_buffer.h @@ -25,7 +25,7 @@ #define VK_COMMAND_BUFFER_H #include "vk_cmd_queue.h" -#include "vk_limits.h" +#include "vk_graphics_state.h" #include "vk_object.h" #include "util/list.h" #include "util/u_dynarray.h" @@ -66,6 +66,8 @@ struct vk_command_buffer { /** VkCommandBufferAllocateInfo::level */ VkCommandBufferLevel level; + struct vk_dynamic_graphics_state dynamic_graphics_state; + /** Link in vk_command_pool::command_buffers if pool != NULL */ struct list_head pool_link; diff --git a/src/vulkan/runtime/vk_graphics_state.c b/src/vulkan/runtime/vk_graphics_state.c index 2a6344b4d1f..a9587568cdd 100644 --- a/src/vulkan/runtime/vk_graphics_state.c +++ b/src/vulkan/runtime/vk_graphics_state.c @@ -1,6 +1,8 @@ #include "vk_graphics_state.h" #include "vk_alloc.h" +#include "vk_command_buffer.h" +#include "vk_common_entrypoints.h" #include "vk_device.h" #include "vk_log.h" #include "vk_render_pass.h" @@ -1476,3 +1478,497 @@ vk_dynamic_graphics_state_copy(struct vk_dynamic_graphics_state *dst, dst->set[w] |= src->set[w]; } } + +void +vk_cmd_set_dynamic_graphics_state(struct vk_command_buffer *cmd, + const struct vk_dynamic_graphics_state *state) +{ + vk_dynamic_graphics_state_copy(&cmd->dynamic_graphics_state, state); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetVertexInputEXT(VkCommandBuffer commandBuffer, + uint32_t vertexBindingDescriptionCount, + const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, + uint32_t vertexAttributeDescriptionCount, + const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + uint32_t bindings_valid = 0; + for (uint32_t i = 0; i < vertexBindingDescriptionCount; i++) { + const VkVertexInputBindingDescription2EXT *desc = + &pVertexBindingDescriptions[i]; + + assert(desc->binding < MESA_VK_MAX_VERTEX_BINDINGS); + assert(desc->stride <= MESA_VK_MAX_VERTEX_BINDING_STRIDE); + assert(desc->inputRate <= UINT8_MAX); + + const uint32_t b = desc->binding; + bindings_valid |= BITFIELD_BIT(b); + SET_DYN_VALUE(dyn, VI, vi->bindings[b].stride, desc->stride); + SET_DYN_VALUE(dyn, VI, vi->bindings[b].input_rate, desc->inputRate); + SET_DYN_VALUE(dyn, VI, vi->bindings[b].divisor, desc->divisor); + + /* Also set bindings_strides in case a driver is keying off that */ + SET_DYN_VALUE(dyn, VI_BINDING_STRIDES, + vi_binding_strides[b], desc->stride); + } + SET_DYN_VALUE(dyn, VI, vi->bindings_valid, bindings_valid); + + uint32_t attributes_valid = 0; + for (uint32_t i = 0; i < vertexAttributeDescriptionCount; i++) { + const VkVertexInputAttributeDescription2EXT *desc = + &pVertexAttributeDescriptions[i]; + + assert(desc->location < MESA_VK_MAX_VERTEX_ATTRIBUTES); + assert(desc->binding < MESA_VK_MAX_VERTEX_BINDINGS); + assert(bindings_valid & BITFIELD_BIT(desc->binding)); + + const uint32_t a = desc->location; + attributes_valid |= BITFIELD_BIT(a); + SET_DYN_VALUE(dyn, VI, vi->attributes[a].binding, desc->binding); + SET_DYN_VALUE(dyn, VI, vi->attributes[a].format, desc->format); + SET_DYN_VALUE(dyn, VI, vi->attributes[a].offset, desc->offset); + } + SET_DYN_VALUE(dyn, VI, vi->attributes_valid, attributes_valid); +} + +void +vk_cmd_set_vertex_binding_strides(struct vk_command_buffer *cmd, + uint32_t first_binding, + uint32_t binding_count, + const VkDeviceSize *strides) +{ + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + for (uint32_t i = 0; i < binding_count; i++) { + SET_DYN_VALUE(dyn, VI_BINDING_STRIDES, + vi_binding_strides[first_binding + i], strides[i]); + } +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetPrimitiveTopology(VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, IA_PRIMITIVE_TOPOLOGY, + ia.primitive_topology, primitiveTopology); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetPrimitiveRestartEnable(VkCommandBuffer commandBuffer, + VkBool32 primitiveRestartEnable) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_BOOL(dyn, IA_PRIMITIVE_RESTART_ENABLE, + ia.primitive_restart_enable, primitiveRestartEnable); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer, + uint32_t patchControlPoints) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, TS_PATCH_CONTROL_POINTS, + ts.patch_control_points, patchControlPoints); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetViewport(VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkViewport *pViewports) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_ARRAY(dyn, VP_VIEWPORTS, vp.viewports, + firstViewport, viewportCount, pViewports); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetViewportWithCount(VkCommandBuffer commandBuffer, + uint32_t viewportCount, + const VkViewport *pViewports) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, VP_VIEWPORT_COUNT, vp.viewport_count, viewportCount); + SET_DYN_ARRAY(dyn, VP_VIEWPORTS, vp.viewports, 0, viewportCount, pViewports); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetScissor(VkCommandBuffer commandBuffer, + uint32_t firstScissor, + uint32_t scissorCount, + const VkRect2D *pScissors) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_ARRAY(dyn, VP_SCISSORS, vp.scissors, + firstScissor, scissorCount, pScissors); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetScissorWithCount(VkCommandBuffer commandBuffer, + uint32_t scissorCount, + const VkRect2D *pScissors) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, VP_SCISSOR_COUNT, vp.scissor_count, scissorCount); + SET_DYN_ARRAY(dyn, VP_SCISSORS, vp.scissors, 0, scissorCount, pScissors); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetDiscardRectangleEXT(VkCommandBuffer commandBuffer, + uint32_t firstDiscardRectangle, + uint32_t discardRectangleCount, + const VkRect2D *pDiscardRectangles) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, DR_RECTANGLES, dr.rectangle_count, discardRectangleCount); + SET_DYN_ARRAY(dyn, DR_RECTANGLES, dr.rectangles, firstDiscardRectangle, + discardRectangleCount, pDiscardRectangles); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetRasterizerDiscardEnableEXT(VkCommandBuffer commandBuffer, + VkBool32 rasterizerDiscardEnable) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_BOOL(dyn, RS_RASTERIZER_DISCARD_ENABLE, + rs.rasterizer_discard_enable, rasterizerDiscardEnable); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetCullMode(VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, RS_CULL_MODE, rs.cull_mode, cullMode); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetFrontFace(VkCommandBuffer commandBuffer, + VkFrontFace frontFace) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, RS_FRONT_FACE, rs.front_face, frontFace); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetDepthBiasEnable(VkCommandBuffer commandBuffer, + VkBool32 depthBiasEnable) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_BOOL(dyn, RS_DEPTH_BIAS_ENABLE, + rs.depth_bias.enable, depthBiasEnable); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetDepthBias(VkCommandBuffer commandBuffer, + float depthBiasConstantFactor, + float depthBiasClamp, + float depthBiasSlopeFactor) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, RS_DEPTH_BIAS_FACTORS, + rs.depth_bias.constant, depthBiasConstantFactor); + SET_DYN_VALUE(dyn, RS_DEPTH_BIAS_FACTORS, + rs.depth_bias.clamp, depthBiasClamp); + SET_DYN_VALUE(dyn, RS_DEPTH_BIAS_FACTORS, + rs.depth_bias.slope, depthBiasSlopeFactor); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetLineWidth(VkCommandBuffer commandBuffer, + float lineWidth) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, RS_LINE_WIDTH, rs.line.width, lineWidth); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetLineStippleEXT(VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, RS_LINE_STIPPLE, + rs.line.stipple.factor, lineStippleFactor); + SET_DYN_VALUE(dyn, RS_LINE_STIPPLE, + rs.line.stipple.pattern, lineStipplePattern); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetFragmentShadingRateKHR(VkCommandBuffer commandBuffer, + const VkExtent2D *pFragmentSize, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, FSR, fsr.fragment_size.width, pFragmentSize->width); + SET_DYN_VALUE(dyn, FSR, fsr.fragment_size.height, pFragmentSize->height); + SET_DYN_VALUE(dyn, FSR, fsr.combiner_ops[0], combinerOps[0]); + SET_DYN_VALUE(dyn, FSR, fsr.combiner_ops[1], combinerOps[1]); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetSampleLocationsEXT(VkCommandBuffer commandBuffer, + const VkSampleLocationsInfoEXT *pSampleLocationsInfo) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, MS_SAMPLE_LOCATIONS, + ms.sample_locations->per_pixel, + pSampleLocationsInfo->sampleLocationsPerPixel); + SET_DYN_VALUE(dyn, MS_SAMPLE_LOCATIONS, + ms.sample_locations->grid_size.width, + pSampleLocationsInfo->sampleLocationGridSize.width); + SET_DYN_VALUE(dyn, MS_SAMPLE_LOCATIONS, + ms.sample_locations->grid_size.height, + pSampleLocationsInfo->sampleLocationGridSize.height); + + assert(pSampleLocationsInfo->sampleLocationsCount == + pSampleLocationsInfo->sampleLocationsPerPixel * + pSampleLocationsInfo->sampleLocationGridSize.width * + pSampleLocationsInfo->sampleLocationGridSize.height); + + assert(pSampleLocationsInfo->sampleLocationsCount <= + MESA_VK_MAX_SAMPLE_LOCATIONS); + + SET_DYN_ARRAY(dyn, MS_SAMPLE_LOCATIONS, + ms.sample_locations->locations, + 0, pSampleLocationsInfo->sampleLocationsCount, + pSampleLocationsInfo->pSampleLocations); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetDepthTestEnable(VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_BOOL(dyn, DS_DEPTH_TEST_ENABLE, + ds.depth.test_enable, depthTestEnable); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetDepthWriteEnable(VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_BOOL(dyn, DS_DEPTH_WRITE_ENABLE, + ds.depth.write_enable, depthWriteEnable); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetDepthCompareOp(VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, DS_DEPTH_COMPARE_OP, ds.depth.compare_op, + depthCompareOp); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetDepthBoundsTestEnable(VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_BOOL(dyn, DS_DEPTH_BOUNDS_TEST_ENABLE, + ds.depth.bounds_test.enable, depthBoundsTestEnable); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetDepthBounds(VkCommandBuffer commandBuffer, + float minDepthBounds, + float maxDepthBounds) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, DS_DEPTH_BOUNDS_TEST_BOUNDS, + ds.depth.bounds_test.min, minDepthBounds); + SET_DYN_VALUE(dyn, DS_DEPTH_BOUNDS_TEST_BOUNDS, + ds.depth.bounds_test.max, maxDepthBounds); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetStencilTestEnable(VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_BOOL(dyn, DS_STENCIL_TEST_ENABLE, + ds.stencil.test_enable, stencilTestEnable); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetStencilOp(VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + if (faceMask & VK_STENCIL_FACE_FRONT_BIT) { + SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.front.op.fail, failOp); + SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.front.op.pass, passOp); + SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.front.op.depth_fail, depthFailOp); + SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.front.op.compare, compareOp); + } + + if (faceMask & VK_STENCIL_FACE_BACK_BIT) { + SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.back.op.fail, failOp); + SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.back.op.pass, passOp); + SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.back.op.depth_fail, depthFailOp); + SET_DYN_VALUE(dyn, DS_STENCIL_OP, ds.stencil.back.op.compare, compareOp); + } +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t compareMask) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + /* We assume 8-bit stencil always */ + STATIC_ASSERT(sizeof(dyn->ds.stencil.front.write_mask) == 1); + + if (faceMask & VK_STENCIL_FACE_FRONT_BIT) { + SET_DYN_VALUE(dyn, DS_STENCIL_COMPARE_MASK, + ds.stencil.front.compare_mask, (uint8_t)compareMask); + } + if (faceMask & VK_STENCIL_FACE_BACK_BIT) { + SET_DYN_VALUE(dyn, DS_STENCIL_COMPARE_MASK, + ds.stencil.back.compare_mask, (uint8_t)compareMask); + } +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t writeMask) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + /* We assume 8-bit stencil always */ + STATIC_ASSERT(sizeof(dyn->ds.stencil.front.write_mask) == 1); + + if (faceMask & VK_STENCIL_FACE_FRONT_BIT) { + SET_DYN_VALUE(dyn, DS_STENCIL_WRITE_MASK, + ds.stencil.front.write_mask, (uint8_t)writeMask); + } + if (faceMask & VK_STENCIL_FACE_BACK_BIT) { + SET_DYN_VALUE(dyn, DS_STENCIL_WRITE_MASK, + ds.stencil.back.write_mask, (uint8_t)writeMask); + } +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetStencilReference(VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + uint32_t reference) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + /* We assume 8-bit stencil always */ + STATIC_ASSERT(sizeof(dyn->ds.stencil.front.write_mask) == 1); + + if (faceMask & VK_STENCIL_FACE_FRONT_BIT) { + SET_DYN_VALUE(dyn, DS_STENCIL_REFERENCE, + ds.stencil.front.reference, (uint8_t)reference); + } + if (faceMask & VK_STENCIL_FACE_BACK_BIT) { + SET_DYN_VALUE(dyn, DS_STENCIL_REFERENCE, + ds.stencil.back.reference, (uint8_t)reference); + } +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetLogicOpEXT(VkCommandBuffer commandBuffer, + VkLogicOp logicOp) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_VALUE(dyn, CB_LOGIC_OP, cb.logic_op, logicOp); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetColorWriteEnableEXT(VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkBool32 *pColorWriteEnables) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + assert(attachmentCount <= MESA_VK_MAX_COLOR_ATTACHMENTS); + + uint8_t color_write_enables = 0; + for (uint32_t a = 0; a < attachmentCount; a++) { + if (pColorWriteEnables[a]) + color_write_enables |= BITFIELD_BIT(a); + } + + SET_DYN_VALUE(dyn, CB_COLOR_WRITE_ENABLES, + cb.color_write_enables, color_write_enables); +} + +VKAPI_ATTR void VKAPI_CALL +vk_common_CmdSetBlendConstants(VkCommandBuffer commandBuffer, + const float blendConstants[4]) +{ + VK_FROM_HANDLE(vk_command_buffer, cmd, commandBuffer); + struct vk_dynamic_graphics_state *dyn = &cmd->dynamic_graphics_state; + + SET_DYN_ARRAY(dyn, CB_BLEND_CONSTANTS, cb.blend_constants, + 0, 4, blendConstants); +} diff --git a/src/vulkan/runtime/vk_graphics_state.h b/src/vulkan/runtime/vk_graphics_state.h index f593052fdaa..9a56c4f2282 100644 --- a/src/vulkan/runtime/vk_graphics_state.h +++ b/src/vulkan/runtime/vk_graphics_state.h @@ -34,6 +34,7 @@ extern "C" { #endif +struct vk_command_buffer; struct vk_device; /** Enumeration of all Vulkan dynamic graphics states @@ -828,7 +829,7 @@ vk_dynamic_graphics_state_dirty_all(struct vk_dynamic_graphics_state *d) static inline void vk_dynamic_graphics_state_clear_dirty(struct vk_dynamic_graphics_state *d) { - memset(d->dirty, 0, sizeof(d->dirty)); + BITSET_ZERO(d->dirty); } /** Test if any states in the given vk_dynamic_graphics_state are dirty @@ -848,11 +849,41 @@ vk_dynamic_graphics_state_any_dirty(const struct vk_dynamic_graphics_state *d) * Both src and dst are assumed to be properly initialized dynamic state * structs. Anything not set in src, as indicated by src->set, is ignored and * those bits of dst are left untouched. + * + * @param[out] dst Copy destination + * @param[in] src Copy source */ void vk_dynamic_graphics_state_copy(struct vk_dynamic_graphics_state *dst, const struct vk_dynamic_graphics_state *src); +/** Set all of the state in src on a command buffer + * + * Anything not set, as indicated by src->set, is ignored and those states in + * the command buffer are left untouched. + * + * @param[inout] cmd Command buffer to update + * @param[in] src State to set + */ +void +vk_cmd_set_dynamic_graphics_state(struct vk_command_buffer *cmd, + const struct vk_dynamic_graphics_state *src); + +/** Set vertex binding strides on a command buffer + * + * This is the dynamic state part of vkCmdBindVertexBuffers2(). + * + * @param[inout] cmd Command buffer to update + * @param[in] first_binding First binding to update + * @param[in] binding_count Number of bindings to update + * @param[in] strides binding_count many stride values to set + */ +void +vk_cmd_set_vertex_binding_strides(struct vk_command_buffer *cmd, + uint32_t first_binding, + uint32_t binding_count, + const VkDeviceSize *strides); + #ifdef __cplusplus } #endif