compute pipeline以及buffer绑定
This commit is contained in:
parent
f055bfbd76
commit
b996cf26bb
@ -10,6 +10,7 @@ buffer_vk::buffer_vk() {
|
||||
|
||||
void buffer_vk::create(uint32_t size, vk::BufferUsageFlagBits in_usage, vk::DescriptorType in_descriptor_type) {
|
||||
destroy();
|
||||
buffer_size = size;
|
||||
descriptor_type = in_descriptor_type;
|
||||
const renderer* render_vk = application::get()->get_renderer();
|
||||
const vk::Device& device = render_vk->device;
|
||||
@ -43,7 +44,7 @@ void buffer_vk::create_staging(uint32_t size) {
|
||||
create(size, vk::BufferUsageFlagBits::eTransferSrc, vk::DescriptorType::eUniformBuffer);
|
||||
}
|
||||
|
||||
void buffer_vk::destroy() const {
|
||||
void buffer_vk::destroy() {
|
||||
if (!buffer) {
|
||||
return;
|
||||
}
|
||||
@ -52,6 +53,9 @@ void buffer_vk::destroy() const {
|
||||
|
||||
device.destroyBuffer(buffer);
|
||||
device.freeMemory(memory);
|
||||
|
||||
buffer = nullptr;
|
||||
memory = nullptr;
|
||||
}
|
||||
|
||||
void buffer_vk::update(const void* data, uint32_t size) {
|
||||
|
@ -13,13 +13,13 @@ public:
|
||||
void create_storage(uint32_t size);
|
||||
void create_uniform(uint32_t size);
|
||||
void create_staging(uint32_t size);
|
||||
void destroy() const;
|
||||
void destroy();
|
||||
|
||||
template <typename T>
|
||||
T* map() {
|
||||
const auto& device = application::get()->get_renderer()->device;
|
||||
void* mapped;
|
||||
const auto err = device.mapMemory(memory, 0, VK_WHOLE_SIZE, vk::MemoryMapFlags(), &mapped);
|
||||
const auto err = device.mapMemory(memory, 0, buffer_size, vk::MemoryMapFlags(), &mapped);
|
||||
check_vk_result(err);
|
||||
return static_cast<T*>(mapped);
|
||||
}
|
||||
@ -38,15 +38,16 @@ public:
|
||||
update(data.data(), data.size() * sizeof(T));
|
||||
}
|
||||
|
||||
operator vk::DescriptorBufferInfo() const {
|
||||
[[nodiscard]] vk::DescriptorBufferInfo get_descriptor_info() const {
|
||||
vk::DescriptorBufferInfo descriptor_buffer_info;
|
||||
descriptor_buffer_info.setBuffer(buffer);
|
||||
descriptor_buffer_info.setOffset(0);
|
||||
descriptor_buffer_info.setRange(VK_WHOLE_SIZE);
|
||||
descriptor_buffer_info.setRange(buffer_size);
|
||||
return descriptor_buffer_info;
|
||||
}
|
||||
|
||||
vk::Buffer buffer;
|
||||
vk::DeviceMemory memory;
|
||||
vk::DescriptorType descriptor_type;
|
||||
uint32_t buffer_size;
|
||||
};
|
||||
|
@ -4,8 +4,15 @@
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
compute_pipeline::~compute_pipeline() {
|
||||
const renderer* render_vk = application::get()->get_renderer();
|
||||
const vk::Device& device = render_vk->device;
|
||||
|
||||
device.destroyShaderModule(shader_module_);
|
||||
}
|
||||
|
||||
void compute_pipeline::add_binding(uint32_t binding, vk::DescriptorType descriptor_type, uint32_t descriptor_count,
|
||||
const vk::Sampler* immutable_samplers) {
|
||||
vk::Sampler immutable_samplers) {
|
||||
const vk::ShaderStageFlags flag = vk::ShaderStageFlagBits::eCompute;
|
||||
|
||||
vk::DescriptorSetLayoutBinding descriptor_set_layout_binding;
|
||||
@ -13,7 +20,8 @@ void compute_pipeline::add_binding(uint32_t binding, vk::DescriptorType descript
|
||||
descriptor_set_layout_binding.setDescriptorType(descriptor_type);
|
||||
descriptor_set_layout_binding.setDescriptorCount(descriptor_count);
|
||||
descriptor_set_layout_binding.setStageFlags(flag);
|
||||
descriptor_set_layout_binding.setPImmutableSamplers(immutable_samplers);
|
||||
if (immutable_samplers)
|
||||
descriptor_set_layout_binding.setImmutableSamplers(immutable_samplers);
|
||||
descriptor_set_layout_bindings_.push_back(descriptor_set_layout_binding);
|
||||
}
|
||||
|
||||
@ -21,13 +29,8 @@ void compute_pipeline::create() {
|
||||
const renderer* render_vk = application::get()->get_renderer();
|
||||
const vk::Device& device = render_vk->device;
|
||||
|
||||
vk::PipelineCacheCreateInfo pipeline_cache_create_info;
|
||||
pipeline_cache_create_info.setInitialDataSize(0);
|
||||
pipeline_cache_ = device.createPipelineCache(pipeline_cache_create_info);
|
||||
|
||||
create_pipeline_layout();
|
||||
|
||||
|
||||
vk::PipelineShaderStageCreateInfo pipeline_shader_stage_create_info;
|
||||
pipeline_shader_stage_create_info.setStage(vk::ShaderStageFlagBits::eCompute);
|
||||
pipeline_shader_stage_create_info.setModule(shader_module_);
|
||||
@ -36,55 +39,27 @@ void compute_pipeline::create() {
|
||||
vk::ComputePipelineCreateInfo pipeline_create_info;
|
||||
pipeline_create_info.setLayout(pipeline_layout_);
|
||||
pipeline_create_info.setStage(pipeline_shader_stage_create_info);
|
||||
const auto pipeline_result = device.createComputePipeline(pipeline_cache_, pipeline_create_info);
|
||||
const auto pipeline_result = device.createComputePipeline(VK_NULL_HANDLE, pipeline_create_info);
|
||||
|
||||
check_vk_result(pipeline_result.result);
|
||||
pipeline_ = pipeline_result.value;
|
||||
}
|
||||
|
||||
void compute_pipeline::destroy() {
|
||||
const renderer* render_vk = application::get()->get_renderer();
|
||||
const vk::Device& device = render_vk->device;
|
||||
|
||||
device.destroyPipeline(pipeline_);
|
||||
device.destroyPipelineCache(pipeline_cache_);
|
||||
device.destroyPipelineLayout(pipeline_layout_);
|
||||
}
|
||||
|
||||
void compute_pipeline::dispatch(uint32_t group_count_x, uint32_t group_count_y, uint32_t group_count_z) const {
|
||||
#ifdef _DEBUG
|
||||
if (pipeline_ == vk::Pipeline()) {
|
||||
throw std::runtime_error("Pipeline not created");
|
||||
}
|
||||
#endif
|
||||
const renderer* render_vk = application::get()->get_renderer();
|
||||
const vk::Device& device = render_vk->device;
|
||||
const vk::CommandPool& command_pool = render_vk->get_command_pool();
|
||||
renderer* render_vk = application::get()->get_renderer();
|
||||
|
||||
vk::CommandBufferAllocateInfo command_buffer_allocate_info;
|
||||
command_buffer_allocate_info.setCommandPool(command_pool);
|
||||
command_buffer_allocate_info.setLevel(vk::CommandBufferLevel::ePrimary);
|
||||
command_buffer_allocate_info.setCommandBufferCount(1);
|
||||
const vk::CommandBuffer command_buffer = device.allocateCommandBuffers(command_buffer_allocate_info)[0];
|
||||
|
||||
vk::CommandBufferBeginInfo command_buffer_begin_info;
|
||||
command_buffer_begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
|
||||
command_buffer.begin(command_buffer_begin_info);
|
||||
const vk::CommandBuffer command_buffer = render_vk->create_command_buffer(vk::CommandBufferLevel::ePrimary, true);
|
||||
|
||||
command_buffer.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline_);
|
||||
command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eCompute, pipeline_layout_, 0, descriptor_set_, nullptr);
|
||||
command_buffer.dispatch(group_count_x, group_count_y, group_count_z);
|
||||
|
||||
command_buffer.end();
|
||||
|
||||
vk::SubmitInfo submit_info;
|
||||
submit_info.setCommandBufferCount(1);
|
||||
submit_info.setPCommandBuffers(&command_buffer);
|
||||
render_vk->queue.submit(submit_info, nullptr);
|
||||
render_vk->queue.waitIdle();
|
||||
|
||||
device.freeCommandBuffers(command_pool, command_buffer);
|
||||
device.destroyCommandPool(command_pool);
|
||||
render_vk->end_command_buffer(command_buffer, true);
|
||||
}
|
||||
|
||||
void compute_pipeline::set_shader(const uint8_t* shader_code, size_t shader_code_size) {
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
class CORE_API compute_pipeline : public pipeline {
|
||||
public:
|
||||
void add_binding(uint32_t binding, vk::DescriptorType descriptor_type, uint32_t descriptor_count, const vk::Sampler* immutable_samplers) override;
|
||||
~compute_pipeline() override;
|
||||
void add_binding(uint32_t binding, vk::DescriptorType descriptor_type, uint32_t descriptor_count, vk::Sampler immutable_samplers) override;
|
||||
void create() override;
|
||||
void destroy() override;
|
||||
|
||||
void dispatch(uint32_t group_count_x, uint32_t group_count_y, uint32_t group_count_z) const;
|
||||
|
||||
|
@ -3,6 +3,49 @@
|
||||
#include "renderer.h"
|
||||
#include "texture.h"
|
||||
|
||||
pipeline::~pipeline() {
|
||||
const renderer* render_vk = application::get()->get_renderer();
|
||||
const vk::Device& device = render_vk->device;
|
||||
|
||||
device.destroyDescriptorPool(descriptor_pool_);
|
||||
device.destroyDescriptorSetLayout(descriptor_set_layout_);
|
||||
device.destroyPipelineLayout(pipeline_layout_);
|
||||
device.destroyPipeline(pipeline_);
|
||||
}
|
||||
|
||||
void pipeline::add_uniform_buffer(uint32_t binding, std::shared_ptr<buffer_vk> buf) {
|
||||
add_binding(binding, vk::DescriptorType::eUniformBuffer, 1, nullptr);
|
||||
buffers_[binding] = buf;
|
||||
}
|
||||
|
||||
void pipeline::add_storage_buffer(uint32_t binding, std::shared_ptr<buffer_vk> buf) {
|
||||
add_binding(binding, vk::DescriptorType::eStorageBuffer, 1, nullptr);
|
||||
buffers_[binding] = buf;
|
||||
}
|
||||
|
||||
void pipeline::add_sampled_image(uint32_t binding, std::shared_ptr<render_resource> in_texture) {
|
||||
add_binding(binding, vk::DescriptorType::eSampledImage, 1, in_texture->sampler);
|
||||
textures_[binding] = in_texture;
|
||||
}
|
||||
|
||||
void pipeline::add_storage_image(uint32_t binding, std::shared_ptr<render_resource> in_texture) {
|
||||
add_binding(binding, vk::DescriptorType::eStorageImage, 1, in_texture->sampler);
|
||||
textures_[binding] = in_texture;
|
||||
}
|
||||
|
||||
void pipeline::add_input_attachment(uint32_t binding) {
|
||||
add_binding(binding, vk::DescriptorType::eInputAttachment, 1, nullptr);
|
||||
}
|
||||
|
||||
void pipeline::add_sampler(uint32_t binding, vk::Sampler immutable_samplers) {
|
||||
add_binding(binding, vk::DescriptorType::eSampler, 1, immutable_samplers);
|
||||
}
|
||||
|
||||
void pipeline::add_combined_image(uint32_t binding, std::shared_ptr<render_resource> in_texture) {
|
||||
add_binding(binding, vk::DescriptorType::eCombinedImageSampler, 1, in_texture->sampler);
|
||||
textures_[binding] = in_texture;
|
||||
}
|
||||
|
||||
void pipeline::create_pipeline_layout() {
|
||||
const renderer* render_vk = application::get()->get_renderer();
|
||||
const vk::Device& device = render_vk->device;
|
||||
@ -11,16 +54,32 @@ void pipeline::create_pipeline_layout() {
|
||||
descriptor_set_layout_create_info.setBindings(descriptor_set_layout_bindings_);
|
||||
descriptor_set_layout_ = device.createDescriptorSetLayout(descriptor_set_layout_create_info);
|
||||
|
||||
vk::PipelineLayoutCreateInfo pipeline_layout_create_info;
|
||||
pipeline_layout_create_info.setSetLayouts(descriptor_set_layout_);
|
||||
pipeline_layout_ = device.createPipelineLayout(pipeline_layout_create_info);
|
||||
std::vector<vk::DescriptorPoolSize> pool_sizes;
|
||||
{
|
||||
std::map<vk::DescriptorType, uint32_t> temp_pool_sizes;
|
||||
for (const auto& binding: descriptor_set_layout_bindings_) {
|
||||
temp_pool_sizes[binding.descriptorType]++;
|
||||
}
|
||||
for (const auto& pair: temp_pool_sizes) {
|
||||
pool_sizes.emplace_back(pair.first, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
vk::DescriptorPoolCreateInfo descriptor_pool_create_info;
|
||||
descriptor_pool_create_info.setMaxSets(1);
|
||||
descriptor_pool_create_info.setPoolSizes(pool_sizes);
|
||||
descriptor_pool_ = device.createDescriptorPool(descriptor_pool_create_info);
|
||||
|
||||
vk::DescriptorSetAllocateInfo descriptor_set_allocate_info;
|
||||
descriptor_set_allocate_info.setDescriptorPool(render_vk->descriptor_pool);
|
||||
descriptor_set_allocate_info.setDescriptorPool(descriptor_pool_);
|
||||
descriptor_set_allocate_info.setDescriptorSetCount(1);
|
||||
descriptor_set_allocate_info.setSetLayouts(descriptor_set_layout_);
|
||||
descriptor_set_ = device.allocateDescriptorSets(descriptor_set_allocate_info).front();
|
||||
const std::vector<vk::DescriptorSet>& sets = device.allocateDescriptorSets(descriptor_set_allocate_info);
|
||||
descriptor_set_ = sets.front();
|
||||
|
||||
std::vector<vk::WriteDescriptorSet> write_descriptor_sets;
|
||||
std::vector<std::vector<vk::DescriptorBufferInfo>> temp_buffer_infos;
|
||||
std::vector<std::vector<vk::DescriptorImageInfo>> temp_image_infoses;
|
||||
|
||||
for (const auto& binding_info: descriptor_set_layout_bindings_) {
|
||||
vk::WriteDescriptorSet write_descriptor_set;
|
||||
@ -33,14 +92,17 @@ void pipeline::create_pipeline_layout() {
|
||||
case vk::DescriptorType::eSampledImage:
|
||||
case vk::DescriptorType::eStorageImage: {
|
||||
const auto& t = textures_[binding_info.binding];
|
||||
vk::DescriptorImageInfo image_info = *t.get();
|
||||
write_descriptor_set.setImageInfo(image_info);
|
||||
vk::DescriptorImageInfo image_info = t->get_descriptor_info();
|
||||
temp_image_infoses.push_back({image_info});
|
||||
write_descriptor_set.setImageInfo(temp_image_infoses.back());
|
||||
}
|
||||
break;
|
||||
case vk::DescriptorType::eUniformBuffer:
|
||||
case vk::DescriptorType::eStorageBuffer: {
|
||||
vk::DescriptorBufferInfo buffer_info = buffers_[binding_info.binding];
|
||||
write_descriptor_set.setBufferInfo(buffer_info);
|
||||
const auto& b = buffers_[binding_info.binding];
|
||||
vk::DescriptorBufferInfo buffer_info = b->get_descriptor_info();
|
||||
temp_buffer_infos.push_back( {buffer_info} );
|
||||
write_descriptor_set.setBufferInfo(temp_buffer_infos.back());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -50,4 +112,8 @@ void pipeline::create_pipeline_layout() {
|
||||
}
|
||||
|
||||
device.updateDescriptorSets(write_descriptor_sets, nullptr);
|
||||
|
||||
vk::PipelineLayoutCreateInfo pipeline_layout_create_info;
|
||||
pipeline_layout_create_info.setSetLayouts(descriptor_set_layout_);
|
||||
pipeline_layout_ = device.createPipelineLayout(pipeline_layout_create_info);
|
||||
}
|
||||
|
@ -4,55 +4,44 @@
|
||||
|
||||
#include "buffer_vk.h"
|
||||
|
||||
class render_resource;
|
||||
class texture;
|
||||
|
||||
/// 1. add_binding
|
||||
/// 2. create();
|
||||
/// 3. dispatch();
|
||||
class pipeline {
|
||||
class CORE_API pipeline {
|
||||
public:
|
||||
virtual ~pipeline() = default;
|
||||
virtual ~pipeline();
|
||||
|
||||
virtual void add_binding(uint32_t binding, vk::DescriptorType descriptor_type, uint32_t descriptor_count, const vk::Sampler* immutable_samplers) = 0;
|
||||
virtual void add_binding(uint32_t binding, vk::DescriptorType descriptor_type, uint32_t descriptor_count, vk::Sampler immutable_samplers) = 0;
|
||||
|
||||
void add_uniform_buffer(uint32_t binding, const buffer_vk& buf, uint32_t descriptor_count = 1) {
|
||||
add_binding(binding, vk::DescriptorType::eUniformBuffer, descriptor_count, nullptr);
|
||||
buffers_[binding] = buf;
|
||||
}
|
||||
void add_storage_buffer(uint32_t binding, const buffer_vk& buf, uint32_t descriptor_count = 1) {
|
||||
add_binding(binding, vk::DescriptorType::eStorageBuffer, descriptor_count, nullptr);
|
||||
buffers_[binding] = buf;
|
||||
}
|
||||
void add_sampled_image(uint32_t binding, uint32_t descriptor_count = 1, const vk::Sampler* immutable_samplers = nullptr) {
|
||||
add_binding(binding, vk::DescriptorType::eSampledImage, descriptor_count, immutable_samplers);
|
||||
}
|
||||
void add_storage_image(uint32_t binding, std::shared_ptr<texture> in_texture, uint32_t descriptor_count = 1) {
|
||||
add_binding(binding, vk::DescriptorType::eStorageImage, descriptor_count, nullptr);
|
||||
textures_[binding] = in_texture;
|
||||
}
|
||||
void add_input_attachment(uint32_t binding, uint32_t descriptor_count = 1) {
|
||||
add_binding(binding, vk::DescriptorType::eInputAttachment, descriptor_count, nullptr);
|
||||
}
|
||||
void add_sampler(uint32_t binding, uint32_t descriptor_count = 1, const vk::Sampler* immutable_samplers = nullptr) {
|
||||
add_binding(binding, vk::DescriptorType::eSampler, descriptor_count, immutable_samplers);
|
||||
}
|
||||
void add_uniform_image(uint32_t binding, std::shared_ptr<texture> in_texture, uint32_t descriptor_count = 1, const vk::Sampler* immutable_samplers = nullptr) {
|
||||
add_binding(binding, vk::DescriptorType::eCombinedImageSampler, descriptor_count, immutable_samplers);
|
||||
textures_[binding] = in_texture;
|
||||
}
|
||||
void add_uniform_buffer(uint32_t binding, std::shared_ptr<buffer_vk> buf);
|
||||
|
||||
void add_storage_buffer(uint32_t binding, std::shared_ptr<buffer_vk> buf);
|
||||
|
||||
void add_sampled_image(uint32_t binding, std::shared_ptr<render_resource> in_texture);
|
||||
|
||||
void add_storage_image(uint32_t binding, std::shared_ptr<render_resource> in_texture);
|
||||
|
||||
void add_input_attachment(uint32_t binding);
|
||||
|
||||
void add_sampler(uint32_t binding, vk::Sampler immutable_samplers = nullptr);
|
||||
|
||||
void add_combined_image(uint32_t binding, std::shared_ptr<render_resource> in_texture);
|
||||
|
||||
virtual void create() = 0;
|
||||
virtual void destroy() = 0;
|
||||
|
||||
protected:
|
||||
vk::Pipeline pipeline_;
|
||||
vk::PipelineCache pipeline_cache_;
|
||||
vk::PipelineLayout pipeline_layout_;
|
||||
vk::DescriptorSetLayout descriptor_set_layout_;
|
||||
vk::DescriptorSet descriptor_set_;
|
||||
|
||||
vk::DescriptorPool descriptor_pool_;
|
||||
std::vector<vk::DescriptorSetLayoutBinding> descriptor_set_layout_bindings_;
|
||||
|
||||
std::map<uint32_t, buffer_vk> buffers_;
|
||||
std::map<uint32_t, std::shared_ptr<texture>> textures_;
|
||||
std::map<uint32_t, std::shared_ptr<buffer_vk>> buffers_;
|
||||
std::map<uint32_t, std::shared_ptr<render_resource>> textures_;
|
||||
protected:
|
||||
void create_pipeline_layout();
|
||||
};
|
||||
|
@ -1,17 +1,67 @@
|
||||
#pragma once
|
||||
#include "imgui.h"
|
||||
#include "renderer.h"
|
||||
#include "application/application.h"
|
||||
|
||||
class render_resource : public std::enable_shared_from_this<render_resource> {
|
||||
public:
|
||||
virtual ~render_resource() = default;
|
||||
render_resource() {
|
||||
format = vk::Format::eUndefined;
|
||||
width_ = 0;
|
||||
height_ = 0;
|
||||
image = nullptr;
|
||||
image_view = nullptr;
|
||||
sampler = nullptr;
|
||||
memory = nullptr;
|
||||
descriptor_set = nullptr;
|
||||
}
|
||||
virtual ~render_resource() {
|
||||
render_resource::destroy();
|
||||
}
|
||||
|
||||
virtual int get_width() const = 0;
|
||||
[[nodiscard]] int get_width() const { return width_; }
|
||||
[[nodiscard]] int get_height() const { return height_; }
|
||||
[[nodiscard]] ImTextureID get_texture_id() const { return descriptor_set; }
|
||||
[[nodiscard]] vk::DescriptorImageInfo get_descriptor_info() const {
|
||||
vk::DescriptorImageInfo info;
|
||||
info.setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
info.setImageView(image_view);
|
||||
info.setSampler(sampler);
|
||||
return info;
|
||||
}
|
||||
|
||||
virtual int get_height() const = 0;
|
||||
|
||||
virtual ImTextureID get_texture_id() = 0;
|
||||
|
||||
void draw() {
|
||||
void init(uint32_t width, uint32_t height, vk::Format in_format) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
format = in_format;
|
||||
on_init();
|
||||
}
|
||||
void draw() const {
|
||||
ImGui::Image(get_texture_id(), ImVec2(static_cast<float>(get_width()), static_cast<float>(get_height())));
|
||||
}
|
||||
virtual void destroy() {
|
||||
const auto r = application::get()->get_renderer();
|
||||
const auto& device = r->device;
|
||||
device.destroySampler(sampler);
|
||||
device.destroyImageView(image_view);
|
||||
device.destroyImage(image);
|
||||
device.freeMemory(memory);
|
||||
ImGui_ImplVulkan_RemoveTexture(descriptor_set);
|
||||
sampler = nullptr;
|
||||
image_view = nullptr;
|
||||
image = nullptr;
|
||||
memory = nullptr;
|
||||
descriptor_set = nullptr;
|
||||
}
|
||||
|
||||
vk::Image image;
|
||||
vk::ImageView image_view;
|
||||
vk::Sampler sampler;
|
||||
vk::DescriptorSet descriptor_set;
|
||||
vk::DeviceMemory memory;
|
||||
vk::Format format;
|
||||
protected:
|
||||
virtual void on_init() = 0;
|
||||
uint32_t width_;
|
||||
uint32_t height_;
|
||||
};
|
||||
|
@ -4,14 +4,6 @@
|
||||
#include "application/application.h"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
void render_target::init(const int width, const int height, const vk::Format in_format) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
format = in_format;
|
||||
|
||||
create(width, height);
|
||||
}
|
||||
|
||||
void* render_target::lock(lock_state state) const {
|
||||
const auto r = application::get()->get_renderer();
|
||||
const auto& device = r->device;
|
||||
@ -37,7 +29,14 @@ void render_target::unlock() {
|
||||
device.unmapMemory(memory);
|
||||
}
|
||||
|
||||
void render_target::create(int width, int height) {
|
||||
void render_target::destroy() {
|
||||
render_resource::destroy();
|
||||
const auto r = application::get()->get_renderer();
|
||||
const auto& device = r->device;
|
||||
device.destroyFramebuffer(framebuffer);
|
||||
}
|
||||
|
||||
void render_target::create(uint32_t width, uint32_t height) {
|
||||
auto r = application::get()->get_renderer();
|
||||
const auto& device = r->device;
|
||||
const auto& physical_device = r->physical_device;
|
||||
@ -50,7 +49,7 @@ void render_target::create(int width, int height) {
|
||||
image_create_info.setArrayLayers(1);
|
||||
image_create_info.setSamples(vk::SampleCountFlagBits::e1);
|
||||
image_create_info.setTiling(vk::ImageTiling::eOptimal);
|
||||
image_create_info.setUsage(vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eColorAttachment);
|
||||
image_create_info.setUsage(vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage);
|
||||
image_create_info.setSharingMode(vk::SharingMode::eExclusive);
|
||||
image_create_info.setInitialLayout(vk::ImageLayout::eUndefined);
|
||||
image = device.createImage(image_create_info);
|
||||
@ -80,16 +79,27 @@ void render_target::create(int width, int height) {
|
||||
framebuffer_create_info.setHeight(height);
|
||||
framebuffer_create_info.setLayers(1);
|
||||
framebuffer = device.createFramebuffer(framebuffer_create_info);
|
||||
|
||||
vk::SamplerCreateInfo sampler_info;
|
||||
sampler_info.setMagFilter(vk::Filter::eLinear);
|
||||
sampler_info.setMinFilter(vk::Filter::eLinear);
|
||||
sampler_info.setMipmapMode(vk::SamplerMipmapMode::eLinear);
|
||||
sampler_info.setAddressModeU(vk::SamplerAddressMode::eRepeat);
|
||||
sampler_info.setAddressModeV(vk::SamplerAddressMode::eRepeat);
|
||||
sampler_info.setAddressModeW(vk::SamplerAddressMode::eRepeat);
|
||||
sampler_info.setMinLod(-1000);
|
||||
sampler_info.setMaxLod(1000);
|
||||
sampler_info.setMaxAnisotropy(1);
|
||||
sampler = device.createSampler(sampler_info);
|
||||
|
||||
descriptor_set = ImGui_ImplVulkan_AddTexture(sampler, image_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
void render_target::on_resize(int width, int height) {
|
||||
const auto r = application::get()->get_renderer();
|
||||
const auto& device = r->device;
|
||||
|
||||
device.destroyFramebuffer(framebuffer);
|
||||
device.destroyImageView(image_view);
|
||||
device.destroyImage(image);
|
||||
device.freeMemory(memory);
|
||||
void render_target::on_init() {
|
||||
create(width_, height_);
|
||||
}
|
||||
|
||||
void render_target::on_resize(uint32_t width, uint32_t height) {
|
||||
destroy();
|
||||
create(width, height);
|
||||
}
|
||||
|
@ -12,13 +12,8 @@ enum class lock_state {
|
||||
|
||||
class render_target : public render_resource {
|
||||
public:
|
||||
[[nodiscard]] int get_height() const override { return height_; }
|
||||
[[nodiscard]] int get_width() const override { return width_; }
|
||||
[[nodiscard]] ImTextureID get_texture_id() override { return descriptor_set; }
|
||||
|
||||
void init(const int width, const int height, const vk::Format in_format);
|
||||
|
||||
void resize(const int width, const int height) {
|
||||
void resize(const uint32_t width, const uint32_t height) {
|
||||
if (width_ == width && height_ == height)
|
||||
return;
|
||||
|
||||
@ -32,17 +27,12 @@ public:
|
||||
void* lock(lock_state state) const;
|
||||
void unlock();
|
||||
|
||||
std::function<void(std::shared_ptr<render_resource>)> on_resize_callback;
|
||||
vk::Image image;
|
||||
vk::ImageView image_view;
|
||||
vk::DeviceMemory memory;
|
||||
vk::Framebuffer framebuffer;
|
||||
vk::Format format;
|
||||
vk::DescriptorSet descriptor_set;
|
||||
protected:
|
||||
void create(int width, int height);
|
||||
void on_resize(int width, int height);
|
||||
void destroy() override;
|
||||
|
||||
int width_ = 0;
|
||||
int height_ = 0;
|
||||
std::function<void(std::shared_ptr<render_resource>)> on_resize_callback;
|
||||
vk::Framebuffer framebuffer;
|
||||
protected:
|
||||
void create(uint32_t width, uint32_t height);
|
||||
void on_init() override;
|
||||
void on_resize(uint32_t width, uint32_t height);
|
||||
};
|
||||
|
@ -6,6 +6,17 @@
|
||||
#include "application/application.h"
|
||||
#include "texture.h"
|
||||
|
||||
|
||||
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL on_debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
|
||||
{
|
||||
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
|
||||
fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
||||
return VK_FALSE;
|
||||
}
|
||||
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
||||
|
||||
static bool is_extension_available(const std::vector<vk::ExtensionProperties>& properties, const char* extension) {
|
||||
return std::ranges::any_of(properties, [extension](const vk::ExtensionProperties& p) {
|
||||
return strcmp(p.extensionName, extension) == 0;
|
||||
@ -36,12 +47,27 @@ vk::CommandBuffer renderer::create_command_buffer(vk::CommandBufferLevel level,
|
||||
return command_buffer;
|
||||
}
|
||||
|
||||
void renderer::end_command_buffer(vk::CommandBuffer command_buffer) {
|
||||
void renderer::end_command_buffer(vk::CommandBuffer command_buffer, bool use_fence) const {
|
||||
command_buffer.end();
|
||||
|
||||
if (use_fence) {
|
||||
vk::FenceCreateInfo fence_create_info = {};
|
||||
vk::Fence fence = device.createFence(fence_create_info);
|
||||
|
||||
vk::SubmitInfo submit_info;
|
||||
submit_info.setCommandBuffers(command_buffer);
|
||||
queue.submit(submit_info, fence);
|
||||
|
||||
const auto err = device.waitForFences(1, &fence, VK_TRUE, 100000000000);
|
||||
check_vk_result(err);
|
||||
|
||||
device.destroyFence(fence);
|
||||
}
|
||||
else {
|
||||
vk::SubmitInfo submit_info;
|
||||
submit_info.setCommandBuffers(command_buffer);
|
||||
queue.submit(submit_info, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void renderer::init_vulkan(GLFWwindow* window_handle) {
|
||||
@ -70,7 +96,7 @@ void renderer::init_vulkan(GLFWwindow* window_handle) {
|
||||
init_info.Device = device;
|
||||
init_info.QueueFamily = queue_family;
|
||||
init_info.Queue = queue;
|
||||
init_info.PipelineCache = pipeline_cache;
|
||||
init_info.PipelineCache = VK_NULL_HANDLE;
|
||||
init_info.DescriptorPool = descriptor_pool;
|
||||
init_info.RenderPass = main_window_data.RenderPass;
|
||||
init_info.Subpass = 0;
|
||||
@ -120,10 +146,30 @@ void renderer::setup_vulkan(std::vector<const char*> instance_extensions) {
|
||||
create_info.flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
|
||||
}
|
||||
#endif
|
||||
// Enabling validation layers
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
|
||||
create_info.enabledLayerCount = 1;
|
||||
create_info.ppEnabledLayerNames = layers;
|
||||
instance_extensions.push_back("VK_EXT_debug_report");
|
||||
#endif
|
||||
|
||||
// Create Vulkan Instance
|
||||
create_info.setPEnabledExtensionNames(instance_extensions);
|
||||
instance = vk::createInstance(create_info, allocator);
|
||||
|
||||
// Setup the debug report callback
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT");
|
||||
IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr);
|
||||
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
||||
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
||||
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||
debug_report_ci.pfnCallback = on_debug_report;
|
||||
debug_report_ci.pUserData = nullptr;
|
||||
auto err = vkCreateDebugReportCallbackEXT(instance, &debug_report_ci, (VkAllocationCallbacks*)allocator, &debug_report);
|
||||
check_vk_result(err);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Select Physical Device (GPU)
|
||||
@ -228,8 +274,8 @@ void renderer::cleanup_vulkan() const {
|
||||
device.destroyDescriptorPool(descriptor_pool);
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
// Remove the debug report callback
|
||||
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
||||
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
|
||||
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT");
|
||||
vkDestroyDebugReportCallbackEXT(instance, debug_report, (VkAllocationCallbacks*)allocator);
|
||||
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
||||
|
||||
device.destroy();
|
||||
@ -413,7 +459,9 @@ void renderer::end_frame(GLFWwindow* window_handle) {
|
||||
|
||||
std::shared_ptr<texture> renderer::create_texture(const uint8_t* data, int width, int height, vk::Format format) {
|
||||
auto out = std::make_shared<texture>();
|
||||
out->init_data(data, width, height, format);
|
||||
out->init(width, height, format);
|
||||
if (data)
|
||||
out->upload(data, width * height * 4);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,10 @@
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define APP_USE_VULKAN_DEBUG_REPORT
|
||||
#endif
|
||||
|
||||
class pixel_shader_drawer;
|
||||
class render_target;
|
||||
class texture;
|
||||
@ -58,10 +62,12 @@ public:
|
||||
uint32_t queue_family = (uint32_t) -1;
|
||||
vk::Queue queue = VK_NULL_HANDLE;
|
||||
vk::DescriptorPool descriptor_pool = VK_NULL_HANDLE;
|
||||
vk::PipelineCache pipeline_cache = VK_NULL_HANDLE;
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
VkDebugReportCallbackEXT debug_report = VK_NULL_HANDLE;
|
||||
#endif
|
||||
[[nodiscard]] vk::CommandPool get_command_pool() const;
|
||||
[[nodiscard]] vk::CommandBuffer create_command_buffer(vk::CommandBufferLevel level, bool begin) const;
|
||||
void end_command_buffer(vk::CommandBuffer command_buffer);
|
||||
void end_command_buffer(vk::CommandBuffer command_buffer, bool use_fence = false) const;
|
||||
|
||||
ImGui_ImplVulkanH_Window main_window_data;
|
||||
int min_image_count = 2;
|
||||
|
@ -8,12 +8,6 @@
|
||||
|
||||
|
||||
texture::texture() {
|
||||
format = vk::Format::eUndefined;
|
||||
width_ = 0;
|
||||
height_ = 0;
|
||||
image = nullptr;
|
||||
image_view = nullptr;
|
||||
sampler = nullptr;
|
||||
memory = nullptr;
|
||||
}
|
||||
|
||||
@ -28,67 +22,6 @@ texture::~texture() {
|
||||
}
|
||||
}
|
||||
|
||||
bool texture::init_data(const uint8_t* data, int width, int height, vk::Format in_format) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
format = in_format;
|
||||
|
||||
const renderer* r = application::get()->get_renderer();
|
||||
const vk::Device& device = r->device;
|
||||
const vk::PhysicalDevice& physical_device = r->physical_device;
|
||||
|
||||
vk::ImageCreateInfo image_info;
|
||||
image_info.setImageType(vk::ImageType::e2D);
|
||||
image_info.setFormat(format);
|
||||
image_info.setExtent({static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1});
|
||||
image_info.setMipLevels(1);
|
||||
image_info.setArrayLayers(1);
|
||||
image_info.setSamples(vk::SampleCountFlagBits::e1);
|
||||
image_info.setTiling(vk::ImageTiling::eOptimal);
|
||||
image_info.setUsage(vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst);
|
||||
image_info.setSharingMode(vk::SharingMode::eExclusive);
|
||||
image_info.setInitialLayout(vk::ImageLayout::eUndefined);
|
||||
image = device.createImage(image_info);
|
||||
|
||||
const vk::PhysicalDeviceMemoryProperties memory_properties = physical_device.getMemoryProperties();
|
||||
const vk::MemoryRequirements memory_requirements = device.getImageMemoryRequirements(image);
|
||||
const uint32_t memory_type = vk::su::findMemoryType(memory_properties, memory_requirements.memoryTypeBits,
|
||||
vk::MemoryPropertyFlagBits::eDeviceLocal);
|
||||
|
||||
vk::MemoryAllocateInfo memory_allocate_info;
|
||||
memory_allocate_info.setAllocationSize(memory_requirements.size);
|
||||
memory_allocate_info.setMemoryTypeIndex(memory_type);
|
||||
memory = device.allocateMemory(memory_allocate_info);
|
||||
device.bindImageMemory(image, memory, 0);
|
||||
|
||||
vk::ImageViewCreateInfo view_info;
|
||||
view_info.setImage(image);
|
||||
view_info.setViewType(vk::ImageViewType::e2D);
|
||||
view_info.setFormat(format);
|
||||
view_info.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
|
||||
image_view = device.createImageView(view_info);
|
||||
|
||||
vk::SamplerCreateInfo sampler_info;
|
||||
sampler_info.setMagFilter(vk::Filter::eLinear);
|
||||
sampler_info.setMinFilter(vk::Filter::eLinear);
|
||||
sampler_info.setMipmapMode(vk::SamplerMipmapMode::eLinear);
|
||||
sampler_info.setAddressModeU(vk::SamplerAddressMode::eRepeat);
|
||||
sampler_info.setAddressModeV(vk::SamplerAddressMode::eRepeat);
|
||||
sampler_info.setAddressModeW(vk::SamplerAddressMode::eRepeat);
|
||||
sampler_info.setMinLod(-1000);
|
||||
sampler_info.setMaxLod(1000);
|
||||
sampler_info.setMaxAnisotropy(1);
|
||||
sampler = device.createSampler(sampler_info);
|
||||
|
||||
descriptor_set = ImGui_ImplVulkan_AddTexture(sampler, image_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
uint32_t image_size = width * height * 4;
|
||||
|
||||
if (data) {
|
||||
upload(data, image_size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void texture::upload(const void* data, size_t size) {
|
||||
renderer* r = application::get()->get_renderer();
|
||||
const vk::Device& device = r->device;
|
||||
@ -155,3 +88,54 @@ void texture::upload(const void* data, size_t size) {
|
||||
|
||||
// device.freeCommandBuffers(command_pool, command_buffer);
|
||||
}
|
||||
|
||||
void texture::on_init() {
|
||||
const renderer* r = application::get()->get_renderer();
|
||||
const vk::Device& device = r->device;
|
||||
const vk::PhysicalDevice& physical_device = r->physical_device;
|
||||
|
||||
vk::ImageCreateInfo image_info;
|
||||
image_info.setImageType(vk::ImageType::e2D);
|
||||
image_info.setFormat(format);
|
||||
image_info.setExtent({ width_, height_, 1 });
|
||||
image_info.setMipLevels(1);
|
||||
image_info.setArrayLayers(1);
|
||||
image_info.setSamples(vk::SampleCountFlagBits::e1);
|
||||
image_info.setTiling(vk::ImageTiling::eOptimal);
|
||||
image_info.setUsage(vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eStorage);
|
||||
image_info.setSharingMode(vk::SharingMode::eExclusive);
|
||||
image_info.setInitialLayout(vk::ImageLayout::eUndefined);
|
||||
image = device.createImage(image_info);
|
||||
|
||||
const vk::PhysicalDeviceMemoryProperties memory_properties = physical_device.getMemoryProperties();
|
||||
const vk::MemoryRequirements memory_requirements = device.getImageMemoryRequirements(image);
|
||||
const uint32_t memory_type = vk::su::findMemoryType(memory_properties, memory_requirements.memoryTypeBits,
|
||||
vk::MemoryPropertyFlagBits::eDeviceLocal);
|
||||
|
||||
vk::MemoryAllocateInfo memory_allocate_info;
|
||||
memory_allocate_info.setAllocationSize(memory_requirements.size);
|
||||
memory_allocate_info.setMemoryTypeIndex(memory_type);
|
||||
memory = device.allocateMemory(memory_allocate_info);
|
||||
device.bindImageMemory(image, memory, 0);
|
||||
|
||||
vk::ImageViewCreateInfo view_info;
|
||||
view_info.setImage(image);
|
||||
view_info.setViewType(vk::ImageViewType::e2D);
|
||||
view_info.setFormat(format);
|
||||
view_info.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
|
||||
image_view = device.createImageView(view_info);
|
||||
|
||||
vk::SamplerCreateInfo sampler_info;
|
||||
sampler_info.setMagFilter(vk::Filter::eLinear);
|
||||
sampler_info.setMinFilter(vk::Filter::eLinear);
|
||||
sampler_info.setMipmapMode(vk::SamplerMipmapMode::eLinear);
|
||||
sampler_info.setAddressModeU(vk::SamplerAddressMode::eRepeat);
|
||||
sampler_info.setAddressModeV(vk::SamplerAddressMode::eRepeat);
|
||||
sampler_info.setAddressModeW(vk::SamplerAddressMode::eRepeat);
|
||||
sampler_info.setMinLod(-1000);
|
||||
sampler_info.setMaxLod(1000);
|
||||
sampler_info.setMaxAnisotropy(1);
|
||||
sampler = device.createSampler(sampler_info);
|
||||
|
||||
descriptor_set = ImGui_ImplVulkan_AddTexture(sampler, image_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
@ -11,30 +11,9 @@ public:
|
||||
|
||||
~texture() override;
|
||||
|
||||
[[nodiscard]] int get_width() const override { return width_; }
|
||||
[[nodiscard]] int get_height() const override { return height_; }
|
||||
[[nodiscard]] ImTextureID get_texture_id() override { return descriptor_set; }
|
||||
|
||||
bool init_data(const uint8_t* data, int width, int height, vk::Format in_format);
|
||||
bool is_valid() const { return image_view; }
|
||||
|
||||
operator vk::DescriptorImageInfo() const {
|
||||
vk::DescriptorImageInfo info;
|
||||
info.setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
info.setImageView(image_view);
|
||||
info.setSampler(sampler);
|
||||
return info;
|
||||
}
|
||||
void upload(const void* data, size_t size);
|
||||
|
||||
vk::Image image;
|
||||
vk::ImageView image_view;
|
||||
vk::Sampler sampler;
|
||||
vk::DeviceMemory memory;
|
||||
vk::DescriptorSet descriptor_set;
|
||||
|
||||
vk::Format format;
|
||||
protected:
|
||||
int width_;
|
||||
int height_;
|
||||
void on_init() override;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user