mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-01-20 05:32:13 +00:00
refactor(cleanup): shader/descriptor set helper
This commit is contained in:
parent
aef82b01c7
commit
28ee6dbce0
5 changed files with 262 additions and 1 deletions
|
|
@ -1,6 +1,7 @@
|
|||
set(BACKEND_SOURCES
|
||||
"src/extraction/dll_reader.cpp"
|
||||
"src/extraction/shader_registry.cpp")
|
||||
"src/extraction/shader_registry.cpp"
|
||||
"src/helpers/managed_shader.cpp")
|
||||
|
||||
add_library(lsfg-vk-backend STATIC ${BACKEND_SOURCES})
|
||||
|
||||
|
|
|
|||
120
lsfg-vk-backend/src/helpers/managed_shader.cpp
Normal file
120
lsfg-vk-backend/src/helpers/managed_shader.cpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
#include "managed_shader.hpp"
|
||||
#include "lsfg-vk-common/vulkan/buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/sampler.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shader.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
using namespace ls;
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::sampled(const vk::Image& image) {
|
||||
this->sampledImages.push_back(std::ref(image));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::sampleds(
|
||||
const std::vector<vk::Image>& images,
|
||||
size_t offset, size_t count) {
|
||||
if (count == 0 || offset + count > images.size())
|
||||
count = images.size() - offset;
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
this->sampledImages.push_back(std::ref(images[offset + i]));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::storage(const vk::Image& image) {
|
||||
this->storageImages.push_back(std::ref(image));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::storages(
|
||||
const std::vector<vk::Image>& images,
|
||||
size_t offset, size_t count) {
|
||||
if (count == 0 || offset + count > images.size())
|
||||
count = images.size() - offset;
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
this->storageImages.push_back(std::ref(images[offset + i]));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::sampler(const vk::Sampler& sampler) {
|
||||
this->imageSamplers.push_back(std::ref(sampler));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::samplers(
|
||||
const std::vector<vk::Sampler>& samplers) {
|
||||
for (const auto& sampler : samplers)
|
||||
this->imageSamplers.push_back(std::ref(sampler));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::buffer(const vk::Buffer& buffer) {
|
||||
this->constantBuffers.push_back(std::ref(buffer));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShader ManagedShaderBuilder::build(const vk::Vulkan& vk,
|
||||
const vk::Shader& shader) const {
|
||||
std::vector<vk::Barrier> barriers;
|
||||
barriers.reserve(this->storageImages.size() + this->sampledImages.size());
|
||||
|
||||
for (const auto& img : this->sampledImages)
|
||||
barriers.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.image = img.get().handle(),
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
});
|
||||
for (const auto& img : this->storageImages)
|
||||
barriers.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.image = img.get().handle(),
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
std::ref(shader),
|
||||
std::move(barriers),
|
||||
vk::DescriptorSet(vk, shader,
|
||||
this->sampledImages,
|
||||
this->storageImages,
|
||||
this->imageSamplers,
|
||||
this->constantBuffers)
|
||||
};
|
||||
}
|
||||
|
||||
void ManagedShader::dispatch(const vk::CommandBuffer& cmd,
|
||||
VkExtent2D extent) const {
|
||||
cmd.dispatch(this->shader,
|
||||
this->descriptorSet,
|
||||
this->barriers,
|
||||
extent.width, extent.height, 1
|
||||
);
|
||||
}
|
||||
91
lsfg-vk-backend/src/helpers/managed_shader.hpp
Normal file
91
lsfg-vk-backend/src/helpers/managed_shader.hpp
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#pragma once
|
||||
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/descriptor_set.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shader.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace ls {
|
||||
|
||||
/// managed shader handling dispatch and barriers
|
||||
/// this class is NOT memory-safe
|
||||
class ManagedShader {
|
||||
friend class ManagedShaderBuilder;
|
||||
public:
|
||||
/// dispatch the managed shader
|
||||
/// @param cmd command buffer to use
|
||||
/// @param extent dispatch size
|
||||
/// @throws ls::vulkan_error on failure
|
||||
void dispatch(const vk::CommandBuffer& cmd, VkExtent2D extent) const;
|
||||
private:
|
||||
ls::R<const vk::Shader> shader;
|
||||
|
||||
std::vector<vk::Barrier> barriers;
|
||||
vk::DescriptorSet descriptorSet;
|
||||
|
||||
// simple move constructor
|
||||
ManagedShader(ls::R<const vk::Shader> shader,
|
||||
std::vector<vk::Barrier> barriers,
|
||||
vk::DescriptorSet descriptorSet) :
|
||||
shader(shader),
|
||||
barriers(std::move(barriers)),
|
||||
descriptorSet(std::move(descriptorSet)) {
|
||||
}
|
||||
};
|
||||
|
||||
/// class for building managed shaders
|
||||
/// this class is NOT memory-safe
|
||||
class ManagedShaderBuilder {
|
||||
public:
|
||||
/// default constructor
|
||||
ManagedShaderBuilder() = default;
|
||||
|
||||
/// add a sampled image
|
||||
/// @param image image to add
|
||||
[[nodiscard]] ManagedShaderBuilder& sampled(const vk::Image& image);
|
||||
/// add multiple sampled images
|
||||
/// @param images images to add
|
||||
/// @param offset offset into images
|
||||
/// @param count number of images to add (0 = all)
|
||||
[[nodiscard]] ManagedShaderBuilder& sampleds(const std::vector<vk::Image>& images,
|
||||
size_t offset = 0, size_t count = 0);
|
||||
|
||||
/// add a storage image
|
||||
/// @param image image to add
|
||||
[[nodiscard]] ManagedShaderBuilder& storage(const vk::Image& image);
|
||||
/// add multiple storage images
|
||||
/// @param images images to add
|
||||
/// @param offset offset into images
|
||||
/// @param count number of images to add (0 = all)
|
||||
[[nodiscard]] ManagedShaderBuilder& storages(const std::vector<vk::Image>& images,
|
||||
size_t offset = 0, size_t count = 0);
|
||||
|
||||
/// add a sampler
|
||||
/// @param sampler sampler to add
|
||||
[[nodiscard]] ManagedShaderBuilder& sampler(const vk::Sampler& sampler);
|
||||
/// add multiple samplers
|
||||
/// @param samplers samplers to add
|
||||
[[nodiscard]] ManagedShaderBuilder& samplers(const std::vector<vk::Sampler>& samplers);
|
||||
|
||||
/// add a buffer
|
||||
/// @param buffer buffer to add
|
||||
[[nodiscard]] ManagedShaderBuilder& buffer(const vk::Buffer& buffer);
|
||||
|
||||
/// build the managed shader
|
||||
/// @param vk the vulkan instance
|
||||
/// @param shader the shader to use
|
||||
/// @returns the built managed shader
|
||||
[[nodiscard]] ManagedShader build(const vk::Vulkan& vk, const vk::Shader& shader) const;
|
||||
private:
|
||||
std::vector<ls::R<const vk::Image>> sampledImages;
|
||||
std::vector<ls::R<const vk::Image>> storageImages;
|
||||
std::vector<ls::R<const vk::Sampler>> imageSamplers;
|
||||
std::vector<ls::R<const vk::Buffer>> constantBuffers;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "../helpers/pointers.hpp"
|
||||
#include "descriptor_set.hpp"
|
||||
#include "shader.hpp"
|
||||
#include "vulkan.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace vk {
|
||||
|
||||
using Barrier = VkImageMemoryBarrier;
|
||||
|
||||
/// vulkan command buffer
|
||||
class CommandBuffer {
|
||||
public:
|
||||
|
|
@ -14,6 +22,17 @@ namespace vk {
|
|||
/// @throws ls::vulkan_error on failure
|
||||
CommandBuffer(const vk::Vulkan& vk);
|
||||
|
||||
/// dispatch a compute shader
|
||||
/// @param shader the compute shader
|
||||
/// @param set the descriptor set
|
||||
/// @param barriers image memory barriers to apply
|
||||
/// @param x dispatch size in X
|
||||
/// @param y dispatch size in Y
|
||||
/// @param z dispatch size in Z
|
||||
void dispatch(const vk::Shader& shader, const vk::DescriptorSet& set,
|
||||
const std::vector<vk::Barrier>& barriers,
|
||||
uint32_t x, uint32_t y, uint32_t z) const;
|
||||
|
||||
/// submit the command buffer
|
||||
/// @throws ls::vulkan_error on failure
|
||||
void submit(); // FIXME: method needs to actually submit, depending on needs
|
||||
|
|
|
|||
|
|
@ -1,8 +1,13 @@
|
|||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/helpers/errors.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/descriptor_set.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shader.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
using namespace vk;
|
||||
|
|
@ -43,6 +48,31 @@ CommandBuffer::CommandBuffer(const vk::Vulkan& vk)
|
|||
throw ls::vulkan_error(res, "vkBeginCommandBuffer() failed");
|
||||
}
|
||||
|
||||
void CommandBuffer::dispatch(const vk::Shader& shader,
|
||||
const vk::DescriptorSet& set,
|
||||
const std::vector<vk::Barrier>& barriers,
|
||||
uint32_t x, uint32_t y, uint32_t z) const {
|
||||
vkCmdPipelineBarrier(*this->commandBuffer,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
static_cast<uint32_t>(barriers.size()), barriers.data()
|
||||
);
|
||||
vkCmdBindPipeline(*this->commandBuffer,
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
shader.pipeline()
|
||||
);
|
||||
vkCmdBindDescriptorSets(*this->commandBuffer,
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
shader.pipelinelayout(),
|
||||
0, 1, &set.handle(),
|
||||
0, nullptr
|
||||
);
|
||||
vkCmdDispatch(*this->commandBuffer, x, y, z);
|
||||
}
|
||||
|
||||
void CommandBuffer::submit() {
|
||||
auto res = vkEndCommandBuffer(*this->commandBuffer);
|
||||
if (res != VK_SUCCESS)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue