mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
bugfixes and pipeline barriers
This commit is contained in:
parent
dc11a64c0a
commit
f724229ae4
7 changed files with 146 additions and 51 deletions
|
|
@ -38,6 +38,8 @@ namespace Vulkan::Core {
|
|||
[[nodiscard]] VkExtent2D getExtent() const { return this->extent; }
|
||||
/// Get the format of the image.
|
||||
[[nodiscard]] VkFormat getFormat() const { return this->format; }
|
||||
/// Get the aspect flags of the image.
|
||||
[[nodiscard]] VkImageAspectFlags getAspectFlags() const { return this->aspectFlags; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
Image(const Image&) noexcept = default;
|
||||
|
|
@ -52,6 +54,7 @@ namespace Vulkan::Core {
|
|||
|
||||
VkExtent2D extent;
|
||||
VkFormat format;
|
||||
VkImageAspectFlags aspectFlags;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
40
include/utils/memorybarriers.hpp
Normal file
40
include/utils/memorybarriers.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef BARRIERS_HPP
|
||||
#define BARRIERS_HPP
|
||||
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/image.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace Barriers {
|
||||
|
||||
///
|
||||
/// Insert memory barriers for images in a command buffer.
|
||||
///
|
||||
/// @param buffer Command buffer to insert barriers into
|
||||
/// @param r2wImages Images that are being read and will be written to
|
||||
/// @param w2rImages Images that are being written to and will be read from
|
||||
/// @param srcLayout Optional source layout for the images, defaults to VK_IMAGE_LAYOUT_GENERAL
|
||||
///
|
||||
/// @throws std::logic_error if the command buffer is not in Recording state
|
||||
///
|
||||
void insertBarrier(
|
||||
const Vulkan::Core::CommandBuffer& buffer,
|
||||
const std::vector<Vulkan::Core::Image>& r2wImages,
|
||||
const std::vector<Vulkan::Core::Image>& w2rImages,
|
||||
std::optional<VkImageLayout> srcLayout = std::nullopt);
|
||||
|
||||
///
|
||||
/// Insert a global memory barrier in a command buffer.
|
||||
///
|
||||
/// @param buffer Command buffer to insert the barrier into
|
||||
///
|
||||
/// @throws std::logic_error if the command buffer is not in Recording state
|
||||
///
|
||||
void insertGlobalBarrier(const Vulkan::Core::CommandBuffer& buffer);
|
||||
|
||||
};
|
||||
|
||||
#endif // BARRIERS_HPP
|
||||
|
|
@ -15,6 +15,7 @@ DescriptorPool::DescriptorPool(const Device& device) {
|
|||
}};
|
||||
const VkDescriptorPoolCreateInfo desc{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
|
||||
.maxSets = 16384,
|
||||
.poolSizeCount = static_cast<uint32_t>(pools.size()),
|
||||
.pPoolSizes = pools.data()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ using namespace Vulkan::Core;
|
|||
|
||||
Image::Image(const Device& device, VkExtent2D extent, VkFormat format,
|
||||
VkImageUsageFlags usage, VkImageAspectFlags aspectFlags)
|
||||
: extent(extent), format(format) {
|
||||
: extent(extent), format(format), aspectFlags(aspectFlags) {
|
||||
// create image
|
||||
const VkImageCreateInfo desc{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
using namespace Vulkan;
|
||||
|
||||
|
|
@ -49,10 +50,15 @@ Device::Device(const Instance& instance) {
|
|||
|
||||
// create logical device
|
||||
const float queuePriority{1.0F}; // highest priority
|
||||
const VkPhysicalDeviceVulkan12Features features{
|
||||
VkPhysicalDeviceVulkan13Features features13{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
|
||||
.synchronization2 = VK_TRUE
|
||||
};
|
||||
const VkPhysicalDeviceVulkan12Features features12{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
.pNext = &features13,
|
||||
.timelineSemaphore = VK_TRUE,
|
||||
.vulkanMemoryModel = VK_TRUE,
|
||||
.vulkanMemoryModel = VK_TRUE
|
||||
};
|
||||
const VkDeviceQueueCreateInfo computeQueueDesc{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||
|
|
@ -62,7 +68,7 @@ Device::Device(const Instance& instance) {
|
|||
};
|
||||
const VkDeviceCreateInfo deviceCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = &features,
|
||||
.pNext = &features12,
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &computeQueueDesc
|
||||
};
|
||||
|
|
|
|||
68
src/main.cpp
68
src/main.cpp
|
|
@ -10,6 +10,7 @@
|
|||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "instance.hpp"
|
||||
#include "utils/memorybarriers.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
|
@ -40,27 +41,22 @@ const static DataBuffer data{
|
|||
};
|
||||
|
||||
int main() {
|
||||
// initialize Vulkan
|
||||
// initialize application
|
||||
const Instance instance;
|
||||
const Device device(instance);
|
||||
const Core::DescriptorPool descriptorPool(device);
|
||||
const Core::CommandPool commandPool(device);
|
||||
|
||||
// load shader
|
||||
const Core::ShaderModule computeShader(device, "shaders/downsample.spv",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER},
|
||||
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE},
|
||||
{ 7, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE},
|
||||
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER} });
|
||||
|
||||
// prepare render pass
|
||||
const Core::CommandPool commandPool(device);
|
||||
const Core::DescriptorPool descriptorPool(device);
|
||||
const Core::Pipeline computePipeline(device, computeShader);
|
||||
const Core::DescriptorSet descriptorSet(device, descriptorPool, computeShader);
|
||||
|
||||
// create shader inputs
|
||||
const Core::Sampler sampler(device, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
|
||||
|
||||
const std::vector<Core::Image> images(1, Core::Image(
|
||||
const std::vector<Core::Image> inputImages(1, Core::Image(
|
||||
device, { 2560, 1411 }, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT
|
||||
|
|
@ -72,51 +68,22 @@ int main() {
|
|||
const Core::Buffer buffer(device, dataVec.size(), dataVec,
|
||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
|
||||
// create shader outputs
|
||||
const std::vector<Core::Image> outputImages = {
|
||||
Core::Image(
|
||||
device, { 1280, 705 }, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
std::vector<Core::Image> outputImages;
|
||||
outputImages.reserve(7);
|
||||
for (size_t i = 0; i < 7; ++i)
|
||||
outputImages.emplace_back(device,
|
||||
VkExtent2D { .width = 2560U >> i, .height = 1411U >> i },
|
||||
VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT
|
||||
),
|
||||
Core::Image(
|
||||
device, { 640, 352 }, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT
|
||||
),
|
||||
Core::Image(
|
||||
device, { 320, 176 }, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT
|
||||
),
|
||||
Core::Image(
|
||||
device, { 160, 88 }, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT
|
||||
),
|
||||
Core::Image(
|
||||
device, { 80, 44 }, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT
|
||||
),
|
||||
Core::Image(
|
||||
device, { 40, 22 }, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT
|
||||
),
|
||||
Core::Image(
|
||||
device, { 20, 11 }, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT
|
||||
)
|
||||
};
|
||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
|
||||
// load descriptor set
|
||||
const Core::DescriptorSet descriptorSet(device, descriptorPool, computeShader);
|
||||
descriptorSet.update(
|
||||
device,
|
||||
{
|
||||
{{ VK_DESCRIPTOR_TYPE_SAMPLER, sampler }},
|
||||
{{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, images[0] }},
|
||||
{{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, inputImages[0] }},
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[0] },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[1] },
|
||||
|
|
@ -137,6 +104,13 @@ int main() {
|
|||
commandBuffer.begin();
|
||||
|
||||
// render
|
||||
Barriers::insertBarrier(
|
||||
commandBuffer,
|
||||
inputImages,
|
||||
outputImages,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED
|
||||
);
|
||||
|
||||
computePipeline.bind(commandBuffer);
|
||||
descriptorSet.bind(commandBuffer, computePipeline);
|
||||
commandBuffer.dispatch(40, 23, 1);
|
||||
|
|
|
|||
71
src/utils/memorybarriers.cpp
Normal file
71
src/utils/memorybarriers.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#include "utils/memorybarriers.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
using namespace Barriers;
|
||||
|
||||
void Barriers::insertBarrier(
|
||||
const Vulkan::Core::CommandBuffer& buffer,
|
||||
const std::vector<Vulkan::Core::Image>& r2wImages,
|
||||
const std::vector<Vulkan::Core::Image>& w2rImages,
|
||||
std::optional<VkImageLayout> srcLayout) {
|
||||
std::vector<VkImageMemoryBarrier2> barriers(r2wImages.size() + w2rImages.size());
|
||||
|
||||
size_t index = 0;
|
||||
for (const auto& image : r2wImages) {
|
||||
barriers[index++] = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||
.oldLayout = srcLayout.value_or(VK_IMAGE_LAYOUT_GENERAL),
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.image = image.handle(),
|
||||
.subresourceRange = {
|
||||
.aspectMask = image.getAspectFlags(),
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
};
|
||||
}
|
||||
for (const auto& image : w2rImages) {
|
||||
barriers[index++] = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
|
||||
.oldLayout = srcLayout.value_or(VK_IMAGE_LAYOUT_GENERAL),
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.image = image.handle(),
|
||||
.subresourceRange = {
|
||||
.aspectMask = image.getAspectFlags(),
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
};
|
||||
}
|
||||
const VkDependencyInfo dependencyInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||
.imageMemoryBarrierCount = static_cast<uint32_t>(barriers.size()),
|
||||
.pImageMemoryBarriers = barriers.data()
|
||||
};
|
||||
vkCmdPipelineBarrier2(buffer.handle(), &dependencyInfo);
|
||||
}
|
||||
|
||||
void Barriers::insertGlobalBarrier(const Vulkan::Core::CommandBuffer& buffer) {
|
||||
const VkMemoryBarrier2 barrier = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT
|
||||
};
|
||||
const VkDependencyInfo dependencyInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||
.memoryBarrierCount = 1,
|
||||
.pMemoryBarriers = &barrier
|
||||
};
|
||||
vkCmdPipelineBarrier2(buffer.handle(), &dependencyInfo);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue