mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-05 13:18:01 +03:00
Experimental Vulkan support
This commit is contained in:
@@ -0,0 +1,761 @@
|
||||
/*
|
||||
by korenkonder
|
||||
GitHub/GitLab: korenkonder
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "manager.hpp"
|
||||
#include "../../KKdLib/prj/shared_ptr.hpp"
|
||||
#include "../../KKdLib/hash.hpp"
|
||||
#include "../static_var.hpp"
|
||||
#include "DescriptorPipeline.hpp"
|
||||
#include "Pipeline.hpp"
|
||||
#include "RenderPass.hpp"
|
||||
#include "Sampler.hpp"
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
struct descriptor_pipeline_data {
|
||||
uint64_t vp_desc_hash;
|
||||
uint64_t fp_desc_hash;
|
||||
uint64_t unival_hash;
|
||||
|
||||
inline descriptor_pipeline_data() : vp_desc_hash(), fp_desc_hash(), unival_hash() {
|
||||
|
||||
}
|
||||
|
||||
inline descriptor_pipeline_data(uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash) {
|
||||
this->vp_desc_hash = vp_desc_hash;
|
||||
this->fp_desc_hash = fp_desc_hash;
|
||||
this->unival_hash = unival_hash;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class std::hash<descriptor_pipeline_data> {
|
||||
public:
|
||||
size_t operator()(const descriptor_pipeline_data& format) const {
|
||||
return (size_t)hash_xxh3_64bits(&format, sizeof(format));
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool operator==(const descriptor_pipeline_data& left, const descriptor_pipeline_data& right) {
|
||||
return left.vp_desc_hash == right.vp_desc_hash && left.fp_desc_hash == right.fp_desc_hash
|
||||
&& left.unival_hash == right.unival_hash;
|
||||
}
|
||||
|
||||
struct pipeline_data {
|
||||
uint64_t stages_hash;
|
||||
uint64_t vertex_input_info_binding_hash;
|
||||
uint64_t vertex_input_info_attribute_hash;
|
||||
uint64_t input_assembly_state_hash;
|
||||
uint64_t viewport_state_hash;
|
||||
uint64_t rasterization_state_hash;
|
||||
uint64_t depth_stencil_state_hash;
|
||||
uint64_t color_blend_attachmen_hash;
|
||||
VkPipelineLayout layout;
|
||||
VkRenderPass render_pass;
|
||||
|
||||
inline pipeline_data() : stages_hash(), vertex_input_info_binding_hash(),
|
||||
vertex_input_info_attribute_hash(), input_assembly_state_hash(),
|
||||
viewport_state_hash(), rasterization_state_hash(), depth_stencil_state_hash(),
|
||||
color_blend_attachmen_hash(), layout(), render_pass() {
|
||||
|
||||
}
|
||||
|
||||
inline pipeline_data(uint64_t stages_hash,
|
||||
uint64_t vertex_input_info_binding_hash, uint64_t vertex_input_info_attribute_hash,
|
||||
uint64_t input_assembly_state_hash, uint64_t viewport_state_hash,
|
||||
uint64_t rasterization_state_hash, uint64_t depth_stencil_state_hash, uint64_t color_blend_attachmen_hash,
|
||||
VkPipelineLayout layout, VkRenderPass render_pass) {
|
||||
this->stages_hash = stages_hash;
|
||||
this->vertex_input_info_binding_hash = vertex_input_info_binding_hash;
|
||||
this->vertex_input_info_attribute_hash = vertex_input_info_attribute_hash;
|
||||
this->input_assembly_state_hash = input_assembly_state_hash;
|
||||
this->viewport_state_hash = viewport_state_hash;
|
||||
this->rasterization_state_hash = rasterization_state_hash;
|
||||
this->depth_stencil_state_hash = depth_stencil_state_hash;
|
||||
this->color_blend_attachmen_hash = color_blend_attachmen_hash;
|
||||
this->layout = layout;
|
||||
this->render_pass = render_pass;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class std::hash<pipeline_data> {
|
||||
public:
|
||||
size_t operator()(const pipeline_data& format) const {
|
||||
return (size_t)hash_xxh3_64bits(&format, sizeof(format));
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool operator==(const pipeline_data& left, const pipeline_data& right) {
|
||||
return left.stages_hash == right.stages_hash
|
||||
&& left.vertex_input_info_binding_hash == right.vertex_input_info_binding_hash
|
||||
&& left.vertex_input_info_attribute_hash == right.vertex_input_info_attribute_hash
|
||||
&& left.input_assembly_state_hash == right.input_assembly_state_hash
|
||||
&& left.viewport_state_hash == right.viewport_state_hash
|
||||
&& left.rasterization_state_hash == right.rasterization_state_hash
|
||||
&& left.depth_stencil_state_hash == right.depth_stencil_state_hash
|
||||
&& left.color_blend_attachmen_hash == right.color_blend_attachmen_hash
|
||||
&& left.layout == right.layout && left.render_pass == right.render_pass;
|
||||
}
|
||||
|
||||
struct render_pass_data {
|
||||
uint64_t color_formats_hash;
|
||||
GLenum depth_format;
|
||||
bool stencil;
|
||||
uint8_t pad[3];
|
||||
|
||||
inline render_pass_data() : color_formats_hash(), depth_format(), stencil(), pad() {
|
||||
|
||||
}
|
||||
|
||||
inline render_pass_data(uint64_t color_formats_hash, GLenum depth_format, bool stencil) : pad() {
|
||||
this->color_formats_hash = color_formats_hash;
|
||||
this->depth_format = depth_format;
|
||||
this->stencil = stencil;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class std::hash<render_pass_data> {
|
||||
public:
|
||||
size_t operator()(const render_pass_data& format) const {
|
||||
return (size_t)hash_xxh3_64bits(&format, sizeof(format));
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool operator==(const render_pass_data& left, const render_pass_data& right) {
|
||||
return left.color_formats_hash == right.color_formats_hash
|
||||
&& left.depth_format == right.depth_format && left.stencil == right.stencil;
|
||||
}
|
||||
|
||||
namespace Vulkan {
|
||||
struct manager {
|
||||
struct free_framebuffer_data {
|
||||
VkDevice device;
|
||||
VkFramebuffer framebuffer;
|
||||
const VkAllocationCallbacks* allocator;
|
||||
|
||||
inline free_framebuffer_data() : device(), framebuffer(), allocator() {
|
||||
|
||||
}
|
||||
|
||||
inline free_framebuffer_data(VkDevice device,
|
||||
VkFramebuffer framebuffer, const VkAllocationCallbacks* allocator) {
|
||||
this->device = device;
|
||||
this->framebuffer = framebuffer;
|
||||
this->allocator = allocator;
|
||||
}
|
||||
};
|
||||
|
||||
struct free_image_view_data {
|
||||
VkDevice device;
|
||||
VkImageView image_view;
|
||||
const VkAllocationCallbacks* allocator;
|
||||
|
||||
inline free_image_view_data() : device(), image_view(), allocator() {
|
||||
|
||||
}
|
||||
|
||||
inline free_image_view_data(VkDevice device,
|
||||
VkImageView image_view, const VkAllocationCallbacks* allocator) {
|
||||
this->device = device;
|
||||
this->image_view = image_view;
|
||||
this->allocator = allocator;
|
||||
}
|
||||
};
|
||||
|
||||
struct frame_data {
|
||||
std::vector<free_framebuffer_data> free_framebuffers;
|
||||
std::vector<free_image_view_data> free_image_views;
|
||||
std::vector<Vulkan::DynamicBuffer> dynamic_buffers;
|
||||
std::vector<Vulkan::StagingBuffer> staging_buffers;
|
||||
|
||||
frame_data();
|
||||
~frame_data();
|
||||
|
||||
void ctrl();
|
||||
};
|
||||
|
||||
std::vector<frame_data> frames_data;
|
||||
uint32_t frame;
|
||||
|
||||
std::unordered_map<descriptor_pipeline_data,
|
||||
prj::shared_ptr<Vulkan::DescriptorPipeline>> descriptor_pipelines;
|
||||
std::unordered_map<pipeline_data, prj::shared_ptr<Vulkan::Pipeline>> pipelines;
|
||||
std::unordered_map<render_pass_data, prj::shared_ptr<Vulkan::RenderPass>> render_passes;
|
||||
std::unordered_map<uint64_t, prj::shared_ptr<Vulkan::Sampler>> samplers;
|
||||
|
||||
manager(uint32_t max_frames);
|
||||
~manager();
|
||||
|
||||
void free_framebuffer(VkDevice device,
|
||||
VkFramebuffer framebuffer, const VkAllocationCallbacks* allocator);
|
||||
void free_image_view(VkDevice device,
|
||||
VkImageView image_view, const VkAllocationCallbacks* allocator);
|
||||
prj::shared_ptr<Vulkan::DescriptorPipeline> get_descriptor_pipeline(
|
||||
uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash);
|
||||
prj::shared_ptr<Vulkan::DescriptorPipeline> get_descriptor_pipeline(
|
||||
uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash,
|
||||
uint32_t sampler_count, uint32_t uniform_count, uint32_t storage_count,
|
||||
const VkDescriptorSetLayoutBinding* bindings);
|
||||
frame_data& get_frame_data();
|
||||
prj::shared_ptr<Vulkan::Pipeline> get_pipeline(uint32_t stage_count,
|
||||
const VkPipelineShaderStageCreateInfo* stages,
|
||||
uint32_t vertex_input_binding_description_count,
|
||||
const VkVertexInputBindingDescription* vertex_input_binding_descriptions,
|
||||
uint32_t vertex_input_attribute_description_count,
|
||||
const VkVertexInputAttributeDescription* vertex_input_attribute_descriptions,
|
||||
const VkPipelineInputAssemblyStateCreateInfo* input_assembly_state,
|
||||
const VkRect2D viewport_scissor_rect[2],
|
||||
const VkPipelineRasterizationStateCreateInfo* rasterization_state,
|
||||
const VkPipelineDepthStencilStateCreateInfo* depth_stencil_state,
|
||||
uint32_t color_blend_attachment_count,
|
||||
const VkPipelineColorBlendAttachmentState* color_blend_attachments,
|
||||
VkPipelineLayout layout, VkRenderPass render_pass);
|
||||
prj::shared_ptr<Vulkan::RenderPass> get_render_pass(GLenum* color_formats,
|
||||
uint32_t color_format_count, GLenum depth_format, bool stencil);
|
||||
prj::shared_ptr<Vulkan::Sampler> get_sampler(const gl_sampler& sampler_data);
|
||||
Vulkan::Buffer get_dynamic_buffer(VkDeviceSize size, VkDeviceSize alignment, bool uniform);
|
||||
Vulkan::Buffer get_staging_buffer(VkDeviceSize size, VkDeviceSize alignment);
|
||||
void next_frame(uint32_t frame);
|
||||
void reset_descriptor_pipelines_descriptor_set_collections();
|
||||
};
|
||||
|
||||
manager* manager_ptr;
|
||||
|
||||
void manager_init(uint32_t max_frames) {
|
||||
manager_ptr = new manager(max_frames);
|
||||
}
|
||||
|
||||
void manager_free_descriptor_pipelines() {
|
||||
manager_ptr->descriptor_pipelines.clear();
|
||||
}
|
||||
|
||||
void manager_free_framebuffer(VkDevice device,
|
||||
VkFramebuffer framebuffer, const VkAllocationCallbacks* allocator) {
|
||||
manager_ptr->free_framebuffer(device, framebuffer, allocator);
|
||||
}
|
||||
|
||||
void manager_free_image_view(VkDevice device,
|
||||
VkImageView image_view, const VkAllocationCallbacks* allocator) {
|
||||
manager_ptr->free_image_view(device, image_view, allocator);
|
||||
}
|
||||
|
||||
void manager_free_pipelines() {
|
||||
manager_ptr->pipelines.clear();
|
||||
}
|
||||
|
||||
void manager_free_render_passes() {
|
||||
manager_ptr->render_passes.clear();
|
||||
}
|
||||
|
||||
void manager_free_samplers() {
|
||||
manager_ptr->samplers.clear();
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::DescriptorPipeline> manager_get_descriptor_pipeline(
|
||||
uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash) {
|
||||
return manager_ptr->get_descriptor_pipeline(vp_desc_hash, fp_desc_hash, unival_hash);
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::DescriptorPipeline> manager_get_descriptor_pipeline(
|
||||
uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash,
|
||||
uint32_t sampler_count, uint32_t uniform_count, uint32_t storage_count,
|
||||
const VkDescriptorSetLayoutBinding* bindings) {
|
||||
return manager_ptr->get_descriptor_pipeline(vp_desc_hash, fp_desc_hash, unival_hash,
|
||||
sampler_count, uniform_count, storage_count, bindings);
|
||||
}
|
||||
|
||||
uint32_t manager_get_frame() {
|
||||
return manager_ptr->frame;
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::Pipeline> manager_get_pipeline(uint32_t stage_count,
|
||||
const VkPipelineShaderStageCreateInfo* stages,
|
||||
uint32_t vertex_input_binding_description_count,
|
||||
const VkVertexInputBindingDescription* vertex_input_binding_descriptions,
|
||||
uint32_t vertex_input_attribute_description_count,
|
||||
const VkVertexInputAttributeDescription* vertex_input_attribute_descriptions,
|
||||
const VkPipelineInputAssemblyStateCreateInfo* input_assembly_state,
|
||||
const VkRect2D viewport_scissor_rect[2],
|
||||
const VkPipelineRasterizationStateCreateInfo* rasterization_state,
|
||||
const VkPipelineDepthStencilStateCreateInfo* depth_stencil_state,
|
||||
uint32_t color_blend_attachment_count,
|
||||
const VkPipelineColorBlendAttachmentState* color_blend_attachments,
|
||||
VkPipelineLayout layout, VkRenderPass render_pass) {
|
||||
return manager_ptr->get_pipeline(stage_count, stages,
|
||||
vertex_input_binding_description_count, vertex_input_binding_descriptions,
|
||||
vertex_input_attribute_description_count, vertex_input_attribute_descriptions,
|
||||
input_assembly_state, viewport_scissor_rect, rasterization_state, depth_stencil_state,
|
||||
color_blend_attachment_count, color_blend_attachments, layout, render_pass);
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::RenderPass> manager_get_render_pass(
|
||||
GLenum* color_formats, uint32_t color_format_count, GLenum depth_format, bool stencil) {
|
||||
return manager_ptr->get_render_pass(color_formats,
|
||||
color_format_count, depth_format, stencil);
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::Sampler> manager_get_sampler(const gl_sampler& sampler_data) {
|
||||
return manager_ptr->get_sampler(sampler_data);
|
||||
}
|
||||
|
||||
Vulkan::Buffer manager_get_dynamic_buffer(VkDeviceSize size, VkDeviceSize alignment) {
|
||||
return manager_ptr->get_dynamic_buffer(size, alignment, false);
|
||||
}
|
||||
|
||||
Vulkan::Buffer manager_get_dynamic_uniform_buffer(VkDeviceSize size, VkDeviceSize alignment) {
|
||||
return manager_ptr->get_dynamic_buffer(size, alignment, true);
|
||||
}
|
||||
|
||||
Vulkan::Buffer manager_get_staging_buffer(VkDeviceSize size, VkDeviceSize alignment) {
|
||||
return manager_ptr->get_staging_buffer(size, alignment);
|
||||
}
|
||||
|
||||
void manager_next_frame(uint32_t frame) {
|
||||
manager_ptr->next_frame(frame);
|
||||
}
|
||||
|
||||
void manager_reset_descriptor_pipelines_descriptor_set_collections() {
|
||||
manager_ptr->reset_descriptor_pipelines_descriptor_set_collections();
|
||||
}
|
||||
|
||||
void manager_free() {
|
||||
delete manager_ptr;
|
||||
}
|
||||
|
||||
manager::frame_data::frame_data() {
|
||||
|
||||
}
|
||||
|
||||
manager::frame_data::~frame_data() {
|
||||
ctrl();
|
||||
|
||||
for (Vulkan::StagingBuffer& i : staging_buffers)
|
||||
i.Destroy();
|
||||
for (Vulkan::DynamicBuffer& i : dynamic_buffers)
|
||||
i.Destroy();
|
||||
}
|
||||
|
||||
void manager::frame_data::ctrl() {
|
||||
for (free_framebuffer_data& i : free_framebuffers)
|
||||
vkDestroyFramebuffer(i.device, i.framebuffer, i.allocator);
|
||||
free_framebuffers.clear();
|
||||
|
||||
for (free_image_view_data& i : free_image_views)
|
||||
vkDestroyImageView(i.device, i.image_view, i.allocator);
|
||||
free_image_views.clear();
|
||||
|
||||
for (Vulkan::DynamicBuffer& i : dynamic_buffers) {
|
||||
if (!i.curr_size)
|
||||
i.empty_frame_count++;
|
||||
}
|
||||
|
||||
auto i_dyn_begin = dynamic_buffers.begin();
|
||||
auto i_dyn_end = dynamic_buffers.end();
|
||||
for (auto i = i_dyn_end; i != i_dyn_begin; ) {
|
||||
i--;
|
||||
|
||||
if (!i->curr_size) {
|
||||
i->empty_frame_count++;
|
||||
|
||||
if (i->empty_frame_count >= 60) {
|
||||
i->Destroy();
|
||||
dynamic_buffers.erase(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
i->empty_frame_count = 0;
|
||||
|
||||
i->curr_size = 0;
|
||||
}
|
||||
|
||||
auto i_stg_begin = staging_buffers.begin();
|
||||
auto i_stg_end = staging_buffers.end();
|
||||
for (auto i = i_stg_end; i != i_stg_begin; ) {
|
||||
i--;
|
||||
|
||||
if (!i->curr_size) {
|
||||
i->empty_frame_count++;
|
||||
|
||||
if (i->empty_frame_count >= 60) {
|
||||
i->Destroy();
|
||||
staging_buffers.erase(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
i->empty_frame_count = 0;
|
||||
|
||||
i->curr_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
manager::manager(uint32_t max_frames) : frame() {
|
||||
frames_data.resize(max_frames);
|
||||
}
|
||||
|
||||
manager::~manager() {
|
||||
|
||||
}
|
||||
|
||||
void manager::free_framebuffer(VkDevice device,
|
||||
VkFramebuffer framebuffer, const VkAllocationCallbacks* allocator) {
|
||||
if (framebuffer) {
|
||||
frame_data& frame_data = get_frame_data();
|
||||
frame_data.free_framebuffers.push_back({ device, framebuffer, allocator });
|
||||
}
|
||||
}
|
||||
|
||||
void manager::free_image_view(VkDevice device,
|
||||
VkImageView image_view, const VkAllocationCallbacks* allocator) {
|
||||
if (image_view) {
|
||||
frame_data& frame_data = get_frame_data();
|
||||
frame_data.free_image_views.push_back({ device, image_view, allocator });
|
||||
}
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::DescriptorPipeline> manager::get_descriptor_pipeline(
|
||||
uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash) {
|
||||
auto elem = descriptor_pipelines.find({ vp_desc_hash, fp_desc_hash, unival_hash });
|
||||
if (elem != descriptor_pipelines.end())
|
||||
return elem->second;
|
||||
return {};
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::DescriptorPipeline> manager::get_descriptor_pipeline(
|
||||
uint64_t vp_desc_hash, uint64_t fp_desc_hash, uint64_t unival_hash,
|
||||
uint32_t sampler_count, uint32_t uniform_count, uint32_t storage_count,
|
||||
const VkDescriptorSetLayoutBinding* bindings) {
|
||||
auto elem = descriptor_pipelines.find({ vp_desc_hash, fp_desc_hash, unival_hash });
|
||||
if (elem != descriptor_pipelines.end())
|
||||
return elem->second;
|
||||
|
||||
prj::shared_ptr<Vulkan::DescriptorPipeline> descriptor_pipeline(
|
||||
new Vulkan::DescriptorPipeline(Vulkan::current_device, Vulkan::current_descriptor_pool,
|
||||
sampler_count, uniform_count, storage_count, bindings));
|
||||
descriptor_pipelines.insert({ { vp_desc_hash, fp_desc_hash, unival_hash }, descriptor_pipeline });
|
||||
return descriptor_pipeline;
|
||||
}
|
||||
|
||||
manager::frame_data& manager::get_frame_data() {
|
||||
return frames_data.data()[frame];
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::Pipeline> manager::get_pipeline(uint32_t stage_count,
|
||||
const VkPipelineShaderStageCreateInfo* stages,
|
||||
uint32_t vertex_input_binding_description_count,
|
||||
const VkVertexInputBindingDescription* vertex_input_binding_descriptions,
|
||||
uint32_t vertex_input_attribute_description_count,
|
||||
const VkVertexInputAttributeDescription* vertex_input_attribute_descriptions,
|
||||
const VkPipelineInputAssemblyStateCreateInfo* input_assembly_state,
|
||||
const VkRect2D viewport_scissor_rect[2],
|
||||
const VkPipelineRasterizationStateCreateInfo* rasterization_state,
|
||||
const VkPipelineDepthStencilStateCreateInfo* depth_stencil_state,
|
||||
uint32_t color_blend_attachment_count,
|
||||
const VkPipelineColorBlendAttachmentState* color_blend_attachments,
|
||||
VkPipelineLayout layout, VkRenderPass render_pass) {
|
||||
uint64_t stages_hash = hash_xxh3_64bits(stages,
|
||||
sizeof(VkPipelineShaderStageCreateInfo) * stage_count);
|
||||
uint64_t vertex_input_info_binding_hash = hash_xxh3_64bits(vertex_input_binding_descriptions,
|
||||
sizeof(VkVertexInputBindingDescription) * vertex_input_binding_description_count);
|
||||
uint64_t vertex_input_info_attribute_hash = hash_xxh3_64bits(vertex_input_attribute_descriptions,
|
||||
sizeof(VkVertexInputBindingDescription) * vertex_input_attribute_description_count);
|
||||
uint64_t input_assembly_state_hash = hash_xxh3_64bits(input_assembly_state,
|
||||
sizeof(VkPipelineInputAssemblyStateCreateInfo));
|
||||
uint64_t viewport_state_hash = hash_xxh3_64bits(viewport_scissor_rect,
|
||||
sizeof(VkRect2D) * 2);
|
||||
uint64_t rasterization_state_hash = hash_xxh3_64bits(rasterization_state,
|
||||
sizeof(VkPipelineRasterizationStateCreateInfo));
|
||||
uint64_t depth_stencil_state_hash = hash_xxh3_64bits(depth_stencil_state,
|
||||
sizeof(VkPipelineDepthStencilStateCreateInfo));
|
||||
uint64_t color_blend_attachmen_hash = hash_xxh3_64bits(color_blend_attachments,
|
||||
sizeof(VkPipelineColorBlendAttachmentState) * color_blend_attachment_count);
|
||||
|
||||
auto elem = pipelines.find({ stages_hash, vertex_input_info_binding_hash, vertex_input_info_attribute_hash,
|
||||
input_assembly_state_hash, viewport_state_hash, rasterization_state_hash,
|
||||
depth_stencil_state_hash, color_blend_attachmen_hash, layout, render_pass });
|
||||
if (elem != pipelines.end())
|
||||
return elem->second;
|
||||
|
||||
VkViewport viewport;
|
||||
viewport.x = (float_t)viewport_scissor_rect[0].offset.x;
|
||||
viewport.y = (float_t)viewport_scissor_rect[0].offset.y;
|
||||
viewport.width = (float_t)viewport_scissor_rect[0].extent.width;
|
||||
viewport.height = (float_t)viewport_scissor_rect[0].extent.height;
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
VkRect2D scissor = viewport_scissor_rect[1];
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewport_state = {};
|
||||
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
viewport_state.viewportCount = 1;
|
||||
viewport_state.pViewports = &viewport;
|
||||
viewport_state.scissorCount = 1;
|
||||
viewport_state.pScissors = &scissor;
|
||||
|
||||
prj::shared_ptr<Vulkan::Pipeline> pipeline(new Vulkan::Pipeline(Vulkan::current_device, 0,
|
||||
stage_count, stages, vertex_input_binding_description_count, vertex_input_binding_descriptions,
|
||||
vertex_input_attribute_description_count, vertex_input_attribute_descriptions,
|
||||
input_assembly_state, &viewport_state, rasterization_state, depth_stencil_state,
|
||||
color_blend_attachment_count, color_blend_attachments, layout, render_pass));
|
||||
pipelines.insert({ { stages_hash, vertex_input_info_binding_hash, vertex_input_info_attribute_hash,
|
||||
input_assembly_state_hash, viewport_state_hash, rasterization_state_hash,
|
||||
depth_stencil_state_hash, color_blend_attachmen_hash, layout, render_pass }, pipeline });
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::RenderPass> manager::get_render_pass(GLenum* color_formats,
|
||||
uint32_t color_format_count, GLenum depth_format, bool stencil) {
|
||||
uint64_t color_formats_hash = hash_xxh3_64bits(color_formats,
|
||||
sizeof(GLenum) * color_format_count);
|
||||
|
||||
auto elem = render_passes.find({ color_formats_hash, depth_format, stencil });
|
||||
if (elem != render_passes.end())
|
||||
return elem->second;
|
||||
|
||||
VkAttachmentReference* color_attachment_reference = force_malloc<VkAttachmentReference>(color_format_count);
|
||||
VkAttachmentReference depth_attachment_reference = {};
|
||||
|
||||
VkSubpassDescription subpass_description = {};
|
||||
subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
if (color_format_count) {
|
||||
for (uint32_t i = 0; i < color_format_count; i++) {
|
||||
color_attachment_reference[i].attachment = i;
|
||||
color_attachment_reference[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
|
||||
subpass_description.colorAttachmentCount = color_format_count;
|
||||
subpass_description.pColorAttachments = color_attachment_reference;
|
||||
}
|
||||
else
|
||||
subpass_description.colorAttachmentCount = 0;
|
||||
|
||||
if (depth_format) {
|
||||
depth_attachment_reference.attachment = 1;
|
||||
depth_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
subpass_description.pDepthStencilAttachment = &depth_attachment_reference;
|
||||
}
|
||||
|
||||
VkSubpassDependency subpass_dependency = {};
|
||||
subpass_dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||
subpass_dependency.dstSubpass = 0;
|
||||
subpass_dependency.srcStageMask = 0;
|
||||
subpass_dependency.srcAccessMask = 0;
|
||||
subpass_dependency.dstStageMask = 0;
|
||||
subpass_dependency.dstAccessMask = 0;
|
||||
|
||||
if (color_format_count) {
|
||||
subpass_dependency.srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
subpass_dependency.dstStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
subpass_dependency.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
}
|
||||
|
||||
if (depth_format) {
|
||||
subpass_dependency.srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||
subpass_dependency.dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||
subpass_dependency.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
}
|
||||
|
||||
int32_t attachment_count = 0;
|
||||
|
||||
VkAttachmentDescription* attachments
|
||||
= force_malloc<VkAttachmentDescription>((size_t)color_format_count + 1);
|
||||
if (color_format_count)
|
||||
for (uint32_t i = 0; i < color_format_count; i++) {
|
||||
VkAttachmentDescription& color_attachment = attachments[attachment_count];
|
||||
color_attachment.flags = 0;
|
||||
color_attachment.format = Vulkan::get_format(color_formats[i]);
|
||||
color_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
color_attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
color_attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
attachment_count++;
|
||||
}
|
||||
|
||||
if (depth_format) {
|
||||
VkAttachmentDescription& depth_attachment = attachments[attachment_count];
|
||||
depth_attachment.flags = 0;
|
||||
depth_attachment.format = Vulkan::get_format(depth_format);
|
||||
depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
depth_attachment.stencilLoadOp = stencil
|
||||
? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
depth_attachment.stencilStoreOp = stencil
|
||||
? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depth_attachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
attachment_count++;
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::RenderPass> render_pass(new Vulkan::RenderPass(Vulkan::current_device, 0,
|
||||
attachment_count, attachments, 1, &subpass_description, 1, &subpass_dependency));
|
||||
render_passes.insert({ { color_formats_hash, depth_format, stencil }, render_pass });
|
||||
|
||||
free_def(attachments);
|
||||
free_def(color_attachment_reference);
|
||||
return render_pass;
|
||||
}
|
||||
|
||||
static VkSamplerAddressMode get_sampler_address_mode(GLenum wrap) {
|
||||
switch (wrap) {
|
||||
case GL_REPEAT:
|
||||
default:
|
||||
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case GL_CLAMP_TO_BORDER:
|
||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
case GL_CLAMP_TO_EDGE:
|
||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case GL_MIRRORED_REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
case GL_MIRROR_CLAMP_TO_EDGE:
|
||||
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
|
||||
}
|
||||
}
|
||||
|
||||
prj::shared_ptr<Vulkan::Sampler> manager::get_sampler(const gl_sampler& sampler_data) {
|
||||
uint64_t sampler_hash = hash_xxh3_64bits(&sampler_data, sizeof(gl_sampler));
|
||||
|
||||
auto elem = samplers.find(sampler_hash);
|
||||
if (elem != samplers.end())
|
||||
return elem->second;
|
||||
|
||||
VkFilter vk_mag_filter = sampler_data.mag_filter != GL_NEAREST ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
||||
VkFilter vk_min_filter;
|
||||
VkSamplerMipmapMode vk_mipmap_mode;
|
||||
switch (sampler_data.min_filter) {
|
||||
case GL_NEAREST:
|
||||
case GL_NEAREST_MIPMAP_NEAREST:
|
||||
vk_min_filter = VK_FILTER_NEAREST;
|
||||
vk_mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
break;
|
||||
case GL_LINEAR:
|
||||
case GL_LINEAR_MIPMAP_NEAREST:
|
||||
default:
|
||||
vk_min_filter = VK_FILTER_LINEAR;
|
||||
vk_mipmap_mode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
break;
|
||||
case GL_NEAREST_MIPMAP_LINEAR:
|
||||
vk_min_filter = VK_FILTER_NEAREST;
|
||||
vk_mipmap_mode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
break;
|
||||
case GL_LINEAR_MIPMAP_LINEAR:
|
||||
vk_min_filter = VK_FILTER_LINEAR;
|
||||
vk_mipmap_mode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
break;
|
||||
}
|
||||
|
||||
VkBorderColor vk_border_color;
|
||||
if (sampler_data.border_color == 0.0f)
|
||||
vk_border_color = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
else if (sampler_data.border_color == vec4(0.0f, 0.0f, 0.0f, 1.0f))
|
||||
vk_border_color = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
|
||||
else if (sampler_data.border_color == 1.0f)
|
||||
vk_border_color = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
else
|
||||
vk_border_color = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
|
||||
prj::shared_ptr<Vulkan::Sampler> sampler(new Vulkan::Sampler(Vulkan::current_device, 0,
|
||||
vk_mag_filter, vk_min_filter, vk_mipmap_mode,
|
||||
get_sampler_address_mode(sampler_data.wrap_s),
|
||||
get_sampler_address_mode(sampler_data.wrap_t),
|
||||
get_sampler_address_mode(sampler_data.wrap_r),
|
||||
-1000.0f, 1000.0f, sampler_data.max_anisotropy, vk_border_color));
|
||||
samplers.insert({ sampler_hash, sampler });
|
||||
return sampler;
|
||||
}
|
||||
|
||||
Vulkan::Buffer manager::get_dynamic_buffer(VkDeviceSize size, VkDeviceSize alignment, bool uniform) {
|
||||
frame_data& frame_data = get_frame_data();
|
||||
|
||||
VkBufferUsageFlags usage = 0;
|
||||
if (uniform)
|
||||
usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
else {
|
||||
usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||
usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||
}
|
||||
|
||||
for (Vulkan::DynamicBuffer& i : frame_data.dynamic_buffers)
|
||||
if ((i.usage & usage) == usage
|
||||
&& align_val(i.curr_size, alignment) + align_val(size, alignment) <= i.GetSize()) {
|
||||
i.curr_size = align_val(i.curr_size, alignment);
|
||||
|
||||
Vulkan::Buffer buffer = (Vulkan::Buffer)i;
|
||||
buffer.SetOffset(i.curr_size);
|
||||
buffer.SetSize(size);
|
||||
i.curr_size += align_val(size, alignment);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
VkDeviceSize buffer_size = sv_max_uniform_buffer_size;
|
||||
if (!uniform) {
|
||||
buffer_size = 0x1000000;
|
||||
while (buffer_size <= size)
|
||||
buffer_size *= 2;
|
||||
}
|
||||
|
||||
frame_data.dynamic_buffers.push_back({});
|
||||
Vulkan::DynamicBuffer& dynamic_buffer = frame_data.dynamic_buffers.back();
|
||||
dynamic_buffer.Create(Vulkan::current_allocator, buffer_size, usage);
|
||||
|
||||
Vulkan::Buffer buffer = (Vulkan::Buffer)dynamic_buffer;
|
||||
buffer.SetOffset(0);
|
||||
buffer.SetSize(size);
|
||||
dynamic_buffer.curr_size = align_val(size, alignment);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Vulkan::Buffer manager::get_staging_buffer(VkDeviceSize size, VkDeviceSize alignment) {
|
||||
frame_data& frame_data = get_frame_data();
|
||||
|
||||
for (Vulkan::StagingBuffer& i : frame_data.staging_buffers)
|
||||
if (align_val(i.curr_size, alignment) + align_val(size, alignment) <= i.GetSize()) {
|
||||
i.curr_size = align_val(i.curr_size, alignment);
|
||||
|
||||
Vulkan::Buffer buffer = (Vulkan::Buffer)i;
|
||||
buffer.SetOffset(i.curr_size);
|
||||
buffer.SetSize(size);
|
||||
i.curr_size += align_val(size, alignment);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
VkDeviceSize buffer_size = 0x1000000;
|
||||
while (buffer_size <= size)
|
||||
buffer_size *= 2;
|
||||
|
||||
frame_data.staging_buffers.push_back({});
|
||||
Vulkan::StagingBuffer& staging_buffer = frame_data.staging_buffers.back();
|
||||
staging_buffer.Create(Vulkan::current_allocator, buffer_size);
|
||||
|
||||
Vulkan::Buffer buffer = (Vulkan::Buffer)staging_buffer;
|
||||
buffer.SetOffset(0);
|
||||
buffer.SetSize(size);
|
||||
staging_buffer.curr_size = align_val(size, alignment);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void manager::next_frame(uint32_t frame) {
|
||||
this->frame = frame;
|
||||
get_frame_data().ctrl();
|
||||
}
|
||||
|
||||
void manager::reset_descriptor_pipelines_descriptor_set_collections() {
|
||||
for (auto& i : descriptor_pipelines)
|
||||
i.second.get()->ResetSetCollectionsState();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user