diff options
author | Frederico Linhares <fred@linhares.blue> | 2022-11-09 16:11:15 -0300 |
---|---|---|
committer | Frederico Linhares <fred@linhares.blue> | 2022-11-09 17:19:06 -0300 |
commit | bde8c8bd073abeb314748d66d6402f951ecb2902 (patch) | |
tree | 69c91317baf62a0ad9e36d8e35969fd82a02e91d | |
parent | 7e9107cb1c5012fef900dfa03408e2179f1f9915 (diff) |
feat create method Rectangle#draw
31 files changed, 1323 insertions, 199 deletions
diff --git a/glsl/shader_2d_wired.frag.glsl b/glsl/shader_2d_wired.frag.glsl new file mode 100644 index 0000000..0671223 --- /dev/null +++ b/glsl/shader_2d_wired.frag.glsl @@ -0,0 +1,30 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#version 450 + +layout(location = 0) out vec4 out_color; + +layout(set = 1, binding = 0) uniform UBOModel2D +{ + vec3 color; +} ubo_model_2d; + +void +main() +{ + out_color = vec4(ubo_model_2d.color, 1.0); +} diff --git a/glsl/shader_2d_wired.vert.glsl b/glsl/shader_2d_wired.vert.glsl new file mode 100644 index 0000000..97330dc --- /dev/null +++ b/glsl/shader_2d_wired.vert.glsl @@ -0,0 +1,30 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#version 450 + +layout(location = 0) in vec2 in_position; + +layout(set = 0, binding = 0) uniform UBOView2D +{ + mat4 proj; +} ubo_view; + +void +main() +{ + gl_Position = ubo_view.proj * vec4(in_position, 0.0, 1.0); +} diff --git a/src/core.cpp b/src/core.cpp index f3f0e14..ae8db70 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -540,12 +540,12 @@ unload_vk_graphics_pipeline_3d_layout(void *obj) } void -load_vk_graphics_pipeline_2d_layout(void *obj) +load_vk_graphics_pipeline_2d_solid_layout(void *obj) { try { - cg_core.vk_graphics_pipeline_2d_layout = - new VK::GraphicsPipeline2DLayout(); + cg_core.vk_graphics_pipeline_2d_solid_layout = + new VK::GraphicsPipeline2DSolidLayout(); } catch(const CommandError &e) { @@ -554,9 +554,29 @@ load_vk_graphics_pipeline_2d_layout(void *obj) } void -unload_vk_graphics_pipeline_2d_layout(void *obj) +unload_vk_graphics_pipeline_2d_solid_layout(void *obj) { - delete cg_core.vk_graphics_pipeline_2d_layout; + delete cg_core.vk_graphics_pipeline_2d_solid_layout; +} + +void +load_vk_graphics_pipeline_2d_wired_layout(void *obj) +{ + try + { + cg_core.vk_graphics_pipeline_2d_wired_layout = + new VK::GraphicsPipeline2DWiredLayout(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_vk_graphics_pipeline_2d_wired_layout(void *obj) +{ + delete cg_core.vk_graphics_pipeline_2d_wired_layout; } void @@ -580,12 +600,32 @@ unload_vk_graphics_pipeline_3d(void *obj) } void -load_vk_graphics_pipeline_2d(void *obj) +load_vk_graphics_pipeline_2d_solid(void *obj) +{ + try + { + cg_core.vk_graphics_pipeline_2d_solid = + std::make_unique<VK::GraphicsPipeline2DSolid>(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_vk_graphics_pipeline_2d_solid(void *obj) +{ + cg_core.vk_graphics_pipeline_2d_solid = nullptr; +} + +void +load_vk_graphics_pipeline_2d_wired(void *obj) { try { - cg_core.vk_graphics_pipeline_2d = - std::make_unique<VK::GraphicsPipeline2D>(); + cg_core.vk_graphics_pipeline_2d_wired = + std::make_unique<VK::GraphicsPipeline2DWired>(); } catch(const CommandError &e) { @@ -594,9 +634,9 @@ load_vk_graphics_pipeline_2d(void *obj) } void -unload_vk_graphics_pipeline_2d(void *obj) +unload_vk_graphics_pipeline_2d_wired(void *obj) { - cg_core.vk_graphics_pipeline_2d = nullptr; + cg_core.vk_graphics_pipeline_2d_wired = nullptr; } void @@ -672,10 +712,13 @@ const CommandChain cg_sCore::loader{ {&load_vk_graphics_pipeline_3d_layout, &unload_vk_graphics_pipeline_3d_layout}, - {&load_vk_graphics_pipeline_2d_layout, - &unload_vk_graphics_pipeline_2d_layout}, + {&load_vk_graphics_pipeline_2d_solid_layout, + &unload_vk_graphics_pipeline_2d_solid_layout}, + {&load_vk_graphics_pipeline_2d_wired_layout, + &unload_vk_graphics_pipeline_2d_wired_layout}, {&load_vk_graphics_pipeline_3d, &unload_vk_graphics_pipeline_3d}, - {&load_vk_graphics_pipeline_2d, &unload_vk_graphics_pipeline_2d}, + {&load_vk_graphics_pipeline_2d_solid, &unload_vk_graphics_pipeline_2d_solid}, + {&load_vk_graphics_pipeline_2d_wired, &unload_vk_graphics_pipeline_2d_wired}, {&load_vk_renderer, &unload_vk_renderer}, {&load_mruby_interface, nullptr} diff --git a/src/core.hpp b/src/core.hpp index 0830a49..5d92cfa 100644 --- a/src/core.hpp +++ b/src/core.hpp @@ -46,10 +46,12 @@ #include "worker.hpp" #include "vk/device.hpp" +#include "vk/graphics_pipeline_2d_solid_layout.hpp" +#include "vk/graphics_pipeline_2d_wired_layout.hpp" +#include "vk/graphics_pipeline_2d_solid.hpp" +#include "vk/graphics_pipeline_2d_wired.hpp" #include "vk/graphics_pipeline_3d_layout.hpp" -#include "vk/graphics_pipeline_2d_layout.hpp" #include "vk/graphics_pipeline_3d.hpp" -#include "vk/graphics_pipeline_2d.hpp" #include "vk/renderer.hpp" #include "vk/swapchain.hpp" @@ -110,9 +112,11 @@ struct cg_sCore VK::Swapchain *vk_swapchain; VK::GraphicsPipeline3DLayout *vk_graphics_pipeline_3d_layout; - VK::GraphicsPipeline2DLayout *vk_graphics_pipeline_2d_layout; + VK::GraphicsPipeline2DSolidLayout *vk_graphics_pipeline_2d_solid_layout; + VK::GraphicsPipeline2DWiredLayout *vk_graphics_pipeline_2d_wired_layout; std::unique_ptr<VK::GraphicsPipeline3D> vk_graphics_pipeline_3d; - std::unique_ptr<VK::GraphicsPipeline2D> vk_graphics_pipeline_2d; + std::unique_ptr<VK::GraphicsPipeline2DSolid> vk_graphics_pipeline_2d_solid; + std::unique_ptr<VK::GraphicsPipeline2DWired> vk_graphics_pipeline_2d_wired; VK::Renderer *vk_renderer; diff --git a/src/rectangle.cpp b/src/rectangle.cpp index 3bc0a84..18c86a4 100644 --- a/src/rectangle.cpp +++ b/src/rectangle.cpp @@ -16,28 +16,16 @@ #include "rectangle.hpp" -namespace -{ - -constexpr bool -align_vertically(float a_x, float a_width, float b_x, float b_width) -{ - return a_x <= b_x + b_width && a_x + a_width >= b_x; -} - -constexpr bool -align_horizontally(float a_y, float a_height, float b_y, float b_height) -{ - return a_y <= b_y + b_height && a_y + a_height >= b_y; -} - -} +#include "vector_3d.hpp" +#include "view_2d.hpp" +#include "view_3d.hpp" void cg_free_rectangle(mrb_state *mrb, void* obj) { - auto ptr = static_cast<cg_rectangle*>(obj); + auto ptr = static_cast<std::shared_ptr<VK::Rectangle>*>(obj); + ptr->~shared_ptr(); mrb_free(mrb, ptr); } @@ -48,17 +36,16 @@ static mrb_value cg_cRectangle_initialize(mrb_state *mrb, mrb_value self) { mrb_float x, y, width, height; - struct cg_rectangle *ptr; + std::shared_ptr<VK::Rectangle> *ptr; mrb_get_args(mrb, "ffff", &x, &y, &width, &height); - ptr = (cg_rectangle *)DATA_PTR(self); + ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); if(ptr) mrb_free(mrb, ptr); - ptr = (cg_rectangle *)mrb_malloc(mrb, sizeof(cg_rectangle)); + ptr = (std::shared_ptr<VK::Rectangle>*)mrb_malloc( + mrb, sizeof(std::shared_ptr<VK::Rectangle>)); - ptr->x = x; - ptr->y = y; - ptr->width = width; - ptr->height = height; + new(ptr)std::shared_ptr<VK::Rectangle>( + std::make_shared<VK::Rectangle>(x, y, width, height)); mrb_data_init(self, ptr, &cg_rectangle_type); return self; @@ -67,122 +54,141 @@ cg_cRectangle_initialize(mrb_state *mrb, mrb_value self) static mrb_value cg_cRectangle_get_x(mrb_state *mrb, mrb_value self) { - auto ptr = (cg_rectangle *)DATA_PTR(self); + auto ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); - return mrb_float_value(mrb, ptr->x); + return mrb_float_value(mrb, (*ptr)->x); } static mrb_value cg_cRectangle_set_x(mrb_state *mrb, mrb_value self) { mrb_float x; - auto ptr = (cg_rectangle *)DATA_PTR(self); + auto ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); mrb_get_args(mrb, "f", &x); - ptr->x = x; + (*ptr)->x = x; - return mrb_float_value(mrb, ptr->x); + return mrb_float_value(mrb, (*ptr)->x); } static mrb_value cg_cRectangle_get_y(mrb_state *mrb, mrb_value self) { - auto ptr = (cg_rectangle *)DATA_PTR(self); + auto ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); - return mrb_float_value(mrb, ptr->y); + return mrb_float_value(mrb, (*ptr)->y); } static mrb_value cg_cRectangle_set_y(mrb_state *mrb, mrb_value self) { mrb_float y; - auto *ptr = (cg_rectangle *)DATA_PTR(self); + auto ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); mrb_get_args(mrb, "f", &y); - ptr->y = y; + (*ptr)->y = y; - return mrb_float_value(mrb, ptr->y); + return mrb_float_value(mrb, (*ptr)->y); } static mrb_value cg_cRectangle_get_width(mrb_state *mrb, mrb_value self) { - auto *ptr = (cg_rectangle *)DATA_PTR(self); + auto ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); - return mrb_float_value(mrb, ptr->width); + return mrb_float_value(mrb, (*ptr)->width); } static mrb_value cg_cRectangle_set_width(mrb_state *mrb, mrb_value self) { mrb_float width; - auto *ptr = (struct cg_rectangle *)DATA_PTR(self); + auto ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); mrb_get_args(mrb, "f", &width); - ptr->width = width; + (*ptr)->width = width; - return mrb_float_value(mrb, ptr->width); + return mrb_float_value(mrb, (*ptr)->width); } static mrb_value cg_cRectangle_get_height(mrb_state *mrb, mrb_value self) { - auto *ptr = (struct cg_rectangle *)DATA_PTR(self); + auto ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); - return mrb_float_value(mrb, ptr->height); + return mrb_float_value(mrb, (*ptr)->height); } static mrb_value cg_cRectangle_set_height(mrb_state *mrb, mrb_value self) { mrb_float height; - auto *ptr = (cg_rectangle *)DATA_PTR(self); + auto ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); mrb_get_args(mrb, "f", &height); - ptr->height = height; + (*ptr)->height = height; - return mrb_float_value(mrb, ptr->height); + return mrb_float_value(mrb, (*ptr)->height); } static mrb_value cg_cRectangle_align_vertically(mrb_state *mrb, mrb_value self) { - cg_rectangle *ptr, *that; + std::shared_ptr<VK::Rectangle> *ptr, *that; mrb_get_args(mrb, "d", &that, &cg_rectangle_type); - ptr = (cg_rectangle *)DATA_PTR(self); + ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); - return mrb_bool_value( - align_vertically(ptr->x, ptr->width, that->x, that->width)); + return mrb_bool_value((*ptr)->align_vertically(**that)); } static mrb_value cg_cRectangle_align_horizontally(mrb_state *mrb, mrb_value self) { - cg_rectangle *ptr, *that; + std::shared_ptr<VK::Rectangle> *ptr, *that; mrb_get_args(mrb, "d", &that, &cg_rectangle_type); - ptr = (cg_rectangle *)DATA_PTR(self); + ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); - return mrb_bool_value( - align_horizontally(ptr->y, ptr->height, that->y, that->height)); + return mrb_bool_value((*ptr)->align_horizontally(**that)); } static mrb_value cg_cRectangle_collide(mrb_state *mrb, mrb_value self) { - cg_rectangle *ptr, *that; + std::shared_ptr<VK::Rectangle> *ptr, *that; mrb_get_args(mrb, "d", &that, &cg_rectangle_type); - ptr = (cg_rectangle *)DATA_PTR(self); + ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); - return mrb_bool_value( - align_vertically(ptr->x, ptr->width, that->x, that->width) && - align_horizontally(ptr->y, ptr->height, that->y, that->height)); + return mrb_bool_value((*ptr)->collide(**that)); +} + +static mrb_value +cg_cRectangle_draw(mrb_state *mrb, mrb_value self) +{ + mrb_value view_value; + VK::View2D *view_2d; + std::shared_ptr<glm::vec3> *color; + auto ptr = (std::shared_ptr<VK::Rectangle>*)DATA_PTR(self); + + mrb_get_args(mrb, "od", &view_value, &color, &cg_vector_3d_type); + + view_2d = cg_cView_to_view_2d(mrb, view_value); + + VK::UBOModel2D model; + model.color = **color; + (*ptr)->ub_rectangle[cg_core.vk_swapchain->current_frame].copy_data(&model); + (*ptr)->update_vertex_buffer(); + auto &rectangles = view_2d->rectangles_to_draw[ + cg_core.vk_swapchain->current_frame]; + rectangles.push_back(*ptr); + + return self; } void @@ -221,4 +227,6 @@ cg_rectangle_init(mrb_state *mrb) cg_cRectangle_align_horizontally, MRB_ARGS_REQ(1)); mrb_define_method( mrb, cg_cRectangle, "collide?", cg_cRectangle_collide, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cRectangle, "draw", cg_cRectangle_draw, MRB_ARGS_REQ(2)); } diff --git a/src/rectangle.hpp b/src/rectangle.hpp index e89b6ba..8ed1748 100644 --- a/src/rectangle.hpp +++ b/src/rectangle.hpp @@ -18,11 +18,7 @@ #define CANDY_GEAR_RECTANGLE_H 1 #include "core.hpp" - -struct cg_rectangle -{ - float x, y, width, height; -}; +#include "vk/rectangle.hpp" extern const struct mrb_data_type cg_rectangle_type; diff --git a/src/sprite.cpp b/src/sprite.cpp index 5f815f6..fa5e22f 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -18,6 +18,7 @@ #include "texture.hpp" #include "vector_4d.hpp" +#include "view_2d.hpp" #include "vk/sprite.hpp" void @@ -52,6 +53,25 @@ cg_cSprite_initialize(mrb_state *mrb, mrb_value self) return self; } +static mrb_value +cg_cSprite_draw(mrb_state *mrb, mrb_value self) +{ + mrb_value view_value; + VK::View2D *view_2d; + std::shared_ptr<glm::vec4> *position; + auto ptr = (std::shared_ptr<VK::Sprite>*)DATA_PTR(self); + + mrb_get_args(mrb, "od", &view_value, &position, &cg_vector_4d_type); + + view_2d = cg_cView_to_view_2d(mrb, view_value); + + auto &positions = view_2d->sprites_to_draw[ + cg_core.vk_swapchain->current_frame][*ptr]; + positions.push_back(*position->get()); + + return self; +} + void cg_sprite_init(mrb_state *mrb) { @@ -62,4 +82,5 @@ cg_sprite_init(mrb_state *mrb) MRB_SET_INSTANCE_TT(cg_cSprite, MRB_TT_DATA); mrb_define_method( mrb, cg_cSprite, "initialize", cg_cSprite_initialize, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, cg_cSprite, "draw", cg_cSprite_draw, MRB_ARGS_REQ(2)); } diff --git a/src/view_2d.cpp b/src/view_2d.cpp index c84cbee..3f4325d 100644 --- a/src/view_2d.cpp +++ b/src/view_2d.cpp @@ -18,6 +18,7 @@ #include "sprite.hpp" #include "vector_4d.hpp" +#include "view_3d.hpp" #include "vk/sprite.hpp" #include "vk/view_2d.hpp" @@ -51,20 +52,26 @@ cg_cView2D_initialize(mrb_state *mrb, mrb_value self) return self; } -static mrb_value -cg_cView2D_draw(mrb_state *mrb, mrb_value self) +VK::View2D* +cg_cView_to_view_2d(mrb_state *mrb, mrb_value view_value) { - std::shared_ptr<VK::Sprite> *sprite; - std::shared_ptr<glm::vec4> *position; - auto *ptr = (std::shared_ptr<VK::View2D>*)DATA_PTR(self); + VK::View2D* view_2d; + const mrb_data_type *type = DATA_TYPE(view_value); - mrb_get_args(mrb, "dd", &sprite, &cg_sprite_type, - &position, &cg_vector_4d_type); - auto &positions = (*ptr)->sprites_to_draw[ - cg_core.vk_swapchain->current_frame][*sprite]; - positions.push_back(*position->get()); + if(type == &cg_view_2d_type) + view_2d = static_cast<std::shared_ptr<VK::View2D>*>( + DATA_PTR(view_value))->get(); + else if (type == &cg_view_3d_type) + view_2d = static_cast<VK::View2D*>( + static_cast<std::shared_ptr<VK::View3D>*>( + DATA_PTR(view_value))->get()); + else + mrb_raisef( + mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s or %s)", + type->struct_name, cg_view_2d_type.struct_name, + cg_view_3d_type.struct_name); - return self; + return view_2d; } void @@ -77,5 +84,4 @@ cg_view_2d_init(mrb_state *mrb) MRB_SET_INSTANCE_TT(cg_cView2D, MRB_TT_DATA); mrb_define_method( mrb, cg_cView2D, "initialize", cg_cView2D_initialize, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, cg_cView2D, "draw", cg_cView2D_draw, MRB_ARGS_REQ(2)); } diff --git a/src/view_2d.hpp b/src/view_2d.hpp index 0b33380..c2b1701 100644 --- a/src/view_2d.hpp +++ b/src/view_2d.hpp @@ -21,6 +21,12 @@ extern const struct mrb_data_type cg_view_2d_type; +// Receives a mrb_value that points to a View2D or a View3D and returns a +// pointer to View2D. If the mrb_value points to a View3D, the view will be +// cast to a VK::View2D. +VK::View2D* +cg_cView_to_view_2d(mrb_state *mrb, mrb_value view_value); + void cg_view_2d_init(mrb_state *mrb); diff --git a/src/view_3d.cpp b/src/view_3d.cpp index 4e8b254..1b733b8 100644 --- a/src/view_3d.cpp +++ b/src/view_3d.cpp @@ -77,22 +77,6 @@ cg_cView3D_set_camera_rotation(mrb_state *mrb, mrb_value self) return self; } -static mrb_value -cg_cView3D_draw(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr<VK::Sprite> *sprite; - std::shared_ptr<glm::vec4> *position; - auto *ptr = (std::shared_ptr<VK::View3D>*)DATA_PTR(self); - - mrb_get_args(mrb, "dd", &sprite, &cg_sprite_type, - &position, &cg_vector_4d_type); - auto &positions = (*ptr)->sprites_to_draw[ - cg_core.vk_swapchain->current_frame][*sprite]; - positions.push_back(*position->get()); - - return self; -} - void cg_view_3d_init(mrb_state *mrb) { @@ -109,5 +93,4 @@ cg_view_3d_init(mrb_state *mrb) mrb_define_method( mrb, cg_cView3D, "camera_rotation=", cg_cView3D_set_camera_rotation, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, cg_cView3D, "draw", cg_cView3D_draw, MRB_ARGS_REQ(2)); } diff --git a/src/vk/destination_buffer.cpp b/src/vk/destination_buffer.cpp index 872f8a8..5c55fd2 100644 --- a/src/vk/destination_buffer.cpp +++ b/src/vk/destination_buffer.cpp @@ -34,39 +34,7 @@ DestinationBuffer::DestinationBuffer( BaseBuffer::loader.execute(dynamic_cast<BaseBuffer*>(this)); - // Load command - { - CommandPool command_pool(this->queue_family, 1); - Queue transfer_queue{this->queue_family->get_queue()}; - - this->vk_command_buffer = command_pool.command_buffers[0]; - - VkCommandBufferBeginInfo begin_info = {}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - - VkBufferCopy copy_region = {}; - copy_region.srcOffset = 0; - copy_region.dstOffset = 0; - copy_region.size = this->device_size; - - vkBeginCommandBuffer(this->vk_command_buffer, &begin_info); - - vkCmdCopyBuffer( - this->vk_command_buffer, this->source_buffer->buffer, this->buffer, 1, - ©_region); - - vkEndCommandBuffer(this->vk_command_buffer); - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &this->vk_command_buffer; - - vkQueueSubmit(transfer_queue.queue, 1, &submit_info, VK_NULL_HANDLE); - - vkQueueWaitIdle(transfer_queue.queue); - } + this->copy_data(); } DestinationBuffer::DestinationBuffer( @@ -102,4 +70,40 @@ DestinationBuffer::~DestinationBuffer() BaseBuffer::loader.revert(dynamic_cast<BaseBuffer*>(this)); } +void +DestinationBuffer::copy_data() +{ + CommandPool command_pool(this->queue_family, 1); + Queue transfer_queue{this->queue_family->get_queue()}; + this->device_size = source_buffer->device_size; + + this->vk_command_buffer = command_pool.command_buffers[0]; + + VkCommandBufferBeginInfo begin_info = {}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + VkBufferCopy copy_region = {}; + copy_region.srcOffset = 0; + copy_region.dstOffset = 0; + copy_region.size = this->device_size; + + vkBeginCommandBuffer(this->vk_command_buffer, &begin_info); + + vkCmdCopyBuffer( + this->vk_command_buffer, this->source_buffer->buffer, this->buffer, 1, + ©_region); + + vkEndCommandBuffer(this->vk_command_buffer); + + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &this->vk_command_buffer; + + vkQueueSubmit(transfer_queue.queue, 1, &submit_info, VK_NULL_HANDLE); + + vkQueueWaitIdle(transfer_queue.queue); +} + } diff --git a/src/vk/destination_buffer.hpp b/src/vk/destination_buffer.hpp index e856f4d..9b42af3 100644 --- a/src/vk/destination_buffer.hpp +++ b/src/vk/destination_buffer.hpp @@ -44,6 +44,9 @@ struct DestinationBuffer: public BaseBuffer operator=(DestinationBuffer &&that); ~DestinationBuffer(); + + void + copy_data(); }; } diff --git a/src/vk/device.cpp b/src/vk/device.cpp index 74727f9..957ae6d 100644 --- a/src/vk/device.cpp +++ b/src/vk/device.cpp @@ -126,6 +126,7 @@ Device::Device(VkPhysicalDevice vk_physical_device, bool with_swapchain) VkPhysicalDeviceFeatures required_features = {}; required_features.multiDrawIndirect = supported_features.multiDrawIndirect; + required_features.fillModeNonSolid = VK_TRUE; required_features.geometryShader = VK_TRUE; required_features.tessellationShader = VK_TRUE; required_features.samplerAnisotropy = VK_TRUE; @@ -165,6 +166,10 @@ Device::Device(VkPhysicalDevice vk_physical_device, bool with_swapchain) this->device, DATA_DIR "/glsl/shader_2d.vert.spv"); this->frag2d_shader_module = create_shader_module( this->device, DATA_DIR "/glsl/shader_2d.frag.spv"); + this->vert2d_wired_shader_module = create_shader_module( + this->device, DATA_DIR "/glsl/shader_2d_wired.vert.spv"); + this->frag2d_wired_shader_module = create_shader_module( + this->device, DATA_DIR "/glsl/shader_2d_wired.frag.spv"); } this->queue_families = static_cast<QueueFamily*>( @@ -202,6 +207,8 @@ Device::~Device() vkDestroyShaderModule(this->device, this->frag3d_shader_module, nullptr); vkDestroyShaderModule(this->device, this->vert2d_shader_module, nullptr); vkDestroyShaderModule(this->device, this->frag2d_shader_module, nullptr); + vkDestroyShaderModule(this->device, this->vert2d_wired_shader_module, nullptr); + vkDestroyShaderModule(this->device, this->frag2d_wired_shader_module, nullptr); vkDeviceWaitIdle(this->device); vkDestroyDevice(this->device, nullptr); diff --git a/src/vk/device.hpp b/src/vk/device.hpp index cc5df82..9f5a776 100644 --- a/src/vk/device.hpp +++ b/src/vk/device.hpp @@ -41,6 +41,8 @@ public: VkShaderModule frag3d_shader_module; VkShaderModule vert2d_shader_module; VkShaderModule frag2d_shader_module; + VkShaderModule vert2d_wired_shader_module; + VkShaderModule frag2d_wired_shader_module; bool with_swapchain; diff --git a/src/vk/graphics_pipeline_2d.cpp b/src/vk/graphics_pipeline_2d_solid.cpp index 734a509..3906cc7 100644 --- a/src/vk/graphics_pipeline_2d.cpp +++ b/src/vk/graphics_pipeline_2d_solid.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "graphics_pipeline_2d.hpp" +#include "graphics_pipeline_2d_solid.hpp" #include <array> @@ -27,7 +27,7 @@ namespace void load_framebuffer(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolid*>(obj); self->swapchain_framebuffers.resize(cg_core.vk_swapchain->images_count); for (auto i{0}; i < cg_core.vk_swapchain->images_count; i++) @@ -39,7 +39,7 @@ load_framebuffer(void *obj) VkFramebufferCreateInfo framebuffer_info{}; framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebuffer_info.renderPass = - cg_core.vk_graphics_pipeline_2d_layout->render_pass; + cg_core.vk_graphics_pipeline_2d_solid_layout->render_pass; framebuffer_info.attachmentCount = attachments.size(); framebuffer_info.pAttachments = attachments.data(); framebuffer_info.width = cg_core.display_width; @@ -57,7 +57,7 @@ load_framebuffer(void *obj) void unload_framebuffer(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolid*>(obj); for(auto framebuffer: self->swapchain_framebuffers) vkDestroyFramebuffer( @@ -67,7 +67,7 @@ unload_framebuffer(void *obj) void load_pipeline(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolid*>(obj); VkPipelineShaderStageCreateInfo vert_shader_stage_info{}; vert_shader_stage_info.sType = @@ -227,9 +227,10 @@ load_pipeline(void *obj) pipeline_info.pDepthStencilState = nullptr; pipeline_info.pColorBlendState = &color_blending; pipeline_info.pDynamicState = &dynamic_state_info; - pipeline_info.layout = cg_core.vk_graphics_pipeline_2d_layout->pipeline; + pipeline_info.layout = + cg_core.vk_graphics_pipeline_2d_solid_layout->pipeline; pipeline_info.renderPass = - cg_core.vk_graphics_pipeline_2d_layout->render_pass; + cg_core.vk_graphics_pipeline_2d_solid_layout->render_pass; pipeline_info.subpass = 0; pipeline_info.basePipelineHandle = VK_NULL_HANDLE; pipeline_info.basePipelineIndex = -1; @@ -244,7 +245,7 @@ load_pipeline(void *obj) void unload_pipeline(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2D*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolid*>(obj); vkDestroyPipeline( cg_core.vk_device_with_swapchain->device, self->graphic_pipeline, nullptr); @@ -260,18 +261,18 @@ const CommandChain loader{ namespace VK { -GraphicsPipeline2D::GraphicsPipeline2D() +GraphicsPipeline2DSolid::GraphicsPipeline2DSolid() { loader.execute(this); } -GraphicsPipeline2D::~GraphicsPipeline2D() +GraphicsPipeline2DSolid::~GraphicsPipeline2DSolid() { loader.revert(this); } void -GraphicsPipeline2D::draw( +GraphicsPipeline2DSolid::draw( std::shared_ptr<View2D> view, const VkCommandBuffer draw_command_buffer, const size_t current_frame, const size_t next_frame, const uint32_t image_index) @@ -307,7 +308,7 @@ GraphicsPipeline2D::draw( vkCmdBindDescriptorSets( draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - cg_core.vk_graphics_pipeline_2d_layout->pipeline, 0, + cg_core.vk_graphics_pipeline_2d_solid_layout->pipeline, 0, vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); vkCmdBindPipeline( draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, diff --git a/src/vk/graphics_pipeline_2d.hpp b/src/vk/graphics_pipeline_2d_solid.hpp index ffa373a..ec3c744 100644 --- a/src/vk/graphics_pipeline_2d.hpp +++ b/src/vk/graphics_pipeline_2d_solid.hpp @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_H -#define CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_H 1 +#ifndef CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_SOLID_H +#define CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_SOLID_H 1 #include <memory> #include <unordered_map> @@ -28,13 +28,13 @@ namespace VK { -struct GraphicsPipeline2D +struct GraphicsPipeline2DSolid { std::vector<VkFramebuffer> swapchain_framebuffers; VkPipeline graphic_pipeline; - GraphicsPipeline2D(); - ~GraphicsPipeline2D(); + GraphicsPipeline2DSolid(); + ~GraphicsPipeline2DSolid(); void draw(std::shared_ptr<View2D> view, const VkCommandBuffer draw_command_buffer, @@ -44,4 +44,4 @@ struct GraphicsPipeline2D } -#endif /* CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_H */ +#endif /* CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_SOLID_H */ diff --git a/src/vk/graphics_pipeline_2d_layout.cpp b/src/vk/graphics_pipeline_2d_solid_layout.cpp index 6840f2c..6f0da0e 100644 --- a/src/vk/graphics_pipeline_2d_layout.cpp +++ b/src/vk/graphics_pipeline_2d_solid_layout.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "graphics_pipeline_2d_layout.hpp" +#include "graphics_pipeline_2d_solid_layout.hpp" #include <array> @@ -26,7 +26,7 @@ namespace void load_descriptor_set_view(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolidLayout*>(obj); std::array<VkDescriptorSetLayoutBinding, 1> layout_bindings{}; @@ -53,7 +53,7 @@ load_descriptor_set_view(void *obj) void unload_descriptor_set_view(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolidLayout*>(obj); vkDestroyDescriptorSetLayout( cg_core.vk_device_with_swapchain->device, self->descriptor_set_view, @@ -63,7 +63,7 @@ unload_descriptor_set_view(void *obj) void load_descriptor_set_sprite(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolidLayout*>(obj); std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings{}; @@ -97,7 +97,7 @@ load_descriptor_set_sprite(void *obj) void unload_descriptor_set_sprite(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolidLayout*>(obj); vkDestroyDescriptorSetLayout( cg_core.vk_device_with_swapchain->device, self->descriptor_set_sprite, @@ -107,7 +107,7 @@ unload_descriptor_set_sprite(void *obj) void load_pipeline(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolidLayout*>(obj); std::array<VkDescriptorSetLayout, 2> set_layouts{ self->descriptor_set_view, self->descriptor_set_sprite @@ -129,7 +129,7 @@ load_pipeline(void *obj) void unload_pipeline(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolidLayout*>(obj); vkDestroyPipelineLayout( cg_core.vk_device_with_swapchain->device, self->pipeline, nullptr); @@ -138,7 +138,7 @@ unload_pipeline(void *obj) void load_render_pass(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolidLayout*>(obj); std::array<VkAttachmentDescription, 1> attachments{}; // Color attachment. @@ -150,7 +150,7 @@ load_render_pass(void *obj) attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkAttachmentReference color_attachment_ref{}; color_attachment_ref.attachment = 0; @@ -200,7 +200,7 @@ load_render_pass(void *obj) static void unload_render_pass(void *obj) { - auto self = static_cast<VK::GraphicsPipeline2DLayout*>(obj); + auto self = static_cast<VK::GraphicsPipeline2DSolidLayout*>(obj); vkDestroyRenderPass( cg_core.vk_device_with_swapchain->device, self->render_pass, nullptr); @@ -218,12 +218,12 @@ const CommandChain loader{ namespace VK { -GraphicsPipeline2DLayout::GraphicsPipeline2DLayout() +GraphicsPipeline2DSolidLayout::GraphicsPipeline2DSolidLayout() { loader.execute(this); } -GraphicsPipeline2DLayout::~GraphicsPipeline2DLayout() +GraphicsPipeline2DSolidLayout::~GraphicsPipeline2DSolidLayout() { loader.revert(this); } diff --git a/src/vk/graphics_pipeline_2d_layout.hpp b/src/vk/graphics_pipeline_2d_solid_layout.hpp index 1e0a794..121ddaa 100644 --- a/src/vk/graphics_pipeline_2d_layout.hpp +++ b/src/vk/graphics_pipeline_2d_solid_layout.hpp @@ -32,15 +32,15 @@ struct UBOSpritePositions glm::vec4 positions[128]; }; -struct GraphicsPipeline2DLayout +struct GraphicsPipeline2DSolidLayout { VkDescriptorSetLayout descriptor_set_view; VkDescriptorSetLayout descriptor_set_sprite; VkPipelineLayout pipeline; VkRenderPass render_pass; - GraphicsPipeline2DLayout(); - ~GraphicsPipeline2DLayout(); + GraphicsPipeline2DSolidLayout(); + ~GraphicsPipeline2DSolidLayout(); }; } diff --git a/src/vk/graphics_pipeline_2d_wired.cpp b/src/vk/graphics_pipeline_2d_wired.cpp new file mode 100644 index 0000000..2b416c2 --- /dev/null +++ b/src/vk/graphics_pipeline_2d_wired.cpp @@ -0,0 +1,324 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "graphics_pipeline_2d_wired.hpp" + +#include <array> + +#include "../core.hpp" +#include "rectangle.hpp" +#include "sprite.hpp" + +namespace +{ + +void +load_framebuffer(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj); + + self->swapchain_framebuffers.resize( + cg_core.vk_swapchain->images_count); + for (auto i{0}; i < cg_core.vk_swapchain->images_count; i++) + { + std::array<VkImageView, 1> attachments = { + cg_core.vk_swapchain->image_views[i] + }; + + VkFramebufferCreateInfo framebuffer_info{}; + framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebuffer_info.renderPass = + cg_core.vk_graphics_pipeline_2d_wired_layout->render_pass; + framebuffer_info.attachmentCount = attachments.size(); + framebuffer_info.pAttachments = attachments.data(); + framebuffer_info.width = cg_core.display_width; + framebuffer_info.height = cg_core.display_height; + framebuffer_info.layers = 1; + + if(vkCreateFramebuffer( + cg_core.vk_device_with_swapchain->device, &framebuffer_info, nullptr, + &self->swapchain_framebuffers[i]) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan Framebuffer."}; + } +} + +void +unload_framebuffer(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj); + + for(auto framebuffer: self->swapchain_framebuffers) + vkDestroyFramebuffer( + cg_core.vk_device_with_swapchain->device, framebuffer, nullptr); +} + +void +load_pipeline(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj); + + VkPipelineShaderStageCreateInfo vert_shader_stage_info{}; + vert_shader_stage_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vert_shader_stage_info.pNext = nullptr; + vert_shader_stage_info.flags = 0; + vert_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT; + vert_shader_stage_info.module = + cg_core.vk_device_with_swapchain->vert2d_wired_shader_module; + vert_shader_stage_info.pName = "main"; + vert_shader_stage_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo frag_shader_stage_info{}; + frag_shader_stage_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + frag_shader_stage_info.pNext = nullptr; + frag_shader_stage_info.flags = 0; + frag_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + frag_shader_stage_info.module = + cg_core.vk_device_with_swapchain->frag2d_wired_shader_module; + frag_shader_stage_info.pName = "main"; + frag_shader_stage_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo shader_stages[] = { + vert_shader_stage_info, + frag_shader_stage_info + }; + + VkVertexInputBindingDescription vertex_input_binding{}; + vertex_input_binding.binding = 0; + vertex_input_binding.stride = sizeof(glm::vec2); + vertex_input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + std::array<VkVertexInputAttributeDescription, 1> vertex_attribute{}; + vertex_attribute[0].location = 0; + vertex_attribute[0].binding = 0; + vertex_attribute[0].format = VK_FORMAT_R32G32_SFLOAT; + vertex_attribute[0].offset = 0; + + VkPipelineVertexInputStateCreateInfo vertex_input_info = {}; + vertex_input_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_input_info.pNext = nullptr; + vertex_input_info.flags = 0; + vertex_input_info.vertexBindingDescriptionCount = 1; + vertex_input_info.pVertexBindingDescriptions = &vertex_input_binding; + vertex_input_info.vertexAttributeDescriptionCount = + static_cast<uint32_t>(vertex_attribute.size()); + vertex_input_info.pVertexAttributeDescriptions = vertex_attribute.data(); + + VkPipelineInputAssemblyStateCreateInfo input_assembly = {}; + input_assembly.sType = + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + input_assembly.pNext = nullptr; + input_assembly.flags = 0; + input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + input_assembly.primitiveRestartEnable = VK_FALSE; + + VkViewport viewport = {}; + viewport.x = 0; + viewport.y = 0; + viewport.width = cg_core.display_width; + viewport.height = cg_core.display_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor = {}; + scissor.offset = {0, 0}; + scissor.extent = {cg_core.display_width, cg_core.display_height}; + + VkPipelineViewportStateCreateInfo viewport_state = {}; + viewport_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_state.pNext = nullptr; + viewport_state.flags = 0; + viewport_state.viewportCount = 1; + viewport_state.pViewports = &viewport; + viewport_state.scissorCount = 1; + viewport_state.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterizer = {}; + rasterizer.sType = + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.pNext = nullptr; + rasterizer.flags = 0; + rasterizer.depthClampEnable = VK_FALSE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_LINE; + rasterizer.cullMode = VK_CULL_MODE_NONE; + rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + rasterizer.depthBiasConstantFactor = 0.0f; + rasterizer.depthBiasClamp = 0.0f; + rasterizer.depthBiasSlopeFactor = 0.0f; + rasterizer.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo multisampling = {}; + multisampling.sType = + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisampling.sampleShadingEnable = VK_FALSE; + multisampling.minSampleShading = 1.0f; + multisampling.pSampleMask = nullptr; + multisampling.alphaToCoverageEnable = VK_FALSE; + multisampling.alphaToOneEnable = VK_FALSE; + + VkPipelineColorBlendAttachmentState color_blend_attachment = {}; + color_blend_attachment.blendEnable = VK_FALSE; + color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + color_blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD; + color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD; + color_blend_attachment.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo color_blending = {}; + color_blending.sType = + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + color_blending.pNext = nullptr; + color_blending.flags = 0; + color_blending.logicOpEnable = VK_FALSE; + color_blending.logicOp = VK_LOGIC_OP_COPY; + color_blending.attachmentCount = 1; + color_blending.pAttachments = &color_blend_attachment; + color_blending.blendConstants[0] = 0.0f; + color_blending.blendConstants[1] = 0.0f; + color_blending.blendConstants[2] = 0.0f; + color_blending.blendConstants[3] = 0.0f; + + VkDynamicState dynamic_states[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_LINE_WIDTH + }; + + VkPipelineDynamicStateCreateInfo dynamic_state_info = {}; + dynamic_state_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state_info.dynamicStateCount = 2; + dynamic_state_info.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo pipeline_info{}; + pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipeline_info.pNext = nullptr; + pipeline_info.flags = 0; + pipeline_info.stageCount = 2; + pipeline_info.pStages = shader_stages; + pipeline_info.pVertexInputState = &vertex_input_info; + pipeline_info.pInputAssemblyState = &input_assembly; + pipeline_info.pTessellationState = nullptr; + pipeline_info.pViewportState = &viewport_state; + pipeline_info.pRasterizationState = &rasterizer; + pipeline_info.pMultisampleState = &multisampling; + pipeline_info.pDepthStencilState = nullptr; + pipeline_info.pColorBlendState = &color_blending; + pipeline_info.pDynamicState = &dynamic_state_info; + pipeline_info.layout = + cg_core.vk_graphics_pipeline_2d_wired_layout->pipeline; + pipeline_info.renderPass = + cg_core.vk_graphics_pipeline_2d_wired_layout->render_pass; + pipeline_info.subpass = 0; + pipeline_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_info.basePipelineIndex = -1; + + if(vkCreateGraphicsPipelines( + cg_core.vk_device_with_swapchain->device, VK_NULL_HANDLE, 1, + &pipeline_info, nullptr, &self->graphic_pipeline) != VK_SUCCESS) + throw CommandError{"Failed to create graphics pipeline."}; +} + +void +unload_pipeline(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWired*>(obj); + + vkDestroyPipeline( + cg_core.vk_device_with_swapchain->device, self->graphic_pipeline, nullptr); +} + +const CommandChain loader{ + {&load_framebuffer, &unload_framebuffer}, + {&load_pipeline, &unload_pipeline} +}; + +} + +namespace VK +{ + +GraphicsPipeline2DWired::GraphicsPipeline2DWired() +{ + loader.execute(this); +} + +GraphicsPipeline2DWired::~GraphicsPipeline2DWired() +{ + loader.revert(this); +} + +void +GraphicsPipeline2DWired::draw( + std::shared_ptr<View2D> view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const size_t next_frame, + const uint32_t image_index) +{ + // Set viewport + { + VkViewport vk_viewport{}; + vk_viewport.x = view->region.x; + vk_viewport.y = view->region.y; + vk_viewport.width = view->region.z; + vk_viewport.height = view->region.w; + vk_viewport.minDepth = 0.0f; + vk_viewport.maxDepth = 1.0f; + vkCmdSetViewport(draw_command_buffer, 0, 1, &vk_viewport); + + VkRect2D vk_scissor{}; + vk_scissor.offset.x = static_cast<int32_t>(view->region.x); + vk_scissor.offset.y = static_cast<int32_t>(view->region.y); + vk_scissor.extent.width = static_cast<uint32_t>(view->region.z); + vk_scissor.extent.height = static_cast<uint32_t>(view->region.w); + vkCmdSetScissor(draw_command_buffer, 0, 1, &vk_scissor); + } + + // Draw rectangles + for(auto& rectangle: view->rectangles_to_draw[current_frame]) + { + std::array<VkDescriptorSet, 2> vk_descriptor_sets{ + view->descriptor_sets_2d[image_index], + rectangle->descriptor_sets[image_index]}; + VkDeviceSize offsets[]{0}; + + vkCmdBindDescriptorSets( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + cg_core.vk_graphics_pipeline_2d_wired_layout->pipeline, 0, + vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); + vkCmdBindPipeline( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + this->graphic_pipeline); + vkCmdBindVertexBuffers( + draw_command_buffer, 0, 1, + &rectangle->vertex_buffers[image_index].buffer, offsets); + vkCmdDraw( + draw_command_buffer, Rectangle::vertex_count, 1, 0, 0); + } + + // Prepare for the next frame. + view->rectangles_to_draw[next_frame].clear(); +} + +} diff --git a/src/vk/graphics_pipeline_2d_wired.hpp b/src/vk/graphics_pipeline_2d_wired.hpp new file mode 100644 index 0000000..e6c40de --- /dev/null +++ b/src/vk/graphics_pipeline_2d_wired.hpp @@ -0,0 +1,46 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_WIRED_H +#define CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_WIRED_H 1 + +#include <memory> +#include <unordered_map> +#include <vector> + +#include "core.hpp" +#include "view_2d.hpp" + +namespace VK +{ + +struct GraphicsPipeline2DWired +{ + std::vector<VkFramebuffer> swapchain_framebuffers; + VkPipeline graphic_pipeline; + + GraphicsPipeline2DWired(); + ~GraphicsPipeline2DWired(); + + void + draw(std::shared_ptr<View2D> view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const size_t next_frame, + const uint32_t image_index); +}; + +} + +#endif /* CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_WIRED_H */ diff --git a/src/vk/graphics_pipeline_2d_wired_layout.cpp b/src/vk/graphics_pipeline_2d_wired_layout.cpp new file mode 100644 index 0000000..c523bc7 --- /dev/null +++ b/src/vk/graphics_pipeline_2d_wired_layout.cpp @@ -0,0 +1,225 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "graphics_pipeline_2d_wired_layout.hpp" + +#include <array> + +#include "../core.hpp" +#include "graphics_pipeline_2d_solid_layout.hpp" + +namespace +{ + +void +load_descriptor_set_view(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj); + + std::array<VkDescriptorSetLayoutBinding, 1> layout_bindings{}; + + layout_bindings[0].binding = 0; + layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + layout_bindings[0].descriptorCount = 1; + layout_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + layout_bindings[0].pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo layout_info{}; + layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout_info.pNext = nullptr; + layout_info.flags = 0; + layout_info.bindingCount = static_cast<uint32_t>(layout_bindings.size()); + layout_info.pBindings = layout_bindings.data(); + + if(vkCreateDescriptorSetLayout( + cg_core.vk_device_with_swapchain->device, &layout_info, nullptr, + &self->descriptor_set_view) != VK_SUCCESS) + throw CommandError{ + "Failed to create Vulkan descriptor set layout for projection."}; +} + +void +unload_descriptor_set_view(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj); + + vkDestroyDescriptorSetLayout( + cg_core.vk_device_with_swapchain->device, self->descriptor_set_view, + nullptr); +} + +void +load_descriptor_set_instance(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj); + + std::array<VkDescriptorSetLayoutBinding, 1> layout_bindings{}; + + layout_bindings[0].binding = 0; + layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + layout_bindings[0].descriptorCount = 1; + layout_bindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + layout_bindings[0].pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo layout_info{}; + layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout_info.pNext = nullptr; + layout_info.flags = 0; + layout_info.bindingCount = static_cast<uint32_t>(layout_bindings.size()); + layout_info.pBindings = layout_bindings.data(); + + if(vkCreateDescriptorSetLayout( + cg_core.vk_device_with_swapchain->device, &layout_info, nullptr, + &self->descriptor_set_instance) != VK_SUCCESS) + throw CommandError{ + "Failed to create Vulkan descriptor set layout for rectangles."}; +} + +void +unload_descriptor_set_instance(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj); + + vkDestroyDescriptorSetLayout( + cg_core.vk_device_with_swapchain->device, self->descriptor_set_instance, + nullptr); +} + +void +load_pipeline(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj); + + std::array<VkDescriptorSetLayout, 2> set_layouts{ + self->descriptor_set_view, self->descriptor_set_instance + }; + + VkPipelineLayoutCreateInfo pipeline_layout_info{}; + pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeline_layout_info.setLayoutCount = set_layouts.size(); + pipeline_layout_info.pSetLayouts = set_layouts.data(); + pipeline_layout_info.pushConstantRangeCount = 0; + pipeline_layout_info.pPushConstantRanges = nullptr; + + if(vkCreatePipelineLayout( + cg_core.vk_device_with_swapchain->device, &pipeline_layout_info, + nullptr, &self->pipeline) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan pipeline layout."}; +} + +void +unload_pipeline(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj); + + vkDestroyPipelineLayout( + cg_core.vk_device_with_swapchain->device, self->pipeline, nullptr); +} + +void +load_render_pass(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj); + + std::array<VkAttachmentDescription, 1> attachments{}; + // Color attachment. + attachments[0].flags = 0; + attachments[0].format = cg_core.vk_swapchain->image_format; + attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + VkAttachmentReference color_attachment_ref{}; + color_attachment_ref.attachment = 0; + color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass{}; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_attachment_ref; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkSubpassDependency dependency{}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo render_pass_info{}; + render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + render_pass_info.pNext = nullptr; + render_pass_info.flags = 0; + render_pass_info.attachmentCount = attachments.size(); + render_pass_info.pAttachments = attachments.data(); + render_pass_info.subpassCount = 1; + render_pass_info.pSubpasses = &subpass; + render_pass_info.dependencyCount = 1; + render_pass_info.pDependencies = &dependency; + + if(vkCreateRenderPass( + cg_core.vk_device_with_swapchain->device, &render_pass_info, + nullptr, &self->render_pass) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan Render Pass 2D."}; +} + +static void +unload_render_pass(void *obj) +{ + auto self = static_cast<VK::GraphicsPipeline2DWiredLayout*>(obj); + + vkDestroyRenderPass( + cg_core.vk_device_with_swapchain->device, self->render_pass, nullptr); +} + +const CommandChain loader{ + {&load_descriptor_set_view, &unload_descriptor_set_view}, + {&load_descriptor_set_instance, &unload_descriptor_set_instance}, + {&load_pipeline, &unload_pipeline}, + {&load_render_pass, &unload_render_pass} +}; + +} + +namespace VK +{ + +GraphicsPipeline2DWiredLayout::GraphicsPipeline2DWiredLayout() +{ + loader.execute(this); +} + +GraphicsPipeline2DWiredLayout::~GraphicsPipeline2DWiredLayout() +{ + loader.revert(this); +} + +} diff --git a/src/vk/graphics_pipeline_2d_wired_layout.hpp b/src/vk/graphics_pipeline_2d_wired_layout.hpp new file mode 100644 index 0000000..3d0268e --- /dev/null +++ b/src/vk/graphics_pipeline_2d_wired_layout.hpp @@ -0,0 +1,43 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_WIRED_LAYOUT_H +#define CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_WIRED_LAYOUT_H 1 + +#include "core.hpp" + +namespace VK +{ + +struct UBOModel2D +{ + glm::vec3 color; +}; + +struct GraphicsPipeline2DWiredLayout +{ + VkDescriptorSetLayout descriptor_set_view; + VkDescriptorSetLayout descriptor_set_instance; + VkPipelineLayout pipeline; + VkRenderPass render_pass; + + GraphicsPipeline2DWiredLayout(); + ~GraphicsPipeline2DWiredLayout(); +}; + +} + +#endif /* CANDY_GEAR_VK_GRAPHICS_PIPELINE_2D_LAYOUT_H */ diff --git a/src/vk/rectangle.cpp b/src/vk/rectangle.cpp new file mode 100644 index 0000000..b0925f1 --- /dev/null +++ b/src/vk/rectangle.cpp @@ -0,0 +1,245 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rectangle.hpp" + +#include <array> + +#include "../core.hpp" +#include "graphics_pipeline_2d_wired_layout.hpp" + +namespace +{ + +void +load_mesh(void *obj) +{ + auto self = static_cast<VK::Rectangle*>(obj); + + self->queue_family = + cg_core.vk_device_with_swapchain->get_queue_family_with_graphics(); + + glm::vec2 rect[4]{ + glm::vec2{self->x, self->y}, + glm::vec2{self->x, self->y + self->height}, + glm::vec2{self->x + self->width, self->y}, + glm::vec2{self->x + self->width, self->y + self->height} + }; + + void *vertexes_data{&rect}; + static const size_t vertexes_size = + sizeof(glm::vec2) * VK::Rectangle::vertex_count; + self->source_buffers.reserve(cg_core.vk_swapchain->images_count); + self->vertex_buffers.reserve(cg_core.vk_swapchain->images_count); + for(int i{0}; i < cg_core.vk_swapchain->images_count; i++) + { + self->source_buffers.emplace_back( + self->queue_family->device, vertexes_data, vertexes_size); + self->vertex_buffers.emplace_back( + self->queue_family, &self->source_buffers[i], + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + } +} + +void +unload_mesh(void *obj) +{ + auto self = static_cast<VK::Rectangle*>(obj); + + self->vertex_buffers.clear(); + self->source_buffers.clear(); +} + +void +load_uniform_buffer(void *obj) +{ + auto self = static_cast<VK::Rectangle*>(obj); + + self->ub_rectangle.reserve(cg_core.vk_swapchain->images_count); + for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++) + self->ub_rectangle.emplace_back( + cg_core.vk_device_with_swapchain, sizeof(VK::UBOModel2D)); +} + +void +unload_uniform_buffer(void *obj) +{ + auto self = static_cast<VK::Rectangle*>(obj); + + self->ub_rectangle.clear(); +} + +void +load_descriptor_set_pool(void *obj) +{ + auto self = static_cast<VK::Rectangle*>(obj); + + std::array<VkDescriptorPoolSize, 1> descriptor_pool_sizes{}; + descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_pool_sizes[0].descriptorCount = self->ub_rectangle.size(); + + VkDescriptorPoolCreateInfo pool_info{}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.pNext = nullptr; + pool_info.flags = 0; + pool_info.maxSets = self->ub_rectangle.size(); + pool_info.poolSizeCount = descriptor_pool_sizes.size(); + pool_info.pPoolSizes = descriptor_pool_sizes.data(); + + if(vkCreateDescriptorPool( + self->queue_family->device->device, &pool_info, nullptr, + &self->descriptor_pool) != VK_SUCCESS) + throw CommandError{"Failed to create a Vulkan descriptor pool."}; +} + +void +unload_descriptor_set_pool(void *obj) +{ + auto self = static_cast<VK::Rectangle*>(obj); + + vkDestroyDescriptorPool( + self->queue_family->device->device, self->descriptor_pool, nullptr); +} + +void +load_descriptor_sets(void *obj) +{ + auto self = static_cast<VK::Rectangle*>(obj); + + std::vector<VkDescriptorSetLayout> layouts( + cg_core.vk_swapchain->images_count, + cg_core.vk_graphics_pipeline_2d_wired_layout->descriptor_set_instance); + + VkDescriptorSetAllocateInfo alloc_info{}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = self->descriptor_pool; + alloc_info.descriptorSetCount = layouts.size(); + alloc_info.pSetLayouts = layouts.data(); + + self->descriptor_sets.resize(layouts.size()); + if(vkAllocateDescriptorSets( + self->queue_family->device->device, &alloc_info, + self->descriptor_sets.data()) != VK_SUCCESS) + CommandError{"Failed to create Vulkan descriptor set."}; +} + +void +load_data_to_descriptor_sets(void *obj) +{ + auto self = static_cast<VK::Rectangle*>(obj); + + for(auto i{0}; i < self->ub_rectangle.size(); i++) + { + VkDescriptorBufferInfo buffer_info{}; + buffer_info.buffer = self->ub_rectangle[i].buffer; + buffer_info.offset = 0; + buffer_info.range = sizeof(VK::UBOModel2D); + + std::array<VkWriteDescriptorSet, 1> write_descriptors{}; + write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[0].dstSet = self->descriptor_sets[i]; + write_descriptors[0].dstBinding = 0; + write_descriptors[0].dstArrayElement = 0; + write_descriptors[0].descriptorCount = 1; + write_descriptors[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + write_descriptors[0].pBufferInfo = &buffer_info; + write_descriptors[0].pImageInfo = nullptr; + write_descriptors[0].pTexelBufferView = nullptr; + + vkUpdateDescriptorSets( + cg_core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); + } +} + +static const CommandChain loader{ + {&load_mesh, &unload_mesh}, + {&load_uniform_buffer, &unload_uniform_buffer}, + {&load_descriptor_set_pool, &unload_descriptor_set_pool}, + {&load_descriptor_sets, nullptr}, + {&load_data_to_descriptor_sets, nullptr}, +}; + +constexpr bool +_align_vertically(const float a_x, const float a_width, + const float b_x, const float b_width) +{ + return a_x <= b_x + b_width && a_x + a_width >= b_x; +} + +constexpr bool +_align_horizontally(const float a_y, const float a_height, + const float b_y, const float b_height) +{ + return a_y <= b_y + b_height && a_y + a_height >= b_y; +} + +} + +namespace VK +{ + +Rectangle::Rectangle(float x, float y, float width, float height): + x{x}, + y{y}, + width{width}, + height{height} +{ + loader.execute(this); +} + +Rectangle::~Rectangle() +{ + loader.revert(this); +} + +bool +Rectangle::align_vertically(const Rectangle &that) const +{ + return _align_vertically(this->x, this->width, that.x, that.width); +} + +bool +Rectangle::align_horizontally(const Rectangle &that) const +{ + return _align_horizontally(this->y, this->height, that.y, that.height); +} + +bool +Rectangle::collide(const Rectangle &that) const +{ + return + _align_vertically(this->x, this->width, that.x, that.width) && + _align_horizontally(this->y, this->height, that.y, that.height); +} + +void +Rectangle::update_vertex_buffer() +{ + glm::vec2 rect[4]{ + glm::vec2{this->x, this->y}, + glm::vec2{this->x, this->y + this->height}, + glm::vec2{this->x + this->width, this->y}, + glm::vec2{this->x + this->width, this->y + this->height} + }; + + void *vertexes_data{&rect}; + this->source_buffers[cg_core.vk_swapchain->current_frame].copy_data( + vertexes_data); + this->vertex_buffers[cg_core.vk_swapchain->current_frame].copy_data(); +} + +} diff --git a/src/vk/rectangle.hpp b/src/vk/rectangle.hpp new file mode 100644 index 0000000..fc21135 --- /dev/null +++ b/src/vk/rectangle.hpp @@ -0,0 +1,66 @@ +/* + * Copyright 2022 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CANDY_GEAR_VK_RECTANGLE_H +#define CANDY_GEAR_VK_RECTANGLE_H 1 + +#include <vector> + +#include "core.hpp" +#include "destination_buffer.hpp" +#include "queue_family.hpp" +#include "uniform_buffer.hpp" + +namespace VK +{ + +struct Rectangle +{ + static const uint32_t vertex_count{4}; + + float x{0}; + float y{0}; + float width{1}; + float height{1}; + + QueueFamily *queue_family; + + std::vector<SourceBuffer> source_buffers; + std::vector<DestinationBuffer> vertex_buffers; + + std::vector<UniformBuffer> ub_rectangle; + + VkDescriptorPool descriptor_pool; + std::vector<VkDescriptorSet> descriptor_sets; + + Rectangle() = default; + Rectangle(float x, float y, float width, float height); + ~Rectangle(); + + bool + align_vertically(const Rectangle &that) const; + bool + align_horizontally(const Rectangle &that) const; + bool + collide(const Rectangle &that) const; + + void + update_vertex_buffer(); +}; + +} + +#endif /* CANDY_GEAR_VK_RECTANGLE_H */ diff --git a/src/vk/renderer.cpp b/src/vk/renderer.cpp index 8d82b00..a7e5f35 100644 --- a/src/vk/renderer.cpp +++ b/src/vk/renderer.cpp @@ -231,15 +231,16 @@ Renderer::draw() vkCmdEndRenderPass(draw_command_buffer); } - // 2D drawing + // 2D solid drawing { VkRenderPassBeginInfo render_pass_begin{}; render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; render_pass_begin.pNext = nullptr; render_pass_begin.renderPass = - cg_core.vk_graphics_pipeline_2d_layout->render_pass; + cg_core.vk_graphics_pipeline_2d_solid_layout->render_pass; render_pass_begin.framebuffer = - cg_core.vk_graphics_pipeline_2d->swapchain_framebuffers[image_index]; + cg_core.vk_graphics_pipeline_2d_solid->swapchain_framebuffers[ + image_index]; render_pass_begin.renderArea.offset = {0, 0}; render_pass_begin.renderArea.extent = { static_cast<uint32_t>(cg_core.display_width), @@ -251,12 +252,45 @@ Renderer::draw() draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); for(auto &view: this->views_2d) - cg_core.vk_graphics_pipeline_2d->draw( + cg_core.vk_graphics_pipeline_2d_solid->draw( view, draw_command_buffer, cg_core.vk_swapchain->current_frame, next_frame, image_index); for(auto &view: this->views_3d) - cg_core.vk_graphics_pipeline_2d->draw( + cg_core.vk_graphics_pipeline_2d_solid->draw( + view, draw_command_buffer, cg_core.vk_swapchain->current_frame, + next_frame, image_index); + + vkCmdEndRenderPass(draw_command_buffer); + } + + // 2D wired drawing + { + VkRenderPassBeginInfo render_pass_begin{}; + render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + render_pass_begin.pNext = nullptr; + render_pass_begin.renderPass = + cg_core.vk_graphics_pipeline_2d_wired_layout->render_pass; + render_pass_begin.framebuffer = + cg_core.vk_graphics_pipeline_2d_wired->swapchain_framebuffers[ + image_index]; + render_pass_begin.renderArea.offset = {0, 0}; + render_pass_begin.renderArea.extent = { + static_cast<uint32_t>(cg_core.display_width), + static_cast<uint32_t>(cg_core.display_height)}; + render_pass_begin.clearValueCount = 0; + render_pass_begin.pClearValues = nullptr; + + vkCmdBeginRenderPass( + draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); + + for(auto &view: this->views_2d) + cg_core.vk_graphics_pipeline_2d_wired->draw( + view, draw_command_buffer, cg_core.vk_swapchain->current_frame, + next_frame, image_index); + + for(auto &view: this->views_3d) + cg_core.vk_graphics_pipeline_2d_wired->draw( view, draw_command_buffer, cg_core.vk_swapchain->current_frame, next_frame, image_index); @@ -313,11 +347,8 @@ Renderer::draw() // Prepare for the next frame. { - this->models_to_draw[next_frame].clear(); - for(auto &view: this->views_2d) view->sprites_to_draw[next_frame].clear(); - for(auto &view: this->views_3d) view->sprites_to_draw[next_frame].clear(); - - cg_core.vk_swapchain->current_frame = next_frame; + this->models_to_draw[next_frame].clear(); + cg_core.vk_swapchain->current_frame = next_frame; } } else diff --git a/src/vk/source_buffer.cpp b/src/vk/source_buffer.cpp index 7e6c570..f8f1aee 100644 --- a/src/vk/source_buffer.cpp +++ b/src/vk/source_buffer.cpp @@ -21,8 +21,7 @@ namespace VK { -SourceBuffer::SourceBuffer(Device *device, void *data, size_t data_size): - data{data} +SourceBuffer::SourceBuffer(Device *device, void *data, size_t data_size) { this->device = device; this->device_size = data_size; @@ -40,7 +39,7 @@ SourceBuffer::SourceBuffer(Device *device, void *data, size_t data_size): error += command_error.what(); throw std::runtime_error{error}; } - this->copy_data(); + this->copy_data(data); } SourceBuffer::SourceBuffer(SourceBuffer &&that) @@ -50,11 +49,9 @@ SourceBuffer::SourceBuffer(SourceBuffer &&that) this->device_size = that.device_size; this->buffer_usage = that.buffer_usage; this->memory_properties = that.memory_properties; - this->data = that.data; that.buffer = VK_NULL_HANDLE; that.device_memory = VK_NULL_HANDLE; - that.data = nullptr; } SourceBuffer& @@ -65,11 +62,9 @@ SourceBuffer::operator=(SourceBuffer &&that) this->device_size = that.device_size; this->buffer_usage = that.buffer_usage; this->memory_properties = that.memory_properties; - this->data = that.data; that.buffer = VK_NULL_HANDLE; that.device_memory = VK_NULL_HANDLE; - that.data = nullptr; return *this; } @@ -80,12 +75,12 @@ SourceBuffer::~SourceBuffer() } void -SourceBuffer::copy_data() +SourceBuffer::copy_data(void *src_data) { void *dst_data; vkMapMemory(this->device->device, this->device_memory, 0, this->device_size, 0, &dst_data); - memcpy(dst_data, this->data, static_cast<size_t>(this->device_size)); + memcpy(dst_data, src_data, static_cast<size_t>(this->device_size)); vkUnmapMemory(this->device->device, this->device_memory); } diff --git a/src/vk/source_buffer.hpp b/src/vk/source_buffer.hpp index 713d708..440e561 100644 --- a/src/vk/source_buffer.hpp +++ b/src/vk/source_buffer.hpp @@ -28,8 +28,6 @@ struct SourceBuffer: public BaseBuffer SourceBuffer& operator=(const SourceBuffer &t) = delete; - void *data; - SourceBuffer(Device *device, void *data, size_t data_size); SourceBuffer(SourceBuffer &&that); @@ -39,7 +37,7 @@ struct SourceBuffer: public BaseBuffer ~SourceBuffer(); void - copy_data(); + copy_data(void *src_data); }; } diff --git a/src/vk/sprite.cpp b/src/vk/sprite.cpp index 9a718d7..a7b802a 100644 --- a/src/vk/sprite.cpp +++ b/src/vk/sprite.cpp @@ -137,7 +137,7 @@ load_descriptor_sets(void *obj) std::vector<VkDescriptorSetLayout> layouts( cg_core.vk_swapchain->images_count, - cg_core.vk_graphics_pipeline_2d_layout->descriptor_set_sprite); + cg_core.vk_graphics_pipeline_2d_solid_layout->descriptor_set_sprite); VkDescriptorSetAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; diff --git a/src/vk/view_2d.cpp b/src/vk/view_2d.cpp index 623aa63..011fb1a 100644 --- a/src/vk/view_2d.cpp +++ b/src/vk/view_2d.cpp @@ -56,7 +56,7 @@ load_descriptor_sets_2d(void *obj) std::vector<VkDescriptorSetLayout> layouts( cg_core.vk_swapchain->images_count, - cg_core.vk_graphics_pipeline_2d_layout->descriptor_set_view); + cg_core.vk_graphics_pipeline_2d_solid_layout->descriptor_set_view); VkDescriptorSetAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; @@ -124,6 +124,7 @@ const CommandChain View2D::descriptor_sets_loader{ View2D::View2D(glm::vec4 region): region{region}, descriptor_pool{VK_NULL_HANDLE}, + rectangles_to_draw{cg_core.vk_swapchain->images_count}, sprites_to_draw{cg_core.vk_swapchain->images_count} { loader.execute(this); diff --git a/src/vk/view_2d.hpp b/src/vk/view_2d.hpp index f6741cc..ec7225f 100644 --- a/src/vk/view_2d.hpp +++ b/src/vk/view_2d.hpp @@ -23,6 +23,7 @@ #include "core.hpp" #include "sprite.hpp" +#include "rectangle.hpp" namespace VK { @@ -37,6 +38,7 @@ struct View2D VkDescriptorPool descriptor_pool; std::vector<VkDescriptorSet> descriptor_sets_2d; + std::vector<std::vector<std::shared_ptr<Rectangle>>> rectangles_to_draw; std::vector< std::unordered_map<std::shared_ptr<Sprite>, std::vector<glm::vec4>>> sprites_to_draw; diff --git a/test/src/main.rb b/test/src/main.rb index be0ae0b..b7bbe85 100644 --- a/test/src/main.rb +++ b/test/src/main.rb @@ -25,9 +25,12 @@ end def init() texture = CandyGear::Texture.from_image("textures/color_texture.png"); mesh = CandyGear::Mesh.new("meshes/cube.cgmesh"); + + $color = CandyGear::Vector3D.new(0.8, 0.2, 0.2); $model = CandyGear::Model.new(mesh, texture); $sprite = CandyGear::Sprite.new( texture, CandyGear::Vector4D.new(0, 0, 1.0, 1.0)); + $rectangle = CandyGear::Rectangle.new(102.0, 1.0, 101.0, 101.0) $sprite_position = CandyGear::Vector4D.new(1.0, 1.0, 101.0, 101.0); $instances = [ @@ -83,8 +86,9 @@ end def quit() = CandyGear.quit(); def tick() - $view1.draw($sprite, $sprite_position); + $sprite.draw($view1, $sprite_position); $instances_rotation.rotate(0.0, BOX_ROTATION_SPEED); + $rectangle.draw($view1, $color); $instances.each do |i| $model.draw(i, $instances_rotation); end |