From bdd35fc2af40496b4cff9121ea5a3a364259642d Mon Sep 17 00:00:00 2001 From: Quentin LADEVIE Date: Thu, 3 Mar 2022 17:49:03 +0100 Subject: Primitive renderpass api & use handle for low level api resources --- src/primitive-renderpass.cpp | 150 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 src/primitive-renderpass.cpp (limited to 'src/primitive-renderpass.cpp') diff --git a/src/primitive-renderpass.cpp b/src/primitive-renderpass.cpp new file mode 100644 index 0000000..f8521e3 --- /dev/null +++ b/src/primitive-renderpass.cpp @@ -0,0 +1,150 @@ +#include "primitive-renderpass.hpp" + +#include "vk-renderer.hpp" +#include "vulkan/vulkan_core.h" +#include + + +void Primitive::set_pipeline(std::string &shader_name) { + std::vector dynamic_states { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + + pipeline = api.create_graphics_pipeline(shader_name.c_str(), (VkShaderStageFlagBits)(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), primitive_render_pass.render_pass, dynamic_states); +} + +void Primitive::set_constant_offset(off_t offset) { + constant_offset = offset; +} + +void Primitive::set_constant(off_t offset, uint64_t* constant) { + memcpy(constants.data() + offset, constant, sizeof(uint64_t)); +} + +void Primitive::set_constant(off_t offset, Texture* texture) { + auto image = api.get_image(texture->device_image); + + memcpy(constants.data() + offset, (void*)&image.bindless_storage_index, sizeof(bindless_index)); +} + +void Primitive::set_constant(off_t offset, Buffer* buffer) { + auto device_buffer = api.get_buffer(buffer->device_buffer); + memcpy(constants.data() + offset, (void*)&device_buffer.device_address, sizeof(VkDeviceAddress)); +} + +void Primitive::set_constant(off_t offset, Sampler* sampler) { + auto device_sampler = api.get_sampler(sampler->device_sampler); + memcpy(constants.data() + offset, (void*)&device_sampler.bindless_index, sizeof(bindless_index)); +} + +void Primitive::set_index_buffer(Buffer* index_buffer) { + this->index_buffer = index_buffer; +} + +void Primitive::set_scissor(int32_t x, int32_t y, uint32_t width, uint32_t height) { + scissor.offset.x = x; + scissor.offset.y = y; + scissor.extent.width = width; + scissor.extent.height = height; +} + +void Primitive::set_draw_info(size_t vertex_count, off_t first_vertex, off_t vertex_offset) { + this->element_count = vertex_count; + this->first_vertex = first_vertex; + this->vertex_offset = vertex_offset; +} + +void Primitive::render(VkCommandBuffer command_buffer) { + vkCmdSetScissor(command_buffer, 0, 1, &scissor); + + api.update_constants(command_buffer, VK_SHADER_STAGE_ALL_GRAPHICS, constant_offset, 64, (void*)&constants); + + api.draw( + command_buffer, + pipeline, + index_buffer->device_buffer, + element_count, + first_vertex, + vertex_offset + ); +}; + + +PrimitiveRenderpass::PrimitiveRenderpass(vkapi& api) + : Renderpass(api) { + }; + +void PrimitiveRenderpass::add_primitive(Primitive* new_primitive) { + primitives.push_back(new_primitive); +} + +void PrimitiveRenderpass::add_color_attachment(VkFormat format) { + color_attachments_format.push_back(format); +} + +void PrimitiveRenderpass::set_viewport(float x, float y, float width, float height) { + viewport.x = x; + viewport.y = y; + viewport.width = width; + viewport.height = height; +} + +void PrimitiveRenderpass::set_color_attachment(uint32_t index, Texture* attachment) { + auto device_image = api.get_image(attachment->device_image); + + if (device_image.size.width != framebuffers[0].size.width || + device_image.size.height != framebuffers[0].size.height) { + recreate_framebuffers(); + } + + + color_attachments[index] = attachment; + color_attachments_view[index] = device_image.view; +} + +void PrimitiveRenderpass::finalize_render_pass() { + render_pass = api.create_render_pass(color_attachments_format, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + create_framebuffers(); + + color_attachments.resize(color_attachments_format.size()); + color_attachments_view.resize(color_attachments_format.size()); +} + +void PrimitiveRenderpass::execute(vkrenderer& renderer, VkCommandBuffer command_buffer) { + VkExtent2D extent = { .width = (uint32_t)viewport.width, .height = (uint32_t)viewport.height }; + + for (auto& attachment : color_attachments) { + api.image_barrier(command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, attachment->device_image); + } + + + api.begin_render_pass(command_buffer, render_pass, color_attachments_view, framebuffers[renderer.frame_index()], extent); + + vkCmdSetViewport(command_buffer, 0, 1, &viewport); + + for (auto primitive : primitives) { + primitive->render(command_buffer); + } + + api.end_render_pass(command_buffer); + + primitives.clear(); +} + +void PrimitiveRenderpass::create_framebuffers() { + VkExtent2D size { .width = (uint32_t) viewport.width, .height = (uint32_t) viewport.height }; + + for(auto& framebuffer : framebuffers) { + framebuffer = api.create_framebuffer(render_pass, color_attachments_format, size); + } +} + +void PrimitiveRenderpass::recreate_framebuffers() { + for (auto& framebuffer: framebuffers) { + api.destroy_framebuffer(framebuffer); + } + + create_framebuffers(); +} -- cgit v1.3