diff --git a/samples/extensions/subgroups_operations/README.adoc b/samples/extensions/subgroups_operations/README.adoc index 0c5fabba5..28ee3fff0 100644 --- a/samples/extensions/subgroups_operations/README.adoc +++ b/samples/extensions/subgroups_operations/README.adoc @@ -1,38 +1,25 @@ - + # Subgroups Operations - ## Overview This sample demonstrates how to use and enable the Subgroups operations feature. - +image:image/image.png[] ## GLSL Shaders + In shader enable `GL_KHR_shader_subgroup_basic` extension. TODO: add more description - ## Enabling the Feature To enable the subgroups feature in the Vulkan API you must create a Vulkan instance with a minimum version of version 1.1. Enable the extension `VK_EXT_subgroup_size_control` and get the subgroup properties of a physical device + ```C++ VkPhysicalDeviceSubgroupProperties subgroups_properties; subgroups_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; @@ -43,6 +30,7 @@ device_properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVI device_properties2.pNext = &subgroups_properties; vkGetPhysicalDeviceProperties2(gpu.get_handle(), &device_properties2); ``` + TODO: add more description ## Additional information diff --git a/samples/extensions/subgroups_operations/image/image.png b/samples/extensions/subgroups_operations/image/image.png new file mode 100644 index 000000000..0c649ff13 Binary files /dev/null and b/samples/extensions/subgroups_operations/image/image.png differ diff --git a/samples/extensions/subgroups_operations/subgroups_operations.cpp b/samples/extensions/subgroups_operations/subgroups_operations.cpp index 891f3ae3e..c308fb63a 100644 --- a/samples/extensions/subgroups_operations/subgroups_operations.cpp +++ b/samples/extensions/subgroups_operations/subgroups_operations.cpp @@ -194,6 +194,20 @@ void SubgroupsOperations::build_compute_command_buffer() VkCommandBufferBeginInfo begin_info = vkb::initializers::command_buffer_begin_info(); VK_CHECK(vkBeginCommandBuffer(compute.command_buffer, &begin_info)); + if (ocean.graphics_queue_family_index != compute.queue_family_index) + { + VkBufferMemoryBarrier memory_barrier = vkb::initializers::buffer_memory_barrier(); + memory_barrier.buffer = bit_reverse_buffer->get_handle(); + memory_barrier.offset = 0u; + memory_barrier.size = bit_reverse_buffer->get_size(); + memory_barrier.srcAccessMask = 0u; + memory_barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + memory_barrier.srcQueueFamilyIndex = ocean.graphics_queue_family_index; + memory_barrier.dstQueueFamilyIndex = compute.queue_family_index; + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 1u, &memory_barrier, 0u, nullptr); + } + // butterfly texture { vkCmdBindPipeline(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, precompute.pipeline.pipeline); @@ -201,7 +215,19 @@ void SubgroupsOperations::build_compute_command_buffer() vkCmdDispatch(compute.command_buffer, 1u, grid_size, 1u); } - + { + VkImageMemoryBarrier img_barrier = vkb::initializers::image_memory_barrier(); + img_barrier.image = butterfly_precomp.image; + img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + img_barrier.subresourceRange.baseMipLevel = 0u; + img_barrier.subresourceRange.levelCount = 1u; + img_barrier.subresourceRange.baseArrayLayer = 0u; + img_barrier.subresourceRange.layerCount = 1u; + img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &img_barrier); + } // initial tildes textures { vkCmdBindPipeline(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, initial_tildes.pipeline.pipeline); @@ -210,6 +236,17 @@ void SubgroupsOperations::build_compute_command_buffer() vkCmdDispatch(compute.command_buffer, grid_size / 32u, grid_size, 1u); } + { + VkBufferMemoryBarrier memory_barrier = vkb::initializers::buffer_memory_barrier(); + memory_barrier.buffer = fft_buffers.fft_input_random->get_handle(); + memory_barrier.offset = 0u; + memory_barrier.size = fft_buffers.fft_input_random->get_size(); + memory_barrier.srcAccessMask = 0u; + memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 1u, &memory_barrier, 0u, nullptr); + } + // tildes textures { vkCmdBindPipeline(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, tildes.pipeline.pipeline); @@ -218,6 +255,20 @@ void SubgroupsOperations::build_compute_command_buffer() vkCmdDispatch(compute.command_buffer, grid_size / 8u, grid_size, 1u); } + { + VkImageMemoryBarrier img_barrier = vkb::initializers::image_memory_barrier(); + img_barrier.image = fft_buffers.fft_input_htilde0->image; + img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + img_barrier.subresourceRange.baseMipLevel = 0u; + img_barrier.subresourceRange.levelCount = 1u; + img_barrier.subresourceRange.baseArrayLayer = 0u; + img_barrier.subresourceRange.layerCount = 1u; + img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &img_barrier); + } + // fft horizontal; for Y axis { vkCmdBindPipeline(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, fft.pipelines.horizontal.pipeline); @@ -290,19 +341,63 @@ void SubgroupsOperations::build_compute_command_buffer() } } + { + VkImageMemoryBarrier img_barrier = vkb::initializers::image_memory_barrier(); + img_barrier.image = fft_buffers.fft_tilde_h_kt_dy->image; + img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + img_barrier.subresourceRange.baseMipLevel = 0u; + img_barrier.subresourceRange.levelCount = 1u; + img_barrier.subresourceRange.baseArrayLayer = 0u; + img_barrier.subresourceRange.layerCount = 1u; + img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &img_barrier); + } + // fft inverse { vkCmdBindPipeline(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, fft_inversion.pipeline.pipeline); vkCmdBindDescriptorSets(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, fft_inversion.pipeline.pipeline_layout, 0u, 1u, &fft_inversion.descriptor_set, 0u, nullptr); vkCmdDispatch(compute.command_buffer, grid_size / 32u, grid_size, 1u); } - + { + VkImageMemoryBarrier img_barrier = vkb::initializers::image_memory_barrier(); + img_barrier.image = fft_buffers.fft_displacement->image; + img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + img_barrier.subresourceRange.baseMipLevel = 0u; + img_barrier.subresourceRange.levelCount = 1u; + img_barrier.subresourceRange.baseArrayLayer = 0u; + img_barrier.subresourceRange.layerCount = 1u; + img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &img_barrier); + } // fft normal map { vkCmdBindPipeline(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, fft_normal_map.pipeline.pipeline); vkCmdBindDescriptorSets(compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, fft_normal_map.pipeline.pipeline_layout, 0u, 1u, &fft_normal_map.descriptor_set, 0u, nullptr); vkCmdDispatch(compute.command_buffer, grid_size / 32u, grid_size, 1u); } + if (ocean.graphics_queue_family_index != compute.queue_family_index) + { + VkImageMemoryBarrier img_barrier = vkb::initializers::image_memory_barrier(); + img_barrier.image = fft_buffers.fft_displacement->image; + img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + img_barrier.subresourceRange.baseMipLevel = 0u; + img_barrier.subresourceRange.levelCount = 1u; + img_barrier.subresourceRange.baseArrayLayer = 0u; + img_barrier.subresourceRange.layerCount = 1u; + img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + img_barrier.srcQueueFamilyIndex = compute.queue_family_index; + img_barrier.dstQueueFamilyIndex = ocean.graphics_queue_family_index; + img_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + img_barrier.dstAccessMask = 0u; + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &img_barrier); + } VK_CHECK(vkEndCommandBuffer(compute.command_buffer)); } @@ -880,6 +975,25 @@ void SubgroupsOperations::build_command_buffers() VK_CHECK(vkBeginCommandBuffer(cmd_buff, &command_buffer_begin_info)); + if (ocean.graphics_queue_family_index != compute.queue_family_index) + { + VkImageMemoryBarrier img_barrier = vkb::initializers::image_memory_barrier(); + img_barrier.image = fft_buffers.fft_normal_map->image; + img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + img_barrier.subresourceRange.baseMipLevel = 0u; + img_barrier.subresourceRange.levelCount = 1u; + img_barrier.subresourceRange.baseArrayLayer = 0u; + img_barrier.subresourceRange.layerCount = 1u; + img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + img_barrier.srcQueueFamilyIndex = compute.queue_family_index; + img_barrier.dstQueueFamilyIndex = ocean.graphics_queue_family_index; + img_barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + img_barrier.srcAccessMask = 0u; + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &img_barrier); + } + 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); @@ -911,6 +1025,25 @@ void SubgroupsOperations::build_command_buffers() vkCmdEndRenderPass(cmd_buff); + if (ocean.graphics_queue_family_index != compute.queue_family_index) + { + VkImageMemoryBarrier img_barrier = vkb::initializers::image_memory_barrier(); + img_barrier.image = fft_buffers.fft_normal_map->image; + img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + img_barrier.subresourceRange.baseMipLevel = 0u; + img_barrier.subresourceRange.levelCount = 1u; + img_barrier.subresourceRange.baseArrayLayer = 0u; + img_barrier.subresourceRange.layerCount = 1u; + img_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + img_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + img_barrier.srcQueueFamilyIndex = ocean.graphics_queue_family_index; + img_barrier.dstQueueFamilyIndex = compute.queue_family_index; + img_barrier.dstAccessMask = 0u; + img_barrier.srcAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + + vkCmdPipelineBarrier(compute.command_buffer, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &img_barrier); + } + VK_CHECK(vkEndCommandBuffer(cmd_buff)); } } diff --git a/shaders/subgroups_operations/ocean.frag b/shaders/subgroups_operations/ocean.frag index ed92b8a1b..68703892f 100644 --- a/shaders/subgroups_operations/ocean.frag +++ b/shaders/subgroups_operations/ocean.frag @@ -177,74 +177,83 @@ ReflectedLight direct_physical(IncidentLight il, Geometry gem, Material mat) void main() { - vec3 total_emissive = vec3(0.3f, 0.3f, 0.3f); - ReflectedLight ref_light = ReflectedLight(vec3(1.0f), vec3(1.0f), vec3(1.0f), vec3(1.0f)); - float metalness = 0.91f; - float roughness = 0.91f; - float ior = 0.5f; - vec3 specular_color = vec3(1.0f); - float specular_intensity = 1.0f; - - vec4 diffuse_color = vec4(ocean_ubo.ocean_color.rgb, 0.5f); + // vec3 total_emissive = vec3(0.3f, 0.3f, 0.3f); + // ReflectedLight ref_light = ReflectedLight(vec3(1.0f), vec3(1.0f), vec3(1.0f), vec3(1.0f)); + // float metalness = 0.91f; + // float roughness = 0.91f; + // float ior = 0.5f; + // vec3 specular_color = vec3(1.0f); + // float specular_intensity = 1.0f; + // + // vec4 diffuse_color = vec4(ocean_ubo.ocean_color.rgb, 0.5f); + // vec3 normal = normalize(texture(fft_normal_map, in_uv).rgb); + // + // Material mat; + // mat.diffuse_color = diffuse_color.rgb * (1.0f - metalness); + // vec3 dxy = max(abs(dFdx(normal)), abs(dFdy(normal))); + // float gem_roughness = max(max(dxy.x, dxy.y), dxy.z); + // + // mat.roughness = max(roughness, 0.0525f); + // mat.roughness += gem_roughness; + // mat.roughness = min(mat.roughness, 1.0f); + // mat.ior = ior; + // mat.specular_f90 = mix(specular_intensity, 1.0f, metalness); + // mat.specular_color = mix(min(pow2((mat.ior - 1.0f) / (mat.ior + 1.0f)) * specular_color, vec3(1.0f)) * specular_intensity, diffuse_color.rgb, metalness); + // + // Geometry geom; + // geom.normal = normal; + // geom.position = -in_pos; + // geom.view_dir = normalize(cam.position.xyz); + // + // PointLight point_light; + // point_light.position = ocean_ubo.light_position; + // point_light.color = ocean_ubo.light_color; + // point_light.dist = length(ocean_ubo.light_position - in_pos); + // point_light.decay = 2.0f; + // + // IncidentLight dir_light = get_point_light_info(point_light, geom); + // + // ref_light = direct_physical(dir_light, geom, mat); + // + // vec3 irradiance = ocean_ubo.ocean_color; + // vec3 ibl_irradiance = vec3(1.0f);// envinroment color value - TODO + // + // vec3 radiance = vec3(1.0f); + // // radiance += get_ibl_radiance(geom.view_dir, geom.normal, mat.roughness); // envinroment color value - TODO + // + // ref_light.indirect_diffuse += irradiance * brdf_lambert(mat.diffuse_color); + // + // vec3 single_scattering = vec3(0.0f); + // vec3 multi_scattering = vec3(0.0f); + // vec3 cos_weighted_irradiance = irradiance * LAMBERT_VAL; + // + // vec2 fab = dfg_approx(geom.normal, geom.view_dir, roughness); + // vec3 FssEss = mat.specular_color + fab.x + mat.specular_f90 * fab.y; + // float Ess = fab.x + fab.y; + // float Ems = 1.0f - Ess; + // vec3 f_avg = mat.specular_color * (1.0f - mat.specular_color) * 0.0476f; + // vec3 f_ms = FssEss * f_avg / (1.0f - Ems * f_avg); + // single_scattering += FssEss; + // multi_scattering += f_ms * Ems; + // + // vec3 total_scattering = single_scattering + multi_scattering; + // vec3 scattering_diffiuse = mat.diffuse_color * (1.0f - max(max(total_scattering.r, total_scattering.g), total_scattering.b)); + // ref_light.indirect_specular += radiance * single_scattering; + // ref_light.indirect_specular += multi_scattering * cos_weighted_irradiance; + // ref_light.indirect_diffuse += scattering_diffiuse * cos_weighted_irradiance; + // + // + // vec3 total_diffuse = ref_light.dir_diffuse + ref_light.indirect_diffuse; + // vec3 total_specular = ref_light.dir_specular + ref_light.indirect_specular; + + // outFragColor = vec4(total_diffuse + total_specular + total_emissive, diffuse_color.a); + + // TODO: implement BRDF reflections; code below is temporary solution vec3 normal = normalize(texture(fft_normal_map, in_uv).rgb); + vec3 ambient = ocean_ubo.light_color * ocean_ubo.ocean_color; + vec3 light_dir = normalize(ocean_ubo.light_position - in_pos); + float diff = max(dot(normal, light_dir), 0.0f); + vec3 diffuse = ambient * diff; - Material mat; - mat.diffuse_color = diffuse_color.rgb * (1.0f - metalness); - vec3 dxy = max(abs(dFdx(normal)), abs(dFdy(normal))); - float gem_roughness = max(max(dxy.x, dxy.y), dxy.z); - - mat.roughness = max(roughness, 0.0525f); - mat.roughness += gem_roughness; - mat.roughness = min(mat.roughness, 1.0f); - mat.ior = ior; - mat.specular_f90 = mix(specular_intensity, 1.0f, metalness); - mat.specular_color = mix(min(pow2((mat.ior - 1.0f) / (mat.ior + 1.0f)) * specular_color, vec3(1.0f)) * specular_intensity, diffuse_color.rgb, metalness); - - Geometry geom; - geom.normal = normal; - geom.position = -in_pos; - geom.view_dir = normalize(cam.position.xyz); - - PointLight point_light; - point_light.position = ocean_ubo.light_position; - point_light.color = ocean_ubo.light_color; - point_light.dist = length(ocean_ubo.light_position - in_pos); - point_light.decay = 2.0f; - - IncidentLight dir_light = get_point_light_info(point_light, geom); - - ref_light = direct_physical(dir_light, geom, mat); - - vec3 irradiance = ocean_ubo.ocean_color; - vec3 ibl_irradiance = vec3(1.0f);// envinroment color value - TODO - - vec3 radiance = vec3(1.0f); - // radiance += get_ibl_radiance(geom.view_dir, geom.normal, mat.roughness); // envinroment color value - TODO - - ref_light.indirect_diffuse += irradiance * brdf_lambert(mat.diffuse_color); - - vec3 single_scattering = vec3(0.0f); - vec3 multi_scattering = vec3(0.0f); - vec3 cos_weighted_irradiance = irradiance * LAMBERT_VAL; - - vec2 fab = dfg_approx(geom.normal, geom.view_dir, roughness); - vec3 FssEss = mat.specular_color + fab.x + mat.specular_f90 * fab.y; - float Ess = fab.x + fab.y; - float Ems = 1.0f - Ess; - vec3 f_avg = mat.specular_color * (1.0f - mat.specular_color) * 0.0476f; - vec3 f_ms = FssEss * f_avg / (1.0f - Ems * f_avg); - single_scattering += FssEss; - multi_scattering += f_ms * Ems; - - vec3 total_scattering = single_scattering + multi_scattering; - vec3 scattering_diffiuse = mat.diffuse_color * (1.0f - max(max(total_scattering.r, total_scattering.g), total_scattering.b)); - ref_light.indirect_specular += radiance * single_scattering; - ref_light.indirect_specular += multi_scattering * cos_weighted_irradiance; - ref_light.indirect_diffuse += scattering_diffiuse * cos_weighted_irradiance; - - - vec3 total_diffuse = ref_light.dir_diffuse + ref_light.indirect_diffuse; - vec3 total_specular = ref_light.dir_specular + ref_light.indirect_specular; - - outFragColor = vec4(total_diffuse + total_specular + total_emissive, diffuse_color.a); + outFragColor = vec4(diffuse, 1.0f); }