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) {
|
void buffer_vk::create(uint32_t size, vk::BufferUsageFlagBits in_usage, vk::DescriptorType in_descriptor_type) {
|
||||||
destroy();
|
destroy();
|
||||||
|
buffer_size = size;
|
||||||
descriptor_type = in_descriptor_type;
|
descriptor_type = in_descriptor_type;
|
||||||
const renderer* render_vk = application::get()->get_renderer();
|
const renderer* render_vk = application::get()->get_renderer();
|
||||||
const vk::Device& device = render_vk->device;
|
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);
|
create(size, vk::BufferUsageFlagBits::eTransferSrc, vk::DescriptorType::eUniformBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void buffer_vk::destroy() const {
|
void buffer_vk::destroy() {
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -52,6 +53,9 @@ void buffer_vk::destroy() const {
|
|||||||
|
|
||||||
device.destroyBuffer(buffer);
|
device.destroyBuffer(buffer);
|
||||||
device.freeMemory(memory);
|
device.freeMemory(memory);
|
||||||
|
|
||||||
|
buffer = nullptr;
|
||||||
|
memory = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buffer_vk::update(const void* data, uint32_t size) {
|
void buffer_vk::update(const void* data, uint32_t size) {
|
||||||
|
@ -13,13 +13,13 @@ public:
|
|||||||
void create_storage(uint32_t size);
|
void create_storage(uint32_t size);
|
||||||
void create_uniform(uint32_t size);
|
void create_uniform(uint32_t size);
|
||||||
void create_staging(uint32_t size);
|
void create_staging(uint32_t size);
|
||||||
void destroy() const;
|
void destroy();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* map() {
|
T* map() {
|
||||||
const auto& device = application::get()->get_renderer()->device;
|
const auto& device = application::get()->get_renderer()->device;
|
||||||
void* mapped;
|
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);
|
check_vk_result(err);
|
||||||
return static_cast<T*>(mapped);
|
return static_cast<T*>(mapped);
|
||||||
}
|
}
|
||||||
@ -38,15 +38,16 @@ public:
|
|||||||
update(data.data(), data.size() * sizeof(T));
|
update(data.data(), data.size() * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
operator vk::DescriptorBufferInfo() const {
|
[[nodiscard]] vk::DescriptorBufferInfo get_descriptor_info() const {
|
||||||
vk::DescriptorBufferInfo descriptor_buffer_info;
|
vk::DescriptorBufferInfo descriptor_buffer_info;
|
||||||
descriptor_buffer_info.setBuffer(buffer);
|
descriptor_buffer_info.setBuffer(buffer);
|
||||||
descriptor_buffer_info.setOffset(0);
|
descriptor_buffer_info.setOffset(0);
|
||||||
descriptor_buffer_info.setRange(VK_WHOLE_SIZE);
|
descriptor_buffer_info.setRange(buffer_size);
|
||||||
return descriptor_buffer_info;
|
return descriptor_buffer_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::Buffer buffer;
|
vk::Buffer buffer;
|
||||||
vk::DeviceMemory memory;
|
vk::DeviceMemory memory;
|
||||||
vk::DescriptorType descriptor_type;
|
vk::DescriptorType descriptor_type;
|
||||||
|
uint32_t buffer_size;
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,15 @@
|
|||||||
|
|
||||||
#include <vulkan/vulkan.hpp>
|
#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,
|
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;
|
const vk::ShaderStageFlags flag = vk::ShaderStageFlagBits::eCompute;
|
||||||
|
|
||||||
vk::DescriptorSetLayoutBinding descriptor_set_layout_binding;
|
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.setDescriptorType(descriptor_type);
|
||||||
descriptor_set_layout_binding.setDescriptorCount(descriptor_count);
|
descriptor_set_layout_binding.setDescriptorCount(descriptor_count);
|
||||||
descriptor_set_layout_binding.setStageFlags(flag);
|
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);
|
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 renderer* render_vk = application::get()->get_renderer();
|
||||||
const vk::Device& device = render_vk->device;
|
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();
|
create_pipeline_layout();
|
||||||
|
|
||||||
|
|
||||||
vk::PipelineShaderStageCreateInfo pipeline_shader_stage_create_info;
|
vk::PipelineShaderStageCreateInfo pipeline_shader_stage_create_info;
|
||||||
pipeline_shader_stage_create_info.setStage(vk::ShaderStageFlagBits::eCompute);
|
pipeline_shader_stage_create_info.setStage(vk::ShaderStageFlagBits::eCompute);
|
||||||
pipeline_shader_stage_create_info.setModule(shader_module_);
|
pipeline_shader_stage_create_info.setModule(shader_module_);
|
||||||
@ -36,55 +39,27 @@ void compute_pipeline::create() {
|
|||||||
vk::ComputePipelineCreateInfo pipeline_create_info;
|
vk::ComputePipelineCreateInfo pipeline_create_info;
|
||||||
pipeline_create_info.setLayout(pipeline_layout_);
|
pipeline_create_info.setLayout(pipeline_layout_);
|
||||||
pipeline_create_info.setStage(pipeline_shader_stage_create_info);
|
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);
|
check_vk_result(pipeline_result.result);
|
||||||
pipeline_ = pipeline_result.value;
|
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 {
|
void compute_pipeline::dispatch(uint32_t group_count_x, uint32_t group_count_y, uint32_t group_count_z) const {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
if (pipeline_ == vk::Pipeline()) {
|
if (pipeline_ == vk::Pipeline()) {
|
||||||
throw std::runtime_error("Pipeline not created");
|
throw std::runtime_error("Pipeline not created");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
const renderer* render_vk = application::get()->get_renderer();
|
renderer* render_vk = application::get()->get_renderer();
|
||||||
const vk::Device& device = render_vk->device;
|
|
||||||
const vk::CommandPool& command_pool = render_vk->get_command_pool();
|
|
||||||
|
|
||||||
vk::CommandBufferAllocateInfo command_buffer_allocate_info;
|
const vk::CommandBuffer command_buffer = render_vk->create_command_buffer(vk::CommandBufferLevel::ePrimary, true);
|
||||||
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);
|
|
||||||
|
|
||||||
command_buffer.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline_);
|
command_buffer.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline_);
|
||||||
command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eCompute, pipeline_layout_, 0, descriptor_set_, nullptr);
|
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.dispatch(group_count_x, group_count_y, group_count_z);
|
||||||
|
|
||||||
command_buffer.end();
|
render_vk->end_command_buffer(command_buffer, true);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compute_pipeline::set_shader(const uint8_t* shader_code, size_t shader_code_size) {
|
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 {
|
class CORE_API compute_pipeline : public pipeline {
|
||||||
public:
|
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 create() override;
|
||||||
void destroy() override;
|
|
||||||
|
|
||||||
void dispatch(uint32_t group_count_x, uint32_t group_count_y, uint32_t group_count_z) const;
|
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 "renderer.h"
|
||||||
#include "texture.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() {
|
void pipeline::create_pipeline_layout() {
|
||||||
const renderer* render_vk = application::get()->get_renderer();
|
const renderer* render_vk = application::get()->get_renderer();
|
||||||
const vk::Device& device = render_vk->device;
|
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_create_info.setBindings(descriptor_set_layout_bindings_);
|
||||||
descriptor_set_layout_ = device.createDescriptorSetLayout(descriptor_set_layout_create_info);
|
descriptor_set_layout_ = device.createDescriptorSetLayout(descriptor_set_layout_create_info);
|
||||||
|
|
||||||
vk::PipelineLayoutCreateInfo pipeline_layout_create_info;
|
std::vector<vk::DescriptorPoolSize> pool_sizes;
|
||||||
pipeline_layout_create_info.setSetLayouts(descriptor_set_layout_);
|
{
|
||||||
pipeline_layout_ = device.createPipelineLayout(pipeline_layout_create_info);
|
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;
|
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_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<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_) {
|
for (const auto& binding_info: descriptor_set_layout_bindings_) {
|
||||||
vk::WriteDescriptorSet write_descriptor_set;
|
vk::WriteDescriptorSet write_descriptor_set;
|
||||||
@ -33,14 +92,17 @@ void pipeline::create_pipeline_layout() {
|
|||||||
case vk::DescriptorType::eSampledImage:
|
case vk::DescriptorType::eSampledImage:
|
||||||
case vk::DescriptorType::eStorageImage: {
|
case vk::DescriptorType::eStorageImage: {
|
||||||
const auto& t = textures_[binding_info.binding];
|
const auto& t = textures_[binding_info.binding];
|
||||||
vk::DescriptorImageInfo image_info = *t.get();
|
vk::DescriptorImageInfo image_info = t->get_descriptor_info();
|
||||||
write_descriptor_set.setImageInfo(image_info);
|
temp_image_infoses.push_back({image_info});
|
||||||
|
write_descriptor_set.setImageInfo(temp_image_infoses.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case vk::DescriptorType::eUniformBuffer:
|
case vk::DescriptorType::eUniformBuffer:
|
||||||
case vk::DescriptorType::eStorageBuffer: {
|
case vk::DescriptorType::eStorageBuffer: {
|
||||||
vk::DescriptorBufferInfo buffer_info = buffers_[binding_info.binding];
|
const auto& b = buffers_[binding_info.binding];
|
||||||
write_descriptor_set.setBufferInfo(buffer_info);
|
vk::DescriptorBufferInfo buffer_info = b->get_descriptor_info();
|
||||||
|
temp_buffer_infos.push_back( {buffer_info} );
|
||||||
|
write_descriptor_set.setBufferInfo(temp_buffer_infos.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -50,4 +112,8 @@ void pipeline::create_pipeline_layout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
device.updateDescriptorSets(write_descriptor_sets, nullptr);
|
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"
|
#include "buffer_vk.h"
|
||||||
|
|
||||||
|
class render_resource;
|
||||||
class texture;
|
class texture;
|
||||||
|
|
||||||
/// 1. add_binding
|
/// 1. add_binding
|
||||||
/// 2. create();
|
/// 2. create();
|
||||||
/// 3. dispatch();
|
/// 3. dispatch();
|
||||||
class pipeline {
|
class CORE_API pipeline {
|
||||||
public:
|
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) {
|
void add_uniform_buffer(uint32_t binding, std::shared_ptr<buffer_vk> buf);
|
||||||
add_binding(binding, vk::DescriptorType::eUniformBuffer, descriptor_count, nullptr);
|
|
||||||
buffers_[binding] = buf;
|
void add_storage_buffer(uint32_t binding, std::shared_ptr<buffer_vk> buf);
|
||||||
}
|
|
||||||
void add_storage_buffer(uint32_t binding, const buffer_vk& buf, uint32_t descriptor_count = 1) {
|
void add_sampled_image(uint32_t binding, std::shared_ptr<render_resource> in_texture);
|
||||||
add_binding(binding, vk::DescriptorType::eStorageBuffer, descriptor_count, nullptr);
|
|
||||||
buffers_[binding] = buf;
|
void add_storage_image(uint32_t binding, std::shared_ptr<render_resource> in_texture);
|
||||||
}
|
|
||||||
void add_sampled_image(uint32_t binding, uint32_t descriptor_count = 1, const vk::Sampler* immutable_samplers = nullptr) {
|
void add_input_attachment(uint32_t binding);
|
||||||
add_binding(binding, vk::DescriptorType::eSampledImage, descriptor_count, immutable_samplers);
|
|
||||||
}
|
void add_sampler(uint32_t binding, vk::Sampler immutable_samplers = nullptr);
|
||||||
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);
|
void add_combined_image(uint32_t binding, std::shared_ptr<render_resource> in_texture);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void create() = 0;
|
virtual void create() = 0;
|
||||||
virtual void destroy() = 0;
|
protected:
|
||||||
|
|
||||||
vk::Pipeline pipeline_;
|
vk::Pipeline pipeline_;
|
||||||
vk::PipelineCache pipeline_cache_;
|
|
||||||
vk::PipelineLayout pipeline_layout_;
|
vk::PipelineLayout pipeline_layout_;
|
||||||
vk::DescriptorSetLayout descriptor_set_layout_;
|
vk::DescriptorSetLayout descriptor_set_layout_;
|
||||||
vk::DescriptorSet descriptor_set_;
|
vk::DescriptorSet descriptor_set_;
|
||||||
|
|
||||||
|
vk::DescriptorPool descriptor_pool_;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> descriptor_set_layout_bindings_;
|
std::vector<vk::DescriptorSetLayoutBinding> descriptor_set_layout_bindings_;
|
||||||
|
|
||||||
std::map<uint32_t, buffer_vk> buffers_;
|
std::map<uint32_t, std::shared_ptr<buffer_vk>> buffers_;
|
||||||
std::map<uint32_t, std::shared_ptr<texture>> textures_;
|
std::map<uint32_t, std::shared_ptr<render_resource>> textures_;
|
||||||
protected:
|
protected:
|
||||||
void create_pipeline_layout();
|
void create_pipeline_layout();
|
||||||
};
|
};
|
||||||
|
@ -1,17 +1,67 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include "renderer.h"
|
||||||
|
#include "application/application.h"
|
||||||
|
|
||||||
class render_resource : public std::enable_shared_from_this<render_resource> {
|
class render_resource : public std::enable_shared_from_this<render_resource> {
|
||||||
public:
|
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;
|
void init(uint32_t width, uint32_t height, vk::Format in_format) {
|
||||||
|
width_ = width;
|
||||||
virtual ImTextureID get_texture_id() = 0;
|
height_ = height;
|
||||||
|
format = in_format;
|
||||||
void draw() {
|
on_init();
|
||||||
|
}
|
||||||
|
void draw() const {
|
||||||
ImGui::Image(get_texture_id(), ImVec2(static_cast<float>(get_width()), static_cast<float>(get_height())));
|
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 "application/application.h"
|
||||||
#include "utils/utils.hpp"
|
#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 {
|
void* render_target::lock(lock_state state) const {
|
||||||
const auto r = application::get()->get_renderer();
|
const auto r = application::get()->get_renderer();
|
||||||
const auto& device = r->device;
|
const auto& device = r->device;
|
||||||
@ -37,7 +29,14 @@ void render_target::unlock() {
|
|||||||
device.unmapMemory(memory);
|
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();
|
auto r = application::get()->get_renderer();
|
||||||
const auto& device = r->device;
|
const auto& device = r->device;
|
||||||
const auto& physical_device = r->physical_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.setArrayLayers(1);
|
||||||
image_create_info.setSamples(vk::SampleCountFlagBits::e1);
|
image_create_info.setSamples(vk::SampleCountFlagBits::e1);
|
||||||
image_create_info.setTiling(vk::ImageTiling::eOptimal);
|
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.setSharingMode(vk::SharingMode::eExclusive);
|
||||||
image_create_info.setInitialLayout(vk::ImageLayout::eUndefined);
|
image_create_info.setInitialLayout(vk::ImageLayout::eUndefined);
|
||||||
image = device.createImage(image_create_info);
|
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.setHeight(height);
|
||||||
framebuffer_create_info.setLayers(1);
|
framebuffer_create_info.setLayers(1);
|
||||||
framebuffer = device.createFramebuffer(framebuffer_create_info);
|
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) {
|
void render_target::on_init() {
|
||||||
const auto r = application::get()->get_renderer();
|
create(width_, height_);
|
||||||
const auto& device = r->device;
|
}
|
||||||
|
|
||||||
device.destroyFramebuffer(framebuffer);
|
|
||||||
device.destroyImageView(image_view);
|
|
||||||
device.destroyImage(image);
|
|
||||||
device.freeMemory(memory);
|
|
||||||
|
|
||||||
|
void render_target::on_resize(uint32_t width, uint32_t height) {
|
||||||
|
destroy();
|
||||||
create(width, height);
|
create(width, height);
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,8 @@ enum class lock_state {
|
|||||||
|
|
||||||
class render_target : public render_resource {
|
class render_target : public render_resource {
|
||||||
public:
|
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 uint32_t width, const uint32_t height) {
|
||||||
|
|
||||||
void resize(const int width, const int height) {
|
|
||||||
if (width_ == width && height_ == height)
|
if (width_ == width && height_ == height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -32,17 +27,12 @@ public:
|
|||||||
void* lock(lock_state state) const;
|
void* lock(lock_state state) const;
|
||||||
void unlock();
|
void unlock();
|
||||||
|
|
||||||
std::function<void(std::shared_ptr<render_resource>)> on_resize_callback;
|
void destroy() override;
|
||||||
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);
|
|
||||||
|
|
||||||
int width_ = 0;
|
std::function<void(std::shared_ptr<render_resource>)> on_resize_callback;
|
||||||
int height_ = 0;
|
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 "application/application.h"
|
||||||
#include "texture.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) {
|
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 std::ranges::any_of(properties, [extension](const vk::ExtensionProperties& p) {
|
||||||
return strcmp(p.extensionName, extension) == 0;
|
return strcmp(p.extensionName, extension) == 0;
|
||||||
@ -36,12 +47,27 @@ vk::CommandBuffer renderer::create_command_buffer(vk::CommandBufferLevel level,
|
|||||||
return command_buffer;
|
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();
|
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;
|
vk::SubmitInfo submit_info;
|
||||||
submit_info.setCommandBuffers(command_buffer);
|
submit_info.setCommandBuffers(command_buffer);
|
||||||
queue.submit(submit_info, nullptr);
|
queue.submit(submit_info, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer::init_vulkan(GLFWwindow* window_handle) {
|
void renderer::init_vulkan(GLFWwindow* window_handle) {
|
||||||
@ -70,7 +96,7 @@ void renderer::init_vulkan(GLFWwindow* window_handle) {
|
|||||||
init_info.Device = device;
|
init_info.Device = device;
|
||||||
init_info.QueueFamily = queue_family;
|
init_info.QueueFamily = queue_family;
|
||||||
init_info.Queue = queue;
|
init_info.Queue = queue;
|
||||||
init_info.PipelineCache = pipeline_cache;
|
init_info.PipelineCache = VK_NULL_HANDLE;
|
||||||
init_info.DescriptorPool = descriptor_pool;
|
init_info.DescriptorPool = descriptor_pool;
|
||||||
init_info.RenderPass = main_window_data.RenderPass;
|
init_info.RenderPass = main_window_data.RenderPass;
|
||||||
init_info.Subpass = 0;
|
init_info.Subpass = 0;
|
||||||
@ -120,10 +146,30 @@ void renderer::setup_vulkan(std::vector<const char*> instance_extensions) {
|
|||||||
create_info.flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
|
create_info.flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
|
||||||
}
|
}
|
||||||
#endif
|
#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 Vulkan Instance
|
||||||
create_info.setPEnabledExtensionNames(instance_extensions);
|
create_info.setPEnabledExtensionNames(instance_extensions);
|
||||||
instance = vk::createInstance(create_info, allocator);
|
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)
|
// Select Physical Device (GPU)
|
||||||
@ -228,8 +274,8 @@ void renderer::cleanup_vulkan() const {
|
|||||||
device.destroyDescriptorPool(descriptor_pool);
|
device.destroyDescriptorPool(descriptor_pool);
|
||||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||||
// Remove the debug report callback
|
// Remove the debug report callback
|
||||||
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT");
|
||||||
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
|
vkDestroyDebugReportCallbackEXT(instance, debug_report, (VkAllocationCallbacks*)allocator);
|
||||||
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
||||||
|
|
||||||
device.destroy();
|
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) {
|
std::shared_ptr<texture> renderer::create_texture(const uint8_t* data, int width, int height, vk::Format format) {
|
||||||
auto out = std::make_shared<texture>();
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
|
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define APP_USE_VULKAN_DEBUG_REPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
class pixel_shader_drawer;
|
class pixel_shader_drawer;
|
||||||
class render_target;
|
class render_target;
|
||||||
class texture;
|
class texture;
|
||||||
@ -58,10 +62,12 @@ public:
|
|||||||
uint32_t queue_family = (uint32_t) -1;
|
uint32_t queue_family = (uint32_t) -1;
|
||||||
vk::Queue queue = VK_NULL_HANDLE;
|
vk::Queue queue = VK_NULL_HANDLE;
|
||||||
vk::DescriptorPool descriptor_pool = 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::CommandPool get_command_pool() const;
|
||||||
[[nodiscard]] vk::CommandBuffer create_command_buffer(vk::CommandBufferLevel level, bool begin) 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;
|
ImGui_ImplVulkanH_Window main_window_data;
|
||||||
int min_image_count = 2;
|
int min_image_count = 2;
|
||||||
|
@ -8,12 +8,6 @@
|
|||||||
|
|
||||||
|
|
||||||
texture::texture() {
|
texture::texture() {
|
||||||
format = vk::Format::eUndefined;
|
|
||||||
width_ = 0;
|
|
||||||
height_ = 0;
|
|
||||||
image = nullptr;
|
|
||||||
image_view = nullptr;
|
|
||||||
sampler = nullptr;
|
|
||||||
memory = 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) {
|
void texture::upload(const void* data, size_t size) {
|
||||||
renderer* r = application::get()->get_renderer();
|
renderer* r = application::get()->get_renderer();
|
||||||
const vk::Device& device = r->device;
|
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);
|
// 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;
|
~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; }
|
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);
|
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:
|
protected:
|
||||||
int width_;
|
void on_init() override;
|
||||||
int height_;
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user