diff --git a/samples/extensions/subgroups_operations/CMakeLists.txt b/samples/extensions/subgroups_operations/CMakeLists.txt index fe4d63f95..d7b0a128b 100644 --- a/samples/extensions/subgroups_operations/CMakeLists.txt +++ b/samples/extensions/subgroups_operations/CMakeLists.txt @@ -26,6 +26,6 @@ add_sample( NAME "subgroups_operations" DESCRIPTION "Demonstrates the use of a subgroups feature" SHADER_FILES_GLSL - "subgroups_operations/base.vert" - "subgroups_operations/base.frag" - "subgroups_operations/blur.comp") + "subgroups_operations/ocean.vert" + "subgroups_operations/ocean.frag" + "subgroups_operations/ocean_fft.comp") diff --git a/samples/extensions/subgroups_operations/subgroups_operations.cpp b/samples/extensions/subgroups_operations/subgroups_operations.cpp index d62d6b8c4..f0e504668 100644 --- a/samples/extensions/subgroups_operations/subgroups_operations.cpp +++ b/samples/extensions/subgroups_operations/subgroups_operations.cpp @@ -16,7 +16,7 @@ */ #include "subgroups_operations.h" -#include +#include void SubgroupsOperations::Pipeline::destroy(VkDevice device) { @@ -44,12 +44,17 @@ SubgroupsOperations::SubgroupsOperations() // Required by VK_KHR_spirv_1_4 add_device_extension(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); + // Targeting SPIR-V version + vkb::GLSLCompiler::set_target_environment(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4); + title = "Subgroups operations"; camera.type = vkb::CameraType::LookAt; camera.set_perspective(60.0f, static_cast(width) / static_cast(height), 0.1f, 256.0f); - camera.set_position({0.0f, 0.0f, -2.0f}); + camera.set_position({-1.98f, -2.24f, -28.55f}); + camera.set_rotation({-24.0f, -7.0f, 0.0f}); } + SubgroupsOperations::~SubgroupsOperations() { if (device) @@ -62,6 +67,7 @@ SubgroupsOperations::~SubgroupsOperations() ocean.pipelines._default.destroy(get_device().get_handle()); ocean.pipelines.wireframe.destroy(get_device().get_handle()); vkDestroyDescriptorSetLayout(get_device().get_handle(), ocean.descriptor_set_layout, nullptr); + vkDestroySemaphore(get_device().get_handle(), ocean.semaphore, nullptr); } } @@ -72,18 +78,28 @@ bool SubgroupsOperations::prepare(vkb::Platform &platform) return false; } + ocean.graphics_queue_family_index = get_device().get_queue_family_index(VK_QUEUE_GRAPHICS_BIT); + load_assets(); setup_descriptor_pool(); prepare_uniform_buffers(); prepare_compute(); // prepare grpahics pipeline + create_semaphore(); create_descriptor_set_layout(); create_descriptor_set(); create_pipelines(); build_command_buffers(); + // signal semaphore + VkSubmitInfo submit_info = vkb::initializers::submit_info(); + submit_info.signalSemaphoreCount = 1u; + submit_info.pSignalSemaphores = &ocean.semaphore; + VK_CHECK(vkQueueSubmit(queue, 1u, &submit_info, VK_NULL_HANDLE)); + get_device().wait_idle(); + prepared = true; return true; } @@ -121,10 +137,7 @@ void SubgroupsOperations::create_compute_command_buffer() { // Create a command buffer for compute operations VkCommandBufferAllocateInfo command_buffer_allocate_info = - vkb::initializers::command_buffer_allocate_info( - compute.command_pool, - VK_COMMAND_BUFFER_LEVEL_PRIMARY, - 1u); + vkb::initializers::command_buffer_allocate_info(compute.command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1u); VK_CHECK(vkAllocateCommandBuffers(get_device().get_handle(), &command_buffer_allocate_info, &compute.command_buffer)); @@ -150,6 +163,11 @@ void SubgroupsOperations::create_compute_descriptor_set() VkDescriptorSetAllocateInfo alloc_info = vkb::initializers::descriptor_set_allocate_info(descriptor_pool, &compute.descriptor_set_layout, 1u); VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info, &compute.descriptor_set)); + update_compute_descriptor(); +} + +void SubgroupsOperations::update_compute_descriptor() +{ VkDescriptorBufferInfo time_ubo_buffer = create_descriptor(*compute_ubo); VkDescriptorBufferInfo input_vertices_buffer = create_descriptor(*input_grid.vertex); VkDescriptorBufferInfo output_vertices_buffer = create_descriptor(*ocean.grid.vertex); @@ -182,18 +200,42 @@ void SubgroupsOperations::prepare_compute_pipeline() void SubgroupsOperations::build_compute_command_buffer() { - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - vkResetCommandBuffer(compute.command_buffer, 0u); - // record command - VkCommandBufferBeginInfo begin_info = {}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + VkCommandBufferBeginInfo begin_info = vkb::initializers::command_buffer_begin_info(); VK_CHECK(vkBeginCommandBuffer(compute.command_buffer, &begin_info)); + if (compute.queue_family_index != ocean.graphics_queue_family_index) + { + VkBufferMemoryBarrier memory_barrier = vkb::initializers::buffer_memory_barrier(); + memory_barrier.srcAccessMask = 0; + memory_barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + memory_barrier.srcQueueFamilyIndex = ocean.graphics_queue_family_index; + memory_barrier.dstQueueFamilyIndex = compute.queue_family_index; + memory_barrier.buffer = ocean.grid.vertex->get_handle(); + memory_barrier.offset = 0; + memory_barrier.size = ocean.grid.vertex->get_size(); + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 1, &memory_barrier, 0, nullptr); + } + vkCmdBindPipeline(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelines._default.pipeline); vkCmdBindDescriptorSets(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelines._default.pipeline_layout, 0u, 1u, &compute.descriptor_set, 0u, nullptr); - vkCmdDispatch(compute.command_buffer, grid_size / 16u, grid_size / 16u, 1u); + + vkCmdDispatch(compute.command_buffer, grid_size, grid_size, 1u); + + if (compute.queue_family_index != ocean.graphics_queue_family_index) + { + VkBufferMemoryBarrier memory_barrier = vkb::initializers::buffer_memory_barrier(); + memory_barrier.srcAccessMask = 0; + memory_barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + memory_barrier.srcQueueFamilyIndex = compute.queue_family_index; + memory_barrier.dstQueueFamilyIndex = ocean.graphics_queue_family_index; + memory_barrier.buffer = ocean.grid.vertex->get_handle(); + memory_barrier.offset = 0; + memory_barrier.size = ocean.grid.vertex->get_size(); + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 1, &memory_barrier, 0, nullptr); + } VK_CHECK(vkEndCommandBuffer(compute.command_buffer)); } @@ -228,30 +270,29 @@ void SubgroupsOperations::prepare_uniform_buffers() void SubgroupsOperations::generate_grid() { - grid_size = static_cast(stoi(ui.grid_sizes[ui.grid_size_idx])); std::vector grid_vertices; std::vector grid_indices; - for (uint32_t z = 0; z <= grid_size; ++z) + for (uint32_t z = 0u; z <= grid_size; ++z) { - for (uint32_t x = 0; x <= grid_size; ++x) + for (uint32_t x = 0u; x <= grid_size; ++x) { Vertex point = {}; - point.pos.x = static_cast(x) / static_cast(grid_size); - point.pos.z = static_cast(z) / static_cast(grid_size); + point.pos.x = static_cast((static_cast(x) / static_cast(grid_size - 1) * 2 - 1) * (grid_size / 2.0f)); + point.pos.z = static_cast((static_cast(z) / static_cast(grid_size - 1) * 2 - 1) * (grid_size / 2.0f)); point.pos.y = 0.0f; grid_vertices.push_back(point); } } - for (uint32_t z = 0; z < grid_size; ++z) + for (uint32_t z = 0u; z < grid_size; ++z) { - for (uint32_t x = 0; x < grid_size; ++x) + for (uint32_t x = 0u; x < grid_size; ++x) { - uint32_t i0 = z * (grid_size + 1) + x; - uint32_t i1 = i0 + 1; - uint32_t i2 = i0 + (grid_size + 1); - uint32_t i3 = i2 + 1; + uint32_t i0 = z * (grid_size + 1u) + x; + uint32_t i1 = i0 + 1u; + uint32_t i2 = i0 + (grid_size + 1u); + uint32_t i3 = i2 + 1u; grid_indices.push_back(i0); grid_indices.push_back(i2); @@ -263,23 +304,13 @@ void SubgroupsOperations::generate_grid() } } - ocean.grid.index_count = vkb::to_u32(grid_indices.size()); auto vertex_buffer_size = vkb::to_u32(grid_vertices.size() * sizeof(Vertex)); auto index_buffer_size = vkb::to_u32(grid_indices.size() * sizeof(uint32_t)); - - if (input_grid.vertex) - { - input_grid.vertex.reset(nullptr); - } - if (ocean.grid.vertex && ocean.grid.index) - { - ocean.grid.vertex.reset(nullptr); - ocean.grid.index.reset(nullptr); - } + ocean.grid.index_count = vkb::to_u32(grid_indices.size()); input_grid.vertex = std::make_unique(get_device(), vertex_buffer_size, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); input_grid.vertex->update(grid_vertices.data(), vertex_buffer_size); @@ -291,20 +322,24 @@ void SubgroupsOperations::generate_grid() ocean.grid.vertex = std::make_unique(get_device(), vertex_buffer_size, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY); } +void SubgroupsOperations::create_semaphore() +{ + // Semaphore for graphics queue + VkSemaphoreCreateInfo semaphore_create_info = vkb::initializers::semaphore_create_info(); + VK_CHECK(vkCreateSemaphore(get_device().get_handle(), &semaphore_create_info, nullptr, &ocean.semaphore)); +} + void SubgroupsOperations::setup_descriptor_pool() { std::vector pool_sizes = { vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u), vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u)}; VkDescriptorPoolCreateInfo descriptor_pool_create_info = - vkb::initializers::descriptor_pool_create_info( - static_cast(pool_sizes.size()), - pool_sizes.data(), - 2u); + vkb::initializers::descriptor_pool_create_info(static_cast(pool_sizes.size()), pool_sizes.data(), 2u); VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool)); } @@ -376,31 +411,26 @@ void SubgroupsOperations::create_pipelines() shader_stages[0] = load_shader("subgroups_operations/ocean.vert", VK_SHADER_STAGE_VERTEX_BIT); shader_stages[1] = load_shader("subgroups_operations/ocean.frag", VK_SHADER_STAGE_FRAGMENT_BIT); const std::vector vertex_input_bindings = { - vkb::initializers::vertex_input_binding_description(0u, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX), - }; + vkb::initializers::vertex_input_binding_description(0u, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX)}; const std::vector vertex_input_attributes = { - vkb::initializers::vertex_input_attribute_description(0u, 0u, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), - }; + vkb::initializers::vertex_input_attribute_description(0u, 0u, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos))}; 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(); - VkGraphicsPipelineCreateInfo pipeline_create_info = - vkb::initializers::pipeline_create_info( - ocean.pipelines._default.pipeline_layout, - render_pass, - 0u); - pipeline_create_info.pVertexInputState = &vertex_input_state; - pipeline_create_info.pInputAssemblyState = &input_assembly_state; - pipeline_create_info.pRasterizationState = &rasterization_state; - pipeline_create_info.pColorBlendState = &color_blend_state; - pipeline_create_info.pMultisampleState = &multisample_state; - pipeline_create_info.pViewportState = &viewport_state; - pipeline_create_info.pDepthStencilState = &depth_stencil_state; - pipeline_create_info.pDynamicState = &dynamic_state; - pipeline_create_info.stageCount = static_cast(shader_stages.size()); - pipeline_create_info.pStages = shader_stages.data(); + + VkGraphicsPipelineCreateInfo pipeline_create_info = vkb::initializers::pipeline_create_info(ocean.pipelines._default.pipeline_layout, render_pass, 0u); + pipeline_create_info.pVertexInputState = &vertex_input_state; + pipeline_create_info.pInputAssemblyState = &input_assembly_state; + pipeline_create_info.pRasterizationState = &rasterization_state; + pipeline_create_info.pColorBlendState = &color_blend_state; + pipeline_create_info.pMultisampleState = &multisample_state; + pipeline_create_info.pViewportState = &viewport_state; + pipeline_create_info.pDepthStencilState = &depth_stencil_state; + pipeline_create_info.pDynamicState = &dynamic_state; + pipeline_create_info.stageCount = static_cast(shader_stages.size()); + pipeline_create_info.pStages = shader_stages.data(); VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1u, &pipeline_create_info, nullptr, &ocean.pipelines._default.pipeline)); if (get_device().get_gpu().get_features().fillModeNonSolid) @@ -422,7 +452,7 @@ void SubgroupsOperations::update_uniform_buffers() ComputeUbo comp_ubo; comp_ubo.grid_size = grid_size; - comp_ubo.time = 0.0f; + comp_ubo.time = float(timer.elapsed()); compute_ubo->convert_and_update(comp_ubo); } @@ -448,12 +478,25 @@ void SubgroupsOperations::build_command_buffers() VK_CHECK(vkBeginCommandBuffer(cmd_buff, &command_buffer_begin_info)); + if (compute.queue_family_index != ocean.graphics_queue_family_index) + { + VkBufferMemoryBarrier memory_barrier = vkb::initializers::buffer_memory_barrier(); + memory_barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + memory_barrier.srcQueueFamilyIndex = compute.queue_family_index; + memory_barrier.dstQueueFamilyIndex = ocean.graphics_queue_family_index; + memory_barrier.buffer = ocean.grid.vertex->get_handle(); + memory_barrier.offset = 0u; + memory_barrier.size = ocean.grid.vertex->get_size(); + + vkCmdPipelineBarrier(cmd_buff, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, &memory_barrier, 0, nullptr); + } + 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); + VkRect2D scissor = vkb::initializers::rect2D(static_cast(width), static_cast(height), 0, 0); vkCmdSetScissor(cmd_buff, 0u, 1u, &scissor); // draw ocean @@ -461,7 +504,7 @@ void SubgroupsOperations::build_command_buffers() vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, ocean.pipelines._default.pipeline_layout, 0u, 1u, &ocean.descriptor_set, 0u, nullptr); vkCmdBindPipeline(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, ui.wireframe ? ocean.pipelines.wireframe.pipeline : ocean.pipelines._default.pipeline); - VkDeviceSize offset[] = {0}; + VkDeviceSize offset[] = {0u}; vkCmdBindVertexBuffers(cmd_buff, 0u, 1u, ocean.grid.vertex->get(), offset); vkCmdBindIndexBuffer(cmd_buff, ocean.grid.index->get_handle(), VkDeviceSize(0), VK_INDEX_TYPE_UINT32); @@ -472,28 +515,52 @@ void SubgroupsOperations::build_command_buffers() vkCmdEndRenderPass(cmd_buff); + if (compute.queue_family_index != ocean.graphics_queue_family_index) + { + VkBufferMemoryBarrier memory_barrier = vkb::initializers::buffer_memory_barrier(); + memory_barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + memory_barrier.srcQueueFamilyIndex = ocean.graphics_queue_family_index; + memory_barrier.dstQueueFamilyIndex = compute.queue_family_index; + memory_barrier.buffer = ocean.grid.vertex->get_handle(); + memory_barrier.offset = 0u; + memory_barrier.size = ocean.grid.vertex->get_size(); + vkCmdPipelineBarrier(cmd_buff, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 1, &memory_barrier, 0, nullptr); + } + VK_CHECK(vkEndCommandBuffer(cmd_buff)); } } void SubgroupsOperations::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(); - - // Wait for rendering finished VkPipelineStageFlags wait_stage_mask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - // Submit compute commands - VkSubmitInfo compute_submit_info = vkb::initializers::submit_info(); - compute_submit_info.commandBufferCount = 1u; - compute_submit_info.pCommandBuffers = &compute.command_buffer; + VkSubmitInfo compute_submit_info = vkb::initializers::submit_info(); + compute_submit_info.commandBufferCount = 1u; + compute_submit_info.pCommandBuffers = &compute.command_buffer; + compute_submit_info.waitSemaphoreCount = 1u; + compute_submit_info.pWaitSemaphores = &ocean.semaphore; + compute_submit_info.pWaitDstStageMask = &wait_stage_mask; + compute_submit_info.signalSemaphoreCount = 1u; + compute_submit_info.pSignalSemaphores = &compute.semaphore; VK_CHECK(vkQueueSubmit(compute.queue, 1u, &compute_submit_info, VK_NULL_HANDLE)); + + VkPipelineStageFlags graphics_wait_stage_masks[] = {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + VkSemaphore graphics_wait_semaphores[] = {compute.semaphore, semaphores.acquired_image_ready}; + VkSemaphore graphics_signal_semaphores[] = {ocean.semaphore, semaphores.render_complete}; + + ApiVulkanSample::prepare_frame(); + submit_info.commandBufferCount = 1u; + submit_info.pCommandBuffers = &draw_cmd_buffers[current_buffer]; + submit_info.waitSemaphoreCount = 2u; + submit_info.pWaitSemaphores = graphics_wait_semaphores; + submit_info.pWaitDstStageMask = graphics_wait_stage_masks; + submit_info.signalSemaphoreCount = 2u; + submit_info.pSignalSemaphores = graphics_signal_semaphores; + + VK_CHECK(vkQueueSubmit(queue, 1u, &submit_info, VK_NULL_HANDLE)); + ApiVulkanSample::submit_frame(); } void SubgroupsOperations::on_update_ui_overlay(vkb::Drawer &drawer) @@ -507,14 +574,6 @@ void SubgroupsOperations::on_update_ui_overlay(vkb::Drawer &drawer) build_command_buffers(); } } - if (drawer.combo_box("Grid Size", &ui.grid_size_idx, ui.grid_sizes)) - { - // recreate grid mesh - generate_grid(); - update_uniform_buffers(); - build_compute_command_buffer(); - build_command_buffers(); - } } } @@ -534,11 +593,16 @@ void SubgroupsOperations::render(float delta_time) { return; } + if (!timer.is_running()) + timer.start(); + + update_uniform_buffers(); draw(); - if (camera.updated) - { - update_uniform_buffers(); - } + + auto elapsed_time = static_cast(timer.elapsed()); + + if (elapsed_time >= 10.0f) + timer.lap(); } std::unique_ptr create_subgroups_operations() diff --git a/samples/extensions/subgroups_operations/subgroups_operations.h b/samples/extensions/subgroups_operations/subgroups_operations.h index 2e786d339..36a07508c 100644 --- a/samples/extensions/subgroups_operations/subgroups_operations.h +++ b/samples/extensions/subgroups_operations/subgroups_operations.h @@ -50,11 +50,13 @@ class SubgroupsOperations : public ApiVulkanSample void generate_grid(); void prepare_uniform_buffers(); void setup_descriptor_pool(); + void create_semaphore(); void create_descriptor_set_layout(); void create_descriptor_set(); void create_pipelines(); void update_uniform_buffers(); + void update_compute_descriptor(); struct Pipeline { @@ -86,19 +88,11 @@ class SubgroupsOperations : public ApiVulkanSample struct GuiConfig { - GuiConfig() - { - grid_sizes = { - "16", "32", "64", "128", "256"}; - } - bool wireframe = {false}; - int32_t grid_size_idx = {0}; - - std::vector grid_sizes; + bool wireframe = {false}; } ui; GridBuffers input_grid; // input buffer for compute shader - uint32_t grid_size; + uint32_t grid_size = {32u}; std::unique_ptr camera_ubo; std::unique_ptr compute_ubo; @@ -120,10 +114,11 @@ class SubgroupsOperations : public ApiVulkanSample struct { - GridBuffers grid; // output (result) buffer for compute shader - + GridBuffers grid; // output (result) buffer for compute shader + uint32_t graphics_queue_family_index; VkDescriptorSetLayout descriptor_set_layout; VkDescriptorSet descriptor_set; + VkSemaphore semaphore; struct { Pipeline _default; @@ -132,6 +127,7 @@ class SubgroupsOperations : public ApiVulkanSample } ocean; VkPhysicalDeviceSubgroupProperties subgroups_properties; + vkb::Timer timer; }; std::unique_ptr create_subgroups_operations(); diff --git a/shaders/subgroups_operations/ocean_fft.comp b/shaders/subgroups_operations/ocean_fft.comp index 3344e423d..7c221c462 100644 --- a/shaders/subgroups_operations/ocean_fft.comp +++ b/shaders/subgroups_operations/ocean_fft.comp @@ -18,34 +18,44 @@ * limitations under the License. */ -layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +layout (local_size_x = 32, local_size_y = 32, local_size_z = 1) in; -struct Vertex { +#define PI 3.141592f + +struct Vertex +{ vec3 position; }; -layout (binding = 0) uniform Ubo +layout (set = 0, binding = 0) uniform Ubo { uint grid_size; float time; } ubo; -layout (std140, binding = 1) readonly buffer VertexInBuffer +layout (std140, set = 0, binding = 1) readonly buffer VertexInBuffer { Vertex verticesIn[]; }; -layout (std140, binding = 2) buffer VertexOutBuffer +layout (std140, set = 0, binding = 2) buffer VertexOutBuffer { Vertex verticesOut[]; }; void main() { - uint idx = gl_LocalInvocationIndex; // gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * ubo.grid_size; + float amplitude = 1.5f; + float wave_length = 25.0f; + float speed = 15.0f; + float k = 2.0f * PI / wave_length; + uint idx = gl_GlobalInvocationID.x * gl_SubgroupInvocationID + gl_GlobalInvocationID.y * gl_SubgroupInvocationID + gl_GlobalInvocationID.z * gl_SubgroupInvocationID; + + subgroupMemoryBarrierBuffer(); + Vertex inVertex = verticesIn[idx]; - // inVertex.position.y = sin(inVertex.position.x * inVertex.position.y); // * sin(uboTime.time); - //subgroupBarrier(); - verticesOut[idx].position = inVertex.position; - + + inVertex.position.y = amplitude * sin(k * (inVertex.position.x - (speed * ubo.time))) * cos(k * (inVertex.position.z - (speed * ubo.time))); + + verticesOut[idx] = inVertex; }