From 97194bfeadf5f742554e0cee2fa12fc813275520 Mon Sep 17 00:00:00 2001 From: Krzysztof-Dmitruk-Mobica Date: Fri, 30 Jun 2023 12:02:08 +0200 Subject: [PATCH 1/3] Add preview for the dynamic blending sample --- framework/gui.cpp | 1 + framework/gui.h | 55 +- .../dynamic_blending/CMakeLists.txt | 31 ++ .../dynamic_blending/dynamic_blending.cpp | 481 ++++++++++++++++++ .../dynamic_blending/dynamic_blending.h | 112 ++++ shaders/dynamic_blending/blending.frag | 56 ++ shaders/dynamic_blending/blending.vert | 37 ++ 7 files changed, 725 insertions(+), 48 deletions(-) create mode 100644 samples/extensions/dynamic_blending/CMakeLists.txt create mode 100644 samples/extensions/dynamic_blending/dynamic_blending.cpp create mode 100644 samples/extensions/dynamic_blending/dynamic_blending.h create mode 100644 shaders/dynamic_blending/blending.frag create mode 100644 shaders/dynamic_blending/blending.vert diff --git a/framework/gui.cpp b/framework/gui.cpp index 9019ef914..5b773994f 100644 --- a/framework/gui.cpp +++ b/framework/gui.cpp @@ -1229,4 +1229,5 @@ bool Drawer::color_op_impl(const char *caption, float return ImGui::ColorPicker4(caption, colors, flags); } + } // namespace vkb diff --git a/framework/gui.h b/framework/gui.h index 628288713..e09a228b3 100644 --- a/framework/gui.h +++ b/framework/gui.h @@ -179,54 +179,13 @@ class Drawer */ void text(const char *formatstr, ...); - /** - * @brief Adds a color picker to the gui - * @param caption The text to display - * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. - * @param width Element width. Zero is a special value for the default element width. - * @param flags Flags to modify the appearance and behavior of the element. - */ - bool color_picker(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); - - /** - * @brief Adds a color picker to the gui - * @param caption The text to display - * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. - * @param width Element width. Zero is a special value for the default element width. - * @param flags Flags to modify the appearance and behavior of the element. - */ - bool color_picker(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); - - /** - * @brief Adds a color edit to the gui - * @param caption The text to display - * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. - * @param width Element width. Zero is a special value for the default element width. - * @param flags Flags to modify the appearance and behavior of the element. - */ - bool color_edit(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); - - /** - * @brief Adds a color edit to the gui - * @tparam OP Mode of the color element. - * @tparam N Color channel count. Must be 3 or 4. - * @param caption The text to display - * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. - * @param width Element width. Zero is a special value for the default element width. - * @param flags Flags to modify the appearance and behavior of the element. - */ - template - bool color_op(const std::string &caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0) - { - static_assert((N == 3) || (N == 4), "The channel count must be 3 or 4."); - - ImGui::PushItemWidth(width); - bool res = color_op_impl(caption.c_str(), color.data(), flags); - ImGui::PopItemWidth(); - if (res) - dirty = true; - return res; - } + /** + * @brief Adds a color picker to the gui + * @param caption The text to display + * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. + * @param flags Flags for modifying the appearance and behavior of the element. A zero value will result in a width determined by ImGui. + */ + bool color_picker(const char *caption, float *color, ImGuiColorEditFlags flags, uint16_t width = 0); private: template diff --git a/samples/extensions/dynamic_blending/CMakeLists.txt b/samples/extensions/dynamic_blending/CMakeLists.txt new file mode 100644 index 000000000..ec095c10f --- /dev/null +++ b/samples/extensions/dynamic_blending/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (c) 2019, Arm Limited and Contributors +# +# 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. +# + +get_filename_component(FOLDER_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) +get_filename_component(PARENT_DIR ${CMAKE_CURRENT_LIST_DIR} PATH) +get_filename_component(CATEGORY_NAME ${PARENT_DIR} NAME) + +add_sample( + ID ${FOLDER_NAME} + CATEGORY ${CATEGORY_NAME} + AUTHOR "Khronos" + NAME "dynamic_blending" + DESCRIPTION "Sample description" + SHADER_FILES_GLSL + "dynamic_blending/blending.vert" + "dynamic_blending/blending.frag" +) diff --git a/samples/extensions/dynamic_blending/dynamic_blending.cpp b/samples/extensions/dynamic_blending/dynamic_blending.cpp new file mode 100644 index 000000000..7f23e26a5 --- /dev/null +++ b/samples/extensions/dynamic_blending/dynamic_blending.cpp @@ -0,0 +1,481 @@ +/* Copyright (c) 2023, Mobica + * + * 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. + */ + +#include "dynamic_blending.h" + +#include "common/vk_common.h" +#include "gui.h" + +DynamicBlending::DynamicBlending() +{ + add_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + add_device_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); + add_device_extension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME); + add_device_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); + add_device_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); + + title = "Dynamic blending"; +} + +DynamicBlending::~DynamicBlending() +{ + if (device) + { + // NYI + } +} + +bool DynamicBlending::prepare(const vkb::ApplicationOptions &options) +{ + if (!ApiVulkanSample::prepare(options)) + { + return false; + } + + camera.type = vkb::CameraType::LookAt; + camera.set_position({0.0f, 0.0f, -5.0f}); + camera.set_rotation({-15.0f, 15.0f, 0.0f}); + camera.set_perspective(45.0f, static_cast(width) / static_cast(height), 256.0f, 0.1f); + + prepare_uniform_buffers(); + prepare_scene(); + setup_descriptor_pool(); + create_descriptor_set_layout(); + create_descriptor_set(); + create_pipelines(); + build_command_buffers(); + + prepared = true; + + return true; +} + +void DynamicBlending::prepare_scene() { + vertices = { + {{-1.0f, -1.0f, 1.0f}, {0.0f, 0.0f}}, + {{1.0f, -1.0f, 1.0f}, {1.0f, 0.0f}}, + {{1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, + {{-1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, + + {{-1.0f, -1.0f, -1.0f},{0.0f, 0.0f}}, + {{1.0f, -1.0f, -1.0f}, {1.0f, 0.0f}}, + {{1.0f, 1.0f, -1.0f}, {1.0f, 1.0f}}, + {{-1.0f, 1.0f, -1.0f}, {0.0f, 1.0f}}, + }; + + std::vector indices = { + 6, 5, 4, 4, 7, 6, + 0, 1, 2, 2, 3, 0 + }; + + index_count = static_cast(indices.size()); + + vertex_buffer_size = vertices.size() * sizeof(Vertex); + auto index_buffer_size = indices.size() * sizeof(uint32_t); + + vertex_buffer = std::make_unique(get_device(), + vertex_buffer_size, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VMA_MEMORY_USAGE_GPU_TO_CPU); + vertex_buffer->update(vertices.data(), vertex_buffer_size); + + index_buffer = std::make_unique(get_device(), + index_buffer_size, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + VMA_MEMORY_USAGE_GPU_TO_CPU); + index_buffer->update(indices.data(), index_buffer_size); + + face_preferences[0].index_offset = 0; + face_preferences[0].index_count = index_count / 2; + face_preferences[0].color_bit_enabled = {true, true, true, true}; + face_preferences[0].color = {{ + {1.0f, 0.0f, 0.0f, 1.0f}, + {0.0f, 1.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f, 1.0f}, + {0.0f, 0.0f, 0.0f, 1.0f} + }}; + + face_preferences[1].index_offset = index_count / 2; + face_preferences[1].index_count = index_count / 2; + face_preferences[1].color_bit_enabled = {true, true, true, true}; + face_preferences[1].color = {{ + {0.0f, 1.0f, 1.0f, 1.0f}, + {1.0f, 0.0f, 1.0f, 1.0f}, + {1.0f, 1.0f, 0.0f, 1.0f}, + {1.0f, 1.0f, 1.0f, 1.0f} + }}; + +} + +void DynamicBlending::request_gpu_features(vkb::PhysicalDevice &gpu) +{ + { + auto &features = gpu.request_extension_features(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT); + features.extendedDynamicState3ColorWriteMask = VK_TRUE; + features.extendedDynamicState3ColorBlendEnable = VK_TRUE; + features.extendedDynamicState3ColorBlendAdvanced = VK_TRUE; + features.extendedDynamicState3ColorBlendEquation = VK_TRUE; + } + { + blend_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT; + blend_properties.pNext = VK_NULL_HANDLE; + + VkPhysicalDeviceProperties2 device_properties2 = {}; + device_properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + device_properties2.pNext = &blend_properties; + vkGetPhysicalDeviceProperties2(gpu.get_handle(), &device_properties2); + + } +} + +void DynamicBlending::prepare_uniform_buffers() { + camera_ubo = std::make_unique(get_device(), sizeof(CameraUbo), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + color_ubo = std::make_unique(get_device(), sizeof(ColorUbo), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + +} + +void DynamicBlending::update_uniform_buffers() { + CameraUbo cam; + cam.model = glm::mat4(1.0f); + cam.model = glm::translate(cam.model, glm::vec3(0.0f)); + cam.view = camera.matrices.view; + cam.projection = camera.matrices.perspective; + + camera_ubo->convert_and_update(cam); + + update_color(); + + glm::mat4 invView = glm::inverse(camera.matrices.view); + glm::vec4 plane0(vertices[0].pos[0], vertices[0].pos[1], vertices[0].pos[2], 1.0f); + glm::vec4 plane1(vertices[4].pos[0], vertices[4].pos[1], vertices[4].pos[2], 1.0f); + + plane0 = invView * plane0; + plane1 = invView * plane1; + + reverse = plane0.z < plane1.z; + + build_command_buffers(); +} + + +void DynamicBlending::setup_descriptor_pool() { + std::vector pool_sizes = { + vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u), + }; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info = + vkb::initializers::descriptor_pool_create_info( + static_cast(pool_sizes.size()), + pool_sizes.data(), + pool_sizes.size()); + VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool)); +} + +void DynamicBlending::create_descriptor_set_layout() { + std::vector set_layout_bindings = { + vkb::initializers::descriptor_set_layout_binding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0u), + vkb::initializers::descriptor_set_layout_binding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 1u) + }; + + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = vkb::initializers::descriptor_set_layout_create_info(set_layout_bindings); + VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_set_layout_create_info, nullptr, &descriptor_set_layout)); + + VkPipelineLayoutCreateInfo pipeline_layout_create_info = vkb::initializers::pipeline_layout_create_info(&descriptor_set_layout); + VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &pipeline_layout)); +} + +void DynamicBlending::create_descriptor_set() { + VkDescriptorSetAllocateInfo alloc_info = vkb::initializers::descriptor_set_allocate_info(descriptor_pool, &descriptor_set_layout, 1u); + VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info, &descriptor_set)); + + VkDescriptorBufferInfo buffer_descriptor = create_descriptor(*camera_ubo); + VkDescriptorBufferInfo color_descriptor = create_descriptor(*color_ubo); + + std::vector write_descriptor_sets = { + vkb::initializers::write_descriptor_set(descriptor_set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0u, &buffer_descriptor), + vkb::initializers::write_descriptor_set(descriptor_set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, &color_descriptor), + }; + + vkUpdateDescriptorSets(get_device().get_handle(), static_cast(write_descriptor_sets.size()), write_descriptor_sets.data(), 0u, nullptr); +} + +void DynamicBlending::create_pipelines() { + VkPipelineInputAssemblyStateCreateInfo input_assembly_state = + vkb::initializers::pipeline_input_assembly_state_create_info( + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + 0, + VK_FALSE); + + VkPipelineRasterizationStateCreateInfo rasterization_state = + vkb::initializers::pipeline_rasterization_state_create_info( + VK_POLYGON_MODE_FILL, + VK_CULL_MODE_NONE, + VK_FRONT_FACE_COUNTER_CLOCKWISE, + 0); + + VkPipelineColorBlendAttachmentState blend_attachment_state = + vkb::initializers::pipeline_color_blend_attachment_state( + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, + VK_TRUE); + + blend_attachment_state.blendEnable = VK_TRUE; + blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD; + blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + blend_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD; + blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + + VkPipelineColorBlendAdvancedStateCreateInfoEXT blendAdvancedEXT{}; + blendAdvancedEXT.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT; + blendAdvancedEXT.blendOverlap = VK_BLEND_OVERLAP_UNCORRELATED_EXT; + + VkPipelineColorBlendStateCreateInfo color_blend_state = + vkb::initializers::pipeline_color_blend_state_create_info( + 1, + &blend_attachment_state); + + color_blend_state.logicOpEnable = VK_FALSE; + color_blend_state.pNext = &blendAdvancedEXT; + + VkPipelineDepthStencilStateCreateInfo depth_stencil_state = + vkb::initializers::pipeline_depth_stencil_state_create_info( + VK_TRUE, + VK_TRUE, + VK_COMPARE_OP_GREATER); + + VkPipelineViewportStateCreateInfo viewport_state = + vkb::initializers::pipeline_viewport_state_create_info(1, 1, 0); + + VkPipelineMultisampleStateCreateInfo multisample_state = + vkb::initializers::pipeline_multisample_state_create_info( + VK_SAMPLE_COUNT_1_BIT, + 0); + + std::vector dynamic_state_enables = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT, + // NYI + // VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, + // VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT, + // VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT + }; + + VkPipelineDynamicStateCreateInfo dynamic_state = + vkb::initializers::pipeline_dynamic_state_create_info( + dynamic_state_enables.data(), + static_cast(dynamic_state_enables.size()), + 0); + + + const std::vector vertex_input_bindings = { + vkb::initializers::vertex_input_binding_description(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX), + }; + const std::vector vertex_input_attributes = { + vkb::initializers::vertex_input_attribute_description(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), + vkb::initializers::vertex_input_attribute_description(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)), + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_state = vkb::initializers::pipeline_vertex_input_state_create_info(); + vertex_input_state.vertexBindingDescriptionCount = static_cast(vertex_input_bindings.size()); + vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data(); + vertex_input_state.vertexAttributeDescriptionCount = static_cast(vertex_input_attributes.size()); + vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data(); + + std::array shader_stages{}; + shader_stages[0] = load_shader("dynamic_blending/blending.vert", VK_SHADER_STAGE_VERTEX_BIT); + shader_stages[1] = load_shader("dynamic_blending/blending.frag", VK_SHADER_STAGE_FRAGMENT_BIT); + + VkGraphicsPipelineCreateInfo graphics_create{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO}; + graphics_create.pNext = VK_NULL_HANDLE; + graphics_create.renderPass = render_pass; + graphics_create.pInputAssemblyState = &input_assembly_state; + graphics_create.pRasterizationState = &rasterization_state; + graphics_create.pColorBlendState = &color_blend_state; + graphics_create.pMultisampleState = &multisample_state; + graphics_create.pViewportState = &viewport_state; + graphics_create.pDepthStencilState = &depth_stencil_state; + graphics_create.pDynamicState = &dynamic_state; + graphics_create.pVertexInputState = &vertex_input_state; + graphics_create.pTessellationState = VK_NULL_HANDLE; + graphics_create.stageCount = 2; + graphics_create.pStages = shader_stages.data(); + graphics_create.layout = pipeline_layout; + + VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), + pipeline_cache, + 1, + &graphics_create, + VK_NULL_HANDLE, + &pipeline)); +} + +void DynamicBlending::update_color() { + for(uint32_t face = 0; face < 2; ++face) + for(uint32_t vertex = 0; vertex < 4; ++vertex) { + auto &input_color = face_preferences[face].color[vertex]; + color.data[face * 4 + vertex] = glm::vec4(input_color[0], input_color[1], input_color[2], input_color[3]); + } + color_ubo->convert_and_update(color); +} + +void DynamicBlending::update_color_uniform() { + update_color(); + build_command_buffers(); +} + +void DynamicBlending::build_command_buffers() +{ + VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info(); + + std::array clear_values; + clear_values[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}}; + clear_values[1].depthStencil = {0.0f, 0u}; + + VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info(); + render_pass_begin_info.renderPass = render_pass; + render_pass_begin_info.renderArea.extent.width = width; + render_pass_begin_info.renderArea.extent.height = height; + render_pass_begin_info.clearValueCount = static_cast(clear_values.size()); + render_pass_begin_info.pClearValues = clear_values.data(); + + for (uint32_t i = 0u; i < draw_cmd_buffers.size(); ++i) + { + render_pass_begin_info.framebuffer = framebuffers[i]; + auto &cmd_buff = draw_cmd_buffers[i]; + + VK_CHECK(vkBeginCommandBuffer(cmd_buff, &command_buffer_begin_info)); + + vkCmdBeginRenderPass(cmd_buff, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); + + VkViewport viewport = vkb::initializers::viewport(static_cast(width), static_cast(height), 0.0f, 1.0f); + vkCmdSetViewport(cmd_buff, 0u, 1u, &viewport); + + VkRect2D scissor = vkb::initializers::rect2D(width, height, 0, 0); + vkCmdSetScissor(cmd_buff, 0u, 1u, &scissor); + + { + vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0u, 1u, &descriptor_set, 0u, nullptr); + vkCmdBindPipeline(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + VkDeviceSize offsets[1] = {0}; + vkCmdBindVertexBuffers(draw_cmd_buffers[i], 0, 1, vertex_buffer->get(), offsets); + vkCmdBindIndexBuffer(draw_cmd_buffers[i], index_buffer->get_handle(), 0, VK_INDEX_TYPE_UINT32); + + if(reverse) { + build_command_buffer_for_plane(cmd_buff, face_preferences[1]); + build_command_buffer_for_plane(cmd_buff, face_preferences[0]); + } + else { + build_command_buffer_for_plane(cmd_buff, face_preferences[0]); + build_command_buffer_for_plane(cmd_buff, face_preferences[1]); + } + } + + draw_ui(cmd_buff); + + + vkCmdEndRenderPass(cmd_buff); + + VK_CHECK(vkEndCommandBuffer(cmd_buff)); + } +} + +void DynamicBlending::build_command_buffer_for_plane(VkCommandBuffer &command_buffer, FacePreferences preferences) { + std::array color_bit = { + (preferences.color_bit_enabled[0] ? VK_COLOR_COMPONENT_R_BIT : 0u) | + (preferences.color_bit_enabled[1] ? VK_COLOR_COMPONENT_G_BIT : 0u) | + (preferences.color_bit_enabled[2] ? VK_COLOR_COMPONENT_B_BIT : 0u) | + (preferences.color_bit_enabled[3] ? VK_COLOR_COMPONENT_A_BIT : 0u) + }; + vkCmdSetColorWriteMaskEXT(command_buffer, 0, 1, color_bit.data()); + vkCmdDrawIndexed(command_buffer, preferences.index_count, 1, preferences.index_offset, 0, 0); +} + + +void DynamicBlending::on_update_ui_overlay(vkb::Drawer &drawer) +{ + FacePreferences ¤t_plane = face_preferences[current_face_index]; + if (drawer.button("Switch face")) { + + current_face_index = current_face_index == 0 ? 1 : 0; + on_update_ui_overlay(drawer); + } + if (drawer.header(current_face_index == 0 ? "Far face" : "Close face")) + { + if (drawer.color_picker("Top left", current_plane.color[0], ImGuiColorEditFlags_None, 200)) + { + update_color_uniform(); + } + if (drawer.color_picker("Top right", current_plane.color[1], ImGuiColorEditFlags_None, 200)) + { + update_color_uniform(); + } + if (drawer.color_picker("Bottom left", current_plane.color[2], ImGuiColorEditFlags_None, 200)) + { + update_color_uniform(); + } + if (drawer.color_picker("Bottom right", current_plane.color[3], ImGuiColorEditFlags_None, 200)) + { + update_color_uniform(); + } + if (drawer.checkbox("Red", ¤t_plane.color_bit_enabled[0])) + { + update_color_uniform(); + } + if (drawer.checkbox("Green",¤t_plane.color_bit_enabled[1])) + { + update_color_uniform(); + } + if (drawer.checkbox("Blue", ¤t_plane.color_bit_enabled[2])) + { + update_color_uniform(); + } + } +} + +void DynamicBlending::render(float delta_time) +{ + if (!prepared) + { + return; + } + draw(); + if (camera.updated) + { + update_uniform_buffers(); + } +} + +void DynamicBlending::draw() +{ + ApiVulkanSample::prepare_frame(); + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer]; + + VK_CHECK(vkQueueSubmit(queue, 1u, &submit_info, VK_NULL_HANDLE)); + ApiVulkanSample::submit_frame(); + + VkPipelineStageFlags wait_stage_mask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; +} + + +std::unique_ptr create_dynamic_blending() +{ + return std::make_unique(); +} diff --git a/samples/extensions/dynamic_blending/dynamic_blending.h b/samples/extensions/dynamic_blending/dynamic_blending.h new file mode 100644 index 000000000..4d23e81e0 --- /dev/null +++ b/samples/extensions/dynamic_blending/dynamic_blending.h @@ -0,0 +1,112 @@ +/* Copyright (c) 2023, Mobica + * + * 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. + */ + +#pragma once + +#include "api_vulkan_sample.h" + +class DynamicBlending : public ApiVulkanSample +{ + public: + DynamicBlending(); + ~DynamicBlending(); + + void render(float delta_time) override; + void build_command_buffers() override; + bool prepare(const vkb::ApplicationOptions &options) override; + void request_gpu_features(vkb::PhysicalDevice &gpu) override; + void on_update_ui_overlay(vkb::Drawer &drawer) override; + + void prepare_scene(); + void setup_descriptor_pool(); + void create_descriptor_set_layout(); + void create_descriptor_set(); + void create_pipelines(); + void prepare_uniform_buffers(); + void update_uniform_buffers(); + void update_color_uniform(); + void draw(); + +private: + VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blend_properties; + + bool reverse = false; + + VkCommandBuffer copy_cmd; + + struct Texture { + VkImage image; + VkDeviceMemory memory; + VkImageView view; + VkSampler sampler; + } texture; + + struct FacePreferences { + uint16_t index_offset; + uint16_t index_count; + std::array color_bit_enabled; + std::array color; + } face_preferences[2]; + + struct Vertex + { + std::array pos; + std::array uv; + }; + + struct CameraUbo + { + alignas(16) glm::mat4 projection; + alignas(16) glm::mat4 view; + alignas(16) glm::mat4 model; + }; + + struct ColorUbo + { + alignas(32) glm::vec4 data[8]; + }; + + struct + { + std::unique_ptr common; + } uniform_buffers; + + std::unique_ptr vertex_buffer; + std::unique_ptr index_buffer; + uint32_t index_count = 0; + + std::vector vertices; + uint32_t vertex_buffer_size; + uint8_t current_face_index = 1; + + std::unique_ptr camera_ubo; + std::array color_bit; + + ColorUbo color; + std::unique_ptr color_ubo; + + VkDescriptorPool descriptor_pool; + VkDescriptorSetLayout descriptor_set_layout; + VkPipelineLayout pipeline_layout; + VkDescriptorSet descriptor_set; + VkPipeline pipeline; + + void build_command_buffer_for_plane(VkCommandBuffer &command_buffer, FacePreferences preferences); + void update_color(); +}; + +std::unique_ptr create_dynamic_blending(); diff --git a/shaders/dynamic_blending/blending.frag b/shaders/dynamic_blending/blending.frag new file mode 100644 index 000000000..73eea247f --- /dev/null +++ b/shaders/dynamic_blending/blending.frag @@ -0,0 +1,56 @@ +#version 450 +/* 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. + */ + +layout (binding = 1) uniform Col +{ + vec4 data[8]; +} color; + + +layout (location = 0) in vec2 inUV; +layout (location = 1) flat in uint colorOffset; + +layout (location = 0) out vec4 outColor; + +vec4 sampleTexture(vec2 uv) +{ + vec4 c00 = color.data[0 + colorOffset]; + vec4 c01 = color.data[1 + colorOffset]; + vec4 c02 = color.data[2 + colorOffset]; + vec4 c03 = color.data[3 + colorOffset]; + + vec4 b0 = mix(c00, c01, uv.x); + vec4 b1 = mix(c02, c03, uv.x); + + vec4 p0 = mix(b0, b1, uv.y); + + return p0; +} + +void main() +{ + outColor = sampleTexture(inUV); +} + + + + + + + + diff --git a/shaders/dynamic_blending/blending.vert b/shaders/dynamic_blending/blending.vert new file mode 100644 index 000000000..2707a0860 --- /dev/null +++ b/shaders/dynamic_blending/blending.vert @@ -0,0 +1,37 @@ +#version 450 +/* 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. + */ + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec2 inUv; + +layout (binding = 0) uniform Ubo +{ + mat4 projection; + mat4 view; + mat4 model; +} ubo; + +layout (location = 0) out vec2 outUV; +layout (location = 1) out uint colorOffset; + +void main() +{ + outUV = inUv; + colorOffset = inPos.z == 1.0f ? 4 : 0; + gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0f); +} From 8a68e42480a519d335ba98fe705f29b982164cfb Mon Sep 17 00:00:00 2001 From: Krzysztof-Dmitruk-Mobica Date: Fri, 14 Jul 2023 16:00:12 +0200 Subject: [PATCH 2/3] Update dynamic blending sample Add blend equadion extension support Add blend advanced extension support --- framework/gui.cpp | 10 +- framework/gui.h | 40 + .../dynamic_blending/dynamic_blending.cpp | 921 ++++++++++-------- .../dynamic_blending/dynamic_blending.h | 202 ++-- 4 files changed, 700 insertions(+), 473 deletions(-) diff --git a/framework/gui.cpp b/framework/gui.cpp index 5b773994f..41373e68d 100644 --- a/framework/gui.cpp +++ b/framework/gui.cpp @@ -1136,6 +1136,15 @@ bool Drawer::checkbox(const char *caption, int32_t *value) return res; } +bool Drawer::radio_button(const char *caption, int32_t *selectedOption, const int32_t elementOption) +{ + bool res = ImGui::RadioButton(caption, selectedOption, elementOption); + if (res) + dirty = true; + + return res; +} + bool Drawer::input_float(const char *caption, float *value, float step, uint32_t precision) { bool res = ImGui::InputFloat(caption, value, step, step * 10.0f, precision); @@ -1229,5 +1238,4 @@ bool Drawer::color_op_impl(const char *caption, float return ImGui::ColorPicker4(caption, colors, flags); } - } // namespace vkb diff --git a/framework/gui.h b/framework/gui.h index e09a228b3..2e811ded8 100644 --- a/framework/gui.h +++ b/framework/gui.h @@ -127,6 +127,8 @@ class Drawer */ bool checkbox(const char *caption, int32_t *value); + bool radio_button(const char *caption, int32_t *selectedOption, const int32_t elementOption); + /** * @brief Adds a number input field to the gui * @param caption The text to display @@ -179,6 +181,7 @@ class Drawer */ void text(const char *formatstr, ...); +<<<<<<< HEAD /** * @brief Adds a color picker to the gui * @param caption The text to display @@ -186,6 +189,43 @@ class Drawer * @param flags Flags for modifying the appearance and behavior of the element. A zero value will result in a width determined by ImGui. */ bool color_picker(const char *caption, float *color, ImGuiColorEditFlags flags, uint16_t width = 0); +======= + /** + * @brief Adds a color picker to the gui + * @param caption The text to display + * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. + * @param width Element width. Zero is a special value for the default element width. + * @param flags Flags to modify the appearance and behavior of the element. + */ + bool color_picker(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); + + /** + * @brief Adds a color picker to the gui + * @param caption The text to display + * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. + * @param width Element width. Zero is a special value for the default element width. + * @param flags Flags to modify the appearance and behavior of the element. + */ + bool color_picker(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); + + /** + * @brief Adds a color edit to the gui + * @param caption The text to display + * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. + * @param width Element width. Zero is a special value for the default element width. + * @param flags Flags to modify the appearance and behavior of the element. + */ + bool color_edit(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); + + /** + * @brief Adds a color edit to the gui + * @param caption The text to display + * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. + * @param width Element width. Zero is a special value for the default element width. + * @param flags Flags to modify the appearance and behavior of the element. + */ + bool color_edit(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); +>>>>>>> 0d71460 (Update dynamic blending sample) private: template diff --git a/samples/extensions/dynamic_blending/dynamic_blending.cpp b/samples/extensions/dynamic_blending/dynamic_blending.cpp index 7f23e26a5..f62de3fb2 100644 --- a/samples/extensions/dynamic_blending/dynamic_blending.cpp +++ b/samples/extensions/dynamic_blending/dynamic_blending.cpp @@ -22,460 +22,607 @@ DynamicBlending::DynamicBlending() { - add_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - add_device_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); - add_device_extension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME); - add_device_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); - add_device_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); + add_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + add_device_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); + add_device_extension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME); - title = "Dynamic blending"; + title = "Dynamic blending"; } DynamicBlending::~DynamicBlending() { - if (device) - { - // NYI - } + if (device) + { + vkDestroyPipeline(get_device().get_handle(), pipeline, nullptr); + vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout, nullptr); + vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout, nullptr); + vkDestroyDescriptorPool(get_device().get_handle(), descriptor_pool, nullptr); + } } bool DynamicBlending::prepare(const vkb::ApplicationOptions &options) { - if (!ApiVulkanSample::prepare(options)) - { - return false; - } - - camera.type = vkb::CameraType::LookAt; - camera.set_position({0.0f, 0.0f, -5.0f}); - camera.set_rotation({-15.0f, 15.0f, 0.0f}); - camera.set_perspective(45.0f, static_cast(width) / static_cast(height), 256.0f, 0.1f); - - prepare_uniform_buffers(); - prepare_scene(); - setup_descriptor_pool(); - create_descriptor_set_layout(); - create_descriptor_set(); - create_pipelines(); - build_command_buffers(); - - prepared = true; - - return true; + if (!ApiVulkanSample::prepare(options)) + { + return false; + } + + camera.type = vkb::CameraType::LookAt; + camera.set_position({0.0f, 0.0f, -5.0f}); + camera.set_rotation({-15.0f, 15.0f, 0.0f}); + camera.set_perspective(45.0f, static_cast(width) / static_cast(height), 256.0f, 0.1f); + + initialize_operator_names(); + prepare_uniform_buffers(); + prepare_scene(); + setup_descriptor_pool(); + create_descriptor_set_layout(); + create_descriptor_set(); + create_pipelines(); + build_command_buffers(); + + rnd_engine = std::default_random_engine(time(nullptr)); + rnd_dist = std::uniform_real_distribution(0.0f, 1.0f); + + prepared = true; + + return true; } -void DynamicBlending::prepare_scene() { - vertices = { - {{-1.0f, -1.0f, 1.0f}, {0.0f, 0.0f}}, - {{1.0f, -1.0f, 1.0f}, {1.0f, 0.0f}}, - {{1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, - {{-1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, - - {{-1.0f, -1.0f, -1.0f},{0.0f, 0.0f}}, - {{1.0f, -1.0f, -1.0f}, {1.0f, 0.0f}}, - {{1.0f, 1.0f, -1.0f}, {1.0f, 1.0f}}, - {{-1.0f, 1.0f, -1.0f}, {0.0f, 1.0f}}, - }; - - std::vector indices = { - 6, 5, 4, 4, 7, 6, - 0, 1, 2, 2, 3, 0 - }; - - index_count = static_cast(indices.size()); - - vertex_buffer_size = vertices.size() * sizeof(Vertex); - auto index_buffer_size = indices.size() * sizeof(uint32_t); - - vertex_buffer = std::make_unique(get_device(), - vertex_buffer_size, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VMA_MEMORY_USAGE_GPU_TO_CPU); - vertex_buffer->update(vertices.data(), vertex_buffer_size); - - index_buffer = std::make_unique(get_device(), - index_buffer_size, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - VMA_MEMORY_USAGE_GPU_TO_CPU); - index_buffer->update(indices.data(), index_buffer_size); - - face_preferences[0].index_offset = 0; - face_preferences[0].index_count = index_count / 2; - face_preferences[0].color_bit_enabled = {true, true, true, true}; - face_preferences[0].color = {{ - {1.0f, 0.0f, 0.0f, 1.0f}, - {0.0f, 1.0f, 0.0f, 1.0f}, - {0.0f, 0.0f, 1.0f, 1.0f}, - {0.0f, 0.0f, 0.0f, 1.0f} - }}; - - face_preferences[1].index_offset = index_count / 2; - face_preferences[1].index_count = index_count / 2; - face_preferences[1].color_bit_enabled = {true, true, true, true}; - face_preferences[1].color = {{ - {0.0f, 1.0f, 1.0f, 1.0f}, - {1.0f, 0.0f, 1.0f, 1.0f}, - {1.0f, 1.0f, 0.0f, 1.0f}, - {1.0f, 1.0f, 1.0f, 1.0f} - }}; +void DynamicBlending::initialize_operator_names() +{ + for (uint32_t i = VK_BLEND_OP_ADD; i <= VK_BLEND_OP_MAX; ++i) + { + VkBlendOp op = static_cast(i); + blend_operator.values.push_back(op); + blend_operator.names.push_back(vkb::to_string(op)); + } + current_blend_color_operator_index = VK_BLEND_OP_ADD; + current_blend_alpha_operator_index = VK_BLEND_OP_ADD; + + for (uint32_t i = VK_BLEND_OP_ZERO_EXT; i <= VK_BLEND_OP_BLUE_EXT; ++i) + { + VkBlendOp op = static_cast(i); + advanced_blend_operator.values.push_back(op); + advanced_blend_operator.names.push_back(vkb::to_string(op)); + } + current_advanced_blend_operator_index = VK_BLEND_OP_SRC_OVER_EXT - VK_BLEND_OP_ZERO_EXT; + + for (uint32_t i = VK_BLEND_FACTOR_ZERO; i <= VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; ++i) + { + // The substr(16) call is used to drop the "VK_BLEND_FACTOR_" prefix + blend_factor_names.push_back(vkb::to_string(static_cast(i)).substr(16)); + } +} +void DynamicBlending::prepare_scene() +{ + vertices = { + {{-1.0f, -1.0f, 1.0f}, {0.0f, 0.0f}}, + {{1.0f, -1.0f, 1.0f}, {1.0f, 0.0f}}, + {{1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, + {{-1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, + + {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f}}, + {{1.0f, -1.0f, -1.0f}, {1.0f, 0.0f}}, + {{1.0f, 1.0f, -1.0f}, {1.0f, 1.0f}}, + {{-1.0f, 1.0f, -1.0f}, {0.0f, 1.0f}}, + }; + + std::vector indices = { + 6, 5, 4, 4, 7, 6, + 0, 1, 2, 2, 3, 0}; + + index_count = static_cast(indices.size()); + + vertex_buffer_size = vertices.size() * sizeof(Vertex); + auto index_buffer_size = indices.size() * sizeof(uint32_t); + + vertex_buffer = std::make_unique(get_device(), + vertex_buffer_size, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VMA_MEMORY_USAGE_GPU_TO_CPU); + vertex_buffer->update(vertices.data(), vertex_buffer_size); + + index_buffer = std::make_unique(get_device(), + index_buffer_size, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + VMA_MEMORY_USAGE_GPU_TO_CPU); + index_buffer->update(indices.data(), index_buffer_size); + + face_preferences[0].index_offset = 0; + face_preferences[0].index_count = index_count / 2; + face_preferences[0].color_bit_enabled = {true, true, true, true}; + face_preferences[0].color = {{{1.0f, 0.0f, 0.0f, 1.0f}, + {0.0f, 1.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f, 1.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}}; + + face_preferences[1].index_offset = index_count / 2; + face_preferences[1].index_count = index_count / 2; + face_preferences[1].color_bit_enabled = {true, true, true, true}; + face_preferences[1].color = {{{0.0f, 1.0f, 1.0f, 0.5f}, + {1.0f, 0.0f, 1.0f, 0.5f}, + {1.0f, 1.0f, 0.0f, 0.5f}, + {1.0f, 1.0f, 1.0f, 0.5f}}}; } void DynamicBlending::request_gpu_features(vkb::PhysicalDevice &gpu) { - { - auto &features = gpu.request_extension_features(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT); - features.extendedDynamicState3ColorWriteMask = VK_TRUE; - features.extendedDynamicState3ColorBlendEnable = VK_TRUE; - features.extendedDynamicState3ColorBlendAdvanced = VK_TRUE; - features.extendedDynamicState3ColorBlendEquation = VK_TRUE; - } - { - blend_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT; - blend_properties.pNext = VK_NULL_HANDLE; - - VkPhysicalDeviceProperties2 device_properties2 = {}; - device_properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - device_properties2.pNext = &blend_properties; - vkGetPhysicalDeviceProperties2(gpu.get_handle(), &device_properties2); - - } + { + auto &features = gpu.request_extension_features(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT); + features.extendedDynamicState3ColorWriteMask = VK_TRUE; + features.extendedDynamicState3ColorBlendEnable = VK_TRUE; + features.extendedDynamicState3ColorBlendAdvanced = VK_TRUE; + features.extendedDynamicState3ColorBlendEquation = VK_TRUE; + } + { + auto &features = gpu.request_extension_features(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT); + features.advancedBlendCoherentOperations = VK_TRUE; + } } -void DynamicBlending::prepare_uniform_buffers() { - camera_ubo = std::make_unique(get_device(), sizeof(CameraUbo), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); - color_ubo = std::make_unique(get_device(), sizeof(ColorUbo), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); - +void DynamicBlending::prepare_uniform_buffers() +{ + camera_ubo = std::make_unique(get_device(), sizeof(CameraUbo), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + color_ubo = std::make_unique(get_device(), sizeof(ColorUbo), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); } -void DynamicBlending::update_uniform_buffers() { - CameraUbo cam; - cam.model = glm::mat4(1.0f); - cam.model = glm::translate(cam.model, glm::vec3(0.0f)); - cam.view = camera.matrices.view; - cam.projection = camera.matrices.perspective; +void DynamicBlending::update_uniform_buffers() +{ + CameraUbo cam; + cam.model = glm::mat4(1.0f); + cam.model = glm::translate(cam.model, glm::vec3(0.0f)); + cam.view = camera.matrices.view; + cam.projection = camera.matrices.perspective; - camera_ubo->convert_and_update(cam); + camera_ubo->convert_and_update(cam); - update_color(); + update_color(); - glm::mat4 invView = glm::inverse(camera.matrices.view); - glm::vec4 plane0(vertices[0].pos[0], vertices[0].pos[1], vertices[0].pos[2], 1.0f); - glm::vec4 plane1(vertices[4].pos[0], vertices[4].pos[1], vertices[4].pos[2], 1.0f); + glm::mat4 invView = glm::inverse(camera.matrices.view); + glm::vec4 plane0(vertices[0].pos[0], vertices[0].pos[1], vertices[0].pos[2], 1.0f); + glm::vec4 plane1(vertices[4].pos[0], vertices[4].pos[1], vertices[4].pos[2], 1.0f); - plane0 = invView * plane0; - plane1 = invView * plane1; + plane0 = invView * plane0; + plane1 = invView * plane1; - reverse = plane0.z < plane1.z; + reverse = plane0.z < plane1.z; - build_command_buffers(); + build_command_buffers(); } - -void DynamicBlending::setup_descriptor_pool() { - std::vector pool_sizes = { - vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u), - }; - - VkDescriptorPoolCreateInfo descriptor_pool_create_info = - vkb::initializers::descriptor_pool_create_info( - static_cast(pool_sizes.size()), - pool_sizes.data(), - pool_sizes.size()); - VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool)); +void DynamicBlending::setup_descriptor_pool() +{ + std::vector pool_sizes = { + vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u), + }; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info = + vkb::initializers::descriptor_pool_create_info( + static_cast(pool_sizes.size()), + pool_sizes.data(), + pool_sizes.size()); + VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool)); } -void DynamicBlending::create_descriptor_set_layout() { - std::vector set_layout_bindings = { - vkb::initializers::descriptor_set_layout_binding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0u), - vkb::initializers::descriptor_set_layout_binding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 1u) - }; +void DynamicBlending::create_descriptor_set_layout() +{ + std::vector set_layout_bindings = { + vkb::initializers::descriptor_set_layout_binding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0u), + vkb::initializers::descriptor_set_layout_binding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 1u)}; - VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = vkb::initializers::descriptor_set_layout_create_info(set_layout_bindings); - VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_set_layout_create_info, nullptr, &descriptor_set_layout)); + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = vkb::initializers::descriptor_set_layout_create_info(set_layout_bindings); + VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_set_layout_create_info, nullptr, &descriptor_set_layout)); - VkPipelineLayoutCreateInfo pipeline_layout_create_info = vkb::initializers::pipeline_layout_create_info(&descriptor_set_layout); - VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &pipeline_layout)); + VkPipelineLayoutCreateInfo pipeline_layout_create_info = vkb::initializers::pipeline_layout_create_info(&descriptor_set_layout); + VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &pipeline_layout)); } -void DynamicBlending::create_descriptor_set() { - VkDescriptorSetAllocateInfo alloc_info = vkb::initializers::descriptor_set_allocate_info(descriptor_pool, &descriptor_set_layout, 1u); - VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info, &descriptor_set)); +void DynamicBlending::create_descriptor_set() +{ + VkDescriptorSetAllocateInfo alloc_info = vkb::initializers::descriptor_set_allocate_info(descriptor_pool, &descriptor_set_layout, 1u); + VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info, &descriptor_set)); - VkDescriptorBufferInfo buffer_descriptor = create_descriptor(*camera_ubo); - VkDescriptorBufferInfo color_descriptor = create_descriptor(*color_ubo); + VkDescriptorBufferInfo buffer_descriptor = create_descriptor(*camera_ubo); + VkDescriptorBufferInfo color_descriptor = create_descriptor(*color_ubo); - std::vector write_descriptor_sets = { - vkb::initializers::write_descriptor_set(descriptor_set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0u, &buffer_descriptor), - vkb::initializers::write_descriptor_set(descriptor_set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, &color_descriptor), - }; + std::vector write_descriptor_sets = { + vkb::initializers::write_descriptor_set(descriptor_set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0u, &buffer_descriptor), + vkb::initializers::write_descriptor_set(descriptor_set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, &color_descriptor), + }; - vkUpdateDescriptorSets(get_device().get_handle(), static_cast(write_descriptor_sets.size()), write_descriptor_sets.data(), 0u, nullptr); + vkUpdateDescriptorSets(get_device().get_handle(), static_cast(write_descriptor_sets.size()), write_descriptor_sets.data(), 0u, nullptr); } -void DynamicBlending::create_pipelines() { - VkPipelineInputAssemblyStateCreateInfo input_assembly_state = - vkb::initializers::pipeline_input_assembly_state_create_info( - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - 0, - VK_FALSE); - - VkPipelineRasterizationStateCreateInfo rasterization_state = - vkb::initializers::pipeline_rasterization_state_create_info( - VK_POLYGON_MODE_FILL, - VK_CULL_MODE_NONE, - VK_FRONT_FACE_COUNTER_CLOCKWISE, - 0); - - VkPipelineColorBlendAttachmentState blend_attachment_state = - vkb::initializers::pipeline_color_blend_attachment_state( - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, - VK_TRUE); - - blend_attachment_state.blendEnable = VK_TRUE; - blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD; - blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blend_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD; - blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - - VkPipelineColorBlendAdvancedStateCreateInfoEXT blendAdvancedEXT{}; - blendAdvancedEXT.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT; - blendAdvancedEXT.blendOverlap = VK_BLEND_OVERLAP_UNCORRELATED_EXT; - - VkPipelineColorBlendStateCreateInfo color_blend_state = - vkb::initializers::pipeline_color_blend_state_create_info( - 1, - &blend_attachment_state); - - color_blend_state.logicOpEnable = VK_FALSE; - color_blend_state.pNext = &blendAdvancedEXT; - - VkPipelineDepthStencilStateCreateInfo depth_stencil_state = - vkb::initializers::pipeline_depth_stencil_state_create_info( - VK_TRUE, - VK_TRUE, - VK_COMPARE_OP_GREATER); - - VkPipelineViewportStateCreateInfo viewport_state = - vkb::initializers::pipeline_viewport_state_create_info(1, 1, 0); - - VkPipelineMultisampleStateCreateInfo multisample_state = - vkb::initializers::pipeline_multisample_state_create_info( - VK_SAMPLE_COUNT_1_BIT, - 0); - - std::vector dynamic_state_enables = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT, - // NYI - // VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, - // VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT, - // VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT - }; - - VkPipelineDynamicStateCreateInfo dynamic_state = - vkb::initializers::pipeline_dynamic_state_create_info( - dynamic_state_enables.data(), - static_cast(dynamic_state_enables.size()), - 0); - - - const std::vector vertex_input_bindings = { - vkb::initializers::vertex_input_binding_description(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - }; - const std::vector vertex_input_attributes = { - vkb::initializers::vertex_input_attribute_description(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), - vkb::initializers::vertex_input_attribute_description(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)), - }; - - VkPipelineVertexInputStateCreateInfo vertex_input_state = vkb::initializers::pipeline_vertex_input_state_create_info(); - vertex_input_state.vertexBindingDescriptionCount = static_cast(vertex_input_bindings.size()); - vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data(); - vertex_input_state.vertexAttributeDescriptionCount = static_cast(vertex_input_attributes.size()); - vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data(); - - std::array shader_stages{}; - shader_stages[0] = load_shader("dynamic_blending/blending.vert", VK_SHADER_STAGE_VERTEX_BIT); - shader_stages[1] = load_shader("dynamic_blending/blending.frag", VK_SHADER_STAGE_FRAGMENT_BIT); - - VkGraphicsPipelineCreateInfo graphics_create{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO}; - graphics_create.pNext = VK_NULL_HANDLE; - graphics_create.renderPass = render_pass; - graphics_create.pInputAssemblyState = &input_assembly_state; - graphics_create.pRasterizationState = &rasterization_state; - graphics_create.pColorBlendState = &color_blend_state; - graphics_create.pMultisampleState = &multisample_state; - graphics_create.pViewportState = &viewport_state; - graphics_create.pDepthStencilState = &depth_stencil_state; - graphics_create.pDynamicState = &dynamic_state; - graphics_create.pVertexInputState = &vertex_input_state; - graphics_create.pTessellationState = VK_NULL_HANDLE; - graphics_create.stageCount = 2; - graphics_create.pStages = shader_stages.data(); - graphics_create.layout = pipeline_layout; - - VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), - pipeline_cache, - 1, - &graphics_create, - VK_NULL_HANDLE, - &pipeline)); +void DynamicBlending::create_pipelines() +{ + VkPipelineInputAssemblyStateCreateInfo input_assembly_state = + vkb::initializers::pipeline_input_assembly_state_create_info( + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + 0, + VK_FALSE); + + VkPipelineRasterizationStateCreateInfo rasterization_state = + vkb::initializers::pipeline_rasterization_state_create_info( + VK_POLYGON_MODE_FILL, + VK_CULL_MODE_NONE, + VK_FRONT_FACE_COUNTER_CLOCKWISE, + 0); + + VkPipelineColorBlendAttachmentState blend_attachment_state = + vkb::initializers::pipeline_color_blend_attachment_state( + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, + VK_TRUE); + + VkPipelineColorBlendAdvancedStateCreateInfoEXT blendAdvancedEXT{}; + blendAdvancedEXT.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT; + blendAdvancedEXT.blendOverlap = VK_BLEND_OVERLAP_UNCORRELATED_EXT; + + VkPipelineColorBlendStateCreateInfo color_blend_state = + vkb::initializers::pipeline_color_blend_state_create_info( + 1, + &blend_attachment_state); + + VkPipelineDepthStencilStateCreateInfo depth_stencil_state = + vkb::initializers::pipeline_depth_stencil_state_create_info( + VK_TRUE, + VK_TRUE, + VK_COMPARE_OP_GREATER); + + VkPipelineViewportStateCreateInfo viewport_state = + vkb::initializers::pipeline_viewport_state_create_info(1, 1, 0); + + VkPipelineMultisampleStateCreateInfo multisample_state = + vkb::initializers::pipeline_multisample_state_create_info( + VK_SAMPLE_COUNT_1_BIT, + 0); + + std::vector dynamic_state_enables = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT, + VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, + }; + + switch (current_blend_option) + { + case 0: + dynamic_state_enables.push_back(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT); + break; + case 1: + dynamic_state_enables.push_back(VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT); + } + + VkPipelineDynamicStateCreateInfo dynamic_state = + vkb::initializers::pipeline_dynamic_state_create_info( + dynamic_state_enables.data(), + static_cast(dynamic_state_enables.size()), + 0); + + const std::vector vertex_input_bindings = { + vkb::initializers::vertex_input_binding_description(0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX), + }; + const std::vector vertex_input_attributes = { + vkb::initializers::vertex_input_attribute_description(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), + vkb::initializers::vertex_input_attribute_description(0, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)), + }; + + VkPipelineVertexInputStateCreateInfo vertex_input_state = vkb::initializers::pipeline_vertex_input_state_create_info(); + vertex_input_state.vertexBindingDescriptionCount = static_cast(vertex_input_bindings.size()); + vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data(); + vertex_input_state.vertexAttributeDescriptionCount = static_cast(vertex_input_attributes.size()); + vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data(); + + std::array shader_stages{}; + shader_stages[0] = load_shader("dynamic_blending/blending.vert", VK_SHADER_STAGE_VERTEX_BIT); + shader_stages[1] = load_shader("dynamic_blending/blending.frag", VK_SHADER_STAGE_FRAGMENT_BIT); + + VkGraphicsPipelineCreateInfo graphics_create{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO}; + graphics_create.pNext = VK_NULL_HANDLE; + graphics_create.renderPass = render_pass; + graphics_create.pInputAssemblyState = &input_assembly_state; + graphics_create.pRasterizationState = &rasterization_state; + graphics_create.pColorBlendState = &color_blend_state; + graphics_create.pMultisampleState = &multisample_state; + graphics_create.pViewportState = &viewport_state; + graphics_create.pDepthStencilState = &depth_stencil_state; + graphics_create.pDynamicState = &dynamic_state; + graphics_create.pVertexInputState = &vertex_input_state; + graphics_create.pTessellationState = VK_NULL_HANDLE; + graphics_create.stageCount = 2; + graphics_create.pStages = shader_stages.data(); + graphics_create.layout = pipeline_layout; + + VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), + pipeline_cache, + 1, + &graphics_create, + VK_NULL_HANDLE, + &pipeline)); } -void DynamicBlending::update_color() { - for(uint32_t face = 0; face < 2; ++face) - for(uint32_t vertex = 0; vertex < 4; ++vertex) { - auto &input_color = face_preferences[face].color[vertex]; - color.data[face * 4 + vertex] = glm::vec4(input_color[0], input_color[1], input_color[2], input_color[3]); - } - color_ubo->convert_and_update(color); +void DynamicBlending::update_pipeline() +{ + vkDestroyPipeline(get_device().get_handle(), pipeline, nullptr); + create_pipelines(); } -void DynamicBlending::update_color_uniform() { - update_color(); - build_command_buffers(); +void DynamicBlending::update_color() +{ + for (uint32_t face = 0; face < 2; ++face) + for (uint32_t vertex = 0; vertex < 4; ++vertex) + { + auto &input_color = face_preferences[face].color[vertex]; + color.data[face * 4 + vertex] = glm::vec4(input_color[0], input_color[1], input_color[2], input_color[3]); + } + color_ubo->convert_and_update(color); } -void DynamicBlending::build_command_buffers() +void DynamicBlending::randomize_color(std::array &color, bool alpha) { - VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info(); - - std::array clear_values; - clear_values[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}}; - clear_values[1].depthStencil = {0.0f, 0u}; - - VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info(); - render_pass_begin_info.renderPass = render_pass; - render_pass_begin_info.renderArea.extent.width = width; - render_pass_begin_info.renderArea.extent.height = height; - render_pass_begin_info.clearValueCount = static_cast(clear_values.size()); - render_pass_begin_info.pClearValues = clear_values.data(); - - for (uint32_t i = 0u; i < draw_cmd_buffers.size(); ++i) - { - render_pass_begin_info.framebuffer = framebuffers[i]; - auto &cmd_buff = draw_cmd_buffers[i]; - - VK_CHECK(vkBeginCommandBuffer(cmd_buff, &command_buffer_begin_info)); - - vkCmdBeginRenderPass(cmd_buff, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport = vkb::initializers::viewport(static_cast(width), static_cast(height), 0.0f, 1.0f); - vkCmdSetViewport(cmd_buff, 0u, 1u, &viewport); - - VkRect2D scissor = vkb::initializers::rect2D(width, height, 0, 0); - vkCmdSetScissor(cmd_buff, 0u, 1u, &scissor); - - { - vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0u, 1u, &descriptor_set, 0u, nullptr); - vkCmdBindPipeline(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - - VkDeviceSize offsets[1] = {0}; - vkCmdBindVertexBuffers(draw_cmd_buffers[i], 0, 1, vertex_buffer->get(), offsets); - vkCmdBindIndexBuffer(draw_cmd_buffers[i], index_buffer->get_handle(), 0, VK_INDEX_TYPE_UINT32); - - if(reverse) { - build_command_buffer_for_plane(cmd_buff, face_preferences[1]); - build_command_buffer_for_plane(cmd_buff, face_preferences[0]); - } - else { - build_command_buffer_for_plane(cmd_buff, face_preferences[0]); - build_command_buffer_for_plane(cmd_buff, face_preferences[1]); - } - } - - draw_ui(cmd_buff); - - - vkCmdEndRenderPass(cmd_buff); + for (size_t i = 0; i < 3; ++i) + { + color[i] = rnd_dist(rnd_engine); + } + if (alpha) + color[3] = rnd_dist(rnd_engine); +} - VK_CHECK(vkEndCommandBuffer(cmd_buff)); - } +void DynamicBlending::update_color_uniform() +{ + update_color(); + build_command_buffers(); } -void DynamicBlending::build_command_buffer_for_plane(VkCommandBuffer &command_buffer, FacePreferences preferences) { - std::array color_bit = { - (preferences.color_bit_enabled[0] ? VK_COLOR_COMPONENT_R_BIT : 0u) | - (preferences.color_bit_enabled[1] ? VK_COLOR_COMPONENT_G_BIT : 0u) | - (preferences.color_bit_enabled[2] ? VK_COLOR_COMPONENT_B_BIT : 0u) | - (preferences.color_bit_enabled[3] ? VK_COLOR_COMPONENT_A_BIT : 0u) - }; - vkCmdSetColorWriteMaskEXT(command_buffer, 0, 1, color_bit.data()); - vkCmdDrawIndexed(command_buffer, preferences.index_count, 1, preferences.index_offset, 0, 0); +void DynamicBlending::build_command_buffers() +{ + VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info(); + + std::array clear_values; + clear_values[0].color = {clear_color[0], clear_color[1], clear_color[2], clear_color[3]}; + clear_values[1].depthStencil = {0.0f, 0u}; + + VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info(); + render_pass_begin_info.renderPass = render_pass; + render_pass_begin_info.renderArea.extent.width = width; + render_pass_begin_info.renderArea.extent.height = height; + render_pass_begin_info.clearValueCount = static_cast(clear_values.size()); + render_pass_begin_info.pClearValues = clear_values.data(); + + for (uint32_t i = 0u; i < draw_cmd_buffers.size(); ++i) + { + render_pass_begin_info.framebuffer = framebuffers[i]; + auto &cmd_buff = draw_cmd_buffers[i]; + + VK_CHECK(vkBeginCommandBuffer(cmd_buff, &command_buffer_begin_info)); + + vkCmdBeginRenderPass(cmd_buff, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); + + VkViewport viewport = vkb::initializers::viewport(static_cast(width), static_cast(height), 0.0f, 1.0f); + vkCmdSetViewport(cmd_buff, 0u, 1u, &viewport); + + VkRect2D scissor = vkb::initializers::rect2D(width, height, 0, 0); + vkCmdSetScissor(cmd_buff, 0u, 1u, &scissor); + + { + vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0u, 1u, &descriptor_set, 0u, nullptr); + vkCmdBindPipeline(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + VkDeviceSize offsets[1] = {0}; + vkCmdBindVertexBuffers(draw_cmd_buffers[i], 0, 1, vertex_buffer->get(), offsets); + vkCmdBindIndexBuffer(draw_cmd_buffers[i], index_buffer->get_handle(), 0, VK_INDEX_TYPE_UINT32); + + const VkBool32 blend_enable = this->blend_enable; + vkCmdSetColorBlendEnableEXT(cmd_buff, 0, 1, &blend_enable); + + if (current_blend_option == 0) + { + VkColorBlendEquationEXT color_blend_equation; + color_blend_equation.colorBlendOp = blend_operator.values[current_blend_color_operator_index]; + color_blend_equation.srcColorBlendFactor = static_cast(current_src_color_blend_factor); + color_blend_equation.dstColorBlendFactor = static_cast(current_dst_color_blend_factor); + color_blend_equation.alphaBlendOp = blend_operator.values[current_blend_alpha_operator_index]; + color_blend_equation.srcAlphaBlendFactor = static_cast(current_src_alpha_blend_factor); + color_blend_equation.dstAlphaBlendFactor = static_cast(current_dst_alpha_blend_factor); + vkCmdSetColorBlendEquationEXT(cmd_buff, 0, 1, &color_blend_equation); + } + else + { + VkColorBlendAdvancedEXT color_blend_advanced; + color_blend_advanced.advancedBlendOp = advanced_blend_operator.values[current_advanced_blend_operator_index]; + color_blend_advanced.srcPremultiplied = src_premultiplied; + color_blend_advanced.dstPremultiplied = dst_premultiplied; + color_blend_advanced.blendOverlap = VK_BLEND_OVERLAP_CONJOINT_EXT; + color_blend_advanced.clampResults = VK_TRUE; + vkCmdSetColorBlendAdvancedEXT(cmd_buff, 0, 1, &color_blend_advanced); + } + + if (reverse) + { + build_command_buffer_for_plane(cmd_buff, face_preferences[1]); + build_command_buffer_for_plane(cmd_buff, face_preferences[0]); + } + else + { + build_command_buffer_for_plane(cmd_buff, face_preferences[0]); + build_command_buffer_for_plane(cmd_buff, face_preferences[1]); + } + } + + draw_ui(cmd_buff); + + vkCmdEndRenderPass(cmd_buff); + + VK_CHECK(vkEndCommandBuffer(cmd_buff)); + } } +void DynamicBlending::build_command_buffer_for_plane(VkCommandBuffer &command_buffer, FacePreferences preferences) +{ + std::array color_bit = { + (preferences.color_bit_enabled[0] ? VK_COLOR_COMPONENT_R_BIT : 0u) | + (preferences.color_bit_enabled[1] ? VK_COLOR_COMPONENT_G_BIT : 0u) | + (preferences.color_bit_enabled[2] ? VK_COLOR_COMPONENT_B_BIT : 0u) | + (preferences.color_bit_enabled[3] ? VK_COLOR_COMPONENT_A_BIT : 0u)}; + vkCmdSetColorWriteMaskEXT(command_buffer, 0, 1, color_bit.data()); + vkCmdDrawIndexed(command_buffer, preferences.index_count, 1, preferences.index_offset, 0, 0); +} void DynamicBlending::on_update_ui_overlay(vkb::Drawer &drawer) { - FacePreferences ¤t_plane = face_preferences[current_face_index]; - if (drawer.button("Switch face")) { - - current_face_index = current_face_index == 0 ? 1 : 0; - on_update_ui_overlay(drawer); - } - if (drawer.header(current_face_index == 0 ? "Far face" : "Close face")) - { - if (drawer.color_picker("Top left", current_plane.color[0], ImGuiColorEditFlags_None, 200)) - { - update_color_uniform(); - } - if (drawer.color_picker("Top right", current_plane.color[1], ImGuiColorEditFlags_None, 200)) - { - update_color_uniform(); - } - if (drawer.color_picker("Bottom left", current_plane.color[2], ImGuiColorEditFlags_None, 200)) - { - update_color_uniform(); - } - if (drawer.color_picker("Bottom right", current_plane.color[3], ImGuiColorEditFlags_None, 200)) - { - update_color_uniform(); - } - if (drawer.checkbox("Red", ¤t_plane.color_bit_enabled[0])) - { - update_color_uniform(); - } - if (drawer.checkbox("Green",¤t_plane.color_bit_enabled[1])) - { - update_color_uniform(); - } - if (drawer.checkbox("Blue", ¤t_plane.color_bit_enabled[2])) - { - update_color_uniform(); - } - } + uint32_t item_id = 0; + + auto add_color_edit = [&](const char *caption, std::array &color) { + ImGuiColorEditFlags flags = ImGuiColorEditFlags_None | ImGuiColorEditFlags_Float; + float color_edit_width = 200; + ImGui::PushID(++item_id); + if (drawer.color_edit(caption, color, color_edit_width, flags)) + { + update_color_uniform(); + } + ImGui::PopID(); + }; + + auto add_color_mask_checkbox = [&](const char *caption, bool &enabled, bool same_line = true) { + ImGui::PushID(++item_id); + if (drawer.checkbox(caption, &enabled)) + { + update_color_uniform(); + } + ImGui::PopID(); + if (same_line) + ImGui::SameLine(); + }; + + auto add_next_button = [&](int32_t &index, int32_t first, int32_t last) { + + }; + + auto add_combo_with_button = [&](const char *caption, int32_t &index, int32_t first, int32_t last, std::vector names) { + ImGui::PushID(++item_id); + if (drawer.button("Next")) + { + index = (index + 1) % (last - first + 1); + update_uniform_buffers(); + } + ImGui::PopID(); + ImGui::SameLine(); + if (drawer.combo_box(caption, &index, names)) + { + update_uniform_buffers(); + } + }; + + add_color_edit("Background", clear_color); + + for (int i = 0; i < 2; ++i) + { + FacePreferences ¤t_face = face_preferences[i]; + if (drawer.header(current_face_index == 0 ? "First face" : "Second face")) + { + add_color_edit("Top left", current_face.color[0]); + add_color_edit("Top right", current_face.color[1]); + add_color_edit("Bottom left", current_face.color[2]); + add_color_edit("Bottom right", current_face.color[3]); + + ImGui::PushID(++item_id); + if (drawer.button("Random")) + { + for (int i = 0; i < 4; ++i) + randomize_color(current_face.color[i]); + update_color(); + } + ImGui::PopID(); + + drawer.text("Color write mask"); + add_color_mask_checkbox("Red", current_face.color_bit_enabled[0]); + add_color_mask_checkbox("Green", current_face.color_bit_enabled[1]); + add_color_mask_checkbox("Blue", current_face.color_bit_enabled[2]); + add_color_mask_checkbox("Alpha", current_face.color_bit_enabled[3], false); + } + } + + if (drawer.header("Blending")) + { + if (drawer.checkbox("Enabled", &blend_enable)) + { + update_color_uniform(); + } + if (drawer.radio_button("BlendEquationEXT", ¤t_blend_option, 0)) + { + update_pipeline(); + update_color_uniform(); + } + if (drawer.radio_button("BlendAdvancedEXT", ¤t_blend_option, 1)) + { + update_pipeline(); + update_color_uniform(); + } + switch (current_blend_option) + { + case 0: + if (drawer.header("BlendEquationEXT")) + { + add_combo_with_button("Color operator", current_blend_color_operator_index, VK_BLEND_OP_ADD, VK_BLEND_OP_MAX, blend_operator.names); + add_combo_with_button("SrcColorBlendFactor", current_src_color_blend_factor, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_SRC_ALPHA_SATURATE, blend_factor_names); + add_combo_with_button("DstColorBlendFactor", current_dst_color_blend_factor, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_SRC_ALPHA_SATURATE, blend_factor_names); + + add_combo_with_button("Alpha operator", current_blend_alpha_operator_index, VK_BLEND_OP_ADD, VK_BLEND_OP_MAX, blend_operator.names); + add_combo_with_button("SrcAlphaBlendFactor", current_src_alpha_blend_factor, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_SRC_ALPHA_SATURATE, blend_factor_names); + add_combo_with_button("DstAlphaBlendFactor", current_dst_alpha_blend_factor, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_SRC_ALPHA_SATURATE, blend_factor_names); + } + break; + case 1: + if (drawer.header("BlendAdvancedEXT")) + { + add_combo_with_button("Operator", current_advanced_blend_operator_index, VK_BLEND_OP_ZERO_EXT, VK_BLEND_OP_BLUE_EXT, advanced_blend_operator.names); + if (drawer.checkbox("Src premultiplied", &src_premultiplied)) + { + update_color_uniform(); + } + if (drawer.checkbox("Dst premultiplied", &dst_premultiplied)) + { + update_color_uniform(); + } + } + } + } } void DynamicBlending::render(float delta_time) { - if (!prepared) - { - return; - } - draw(); - if (camera.updated) - { - update_uniform_buffers(); - } + if (!prepared) + { + return; + } + draw(); + if (camera.updated) + { + update_uniform_buffers(); + } } void DynamicBlending::draw() { - ApiVulkanSample::prepare_frame(); - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer]; + ApiVulkanSample::prepare_frame(); + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer]; - VK_CHECK(vkQueueSubmit(queue, 1u, &submit_info, VK_NULL_HANDLE)); - ApiVulkanSample::submit_frame(); + VK_CHECK(vkQueueSubmit(queue, 1u, &submit_info, VK_NULL_HANDLE)); + ApiVulkanSample::submit_frame(); - VkPipelineStageFlags wait_stage_mask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + VkPipelineStageFlags wait_stage_mask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; } +bool DynamicBlending::resize(const uint32_t width, const uint32_t height) +{ + ApiVulkanSample::resize(width, height); + update_uniform_buffers(); + return true; +} std::unique_ptr create_dynamic_blending() { - return std::make_unique(); + return std::make_unique(); } diff --git a/samples/extensions/dynamic_blending/dynamic_blending.h b/samples/extensions/dynamic_blending/dynamic_blending.h index 4d23e81e0..41dd5de23 100644 --- a/samples/extensions/dynamic_blending/dynamic_blending.h +++ b/samples/extensions/dynamic_blending/dynamic_blending.h @@ -22,91 +22,123 @@ class DynamicBlending : public ApiVulkanSample { public: - DynamicBlending(); - ~DynamicBlending(); - - void render(float delta_time) override; - void build_command_buffers() override; - bool prepare(const vkb::ApplicationOptions &options) override; - void request_gpu_features(vkb::PhysicalDevice &gpu) override; - void on_update_ui_overlay(vkb::Drawer &drawer) override; - - void prepare_scene(); - void setup_descriptor_pool(); - void create_descriptor_set_layout(); - void create_descriptor_set(); - void create_pipelines(); - void prepare_uniform_buffers(); - void update_uniform_buffers(); - void update_color_uniform(); - void draw(); - -private: - VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blend_properties; - - bool reverse = false; - - VkCommandBuffer copy_cmd; - - struct Texture { - VkImage image; - VkDeviceMemory memory; - VkImageView view; - VkSampler sampler; - } texture; - - struct FacePreferences { - uint16_t index_offset; - uint16_t index_count; - std::array color_bit_enabled; - std::array color; - } face_preferences[2]; - - struct Vertex - { - std::array pos; - std::array uv; - }; - - struct CameraUbo - { - alignas(16) glm::mat4 projection; - alignas(16) glm::mat4 view; - alignas(16) glm::mat4 model; - }; - - struct ColorUbo - { - alignas(32) glm::vec4 data[8]; - }; - - struct - { - std::unique_ptr common; - } uniform_buffers; - - std::unique_ptr vertex_buffer; - std::unique_ptr index_buffer; - uint32_t index_count = 0; - - std::vector vertices; - uint32_t vertex_buffer_size; - uint8_t current_face_index = 1; - - std::unique_ptr camera_ubo; - std::array color_bit; - - ColorUbo color; - std::unique_ptr color_ubo; - - VkDescriptorPool descriptor_pool; - VkDescriptorSetLayout descriptor_set_layout; - VkPipelineLayout pipeline_layout; - VkDescriptorSet descriptor_set; - VkPipeline pipeline; - - void build_command_buffer_for_plane(VkCommandBuffer &command_buffer, FacePreferences preferences); - void update_color(); + DynamicBlending(); + ~DynamicBlending(); + + void render(float delta_time) override; + void build_command_buffers() override; + bool prepare(const vkb::ApplicationOptions &options) override; + void request_gpu_features(vkb::PhysicalDevice &gpu) override; + void on_update_ui_overlay(vkb::Drawer &drawer) override; + bool resize(const uint32_t width, const uint32_t height) override; + + void prepare_scene(); + void setup_descriptor_pool(); + void create_descriptor_set_layout(); + void create_descriptor_set(); + void create_pipelines(); + void prepare_uniform_buffers(); + void update_uniform_buffers(); + void update_color_uniform(); + void draw(); + void initialize_operator_names(); + void update_pipeline(); + + private: + VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blend_properties; + + bool reverse = false; + + VkCommandBuffer copy_cmd; + + struct Texture + { + VkImage image; + VkDeviceMemory memory; + VkImageView view; + VkSampler sampler; + } texture; + + struct FacePreferences + { + uint16_t index_offset; + uint16_t index_count; + std::array color_bit_enabled; + std::array, 4> color; + } face_preferences[2]; + + struct Vertex + { + std::array pos; + std::array uv; + }; + + struct CameraUbo + { + alignas(16) glm::mat4 projection; + alignas(16) glm::mat4 view; + alignas(16) glm::mat4 model; + }; + + struct ColorUbo + { + alignas(32) glm::vec4 data[8]; + }; + + struct + { + std::unique_ptr common; + } uniform_buffers; + + struct + { + std::vector values; + std::vector names; + } blend_operator, advanced_blend_operator; + + std::vector blend_factor_names; + + std::unique_ptr vertex_buffer; + std::unique_ptr index_buffer; + uint32_t index_count = 0; + + std::vector vertices; + uint32_t vertex_buffer_size; + uint8_t current_face_index = 1; + + std::unique_ptr camera_ubo; + std::array color_bit; + + ColorUbo color; + std::unique_ptr color_ubo; + + VkDescriptorPool descriptor_pool; + VkDescriptorSetLayout descriptor_set_layout; + VkPipelineLayout pipeline_layout; + VkDescriptorSet descriptor_set; + VkPipeline pipeline; + + std::array clear_color = {0.5f, 0.5f, 0.5f, 1.0f}; + int32_t current_blend_color_operator_index; + int32_t current_blend_alpha_operator_index; + int32_t current_advanced_blend_operator_index; + int32_t current_blend_option = 0; + int32_t current_src_color_blend_factor = VK_BLEND_FACTOR_SRC_ALPHA; + int32_t current_dst_color_blend_factor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + int32_t current_src_alpha_blend_factor = VK_BLEND_FACTOR_ZERO; + int32_t current_dst_alpha_blend_factor = VK_BLEND_FACTOR_ONE; + + bool blend_enable = true; + bool src_premultiplied = true; + bool dst_premultiplied = true; + bool clamp_results = true; + + std::default_random_engine rnd_engine; + std::uniform_real_distribution rnd_dist; + + void build_command_buffer_for_plane(VkCommandBuffer &command_buffer, FacePreferences preferences); + void update_color(); + void randomize_color(std::array &color, bool alpha = false); }; std::unique_ptr create_dynamic_blending(); From e0941df62a88d02697b81969a6eebdcfcffe0a10 Mon Sep 17 00:00:00 2001 From: Krzysztof-Dmitruk-Mobica Date: Mon, 21 Aug 2023 10:26:10 +0200 Subject: [PATCH 3/3] Fix according to the review --- framework/gui.h | 59 ++++++---------- framework/hpp_gui.cpp | 9 +++ framework/hpp_gui.h | 9 +++ samples/README.adoc | 5 ++ .../dynamic_blending/CMakeLists.txt | 4 +- .../extensions/dynamic_blending/README.adoc | 67 +++++++++++++++++++ .../dynamic_blending/dynamic_blending.cpp | 5 +- 7 files changed, 116 insertions(+), 42 deletions(-) create mode 100644 samples/extensions/dynamic_blending/README.adoc diff --git a/framework/gui.h b/framework/gui.h index 2e811ded8..dd902638a 100644 --- a/framework/gui.h +++ b/framework/gui.h @@ -127,6 +127,13 @@ class Drawer */ bool checkbox(const char *caption, int32_t *value); + /** + * @brief Adds a radio button to the gui + * @param caption The text to display + * @param selectedOption The pointer to the variable set using the radio button. + * @param elementOption Value set to the selectedOption when the button is selected. + * @returns True if adding item was successful + */ bool radio_button(const char *caption, int32_t *selectedOption, const int32_t elementOption); /** @@ -181,51 +188,27 @@ class Drawer */ void text(const char *formatstr, ...); -<<<<<<< HEAD - /** - * @brief Adds a color picker to the gui - * @param caption The text to display - * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. - * @param flags Flags for modifying the appearance and behavior of the element. A zero value will result in a width determined by ImGui. - */ - bool color_picker(const char *caption, float *color, ImGuiColorEditFlags flags, uint16_t width = 0); -======= - /** - * @brief Adds a color picker to the gui - * @param caption The text to display - * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. - * @param width Element width. Zero is a special value for the default element width. - * @param flags Flags to modify the appearance and behavior of the element. - */ - bool color_picker(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); - - /** - * @brief Adds a color picker to the gui - * @param caption The text to display - * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. - * @param width Element width. Zero is a special value for the default element width. - * @param flags Flags to modify the appearance and behavior of the element. - */ - bool color_picker(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); - - /** - * @brief Adds a color edit to the gui - * @param caption The text to display - * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. - * @param width Element width. Zero is a special value for the default element width. - * @param flags Flags to modify the appearance and behavior of the element. - */ - bool color_edit(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); - /** * @brief Adds a color edit to the gui + * @tparam OP Mode of the color element. + * @tparam N Color channel count. Must be 3 or 4. * @param caption The text to display * @param color Color channel array on which the picker works. It contains values ranging from 0 to 1. * @param width Element width. Zero is a special value for the default element width. * @param flags Flags to modify the appearance and behavior of the element. */ - bool color_edit(const char *caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0); ->>>>>>> 0d71460 (Update dynamic blending sample) + template + bool color_op(const std::string &caption, std::array &color, float width = 0.0f, ImGuiColorEditFlags flags = 0) + { + static_assert((N == 3) || (N == 4), "The channel count must be 3 or 4."); + + ImGui::PushItemWidth(width); + bool res = color_op_impl(caption.c_str(), color.data(), flags); + ImGui::PopItemWidth(); + if (res) + dirty = true; + return res; + } private: template diff --git a/framework/hpp_gui.cpp b/framework/hpp_gui.cpp index 063b82476..40d9db9ae 100644 --- a/framework/hpp_gui.cpp +++ b/framework/hpp_gui.cpp @@ -1064,6 +1064,15 @@ bool HPPDrawer::checkbox(const std::string &caption, int32_t *value) return res; } +bool HPPDrawer::radio_button(const char *caption, int32_t *selectedOption, const int32_t elementOption) +{ + bool res = ImGui::RadioButton(caption, selectedOption, elementOption); + if (res) + dirty = true; + + return res; +} + bool HPPDrawer::input_float(const std::string &caption, float *value, float step, uint32_t precision) { bool res = ImGui::InputFloat(caption.c_str(), value, step, step * 10.0f, precision); diff --git a/framework/hpp_gui.h b/framework/hpp_gui.h index 585cd7bc6..37055ddb6 100644 --- a/framework/hpp_gui.h +++ b/framework/hpp_gui.h @@ -115,6 +115,15 @@ class HPPDrawer */ bool checkbox(const std::string &caption, int32_t *value); + /** + * @brief Adds a radio button to the gui + * @param caption The text to display + * @param selectedOption The pointer to the variable set using the radio button. + * @param elementOption Value set to the selectedOption when the button is selected. + * @returns True if adding item was successful + */ + bool radio_button(const char *caption, int32_t *selectedOption, const int32_t elementOption); + /** * @brief Adds a number input field to the gui * @param caption The text to display diff --git a/samples/README.adoc b/samples/README.adoc index b5e5491ef..64555324a 100644 --- a/samples/README.adoc +++ b/samples/README.adoc @@ -480,6 +480,11 @@ Demonstrate how to create multiple color blend attachments and then toggle them Demonstrate how to use shader objects. +=== link:./extensions/dynamic_blending[Dynamic blending] +*Extension:* https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_extended_dynamic_state.html[`VK_EXT_extended_dynamic_state3`] + +Demonstrate how to use the blending related functions available in the VK_EXT_extended_dynamic_state3 extension. + == Tooling Samples The goal of these samples is to demonstrate usage of tooling functions and libraries that are not directly part of the api. diff --git a/samples/extensions/dynamic_blending/CMakeLists.txt b/samples/extensions/dynamic_blending/CMakeLists.txt index ec095c10f..555d1a114 100644 --- a/samples/extensions/dynamic_blending/CMakeLists.txt +++ b/samples/extensions/dynamic_blending/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019, Arm Limited and Contributors +# Copyright (c) 2023, Mobica Limited # # SPDX-License-Identifier: Apache-2.0 # @@ -24,7 +24,7 @@ add_sample( CATEGORY ${CATEGORY_NAME} AUTHOR "Khronos" NAME "dynamic_blending" - DESCRIPTION "Sample description" + DESCRIPTION "Dynamic blending options available in the VK_EXT_extended_dynamic_state3 extension." SHADER_FILES_GLSL "dynamic_blending/blending.vert" "dynamic_blending/blending.frag" diff --git a/samples/extensions/dynamic_blending/README.adoc b/samples/extensions/dynamic_blending/README.adoc new file mode 100644 index 000000000..9c9815b10 --- /dev/null +++ b/samples/extensions/dynamic_blending/README.adoc @@ -0,0 +1,67 @@ +//// +- 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. +- +//// + +== Dynamic blending + +=== Overview + +This sample demonstrates the functionality of VK_EXT_extended_dynamic_state3 related to blending. It includes the +following features: + +* `vkCmdSetColorBlendEnableEXT`: toggles blending on and off. +* `vkCmdSetColorBlendEquationEXT`: modifies blending operators and factors. +* `vkCmdSetColorBlendAdvancedEXT`: utilizes more complex blending operators. +* `vkCmdSetColorWriteMaskEXT`: toggles individual channels on and off. + +=== How to use in Vulkan + +To utilize this feature, the device extension `VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME` need to be enabled. +The extension `VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME` is required for the advanced blend equations. +All presented functions take an array of objects defining their action for subsequent color attachments: + +* The `vkCmdSetColorBlendEnableEXT` +function expects an array of booleans to toggle blending. +* The `vkCmdSetColorBlendEquationEXT` function expects an array of +`VkColorBlendEquationEXT` objects which determine operators and factors for +color and alpha blending. +* The `VkCmdSetColorBlendAdvancedEXT` function expects an array of `VkColorBlendAdvancedEXT` objects, which determine +blending operators and premultiplication for color blending. +* The `vkCmdSetColorWriteMaskEXT` function expects an array of +`VkColorComponentFlags` objects. These objects can be created by combining +the desired color bit flags using bitwise oring. + +=== The sample + +The sample demonstrates how to set up an application to work with this +extension: + +* Enabling the extension. +* Setting parameters for the presented methods. + +The sample demonstrates how the use of each operator affects color blending. + +=== Documentation links + +https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdSetColorBlendEnableEXT.html + +https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdSetColorBlendEquationEXT.html + +https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdSetColorBlendAdvancedEXT.html + +https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdSetColorWriteMaskEXT.html diff --git a/samples/extensions/dynamic_blending/dynamic_blending.cpp b/samples/extensions/dynamic_blending/dynamic_blending.cpp index f62de3fb2..e431ab810 100644 --- a/samples/extensions/dynamic_blending/dynamic_blending.cpp +++ b/samples/extensions/dynamic_blending/dynamic_blending.cpp @@ -202,7 +202,7 @@ void DynamicBlending::setup_descriptor_pool() vkb::initializers::descriptor_pool_create_info( static_cast(pool_sizes.size()), pool_sizes.data(), - pool_sizes.size()); + static_cast(pool_sizes.size())); VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool)); } @@ -477,7 +477,8 @@ void DynamicBlending::on_update_ui_overlay(vkb::Drawer &drawer) ImGuiColorEditFlags flags = ImGuiColorEditFlags_None | ImGuiColorEditFlags_Float; float color_edit_width = 200; ImGui::PushID(++item_id); - if (drawer.color_edit(caption, color, color_edit_width, flags)) + if (drawer.color_op(caption, color, color_edit_width, flags)) + // if (drawer.color_edit(caption, color, color_edit_width, flags)) { update_color_uniform(); }