184 lines
7.6 KiB
Plaintext
184 lines
7.6 KiB
Plaintext
////
|
|
- Copyright (c) 2023, Mobica Limited
|
|
-
|
|
- SPDX-License-Identifier: Apache-2.0
|
|
-
|
|
- Licensed under the Apache License, Version 2.0 the "License";
|
|
- you may not use this file except in compliance with the License.
|
|
- You may obtain a copy of the License at
|
|
-
|
|
- http://www.apache.org/licenses/LICENSE-2.0
|
|
-
|
|
- Unless required by applicable law or agreed to in writing, software
|
|
- distributed under the License is distributed on an "AS IS" BASIS,
|
|
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
- See the License for the specific language governing permissions and
|
|
- limitations under the License.
|
|
-
|
|
////
|
|
= Logic operations dynamic state
|
|
|
|
ifdef::site-gen-antora[]
|
|
TIP: The source for this sample can be found in the https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/extensions/logic_op_dynamic_state[Khronos Vulkan samples github repository].
|
|
endif::[]
|
|
|
|
|
|
image::./images/logic_op_dynamic_state_screenshot.png[Sample]
|
|
|
|
== Overview
|
|
|
|
The https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_extended_dynamic_state2.html[VK_EXT_extended_dynamic_state2] extension allows to use dynamic states e.g.
|
|
the VK_DYNAMIC_STATE_LOGIC_OP_EXT.
|
|
This may help an application to change a logical operation used without creating a new pipeline.
|
|
|
|
The sample demonstrates usage of this extension with dynamically changed logical operations applied to blending.
|
|
|
|
== Surface format setting
|
|
|
|
Logical operations are applied only for https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#framebuffer-logicop[signed and unsigned integer and normalized integer framebuffers].
|
|
|
|
In the sample the surface format is changed to `VK_FORMAT_B8G8R8A8_UNORM` by overriding the virtual method `create_render_context` (derived from `ApiVulkanSample` class).
|
|
|
|
[,C++]
|
|
----
|
|
auto surface_priority_list = std::vector<VkSurfaceFormatKHR>{
|
|
{VK_FORMAT_B8G8R8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR},
|
|
};
|
|
render_context = platform.create_render_context(*device.get(), surface, surface_priority_list);
|
|
----
|
|
|
|
== Enabling logical operations in pipeline creation
|
|
|
|
In the sample two pipelines are created:
|
|
|
|
* a pipeline for a background model (the background pipeline);
|
|
* a pipeline for a cube model (the baseline pipeline).
|
|
|
|
The cube model is used to present blending effect achieved using the dynamic logical operations.
|
|
|
|
The `logicOpEnable` member of the `VkPipelineColorBlendStateCreateInfo` structure https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPipelineColorBlendStateCreateInfo.html[controls if logical operations should be applied].
|
|
|
|
The `logicOpEnable` member is set to `VK_TRUE` during creation of the baseline pipeline in the `create_pipeline` method.
|
|
|
|
[,C++]
|
|
----
|
|
VkPipelineColorBlendStateCreateInfo color_blend_state =
|
|
vkb::initializers::pipeline_color_blend_state_create_info(1, &blend_attachment_state);
|
|
|
|
/* Enable logic operations */
|
|
color_blend_state.logicOpEnable = VK_TRUE;
|
|
----
|
|
|
|
In the same method `VK_DYNAMIC_STATE_LOGIC_OP_EXT` is added to the vector of `VkDynamicState` (used to define pipeline dynamic state in https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPipelineDynamicStateCreateInfo.html[`VkPipelineDynamicStateCreateInfo`]).
|
|
|
|
[,C++]
|
|
----
|
|
std::vector<VkDynamicState> dynamic_state_enables = {
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
VK_DYNAMIC_STATE_LOGIC_OP_EXT,
|
|
};
|
|
VkPipelineDynamicStateCreateInfo dynamic_state =
|
|
vkb::initializers::pipeline_dynamic_state_create_info(
|
|
dynamic_state_enables.data(),
|
|
static_cast<uint32_t>(dynamic_state_enables.size()),
|
|
0);
|
|
----
|
|
|
|
Both structures: `color_blend_state` and `dynamic_state` are used to define https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkGraphicsPipelineCreateInfo.html[`VkGraphicsPipelineCreateInfo`] needed to create the graphics pipeline.
|
|
|
|
[,C++]
|
|
----
|
|
VkGraphicsPipelineCreateInfo graphics_create{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
|
|
graphics_create.pColorBlendState = &color_blend_state;
|
|
graphics_create.pDynamicState = &dynamic_state;
|
|
...
|
|
|
|
VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1, &graphics_create, VK_NULL_HANDLE, &pipeline.baseline));
|
|
----
|
|
|
|
Logical operations are not enabled in the background pipeline.
|
|
|
|
[,C++]
|
|
----
|
|
std::vector<VkDynamicState> dynamic_state_enables_background = {
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
};
|
|
|
|
/* Disable logic operations in background pipeline */
|
|
color_blend_state.logicOpEnable = VK_FALSE;
|
|
----
|
|
|
|
== Logical operation dynamic setting in command buffer creation
|
|
|
|
Calling https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdSetLogicOpEXT.html[`vkCmdSetLogicOpEXT`] allows to set the logic operation dynamically.
|
|
In the sample it is called before drawing the model in the `build_command_buffers` method using a value provided by the GUI.
|
|
Available logical operations are defined by the `VkLogicOp` enumeration (check the Vulkan specification for details of https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VkLogicOp[the logical operations]).
|
|
The background model is drawn before the cube model (with logical operations enabled) to observe blending results on the cube model.
|
|
|
|
[,C++]
|
|
----
|
|
VK_CHECK(vkBeginCommandBuffer(draw_cmd_buffer, &command_begin));
|
|
...
|
|
|
|
/* Drawing background */
|
|
draw_model(background_model, draw_cmd_buffer);
|
|
...
|
|
|
|
/* Set logic operation chosen in GUI for the cube model */
|
|
vkCmdSetLogicOpEXT(draw_cmd_buffer, static_cast<VkLogicOp>(gui_settings.selected_operation));
|
|
|
|
/* Draw model */
|
|
draw_created_model(draw_cmd_buffer);
|
|
...
|
|
|
|
VK_CHECK(vkEndCommandBuffer(draw_cmd_buffer));
|
|
----
|
|
|
|
== Enabling the required extensions
|
|
|
|
The extended dynamic state 2 API requires Vulkan 1.0 and the appropriate headers / SDK is required.
|
|
This extension has been https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_extended_dynamic_state2.html#_promotion_to_vulkan_1_3[partially] promoted to Vulkan 1.3.
|
|
|
|
The device extension `VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME` requires `VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME` instance extension to be enabled.
|
|
|
|
[,C++]
|
|
----
|
|
add_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
|
add_device_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
|
----
|
|
|
|
Enabling extension features is done using `VkPhysicalDeviceExtendedDynamicState2FeaturesEXT` and `VkPhysicalDeviceExtendedDynamicStateFeaturesEXT` structures.
|
|
|
|
[,C++]
|
|
----
|
|
typedef struct VkPhysicalDeviceExtendedDynamicState2FeaturesEXT {
|
|
VkStructureType sType;
|
|
void* pNext;
|
|
VkBool32 extendedDynamicState2;
|
|
VkBool32 extendedDynamicState2LogicOp;
|
|
VkBool32 extendedDynamicState2PatchControlPoints;
|
|
} VkPhysicalD
|
|
|
|
typedef struct VkPhysicalDeviceExtendedDynamicStateFeaturesEXT {
|
|
VkStructureType sType;
|
|
void* pNext;
|
|
VkBool32 extendedDynamicState;
|
|
} VkPhysicalDeviceExtendedDynamicStateFeaturesEXT;
|
|
----
|
|
|
|
In the sample it is implemented in the `request_gpu_features` method.
|
|
|
|
[,C++]
|
|
----
|
|
auto &requested_extended_dynamic_state2_features =
|
|
gpu.request_extension_features<VkPhysicalDeviceExtendedDynamicState2FeaturesEXT>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT);
|
|
requested_extended_dynamic_state2_features.extendedDynamicState2 = VK_TRUE;
|
|
requested_extended_dynamic_state2_features.extendedDynamicState2LogicOp = VK_TRUE;
|
|
|
|
auto &requested_extended_dynamic_state_feature =
|
|
gpu.request_extension_features<VkPhysicalDeviceExtendedDynamicStateFeaturesEXT>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT);
|
|
requested_extended_dynamic_state_feature.extendedDynamicState = VK_TRUE;
|
|
----
|