From 736637680ac7b2cd0d0b878401a7e044fde0ee6a Mon Sep 17 00:00:00 2001 From: Frederico Linhares Date: Tue, 31 Dec 2024 12:32:36 -0300 Subject: refa Split BluCat into several namespaces --- .gitignore | 6 +- Doxyfile | 2 +- doc/architecture.markdown | 10 + src/blu_cat/com/command.cpp | 78 +++ src/blu_cat/com/command.hpp | 92 ++++ src/blu_cat/com/job_queue.cpp | 66 +++ src/blu_cat/com/job_queue.hpp | 57 +++ src/blu_cat/com/worker.cpp | 39 ++ src/blu_cat/com/worker.hpp | 38 ++ src/blu_cat/gra/animation.cpp | 27 + src/blu_cat/gra/animation.hpp | 51 ++ src/blu_cat/gra/animation/frame.hpp | 85 ++++ src/blu_cat/gra/base_buffer.cpp | 96 ++++ src/blu_cat/gra/base_buffer.hpp | 56 ++ src/blu_cat/gra/binary_reader.cpp | 156 ++++++ src/blu_cat/gra/binary_reader.hpp | 69 +++ src/blu_cat/gra/character.cpp | 275 ++++++++++ src/blu_cat/gra/character.hpp | 49 ++ src/blu_cat/gra/command_pool.cpp | 87 ++++ src/blu_cat/gra/command_pool.hpp | 59 +++ src/blu_cat/gra/descriptor_set_layout.cpp | 197 +++++++ src/blu_cat/gra/descriptor_set_layout.hpp | 38 ++ src/blu_cat/gra/destination_buffer.cpp | 109 ++++ src/blu_cat/gra/destination_buffer.hpp | 54 ++ src/blu_cat/gra/device.cpp | 393 ++++++++++++++ src/blu_cat/gra/device.hpp | 69 +++ src/blu_cat/gra/font.cpp | 54 ++ src/blu_cat/gra/font.hpp | 42 ++ src/blu_cat/gra/framebuffer.cpp | 200 ++++++++ src/blu_cat/gra/framebuffer.hpp | 43 ++ src/blu_cat/gra/graphics_pipeline_2d_solid.cpp | 298 +++++++++++ src/blu_cat/gra/graphics_pipeline_2d_solid.hpp | 44 ++ .../gra/graphics_pipeline_2d_solid_layout.cpp | 83 +++ .../gra/graphics_pipeline_2d_solid_layout.hpp | 35 ++ src/blu_cat/gra/graphics_pipeline_2d_wired.cpp | 314 ++++++++++++ src/blu_cat/gra/graphics_pipeline_2d_wired.hpp | 47 ++ .../gra/graphics_pipeline_2d_wired_layout.cpp | 87 ++++ .../gra/graphics_pipeline_2d_wired_layout.hpp | 35 ++ src/blu_cat/gra/graphics_pipeline_3d.cpp | 308 +++++++++++ src/blu_cat/gra/graphics_pipeline_3d.hpp | 43 ++ src/blu_cat/gra/graphics_pipeline_3d_layout.cpp | 79 +++ src/blu_cat/gra/graphics_pipeline_3d_layout.hpp | 35 ++ src/blu_cat/gra/graphics_pipeline_3d_skeletal.cpp | 322 ++++++++++++ src/blu_cat/gra/graphics_pipeline_3d_skeletal.hpp | 43 ++ src/blu_cat/gra/graphics_pipeline_sprite_3d.cpp | 315 ++++++++++++ src/blu_cat/gra/graphics_pipeline_sprite_3d.hpp | 44 ++ src/blu_cat/gra/image.cpp | 149 ++++++ src/blu_cat/gra/image.hpp | 73 +++ src/blu_cat/gra/light.cpp | 205 ++++++++ src/blu_cat/gra/light.hpp | 41 ++ src/blu_cat/gra/log.cpp | 53 ++ src/blu_cat/gra/log.hpp | 54 ++ src/blu_cat/gra/qoi.cpp | 205 ++++++++ src/blu_cat/gra/qoi.hpp | 41 ++ src/blu_cat/gra/queue.cpp | 61 +++ src/blu_cat/gra/queue.hpp | 82 +++ src/blu_cat/gra/queue_family.cpp | 84 +++ src/blu_cat/gra/queue_family.hpp | 58 +++ src/blu_cat/gra/rectangle.cpp | 30 ++ src/blu_cat/gra/rectangle.hpp | 42 ++ src/blu_cat/gra/render_pass.cpp | 203 ++++++++ src/blu_cat/gra/render_pass.hpp | 36 ++ src/blu_cat/gra/renderer.cpp | 425 ++++++++++++++++ src/blu_cat/gra/renderer.hpp | 75 +++ src/blu_cat/gra/skeletal_mesh.cpp | 204 ++++++++ src/blu_cat/gra/skeletal_mesh.hpp | 52 ++ src/blu_cat/gra/skeletal_mesh_vertex.hpp | 42 ++ src/blu_cat/gra/skeletal_model.cpp | 239 +++++++++ src/blu_cat/gra/skeletal_model.hpp | 55 ++ src/blu_cat/gra/source_buffer.cpp | 87 ++++ src/blu_cat/gra/source_buffer.hpp | 45 ++ src/blu_cat/gra/sprite.cpp | 99 ++++ src/blu_cat/gra/sprite.hpp | 50 ++ src/blu_cat/gra/sprite_3d.cpp | 168 ++++++ src/blu_cat/gra/sprite_3d.hpp | 46 ++ src/blu_cat/gra/sprite_to_draw.cpp | 40 ++ src/blu_cat/gra/sprite_to_draw.hpp | 44 ++ src/blu_cat/gra/static_mesh.cpp | 132 +++++ src/blu_cat/gra/static_mesh.hpp | 48 ++ src/blu_cat/gra/static_mesh_vertex.hpp | 34 ++ src/blu_cat/gra/static_model.cpp | 165 ++++++ src/blu_cat/gra/static_model.hpp | 49 ++ src/blu_cat/gra/swapchain.cpp | 207 ++++++++ src/blu_cat/gra/swapchain.hpp | 47 ++ src/blu_cat/gra/texture.cpp | 566 +++++++++++++++++++++ src/blu_cat/gra/texture.hpp | 51 ++ src/blu_cat/gra/uniform_buffer.cpp | 89 ++++ src/blu_cat/gra/uniform_buffer.hpp | 49 ++ src/blu_cat/gra/uniform_data_object.hpp | 80 +++ src/blu_cat/gra/view_2d.cpp | 160 ++++++ src/blu_cat/gra/view_2d.hpp | 60 +++ src/blu_cat/gra/view_3d.cpp | 155 ++++++ src/blu_cat/gra/view_3d.hpp | 48 ++ src/blu_cat/gra/vulkan.hpp | 34 ++ src/blu_cat/int/core.cpp | 503 ++++++++++++++++++ src/blu_cat/int/core.hpp | 123 +++++ src/blucat/animation.cpp | 27 - src/blucat/animation.hpp | 51 -- src/blucat/animation/frame.hpp | 85 ---- src/blucat/base_buffer.cpp | 96 ---- src/blucat/base_buffer.hpp | 56 -- src/blucat/binary_reader.cpp | 156 ------ src/blucat/binary_reader.hpp | 69 --- src/blucat/character.cpp | 275 ---------- src/blucat/character.hpp | 49 -- src/blucat/command.cpp | 78 --- src/blucat/command.hpp | 92 ---- src/blucat/command_pool.cpp | 87 ---- src/blucat/command_pool.hpp | 59 --- src/blucat/core.cpp | 503 ------------------ src/blucat/core.hpp | 118 ----- src/blucat/descriptor_set_layout.cpp | 197 ------- src/blucat/descriptor_set_layout.hpp | 38 -- src/blucat/destination_buffer.cpp | 109 ---- src/blucat/destination_buffer.hpp | 54 -- src/blucat/device.cpp | 392 -------------- src/blucat/device.hpp | 69 --- src/blucat/font.cpp | 53 -- src/blucat/font.hpp | 42 -- src/blucat/framebuffer.cpp | 200 -------- src/blucat/framebuffer.hpp | 43 -- src/blucat/graphics_pipeline_2d_solid.cpp | 298 ----------- src/blucat/graphics_pipeline_2d_solid.hpp | 44 -- src/blucat/graphics_pipeline_2d_solid_layout.cpp | 83 --- src/blucat/graphics_pipeline_2d_solid_layout.hpp | 35 -- src/blucat/graphics_pipeline_2d_wired.cpp | 314 ------------ src/blucat/graphics_pipeline_2d_wired.hpp | 47 -- src/blucat/graphics_pipeline_2d_wired_layout.cpp | 87 ---- src/blucat/graphics_pipeline_2d_wired_layout.hpp | 35 -- src/blucat/graphics_pipeline_3d.cpp | 308 ----------- src/blucat/graphics_pipeline_3d.hpp | 43 -- src/blucat/graphics_pipeline_3d_layout.cpp | 79 --- src/blucat/graphics_pipeline_3d_layout.hpp | 35 -- src/blucat/graphics_pipeline_3d_skeletal.cpp | 322 ------------ src/blucat/graphics_pipeline_3d_skeletal.hpp | 43 -- src/blucat/graphics_pipeline_sprite_3d.cpp | 315 ------------ src/blucat/graphics_pipeline_sprite_3d.hpp | 44 -- src/blucat/image.cpp | 149 ------ src/blucat/image.hpp | 73 --- src/blucat/job_queue.cpp | 61 --- src/blucat/job_queue.hpp | 52 -- src/blucat/light.cpp | 205 -------- src/blucat/light.hpp | 41 -- src/blucat/log.cpp | 53 -- src/blucat/log.hpp | 54 -- src/blucat/qoi.cpp | 205 -------- src/blucat/qoi.hpp | 41 -- src/blucat/queue.cpp | 61 --- src/blucat/queue.hpp | 82 --- src/blucat/queue_family.cpp | 84 --- src/blucat/queue_family.hpp | 58 --- src/blucat/rectangle.cpp | 30 -- src/blucat/rectangle.hpp | 42 -- src/blucat/render_pass.cpp | 203 -------- src/blucat/render_pass.hpp | 36 -- src/blucat/renderer.cpp | 425 ---------------- src/blucat/renderer.hpp | 75 --- src/blucat/skeletal_mesh.cpp | 204 -------- src/blucat/skeletal_mesh.hpp | 52 -- src/blucat/skeletal_mesh_vertex.hpp | 42 -- src/blucat/skeletal_model.cpp | 239 --------- src/blucat/skeletal_model.hpp | 55 -- src/blucat/source_buffer.cpp | 87 ---- src/blucat/source_buffer.hpp | 45 -- src/blucat/sprite.cpp | 99 ---- src/blucat/sprite.hpp | 50 -- src/blucat/sprite_3d.cpp | 168 ------ src/blucat/sprite_3d.hpp | 46 -- src/blucat/sprite_to_draw.cpp | 40 -- src/blucat/sprite_to_draw.hpp | 44 -- src/blucat/static_mesh.cpp | 132 ----- src/blucat/static_mesh.hpp | 48 -- src/blucat/static_mesh_vertex.hpp | 34 -- src/blucat/static_model.cpp | 165 ------ src/blucat/static_model.hpp | 49 -- src/blucat/swapchain.cpp | 207 -------- src/blucat/swapchain.hpp | 47 -- src/blucat/texture.cpp | 566 --------------------- src/blucat/texture.hpp | 51 -- src/blucat/uniform_buffer.cpp | 89 ---- src/blucat/uniform_buffer.hpp | 49 -- src/blucat/uniform_data_object.hpp | 80 --- src/blucat/view_2d.cpp | 160 ------ src/blucat/view_2d.hpp | 60 --- src/blucat/view_3d.cpp | 155 ------ src/blucat/view_3d.hpp | 48 -- src/blucat/vulkan.hpp | 34 -- src/blucat/worker.cpp | 34 -- src/blucat/worker.hpp | 33 -- src/candy_gear.cpp | 146 ------ src/candy_gear.hpp | 32 -- src/candy_gear/candy_gear.cpp | 146 ++++++ src/candy_gear/candy_gear.hpp | 32 ++ src/candy_gear/core.cpp | 398 +++++++++++++++ src/candy_gear/core.hpp | 66 +++ src/candy_gear/font.cpp | 68 +++ src/candy_gear/font.hpp | 28 + src/candy_gear/graphic.cpp | 83 +++ src/candy_gear/graphic.hpp | 29 ++ src/candy_gear/key.cpp | 71 +++ src/candy_gear/key.hpp | 25 + src/candy_gear/main.cpp | 115 +++++ src/candy_gear/orientation_3d.cpp | 135 +++++ src/candy_gear/orientation_3d.hpp | 27 + src/candy_gear/skeletal_mesh.cpp | 67 +++ src/candy_gear/skeletal_mesh.hpp | 27 + src/candy_gear/skeletal_model.cpp | 134 +++++ src/candy_gear/skeletal_model.hpp | 25 + src/candy_gear/sound.cpp | 73 +++ src/candy_gear/sound.hpp | 32 ++ src/candy_gear/sprite.cpp | 93 ++++ src/candy_gear/sprite.hpp | 27 + src/candy_gear/sprite_3d.cpp | 82 +++ src/candy_gear/sprite_3d.hpp | 25 + src/candy_gear/static_mesh.cpp | 67 +++ src/candy_gear/static_mesh.hpp | 27 + src/candy_gear/static_model.cpp | 134 +++++ src/candy_gear/static_model.hpp | 25 + src/candy_gear/texture.cpp | 121 +++++ src/candy_gear/texture.hpp | 28 + src/candy_gear/vector_3d.cpp | 302 +++++++++++ src/candy_gear/vector_3d.hpp | 34 ++ src/candy_gear/vector_4d.cpp | 479 +++++++++++++++++ src/candy_gear/vector_4d.hpp | 27 + src/candy_gear/view_2d.cpp | 90 ++++ src/candy_gear/view_2d.hpp | 33 ++ src/candy_gear/view_3d.cpp | 127 +++++ src/candy_gear/view_3d.hpp | 27 + src/core.cpp | 398 --------------- src/core.hpp | 70 --- src/font.cpp | 68 --- src/font.hpp | 28 - src/graphic.cpp | 83 --- src/graphic.hpp | 29 -- src/key.cpp | 71 --- src/key.hpp | 25 - src/main.cpp | 115 ----- src/orientation_3d.cpp | 135 ----- src/orientation_3d.hpp | 27 - src/skeletal_mesh.cpp | 67 --- src/skeletal_mesh.hpp | 27 - src/skeletal_model.cpp | 134 ----- src/skeletal_model.hpp | 25 - src/sound.cpp | 73 --- src/sound.hpp | 32 -- src/sprite.cpp | 93 ---- src/sprite.hpp | 27 - src/sprite_3d.cpp | 82 --- src/sprite_3d.hpp | 25 - src/static_mesh.cpp | 67 --- src/static_mesh.hpp | 27 - src/static_model.cpp | 134 ----- src/static_model.hpp | 25 - src/texture.cpp | 121 ----- src/texture.hpp | 28 - src/vector_3d.cpp | 302 ----------- src/vector_3d.hpp | 34 -- src/vector_4d.cpp | 479 ----------------- src/vector_4d.hpp | 27 - src/view_2d.cpp | 90 ---- src/view_2d.hpp | 33 -- src/view_3d.cpp | 127 ----- src/view_3d.hpp | 27 - 263 files changed, 13742 insertions(+), 13709 deletions(-) create mode 100644 doc/architecture.markdown create mode 100644 src/blu_cat/com/command.cpp create mode 100644 src/blu_cat/com/command.hpp create mode 100644 src/blu_cat/com/job_queue.cpp create mode 100644 src/blu_cat/com/job_queue.hpp create mode 100644 src/blu_cat/com/worker.cpp create mode 100644 src/blu_cat/com/worker.hpp create mode 100644 src/blu_cat/gra/animation.cpp create mode 100644 src/blu_cat/gra/animation.hpp create mode 100644 src/blu_cat/gra/animation/frame.hpp create mode 100644 src/blu_cat/gra/base_buffer.cpp create mode 100644 src/blu_cat/gra/base_buffer.hpp create mode 100644 src/blu_cat/gra/binary_reader.cpp create mode 100644 src/blu_cat/gra/binary_reader.hpp create mode 100644 src/blu_cat/gra/character.cpp create mode 100644 src/blu_cat/gra/character.hpp create mode 100644 src/blu_cat/gra/command_pool.cpp create mode 100644 src/blu_cat/gra/command_pool.hpp create mode 100644 src/blu_cat/gra/descriptor_set_layout.cpp create mode 100644 src/blu_cat/gra/descriptor_set_layout.hpp create mode 100644 src/blu_cat/gra/destination_buffer.cpp create mode 100644 src/blu_cat/gra/destination_buffer.hpp create mode 100644 src/blu_cat/gra/device.cpp create mode 100644 src/blu_cat/gra/device.hpp create mode 100644 src/blu_cat/gra/font.cpp create mode 100644 src/blu_cat/gra/font.hpp create mode 100644 src/blu_cat/gra/framebuffer.cpp create mode 100644 src/blu_cat/gra/framebuffer.hpp create mode 100644 src/blu_cat/gra/graphics_pipeline_2d_solid.cpp create mode 100644 src/blu_cat/gra/graphics_pipeline_2d_solid.hpp create mode 100644 src/blu_cat/gra/graphics_pipeline_2d_solid_layout.cpp create mode 100644 src/blu_cat/gra/graphics_pipeline_2d_solid_layout.hpp create mode 100644 src/blu_cat/gra/graphics_pipeline_2d_wired.cpp create mode 100644 src/blu_cat/gra/graphics_pipeline_2d_wired.hpp create mode 100644 src/blu_cat/gra/graphics_pipeline_2d_wired_layout.cpp create mode 100644 src/blu_cat/gra/graphics_pipeline_2d_wired_layout.hpp create mode 100644 src/blu_cat/gra/graphics_pipeline_3d.cpp create mode 100644 src/blu_cat/gra/graphics_pipeline_3d.hpp create mode 100644 src/blu_cat/gra/graphics_pipeline_3d_layout.cpp create mode 100644 src/blu_cat/gra/graphics_pipeline_3d_layout.hpp create mode 100644 src/blu_cat/gra/graphics_pipeline_3d_skeletal.cpp create mode 100644 src/blu_cat/gra/graphics_pipeline_3d_skeletal.hpp create mode 100644 src/blu_cat/gra/graphics_pipeline_sprite_3d.cpp create mode 100644 src/blu_cat/gra/graphics_pipeline_sprite_3d.hpp create mode 100644 src/blu_cat/gra/image.cpp create mode 100644 src/blu_cat/gra/image.hpp create mode 100644 src/blu_cat/gra/light.cpp create mode 100644 src/blu_cat/gra/light.hpp create mode 100644 src/blu_cat/gra/log.cpp create mode 100644 src/blu_cat/gra/log.hpp create mode 100644 src/blu_cat/gra/qoi.cpp create mode 100644 src/blu_cat/gra/qoi.hpp create mode 100644 src/blu_cat/gra/queue.cpp create mode 100644 src/blu_cat/gra/queue.hpp create mode 100644 src/blu_cat/gra/queue_family.cpp create mode 100644 src/blu_cat/gra/queue_family.hpp create mode 100644 src/blu_cat/gra/rectangle.cpp create mode 100644 src/blu_cat/gra/rectangle.hpp create mode 100644 src/blu_cat/gra/render_pass.cpp create mode 100644 src/blu_cat/gra/render_pass.hpp create mode 100644 src/blu_cat/gra/renderer.cpp create mode 100644 src/blu_cat/gra/renderer.hpp create mode 100644 src/blu_cat/gra/skeletal_mesh.cpp create mode 100644 src/blu_cat/gra/skeletal_mesh.hpp create mode 100644 src/blu_cat/gra/skeletal_mesh_vertex.hpp create mode 100644 src/blu_cat/gra/skeletal_model.cpp create mode 100644 src/blu_cat/gra/skeletal_model.hpp create mode 100644 src/blu_cat/gra/source_buffer.cpp create mode 100644 src/blu_cat/gra/source_buffer.hpp create mode 100644 src/blu_cat/gra/sprite.cpp create mode 100644 src/blu_cat/gra/sprite.hpp create mode 100644 src/blu_cat/gra/sprite_3d.cpp create mode 100644 src/blu_cat/gra/sprite_3d.hpp create mode 100644 src/blu_cat/gra/sprite_to_draw.cpp create mode 100644 src/blu_cat/gra/sprite_to_draw.hpp create mode 100644 src/blu_cat/gra/static_mesh.cpp create mode 100644 src/blu_cat/gra/static_mesh.hpp create mode 100644 src/blu_cat/gra/static_mesh_vertex.hpp create mode 100644 src/blu_cat/gra/static_model.cpp create mode 100644 src/blu_cat/gra/static_model.hpp create mode 100644 src/blu_cat/gra/swapchain.cpp create mode 100644 src/blu_cat/gra/swapchain.hpp create mode 100644 src/blu_cat/gra/texture.cpp create mode 100644 src/blu_cat/gra/texture.hpp create mode 100644 src/blu_cat/gra/uniform_buffer.cpp create mode 100644 src/blu_cat/gra/uniform_buffer.hpp create mode 100644 src/blu_cat/gra/uniform_data_object.hpp create mode 100644 src/blu_cat/gra/view_2d.cpp create mode 100644 src/blu_cat/gra/view_2d.hpp create mode 100644 src/blu_cat/gra/view_3d.cpp create mode 100644 src/blu_cat/gra/view_3d.hpp create mode 100644 src/blu_cat/gra/vulkan.hpp create mode 100644 src/blu_cat/int/core.cpp create mode 100644 src/blu_cat/int/core.hpp delete mode 100644 src/blucat/animation.cpp delete mode 100644 src/blucat/animation.hpp delete mode 100644 src/blucat/animation/frame.hpp delete mode 100644 src/blucat/base_buffer.cpp delete mode 100644 src/blucat/base_buffer.hpp delete mode 100644 src/blucat/binary_reader.cpp delete mode 100644 src/blucat/binary_reader.hpp delete mode 100644 src/blucat/character.cpp delete mode 100644 src/blucat/character.hpp delete mode 100644 src/blucat/command.cpp delete mode 100644 src/blucat/command.hpp delete mode 100644 src/blucat/command_pool.cpp delete mode 100644 src/blucat/command_pool.hpp delete mode 100644 src/blucat/core.cpp delete mode 100644 src/blucat/core.hpp delete mode 100644 src/blucat/descriptor_set_layout.cpp delete mode 100644 src/blucat/descriptor_set_layout.hpp delete mode 100644 src/blucat/destination_buffer.cpp delete mode 100644 src/blucat/destination_buffer.hpp delete mode 100644 src/blucat/device.cpp delete mode 100644 src/blucat/device.hpp delete mode 100644 src/blucat/font.cpp delete mode 100644 src/blucat/font.hpp delete mode 100644 src/blucat/framebuffer.cpp delete mode 100644 src/blucat/framebuffer.hpp delete mode 100644 src/blucat/graphics_pipeline_2d_solid.cpp delete mode 100644 src/blucat/graphics_pipeline_2d_solid.hpp delete mode 100644 src/blucat/graphics_pipeline_2d_solid_layout.cpp delete mode 100644 src/blucat/graphics_pipeline_2d_solid_layout.hpp delete mode 100644 src/blucat/graphics_pipeline_2d_wired.cpp delete mode 100644 src/blucat/graphics_pipeline_2d_wired.hpp delete mode 100644 src/blucat/graphics_pipeline_2d_wired_layout.cpp delete mode 100644 src/blucat/graphics_pipeline_2d_wired_layout.hpp delete mode 100644 src/blucat/graphics_pipeline_3d.cpp delete mode 100644 src/blucat/graphics_pipeline_3d.hpp delete mode 100644 src/blucat/graphics_pipeline_3d_layout.cpp delete mode 100644 src/blucat/graphics_pipeline_3d_layout.hpp delete mode 100644 src/blucat/graphics_pipeline_3d_skeletal.cpp delete mode 100644 src/blucat/graphics_pipeline_3d_skeletal.hpp delete mode 100644 src/blucat/graphics_pipeline_sprite_3d.cpp delete mode 100644 src/blucat/graphics_pipeline_sprite_3d.hpp delete mode 100644 src/blucat/image.cpp delete mode 100644 src/blucat/image.hpp delete mode 100644 src/blucat/job_queue.cpp delete mode 100644 src/blucat/job_queue.hpp delete mode 100644 src/blucat/light.cpp delete mode 100644 src/blucat/light.hpp delete mode 100644 src/blucat/log.cpp delete mode 100644 src/blucat/log.hpp delete mode 100644 src/blucat/qoi.cpp delete mode 100644 src/blucat/qoi.hpp delete mode 100644 src/blucat/queue.cpp delete mode 100644 src/blucat/queue.hpp delete mode 100644 src/blucat/queue_family.cpp delete mode 100644 src/blucat/queue_family.hpp delete mode 100644 src/blucat/rectangle.cpp delete mode 100644 src/blucat/rectangle.hpp delete mode 100644 src/blucat/render_pass.cpp delete mode 100644 src/blucat/render_pass.hpp delete mode 100644 src/blucat/renderer.cpp delete mode 100644 src/blucat/renderer.hpp delete mode 100644 src/blucat/skeletal_mesh.cpp delete mode 100644 src/blucat/skeletal_mesh.hpp delete mode 100644 src/blucat/skeletal_mesh_vertex.hpp delete mode 100644 src/blucat/skeletal_model.cpp delete mode 100644 src/blucat/skeletal_model.hpp delete mode 100644 src/blucat/source_buffer.cpp delete mode 100644 src/blucat/source_buffer.hpp delete mode 100644 src/blucat/sprite.cpp delete mode 100644 src/blucat/sprite.hpp delete mode 100644 src/blucat/sprite_3d.cpp delete mode 100644 src/blucat/sprite_3d.hpp delete mode 100644 src/blucat/sprite_to_draw.cpp delete mode 100644 src/blucat/sprite_to_draw.hpp delete mode 100644 src/blucat/static_mesh.cpp delete mode 100644 src/blucat/static_mesh.hpp delete mode 100644 src/blucat/static_mesh_vertex.hpp delete mode 100644 src/blucat/static_model.cpp delete mode 100644 src/blucat/static_model.hpp delete mode 100644 src/blucat/swapchain.cpp delete mode 100644 src/blucat/swapchain.hpp delete mode 100644 src/blucat/texture.cpp delete mode 100644 src/blucat/texture.hpp delete mode 100644 src/blucat/uniform_buffer.cpp delete mode 100644 src/blucat/uniform_buffer.hpp delete mode 100644 src/blucat/uniform_data_object.hpp delete mode 100644 src/blucat/view_2d.cpp delete mode 100644 src/blucat/view_2d.hpp delete mode 100644 src/blucat/view_3d.cpp delete mode 100644 src/blucat/view_3d.hpp delete mode 100644 src/blucat/vulkan.hpp delete mode 100644 src/blucat/worker.cpp delete mode 100644 src/blucat/worker.hpp delete mode 100644 src/candy_gear.cpp delete mode 100644 src/candy_gear.hpp create mode 100644 src/candy_gear/candy_gear.cpp create mode 100644 src/candy_gear/candy_gear.hpp create mode 100644 src/candy_gear/core.cpp create mode 100644 src/candy_gear/core.hpp create mode 100644 src/candy_gear/font.cpp create mode 100644 src/candy_gear/font.hpp create mode 100644 src/candy_gear/graphic.cpp create mode 100644 src/candy_gear/graphic.hpp create mode 100644 src/candy_gear/key.cpp create mode 100644 src/candy_gear/key.hpp create mode 100644 src/candy_gear/main.cpp create mode 100644 src/candy_gear/orientation_3d.cpp create mode 100644 src/candy_gear/orientation_3d.hpp create mode 100644 src/candy_gear/skeletal_mesh.cpp create mode 100644 src/candy_gear/skeletal_mesh.hpp create mode 100644 src/candy_gear/skeletal_model.cpp create mode 100644 src/candy_gear/skeletal_model.hpp create mode 100644 src/candy_gear/sound.cpp create mode 100644 src/candy_gear/sound.hpp create mode 100644 src/candy_gear/sprite.cpp create mode 100644 src/candy_gear/sprite.hpp create mode 100644 src/candy_gear/sprite_3d.cpp create mode 100644 src/candy_gear/sprite_3d.hpp create mode 100644 src/candy_gear/static_mesh.cpp create mode 100644 src/candy_gear/static_mesh.hpp create mode 100644 src/candy_gear/static_model.cpp create mode 100644 src/candy_gear/static_model.hpp create mode 100644 src/candy_gear/texture.cpp create mode 100644 src/candy_gear/texture.hpp create mode 100644 src/candy_gear/vector_3d.cpp create mode 100644 src/candy_gear/vector_3d.hpp create mode 100644 src/candy_gear/vector_4d.cpp create mode 100644 src/candy_gear/vector_4d.hpp create mode 100644 src/candy_gear/view_2d.cpp create mode 100644 src/candy_gear/view_2d.hpp create mode 100644 src/candy_gear/view_3d.cpp create mode 100644 src/candy_gear/view_3d.hpp delete mode 100644 src/core.cpp delete mode 100644 src/core.hpp delete mode 100644 src/font.cpp delete mode 100644 src/font.hpp delete mode 100644 src/graphic.cpp delete mode 100644 src/graphic.hpp delete mode 100644 src/key.cpp delete mode 100644 src/key.hpp delete mode 100644 src/main.cpp delete mode 100644 src/orientation_3d.cpp delete mode 100644 src/orientation_3d.hpp delete mode 100644 src/skeletal_mesh.cpp delete mode 100644 src/skeletal_mesh.hpp delete mode 100644 src/skeletal_model.cpp delete mode 100644 src/skeletal_model.hpp delete mode 100644 src/sound.cpp delete mode 100644 src/sound.hpp delete mode 100644 src/sprite.cpp delete mode 100644 src/sprite.hpp delete mode 100644 src/sprite_3d.cpp delete mode 100644 src/sprite_3d.hpp delete mode 100644 src/static_mesh.cpp delete mode 100644 src/static_mesh.hpp delete mode 100644 src/static_model.cpp delete mode 100644 src/static_model.hpp delete mode 100644 src/texture.cpp delete mode 100644 src/texture.hpp delete mode 100644 src/vector_3d.cpp delete mode 100644 src/vector_3d.hpp delete mode 100644 src/vector_4d.cpp delete mode 100644 src/vector_4d.hpp delete mode 100644 src/view_2d.cpp delete mode 100644 src/view_2d.hpp delete mode 100644 src/view_3d.cpp delete mode 100644 src/view_3d.hpp diff --git a/.gitignore b/.gitignore index cc01af7..b631914 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -candy_gear -candy_gear.exe -doc +/candy_gear +/candy_gear.exe +/dox_doc pkg mruby-* diff --git a/Doxyfile b/Doxyfile index 044e484..b25320c 100644 --- a/Doxyfile +++ b/Doxyfile @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = doc +OUTPUT_DIRECTORY = dox_doc # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and diff --git a/doc/architecture.markdown b/doc/architecture.markdown new file mode 100644 index 0000000..e63f23c --- /dev/null +++ b/doc/architecture.markdown @@ -0,0 +1,10 @@ +Architecture +============ + +This project is split into two parts BluCat and CandyGear. +BluCat is the C++ engine, and CandyGear is the mruby engine. +BluCat consists of a few modules: + +- COM: common code that other modules use. +- INT: integration of all modules. +- GRA: graphics module. diff --git a/src/blu_cat/com/command.cpp b/src/blu_cat/com/command.cpp new file mode 100644 index 0000000..a1d3240 --- /dev/null +++ b/src/blu_cat/com/command.cpp @@ -0,0 +1,78 @@ +/* + * 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 + +#include "command.hpp" + +CommandError::CommandError(const std::string &m): + error(m) +{ +} + +CommandError::CommandError(const char &m): + CommandError{std::string{m}} +{ +} + +const char* CommandError::what() const noexcept +{ + return this->error.c_str(); +} + +CommandChain::CommandChain(std::initializer_list commands) +{ + for(auto c: commands) this->add(c); +} + +void +CommandChain::partial_revert(void *obj, int32_t step) const +{ + // Already unloaded, nothing to do. + if(step <= 0) return; + + for(; step > 0; step--) + { + auto command = this->_commands[step -1].undo_command; + if(command != nullptr) command(obj); + } +} + +void +CommandChain::add(const Command &c) +{ + this->_commands.push_back(c); +} + +void +CommandChain::execute(void *obj) const +{ + for(auto i{0}; i < this->_commands.size(); i++) + { + try { this->_commands[i].do_command(obj); } + catch(const CommandError &error) + { + this->partial_revert(obj, i); + throw; + } + } +} + +void +CommandChain::revert(void *obj) const +{ + this->partial_revert(obj, this->_commands.size()); +} diff --git a/src/blu_cat/com/command.hpp b/src/blu_cat/com/command.hpp new file mode 100644 index 0000000..5079c58 --- /dev/null +++ b/src/blu_cat/com/command.hpp @@ -0,0 +1,92 @@ +/* + * 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 BLU_CAT_COM_COMMAND_CHAIN_H +#define BLU_CAT_COM_COMMAND_CHAIN_H 1 + +#include +#include +#include +#include +#include + +class CommandChain; + +struct CommandError: public std::exception +{ + CommandError(const std::string &m); + CommandError(const char &m); + + const char* what() const noexcept; + +private: + std::string error; +}; + +/** + * Stores a reversible action. + */ +struct Command +{ + void (*do_command)(void *obj); + void (*undo_command)(void *obj); +}; + +/** + * Stores a sequence of functions that must be executed and rolled back in + * order. + * + * For example, if the variable _commands contain A→B→C→D→E, it will load A, + * then B, then C, etc. If D fails, it unloads C, then B, then A. + */ +class CommandChain +{ + std::vector _commands; + + void + partial_revert(void *obj, int32_t step) const; + +public: + CommandChain(std::initializer_list commands); + +/** + * Adds a reversible action to the command. The first action added is the first + * to de executed the last rolled back, and so on. Those functions are stored + * inside _commands. + * + * @param[unload] the undo/rollback action, if the action do not need a + * rollback, this pointer can be set to null. + */ + void + add(const Command &c); + +/** + * Execute all of the load functions in the _commands. If one of them fails, + * roll back everything inside _commands. + * @return true on success and false on fail. + */ + void + execute(void *obj) const; + +/** + * Roll back all loaded function inside commands, if there are any. + */ + void + revert(void *obj) const; + +}; + +#endif /* BLU_CAT_COM_COMMAND_CHAIN_H */ diff --git a/src/blu_cat/com/job_queue.cpp b/src/blu_cat/com/job_queue.cpp new file mode 100644 index 0000000..beaf989 --- /dev/null +++ b/src/blu_cat/com/job_queue.cpp @@ -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. + */ + +#include "job_queue.hpp" + +#include + +namespace BluCat::COM +{ + +JobQueue::JobQueue(): + jobs{}, + _stop{false} +{ +} + +void +JobQueue::stop() +{ + using namespace std::chrono_literals; + + while(!this->jobs.empty()) std::this_thread::sleep_for(1000ms); + this->_stop = true; + this->condition.notify_all(); +} + +void +JobQueue::push(Job job) +{ + std::unique_lock lock{this->access}; + this->jobs.push_back(job); + this->condition.notify_one(); +} + +Job +JobQueue::pop() +{ + std::unique_lock lock{this->access}; + this->condition.wait(lock, [this]{ + return !this->jobs.empty() || this->_stop;}); + if(!this->jobs.empty()) + { + auto job{std::move(this->jobs.front())}; + this->jobs.pop_front(); + return job; + } + else + { + return Job{nullptr}; + } +} + +} diff --git a/src/blu_cat/com/job_queue.hpp b/src/blu_cat/com/job_queue.hpp new file mode 100644 index 0000000..856946d --- /dev/null +++ b/src/blu_cat/com/job_queue.hpp @@ -0,0 +1,57 @@ +/* + * 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 BLU_CAT_COM_JOB_QUEUE_H +#define BLU_CAT_COM_JOB_QUEUE_H 1 + +#include +#include +#include +#include +#include + +namespace BluCat::COM +{ + +class Worker; + +typedef std::function Job; + +class JobQueue +{ + friend Worker; + + std::mutex access; + std::condition_variable condition; + std::atomic _stop; + std::deque jobs; + + Job + pop(); + +public: + JobQueue(); + + void + stop(); + + void + push(Job job); +}; + +} + +#endif /* BLU_CAT_COM_JOB_QUEUE_H */ diff --git a/src/blu_cat/com/worker.cpp b/src/blu_cat/com/worker.cpp new file mode 100644 index 0000000..847b571 --- /dev/null +++ b/src/blu_cat/com/worker.cpp @@ -0,0 +1,39 @@ +/* + * 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 "worker.hpp" + +#include + +namespace BluCat::COM +{ + +Worker::Worker(JobQueue *job_queue): + job_queue{job_queue} +{ +} + +void +Worker::operator()() +{ + while(!this->job_queue->_stop) + { + auto job{this->job_queue->pop()}; + if(job) job(); + } +} + +} diff --git a/src/blu_cat/com/worker.hpp b/src/blu_cat/com/worker.hpp new file mode 100644 index 0000000..d74aa24 --- /dev/null +++ b/src/blu_cat/com/worker.hpp @@ -0,0 +1,38 @@ +/* + * 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 BLU_CAT_COM_WORKER_H +#define BLU_CAT_COM_WORKER_H 1 + +#include "job_queue.hpp" + +namespace BluCat::COM +{ + +class Worker +{ + JobQueue *job_queue; + +public: + Worker(JobQueue *job_queue); + + void + operator()(); +}; + +} + +#endif /* BLU_CAT_COM_WORKER_H */ diff --git a/src/blu_cat/gra/animation.cpp b/src/blu_cat/gra/animation.cpp new file mode 100644 index 0000000..dc2c281 --- /dev/null +++ b/src/blu_cat/gra/animation.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2022-2024 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 "animation.hpp" + +namespace BluCat::GRA +{ + +Bone::Bone(glm::mat4 offset_matrix): + offset_matrix{offset_matrix} +{ +} + +} diff --git a/src/blu_cat/gra/animation.hpp b/src/blu_cat/gra/animation.hpp new file mode 100644 index 0000000..1275b48 --- /dev/null +++ b/src/blu_cat/gra/animation.hpp @@ -0,0 +1,51 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_ANIMATION_H +#define BLU_CAT_GRA_ANIMATION_H 1 + +#include + +#include "vulkan.hpp" +#include "animation/frame.hpp" + +namespace BluCat::GRA +{ + +struct Bone +{ + glm::mat4x4 offset_matrix; + + Bone(glm::mat4 offset_matrix); +}; + +struct BoneTransform +{ + uint32_t bone_id; + Channel positions; + Channel rotations; + Channel scales; +}; + +struct Animation +{ + std::vector bone_transforms; + float final_time; +}; + +} + +#endif /* BLU_CAT_GRA_ANIMATION_H */ diff --git a/src/blu_cat/gra/animation/frame.hpp b/src/blu_cat/gra/animation/frame.hpp new file mode 100644 index 0000000..b1ea913 --- /dev/null +++ b/src/blu_cat/gra/animation/frame.hpp @@ -0,0 +1,85 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_FRAME_H +#define BLU_CAT_GRA_FRAME_H 1 + +#include + +#include "../vulkan.hpp" + +namespace BluCat::GRA +{ + +template +struct Frame +{ + const T value; + const float timestamp; + + Frame(T value, float timestamp): + value{value}, + timestamp{timestamp} + { + } + +}; + +template +struct Channel +{ + int current_index{0}; + std::vector> key_frames; + + inline glm::mat4 + interpolate( + float animation_time, + glm::mat4 (*single_frame)(T frame), + glm::mat4 (*multiple_frames)(T current_frame, T next_frame, float scale)) + { + if(this->key_frames.size() == 1) + return single_frame(this->key_frames[0].value); + else + { + while(animation_time > this->key_frames[current_index].timestamp) + this->current_index++; + + float scale_factor; + Frame *previous_frame; + Frame *next_frame{&(this->key_frames[this->current_index])}; + if(this->current_index == 0) + { + previous_frame = &(this->key_frames[this->key_frames.size() - 1]); + float midway_length{animation_time - 0}; + float frames_diff{next_frame->timestamp - 0}; + scale_factor = midway_length / frames_diff; + } + else + { + previous_frame = &(this->key_frames[this->current_index - 1]); + float midway_length{animation_time - previous_frame->timestamp}; + float frames_diff{next_frame->timestamp - previous_frame->timestamp}; + scale_factor = midway_length / frames_diff; + } + + return multiple_frames( + previous_frame->value, next_frame->value, scale_factor); + } + }; +}; + +} +#endif /* BLU_CAT_GRA_FRAME_H */ diff --git a/src/blu_cat/gra/base_buffer.cpp b/src/blu_cat/gra/base_buffer.cpp new file mode 100644 index 0000000..1add9fb --- /dev/null +++ b/src/blu_cat/gra/base_buffer.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2022-2024 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 "base_buffer.hpp" + +namespace BluCat::GRA +{ + +const CommandChain BaseBuffer::loader{ + {&BaseBuffer::load_buffer, &BaseBuffer::unload_buffer}, + {&BaseBuffer::load_memory, &BaseBuffer::unload_memory} +}; + +void +BaseBuffer::load_buffer(void *obj) +{ + auto self = static_cast(obj); + + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.pNext = nullptr; + buffer_info.flags = 0; + buffer_info.size = self->device_size; + buffer_info.usage = self->buffer_usage; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + buffer_info.queueFamilyIndexCount = 0; + buffer_info.pQueueFamilyIndices = nullptr; + + if(vkCreateBuffer( + self->device->device, &buffer_info, nullptr, &self->buffer) + != VK_SUCCESS) + throw CommandError{"Failed to create vertex buffer."}; +} + +void +BaseBuffer::unload_buffer(void *obj) +{ + auto self = static_cast(obj); + + if(self->buffer != VK_NULL_HANDLE) + vkDestroyBuffer(self->device->device, self->buffer, nullptr); +} + +void +BaseBuffer::load_memory(void *obj) +{ + auto self = static_cast(obj); + + VkMemoryRequirements memory_requirements; + vkGetBufferMemoryRequirements( + self->device->device, self->buffer, &memory_requirements); + + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties( + self->device->physical_device, &memory_properties); + + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.allocationSize = memory_requirements.size; + if(!self->device->select_memory_type( + &alloc_info.memoryTypeIndex, &memory_requirements, + self->memory_properties)) + throw CommandError{"Could not allocate memory for Vulkan vertex buffer."}; + + if(vkAllocateMemory(self->device->device, &alloc_info, nullptr, + &self->device_memory) != VK_SUCCESS) + throw CommandError{"Could not allocate memory for Vulkan vertex buffer."}; + + vkBindBufferMemory( + self->device->device, self->buffer, self->device_memory, 0); +} + +void +BaseBuffer::unload_memory(void *obj) +{ + auto self = static_cast(obj); + + if(self->device_memory != VK_NULL_HANDLE) + vkFreeMemory(self->device->device, self->device_memory, nullptr); +} + +} diff --git a/src/blu_cat/gra/base_buffer.hpp b/src/blu_cat/gra/base_buffer.hpp new file mode 100644 index 0000000..cb4cdf8 --- /dev/null +++ b/src/blu_cat/gra/base_buffer.hpp @@ -0,0 +1,56 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_BASE_BUFFER_H +#define BLU_CAT_GRA_BASE_BUFFER_H 1 + +#include "../com/command.hpp" +#include "vulkan.hpp" +#include "device.hpp" + +namespace BluCat::GRA +{ + +class BaseBuffer +{ + public: + virtual ~BaseBuffer(){}; + + VkBuffer buffer; + VkDeviceMemory device_memory; + VkDeviceSize device_size; + VkBufferUsageFlags buffer_usage; + VkMemoryPropertyFlags memory_properties; + + protected: + static const CommandChain loader; + + Device *device; + + static void + load_buffer(void *obj); + static void + unload_buffer(void *obj); + + static void + load_memory(void *obj); + static void + unload_memory(void *obj); +}; + +} + +#endif /* BLU_CAT_GRA_BASE_BUFFER_H */ diff --git a/src/blu_cat/gra/binary_reader.cpp b/src/blu_cat/gra/binary_reader.cpp new file mode 100644 index 0000000..14fc39c --- /dev/null +++ b/src/blu_cat/gra/binary_reader.cpp @@ -0,0 +1,156 @@ +/* + * Copyright 2022-2024 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 "binary_reader.hpp" + +#include + +namespace +{ + +union IntAndFloat32bit{ + uint32_t i; + float f; +}; + +union IntAndFloat64bit{ + uint64_t i; + double f; +}; + +} + +BinaryReader::BinaryReader(std::string file_path): + _pointer{0} +{ + std::ifstream file(file_path, std::ios::binary | std::ios::ate); + if(!file.is_open()) + { + std::string error{"failed to open file: "}; + error += file_path; + throw std::runtime_error{error}; + } + + this->_size = file.tellg(); + file.seekg(0); + this->data = new uint8_t[this->_size]; + file.read((char*)data, this->_size); +} + +BinaryReader::BinaryReader(const char *file_path): + BinaryReader{std::string(file_path)} +{ +} + +BinaryReader::~BinaryReader() +{ + delete[] this->data; +} + +uint8_t +BinaryReader::read_ui8() +{ + return this->data[this->_pointer++]; +} + +uint32_t +BinaryReader::read_ui32() +{ + uint8_t b1{this->data[_pointer++]}, b2{this->data[_pointer++]}, + b3{this->data[_pointer++]}, b4{this->data[_pointer++]}; + + return b1 << 24 | b2 << 16 | b3 << 8 | b4; +} + +uint64_t +BinaryReader::read_ui64() +{ + uint8_t b1{this->data[_pointer++]}, b2{this->data[_pointer++]}, + b3{this->data[_pointer++]}, b4{this->data[_pointer++]}, + b5{this->data[_pointer++]}, b6{this->data[_pointer++]}, + b7{this->data[_pointer++]}, b8{this->data[_pointer++]}; + + return (uint64_t)b1 << 56 | (uint64_t)b2 << 48 | (uint64_t)b3 << 40 | + (uint64_t)b4 << 32 | (uint64_t)b5 << 24 | (uint64_t)b6 << 16 | + (uint64_t)b7 << 8 | (uint64_t)b8; +} + +float +BinaryReader::read_float() +{ + IntAndFloat32bit num; + num.i = read_ui32(); + + return num.f; +} + +double +BinaryReader::read_double() +{ + IntAndFloat64bit num; + num.i = read_ui64(); + + return num.f; +} + +glm::vec2 +BinaryReader::read_vec2() +{ + IntAndFloat32bit x{read_ui32()}, y{read_ui32()}; + + return glm::vec2{x.f, y.f}; +} + +glm::vec3 +BinaryReader::read_vec3() +{ + IntAndFloat32bit x{read_ui32()}, y{read_ui32()}, z{read_ui32()}; + + return glm::vec3{x.f, y.f, z.f}; +} + +glm::quat +BinaryReader::read_quat() +{ + IntAndFloat32bit w{read_ui32()}, x{read_ui32()}, y{read_ui32()}, + z{read_ui32()}; + + return glm::quat{w.f, x.f, y.f, z.f}; +} + +glm::mat4 +BinaryReader::read_mat4() +{ + glm::mat4 matrix; + float *offset_matrix_data{glm::value_ptr(matrix)}; + + for(int i{0}; i < 16; i++) + { + IntAndFloat32bit num; + num.i = read_ui32(); + offset_matrix_data[i] = num.f; + } + + return matrix; +} + +void +BinaryReader::read_chars(char *str, int size) +{ + for(int i{0}; i < size; i++) + str[i] = (char)data[this->_pointer++]; +} + diff --git a/src/blu_cat/gra/binary_reader.hpp b/src/blu_cat/gra/binary_reader.hpp new file mode 100644 index 0000000..1995402 --- /dev/null +++ b/src/blu_cat/gra/binary_reader.hpp @@ -0,0 +1,69 @@ +/* + * Copyright 2022-2024 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 +#include + +#include "vulkan.hpp" + +class BinaryReader +{ + int _pointer; + int _size; + uint8_t *data; + +public: + + BinaryReader(const std::string file_path); + BinaryReader(const char *file_path); + ~BinaryReader(); + + inline int + pointer(){return this->_pointer;}; + + inline int + size(){return this->_size;}; + + uint8_t + read_ui8(); + + uint32_t + read_ui32(); + + uint64_t + read_ui64(); + + float + read_float(); + + double + read_double(); + + glm::vec2 + read_vec2(); + + glm::vec3 + read_vec3(); + + glm::quat + read_quat(); + + glm::mat4 + read_mat4(); + + void + read_chars(char *str, int size); +}; diff --git a/src/blu_cat/gra/character.cpp b/src/blu_cat/gra/character.cpp new file mode 100644 index 0000000..f0e7512 --- /dev/null +++ b/src/blu_cat/gra/character.cpp @@ -0,0 +1,275 @@ +/* + * Copyright 2022-2024 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 "character.hpp" + +#include "../com/command.hpp" +#include "../int/core.hpp" +#include "font.hpp" +#include "image.hpp" +#include "source_buffer.hpp" + +namespace +{ + +struct CharacterBuilder +{ + BluCat::GRA::Character *character; + FT_Face face; + uint32_t character_code; + + CharacterBuilder( + BluCat::GRA::Character *character, FT_Face face, uint32_t character_code); +}; + +CharacterBuilder::CharacterBuilder( + BluCat::GRA::Character *character, FT_Face face, uint32_t character_code): + character{character}, + face{face}, + character_code{character_code} +{ +} + +// TODO: creating one image with one device memory for each character is +// ineficient +void +load_image(void *obj) +{ + auto self = static_cast(obj); + + FT_Error error; + std::vector source_image_raw; + const int num_channels = 4; // all images are converted to RGBA + auto glyph_index{FT_Get_Char_Index(self->face, self->character_code)}; + + error = FT_Load_Glyph(self->face, glyph_index, FT_LOAD_DEFAULT); + if(error) throw CommandError{"failed to load glyph"}; + + error = FT_Render_Glyph(self->face->glyph, FT_RENDER_MODE_NORMAL); + if(error) throw CommandError{"failed to render glyph"}; + + self->character->bearing_x = self->face->glyph->bitmap_left; + self->character->bearing_y = self->face->glyph->bitmap_top; + self->character->advance = (self->face->glyph->advance.x >> 6); + self->character->width = self->face->glyph->bitmap.width; + self->character->height = self->face->glyph->bitmap.rows; + self->character->mip_levels = 1; + + // Character is a white-space. + if(self->character->width <= 0) + { + self->character->image = VK_NULL_HANDLE; + self->character->device_memory = VK_NULL_HANDLE; + + return; + } + + auto image_size{static_cast( + self->face->glyph->bitmap.width * + self->face->glyph->bitmap.rows * num_channels)}; + + { // Create the data for the image buffer + source_image_raw.resize(image_size, 0); + + for(auto y{0}; y < self->face->glyph->bitmap.width; y++) + { + for(auto x{0}; x < self->face->glyph->bitmap.rows; x++) + { + auto image_coord = y * self->face->glyph->bitmap.rows * num_channels + + x * num_channels; + auto glyph_coord = y * self->face->glyph->bitmap.rows + x; + // Red + source_image_raw[image_coord] = 255; + // Green + source_image_raw[image_coord + 1] = 255; + // Blue + source_image_raw[image_coord + 2] = 255; + // Alpha + source_image_raw[image_coord + 3] = + self->face->glyph->bitmap.buffer[glyph_coord]; + } + } + } + + BluCat::GRA::SourceBuffer source_image_buffer{ + BluCat::INT::core.vk_device_with_swapchain, source_image_raw.data(), + image_size}; + + { // Create Vulkan image. + try + { + VkExtent3D vk_extent3d; + vk_extent3d.width = self->face->glyph->bitmap.width; + vk_extent3d.height = self->face->glyph->bitmap.rows; + vk_extent3d.depth = 1; + + BluCat::GRA::Image::create( + BluCat::INT::core.vk_device_with_swapchain, + &self->character->image, + &self->character->device_memory, + VK_FORMAT_R8G8B8A8_UNORM, + vk_extent3d, + self->character->mip_levels, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + } + catch(BluCat::GRA::Image::Error error) + { + throw CommandError{error.what()}; + } + } + + { // Copy image from buffer into image. + auto queue_family{BluCat::INT::core.vk_device_with_swapchain-> + get_queue_family_with_presentation()}; + auto queue{queue_family->get_queue()}; + BluCat::GRA::CommandPool command_pool{queue_family, 1}; + VkCommandBuffer vk_command_buffer{command_pool.command_buffers[0]}; + + queue.submit_one_time_command(vk_command_buffer, [&](){ + BluCat::GRA::Image::move_image_state( + vk_command_buffer, self->character->image, VK_FORMAT_R8G8B8A8_UNORM, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT); + + VkBufferImageCopy image_copy; + image_copy.bufferOffset = 0; + image_copy.bufferRowLength = 0; + image_copy.bufferImageHeight = 0; + image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + image_copy.imageSubresource.mipLevel = 0; + image_copy.imageSubresource.baseArrayLayer = 0; + image_copy.imageSubresource.layerCount = 1; + image_copy.imageOffset = {0, 0, 0}; + image_copy.imageExtent = { + self->character->width, self->character->height, 1}; + + vkCmdCopyBufferToImage( + vk_command_buffer, source_image_buffer.buffer, self->character->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); + + BluCat::GRA::Image::move_image_state( + vk_command_buffer, self->character->image, VK_FORMAT_R8G8B8A8_UNORM, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + }); + } +} + +void +unload_image(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyImage( + BluCat::INT::core.vk_device_with_swapchain->device, self->character->image, + nullptr); + vkFreeMemory( + BluCat::INT::core.vk_device_with_swapchain->device, + self->character->device_memory, nullptr); +} + +const CommandChain loader{ + {&load_image, &unload_image} +}; + +} + +namespace BluCat::GRA +{ + +Character::Character(FT_Face face, uint32_t character_code) +{ + CharacterBuilder character_builder(this, face, character_code); + loader.execute(&character_builder); +} + +Character::~Character() +{ + CharacterBuilder character_builder(this, nullptr, 0); + loader.revert(&character_builder); +} + +std::vector +Character::str_to_unicode(const char* str) +{ + std::vector unicode_text; + int text_width{0}; + int text_height{0}; + + { // Reserve memory + int size{0}; + for(auto i{0}; str[i] != '\0'; i++) + if((str[i] & 0b11000000) != 0b10000000) size++; + unicode_text.reserve(size); + } + + for(auto i{0}; str[i] != '\0'; i++) + { + int num_bytes; + uint32_t codepoint{0}; + + if(str[i] >= 0 && str[i] < 127) + { // Normal ASCI character, 1-byte. + num_bytes = 1; + codepoint = str[i]; + } + else if((str[i] & 0xE0) == 0xC0) + { // 2-byte character. + num_bytes = 2; + codepoint += ((str[i] & 0b00011111) << 6); + } + else if((str[i] & 0xF0) == 0xE0) + { // 3-byte character. + num_bytes = 3; + codepoint += ((str[i] & 0b00001111) << 12); + } + else if((str[i] & 0xF8) == 0xF0) + { // 4-byte character. + num_bytes = 4; + codepoint += ((str[i] & 0b00000111) << 18); + } + else + { // FIXME: Add support to 5-byte and 6-byte characters. + } + + switch (num_bytes) + { + case 4: + i++; + codepoint += ((str[i] & 0b00111111) << 12); + case 3: + i++; + codepoint += ((str[i] & 0b00111111) << 6); + case 2: + i++; + codepoint += (str[i] & 0b00111111); + case 1: + default: + break; + } + + unicode_text.push_back(codepoint); + } + + return unicode_text; +} + +} diff --git a/src/blu_cat/gra/character.hpp b/src/blu_cat/gra/character.hpp new file mode 100644 index 0000000..8968384 --- /dev/null +++ b/src/blu_cat/gra/character.hpp @@ -0,0 +1,49 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_CHARACTER_H +#define BLU_CAT_GRA_CHARACTER_H 1 + +#include +#include FT_FREETYPE_H + +#include "vulkan.hpp" + +#include + +namespace BluCat::GRA +{ + +struct Character +{ + VkImage image; + VkDeviceMemory device_memory; + int32_t bearing_y, bearing_x; + uint32_t width, height, advance, mip_levels; + + Character(FT_Face face, uint32_t character_code); + ~Character(); + + Character(Character const&) = delete; + Character& operator=(Character const&) = delete; + + static std::vector + str_to_unicode(const char* str); +}; + +} + +#endif /* BLU_CAT_GRA_CHARACTER_H */ diff --git a/src/blu_cat/gra/command_pool.cpp b/src/blu_cat/gra/command_pool.cpp new file mode 100644 index 0000000..2602522 --- /dev/null +++ b/src/blu_cat/gra/command_pool.cpp @@ -0,0 +1,87 @@ +/* + * Copyright 2022-2024 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 "command_pool.hpp" + +namespace BluCat::GRA +{ + +const CommandChain CommandPool::loader{ + {&CommandPool::load_command_pool, &CommandPool::unload_command_pool}, + {&CommandPool::load_command_buffers, nullptr} +}; + +CommandPool::CommandPool(QueueFamily *queue_family, uint32_t buffers_quantity): + queue_family{queue_family} +{ + this->command_buffers.resize(buffers_quantity); + + CommandPool::loader.execute(this); +} + +CommandPool::~CommandPool() +{ + CommandPool::loader.revert(this); +} + +void +CommandPool::load_command_pool(void *obj) +{ + auto *self = static_cast(obj); + + VkCommandPoolCreateInfo command_pool_create_info; + + command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + command_pool_create_info.pNext = nullptr; + command_pool_create_info.flags = + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + command_pool_create_info.queueFamilyIndex = self->queue_family->family_index; + + if(vkCreateCommandPool( + self->queue_family->device->device, &command_pool_create_info, + nullptr, &self->command_pool) != VK_SUCCESS) + throw CommandError{"Vulkan command pool could not be created."}; +} + +void +CommandPool::unload_command_pool(void *obj) +{ + auto *self = static_cast(obj); + + vkDestroyCommandPool( + self->queue_family->device->device, self->command_pool, nullptr); +} + +void +CommandPool::load_command_buffers(void *obj) +{ + auto *self = static_cast(obj); + + VkCommandBufferAllocateInfo command_buffer_info; + command_buffer_info.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_info.pNext = nullptr; + command_buffer_info.commandPool = self->command_pool; + command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_info.commandBufferCount = self->command_buffers.size(); + + if(vkAllocateCommandBuffers( + self->queue_family->device->device, + &command_buffer_info, self->command_buffers.data()) != VK_SUCCESS) + throw CommandError{"Vulkan command buffers could not be allocated."}; +} + +} diff --git a/src/blu_cat/gra/command_pool.hpp b/src/blu_cat/gra/command_pool.hpp new file mode 100644 index 0000000..7487365 --- /dev/null +++ b/src/blu_cat/gra/command_pool.hpp @@ -0,0 +1,59 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_COMMAND_POOL_H +#define BLU_CAT_GRA_COMMAND_POOL_H 1 + +#include + +#include "../com/command.hpp" +#include "device.hpp" +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +class CommandPool +{ + CommandPool(const CommandPool &t) = delete; + CommandPool& operator=(const CommandPool &t) = delete; + CommandPool(const CommandPool &&t) = delete; + CommandPool& operator=(const CommandPool &&t) = delete; + +public: + std::vector command_buffers; + + CommandPool(QueueFamily *queue_family, uint32_t buffers_quantity); + ~CommandPool(); + +private: + static const CommandChain loader; + + QueueFamily *queue_family; + VkCommandPool command_pool; + + static void + load_command_pool(void *obj); + static void + unload_command_pool(void *obj); + + static void + load_command_buffers(void *obj); +}; + +} + +#endif /* BLU_CAT_GRA_COMMAND_POOL_H */ diff --git a/src/blu_cat/gra/descriptor_set_layout.cpp b/src/blu_cat/gra/descriptor_set_layout.cpp new file mode 100644 index 0000000..e1e8852 --- /dev/null +++ b/src/blu_cat/gra/descriptor_set_layout.cpp @@ -0,0 +1,197 @@ +/* + * Copyright 2022-2024 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 "descriptor_set_layout.hpp" + +#include + +#include "../int/core.hpp" + +namespace +{ + +void +load_world(void *obj) +{ + auto self = static_cast(obj); + + std::array set_layouts{}; + set_layouts[0].binding = 0; + set_layouts[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + set_layouts[0].descriptorCount = 1; + set_layouts[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + set_layouts[0].pImmutableSamplers = nullptr; + + set_layouts[1].binding = 1; + set_layouts[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + set_layouts[1].descriptorCount = 1; + set_layouts[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + set_layouts[1].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 = set_layouts.size(); + layout_info.pBindings = set_layouts.data(); + + if(vkCreateDescriptorSetLayout( + BluCat::INT::core.vk_device_with_swapchain->device, &layout_info, nullptr, + &self->world) != VK_SUCCESS) + throw CommandError{ + "Failed to create Vulkan descriptor set layout for world view."}; +} + +void +unload_world(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyDescriptorSetLayout( + BluCat::INT::core.vk_device_with_swapchain->device, self->world, nullptr); +} + +void +load_view(void *obj) +{ + auto self = static_cast(obj); + + std::array 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(layout_bindings.size()); + layout_info.pBindings = layout_bindings.data(); + + if(vkCreateDescriptorSetLayout( + BluCat::INT::core.vk_device_with_swapchain->device, &layout_info, nullptr, + &self->view) != VK_SUCCESS) + throw CommandError{ + "Failed to create Vulkan descriptor set layout for view."}; +} + +void +unload_view(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyDescriptorSetLayout( + BluCat::INT::core.vk_device_with_swapchain->device, self->view, nullptr); +} + +void +load_texture(void *obj) +{ + auto self = static_cast(obj); + + std::array layout_bindings{}; + + layout_bindings[0].binding = 0; + layout_bindings[0].descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + 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(layout_bindings.size()); + layout_info.pBindings = layout_bindings.data(); + + if(vkCreateDescriptorSetLayout( + BluCat::INT::core.vk_device_with_swapchain->device, &layout_info, nullptr, + &self->texture) != VK_SUCCESS) + throw CommandError{ + "Failed to create Vulkan descriptor set layout for textures."}; +} + +void +unload_texture(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyDescriptorSetLayout( + BluCat::INT::core.vk_device_with_swapchain->device, self->texture, nullptr); +} + +void +load_model(void *obj) +{ + auto self = static_cast(obj); + + std::array 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(layout_bindings.size()); + layout_info.pBindings = layout_bindings.data(); + + if(vkCreateDescriptorSetLayout( + BluCat::INT::core.vk_device_with_swapchain->device, &layout_info, nullptr, + &self->model) != VK_SUCCESS) + throw CommandError{ + "Failed to create Vulkan descriptor set layout for model instance."}; +} + +void +unload_model(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyDescriptorSetLayout( + BluCat::INT::core.vk_device_with_swapchain->device, self->model, nullptr); +} + +const CommandChain loader{ + {&load_world, &unload_world}, + {&load_view, &unload_view}, + {&load_texture, &unload_texture}, + {&load_model, &unload_model}, +}; + +} + +namespace BluCat::GRA +{ + +DescriptorSetLayout::DescriptorSetLayout() +{ + loader.execute(this); +} + +DescriptorSetLayout::~DescriptorSetLayout() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/descriptor_set_layout.hpp b/src/blu_cat/gra/descriptor_set_layout.hpp new file mode 100644 index 0000000..42003b9 --- /dev/null +++ b/src/blu_cat/gra/descriptor_set_layout.hpp @@ -0,0 +1,38 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_DESCRIPTOR_SET_LAYOUT_H +#define BLU_CAT_GRA_DESCRIPTOR_SET_LAYOUT_H 1 + +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +struct DescriptorSetLayout +{ + VkDescriptorSetLayout world; + VkDescriptorSetLayout view; + VkDescriptorSetLayout texture; + VkDescriptorSetLayout model; + + DescriptorSetLayout(); + ~DescriptorSetLayout(); +}; + +} + +#endif /* BLU_CAT_GRA_DESCRIPTOR_SET_LAYOUT_H */ diff --git a/src/blu_cat/gra/destination_buffer.cpp b/src/blu_cat/gra/destination_buffer.cpp new file mode 100644 index 0000000..3c53db4 --- /dev/null +++ b/src/blu_cat/gra/destination_buffer.cpp @@ -0,0 +1,109 @@ +/* + * Copyright 2022-2024 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 "destination_buffer.hpp" + +#include "command_pool.hpp" + +namespace BluCat::GRA +{ + +DestinationBuffer::DestinationBuffer( + QueueFamily *queue_family, SourceBuffer *source_buffer, + VkBufferUsageFlags buffer_usage) +{ + this->device = queue_family->device; + this->device_size = source_buffer->device_size; + this->buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | buffer_usage; + this->memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + this->queue_family = queue_family; + this->source_buffer = source_buffer; + + BaseBuffer::loader.execute(dynamic_cast(this)); + + this->copy_data(); +} + +DestinationBuffer::DestinationBuffer( + DestinationBuffer &&that) +{ + this->buffer = that.buffer; + this->device_memory = that.device_memory; + this->device_size = that.device_size; + this->buffer_usage = that.buffer_usage; + this->memory_properties = that.memory_properties; + + that.buffer = VK_NULL_HANDLE; + that.device_memory = VK_NULL_HANDLE; +} + +DestinationBuffer& +DestinationBuffer::operator=(DestinationBuffer &&that) +{ + this->buffer = that.buffer; + this->device_memory = that.device_memory; + this->device_size = that.device_size; + this->buffer_usage = that.buffer_usage; + this->memory_properties = that.memory_properties; + + that.buffer = VK_NULL_HANDLE; + that.device_memory = VK_NULL_HANDLE; + + return *this; +} + +DestinationBuffer::~DestinationBuffer() +{ + BaseBuffer::loader.revert(dynamic_cast(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/blu_cat/gra/destination_buffer.hpp b/src/blu_cat/gra/destination_buffer.hpp new file mode 100644 index 0000000..7df1e50 --- /dev/null +++ b/src/blu_cat/gra/destination_buffer.hpp @@ -0,0 +1,54 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_DESTINATION_BUFFER_H +#define BLU_CAT_GRA_DESTINATION_BUFFER_H 1 + +#include "base_buffer.hpp" +#include "vulkan.hpp" +#include "source_buffer.hpp" +#include "queue_family.hpp" + +namespace BluCat::GRA +{ + +struct DestinationBuffer: public BaseBuffer +{ + DestinationBuffer(const DestinationBuffer &t) = delete; + DestinationBuffer& + operator=(const DestinationBuffer &t) = delete; + + QueueFamily *queue_family; + SourceBuffer *source_buffer; + VkCommandBuffer vk_command_buffer; + + DestinationBuffer( + QueueFamily *queue_family, SourceBuffer *source_buffer, + VkBufferUsageFlags buffer_usage); + + DestinationBuffer(DestinationBuffer &&that); + DestinationBuffer& + operator=(DestinationBuffer &&that); + + ~DestinationBuffer(); + + void + copy_data(); +}; + +} + +#endif /* BLU_CAT_GRA_DESTINATION_BUFFER_H */ diff --git a/src/blu_cat/gra/device.cpp b/src/blu_cat/gra/device.cpp new file mode 100644 index 0000000..b2d114a --- /dev/null +++ b/src/blu_cat/gra/device.cpp @@ -0,0 +1,393 @@ +/* + * Copyright 2022-2024 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 "device.hpp" + +#include +#include +#include +#ifdef DEBUG +#include +#endif + +#include "../int/core.hpp" + +namespace +{ +VkShaderModule +create_shader_module(VkDevice vk_device, const char *filename) +{ + std::ifstream file(filename, std::ios::ate | std::ios::binary); + + if (!file.is_open()) + { + throw std::runtime_error("Failed to open shader module file."); + } + + size_t file_size = (size_t) file.tellg(); + std::vector code(file_size); + + file.seekg(0); + file.read(code.data(), file_size); + + file.close(); + + VkShaderModuleCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + create_info.codeSize = code.size(); + create_info.pCode = reinterpret_cast(code.data()); + + VkShaderModule shader_module; + if (vkCreateShaderModule(vk_device, &create_info, nullptr, + &shader_module) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create shader module."); + } + + return shader_module; +} +} + +namespace BluCat::GRA +{ + +Device::Device(VkPhysicalDevice vk_physical_device, bool with_swapchain) +{ + this->physical_device = vk_physical_device; + + std::vector queue_family_properties; + + // Get queue families. + { + vkGetPhysicalDeviceQueueFamilyProperties( + vk_physical_device, &this->queue_families_count, nullptr); + queue_family_properties.resize(this->queue_families_count); + vkGetPhysicalDeviceQueueFamilyProperties( + vk_physical_device, &this->queue_families_count, + queue_family_properties.data()); + } + + // Get information from physical device. + { + VkPhysicalDeviceProperties physical_properties = {}; + vkGetPhysicalDeviceProperties(vk_physical_device, &physical_properties); + VkPhysicalDeviceFeatures supported_features = {}; + vkGetPhysicalDeviceFeatures(vk_physical_device, &supported_features); + +#ifdef DEBUG + std::stringstream message{}; + message << "Name: " << physical_properties.deviceName << std::endl; + message << "API version: " << physical_properties.apiVersion << + std::endl; + message << "Driver version: " << physical_properties.driverVersion << + std::endl; + message << "Vendor ID: " << physical_properties.vendorID << std::endl; + message << "Device ID: " << physical_properties.deviceID << std::endl; + message << "Device type: " << physical_properties.deviceType << + std::endl; + BluCat::INT::core.log.message(Log::Level::Trace, message.str()); +#endif + + std::vector device_queue_create_infos; + std::vector> queue_priorities( + queue_family_properties.size()); + device_queue_create_infos.resize(queue_family_properties.size()); + for(auto i{0}; i < queue_family_properties.size(); i++) + { + // Give different priorities to queues. + int queue_count = queue_family_properties[i].queueCount; + queue_priorities[i].resize(queue_count); + float priority_unity = 1.0f/queue_count; + for(auto ii{0}; ii < queue_count; ii++) + queue_priorities[i][ii] = priority_unity * (queue_count - ii); + + device_queue_create_infos[i].sType = + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + device_queue_create_infos[i].pNext = nullptr; + device_queue_create_infos[i].flags = 0; + device_queue_create_infos[i].queueFamilyIndex = i; + device_queue_create_infos[i].queueCount = queue_priorities[i].size(); + device_queue_create_infos[i].pQueuePriorities = + queue_priorities[i].data(); + } + + 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; + + std::vector device_extensions; + if(with_swapchain) + device_extensions.emplace_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + + VkDeviceCreateInfo device_create_info = {}; + device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + device_create_info.pNext = nullptr; + device_create_info.flags = 0; + device_create_info.queueCreateInfoCount = device_queue_create_infos.size(); + device_create_info.pQueueCreateInfos = device_queue_create_infos.data(); + device_create_info.enabledLayerCount = 0; + device_create_info.ppEnabledLayerNames = nullptr; + device_create_info.enabledExtensionCount = device_extensions.size(); + if(device_extensions.size() == 0) + device_create_info.ppEnabledExtensionNames = nullptr; + else + device_create_info.ppEnabledExtensionNames = device_extensions.data(); + + device_create_info.pEnabledFeatures = &required_features; + + if(vkCreateDevice(this->physical_device, &device_create_info, nullptr, + &this->device) != VK_SUCCESS) + throw std::runtime_error("Failed to create Vulkan physical device."); + } + + // Load Shaders + { + std::string data_dir{""}; +#ifdef _WIN64 + HKEY hKey; + LPCSTR lpSubKey = "SOFTWARE\\CandyGear"; + LPCSTR lpValueName = "InstallLocation"; + DWORD dwType = REG_SZ; + DWORD dwSize = 0; + LPBYTE lpData = NULL; + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ, &hKey) == + ERROR_SUCCESS) + { + if(RegQueryValueEx(hKey, lpValueName, NULL, &dwType, NULL, &dwSize) == + ERROR_SUCCESS) + { + lpData = new BYTE[dwSize]; + if(RegQueryValueEx( + hKey, lpValueName, NULL, &dwType, lpData, &dwSize) == + ERROR_SUCCESS) + { + data_dir = reinterpret_cast(lpData); + } + delete[] lpData; + } + RegCloseKey(hKey); + } + + if(data_dir == "") + throw std::runtime_error("Failed to read CandyGear registry."); + + std::string vert_sprite_3d_shader_module{data_dir}; + vert_sprite_3d_shader_module.append("\\glsl\\shader_sprite_3d.vert.spv"); + this->vert_sprite_3d_shader_module = create_shader_module( + this->device, vert_sprite_3d_shader_module.c_str()); + + std::string frag_sprite_3d_shader_module{data_dir}; + frag_sprite_3d_shader_module.append("\\glsl\\shader_sprite_3d.frag.spv"); + this->frag_sprite_3d_shader_module = create_shader_module( + this->device, frag_sprite_3d_shader_module.c_str()); + + std::string vert3d_shader_module{data_dir}; + vert3d_shader_module.append("\\glsl\\shader_3d.vert.spv"); + this->vert3d_shader_module = create_shader_module( + this->device, vert3d_shader_module.c_str()); + + std::string vert3d_skeletal_shader_module{data_dir}; + vert3d_skeletal_shader_module.append( + "\\glsl\\shader_3d_skeletal.vert.spv"); + this->vert3d_skeletal_shader_module = create_shader_module( + this->device, vert3d_skeletal_shader_module.c_str()); + + std::string frag3d_shader_module{data_dir}; + frag3d_shader_module.append("\\glsl\\shader_3d.frag.spv"); + this->frag3d_shader_module = create_shader_module( + this->device, frag3d_shader_module.c_str()); + + std::string vert2d_solid_shader_module{data_dir}; + vert2d_solid_shader_module.append("\\glsl\\shader_2d_solid.vert.spv"); + this->vert2d_solid_shader_module = create_shader_module( + this->device, vert2d_solid_shader_module.c_str()); + + std::string frag2d_solid_shader_module{data_dir}; + frag2d_solid_shader_module.append("\\glsl\\shader_2d_solid.frag.spv"); + this->frag2d_solid_shader_module = create_shader_module( + this->device, frag2d_solid_shader_module.c_str()); + + std::string vert2d_wired_shader_module{data_dir}; + vert2d_wired_shader_module.append("\\glsl\\shader_2d_wired.vert.spv"); + this->vert2d_wired_shader_module = create_shader_module( + this->device, vert2d_wired_shader_module.c_str()); + + std::string frag2d_wired_shader_module{data_dir}; + frag2d_wired_shader_module.append("\\glsl\\shader_2d_wired.frag.spv"); + this->frag2d_wired_shader_module = create_shader_module( + this->device, frag2d_wired_shader_module.c_str()); +#else + data_dir = "/usr/local/share/candy_gear"; + + std::string vert_sprite_3d_shader_module{data_dir}; + vert_sprite_3d_shader_module.append("/glsl/shader_sprite_3d.vert.spv"); + this->vert_sprite_3d_shader_module = create_shader_module( + this->device, vert_sprite_3d_shader_module.c_str()); + + std::string frag_sprite_3d_shader_module{data_dir}; + frag_sprite_3d_shader_module.append("/glsl/shader_sprite_3d.frag.spv"); + this->frag_sprite_3d_shader_module = create_shader_module( + this->device, frag_sprite_3d_shader_module.c_str()); + + std::string vert3d_shader_module{data_dir}; + vert3d_shader_module.append("/glsl/shader_3d.vert.spv"); + this->vert3d_shader_module = create_shader_module( + this->device, vert3d_shader_module.c_str()); + + std::string vert3d_skeletal_shader_module{data_dir}; + vert3d_skeletal_shader_module.append("/glsl/shader_3d_skeletal.vert.spv"); + this->vert3d_skeletal_shader_module = create_shader_module( + this->device, vert3d_skeletal_shader_module.c_str()); + + std::string frag3d_shader_module{data_dir}; + frag3d_shader_module.append("/glsl/shader_3d.frag.spv"); + this->frag3d_shader_module = create_shader_module( + this->device, frag3d_shader_module.c_str()); + + std::string vert2d_solid_shader_module{data_dir}; + vert2d_solid_shader_module.append("/glsl/shader_2d_solid.vert.spv"); + this->vert2d_solid_shader_module = create_shader_module( + this->device, vert2d_solid_shader_module.c_str()); + + std::string frag2d_solid_shader_module{data_dir}; + frag2d_solid_shader_module.append("/glsl/shader_2d_solid.frag.spv"); + this->frag2d_solid_shader_module = create_shader_module( + this->device, frag2d_solid_shader_module.c_str()); + + std::string vert2d_wired_shader_module{data_dir}; + vert2d_wired_shader_module.append("/glsl/shader_2d_wired.vert.spv"); + this->vert2d_wired_shader_module = create_shader_module( + this->device, vert2d_wired_shader_module.c_str()); + + std::string frag2d_wired_shader_module{data_dir}; + frag2d_wired_shader_module.append("/glsl/shader_2d_wired.frag.spv"); + this->frag2d_wired_shader_module = create_shader_module( + this->device, frag2d_wired_shader_module.c_str()); +#endif + } + + this->queue_families = static_cast( + std::malloc(this->queue_families_count * sizeof(QueueFamily))); + for(auto i{0}; i < this->queue_families_count; i++) + { + new(&this->queue_families[i])QueueFamily( + this, i, queue_family_properties[i]); + + // Select families with graphics support. + auto &family_properties = this->queue_families[i].family_properties; + if(family_properties.queueCount > 0 && + family_properties.queueFlags & VK_QUEUE_GRAPHICS_BIT) + this->queue_families_with_graphics.push_back( + &this->queue_families[i]); + + // Select families with presentation support. + VkBool32 present_supported; + vkGetPhysicalDeviceSurfaceSupportKHR( + vk_physical_device, i, BluCat::INT::core.window_surface, + &present_supported); + if(present_supported) + this->queue_families_with_presentation.push_back( + &this->queue_families[i]); + } +} + +Device::~Device() +{ + for(auto i{0}; i < this->queue_families_count; i++) + this->queue_families[i].~QueueFamily(); + std::free(this->queue_families); + + // Destroy shaders + vkDestroyShaderModule( + this->device, this->vert_sprite_3d_shader_module, nullptr); + vkDestroyShaderModule( + this->device, this->frag_sprite_3d_shader_module, nullptr); + vkDestroyShaderModule(this->device, this->vert3d_shader_module, nullptr); + vkDestroyShaderModule( + this->device, this->vert3d_skeletal_shader_module, nullptr); + vkDestroyShaderModule(this->device, this->frag3d_shader_module, nullptr); + vkDestroyShaderModule( + this->device, this->vert2d_solid_shader_module, nullptr); + vkDestroyShaderModule( + this->device, this->frag2d_solid_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); +} + +bool +Device::select_memory_type( + uint32_t *memory_type_index, VkMemoryRequirements *vk_memory_requirements, + VkMemoryPropertyFlags vk_property_flags) +{ + VkPhysicalDeviceMemoryProperties vk_memory_properties; + vkGetPhysicalDeviceMemoryProperties( + this->physical_device, &vk_memory_properties); + + for (auto i{0}; i < vk_memory_properties.memoryTypeCount; i++) + { + if(vk_memory_requirements->memoryTypeBits & (1 << i)) + { + const VkMemoryType& type = vk_memory_properties.memoryTypes[i]; + + if ((type.propertyFlags & vk_property_flags) == vk_property_flags) + { + *memory_type_index = i; + return true; + } + } + } + + return false; +} + +QueueFamily* +Device::get_queue_family_with_graphics() const +{ + /* + Returns a random queue family, so not all commands in the engine use the + same queue. + TODO: There must be a better way of doing this. + */ + std::uniform_int_distribution random_distribution{ + 0, this->queue_families_with_graphics.size() -1}; + auto random = random_distribution(INT::random_number_generator); + return this->queue_families_with_graphics[0]; +} + +QueueFamily* +Device::get_queue_family_with_presentation() const +{ + /* + Returns a random queue family, so not all commands in the engine use the + same queue. + TODO: There must be a better way of doing this. + */ + std::uniform_int_distribution random_distribution{ + 0, this->queue_families_with_presentation.size() -1}; + auto random = random_distribution(INT::random_number_generator); + return this->queue_families_with_presentation[0]; +} + +} diff --git a/src/blu_cat/gra/device.hpp b/src/blu_cat/gra/device.hpp new file mode 100644 index 0000000..fd53198 --- /dev/null +++ b/src/blu_cat/gra/device.hpp @@ -0,0 +1,69 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_DEVICE_H +#define BLU_CAT_GRA_DEVICE_H 1 + +#include +#include + +#include "vulkan.hpp" +#include "queue_family.hpp" + +namespace BluCat::GRA +{ + +struct Device +{ + uint32_t queue_families_count; + QueueFamily *queue_families; + std::vector queue_families_with_graphics; + std::vector queue_families_with_presentation; + +public: + VkDevice device; + VkPhysicalDevice physical_device; + + VkShaderModule vert_sprite_3d_shader_module; + VkShaderModule frag_sprite_3d_shader_module; + VkShaderModule vert3d_shader_module; + VkShaderModule vert3d_skeletal_shader_module; + VkShaderModule frag3d_shader_module; + VkShaderModule vert2d_solid_shader_module; + VkShaderModule frag2d_solid_shader_module; + VkShaderModule vert2d_wired_shader_module; + VkShaderModule frag2d_wired_shader_module; + + bool with_swapchain; + + Device(VkPhysicalDevice vk_physical_device, bool with_swapchain); + ~Device(); + + bool + select_memory_type( + uint32_t *memoryTypeIndex, VkMemoryRequirements *vk_memory_requirements, + VkMemoryPropertyFlags vk_property_flags); + + QueueFamily* + get_queue_family_with_graphics() const; + + QueueFamily* + get_queue_family_with_presentation() const; +}; + +} + +#endif /* BLU_CAT_GRA_DEVICE_H */ diff --git a/src/blu_cat/gra/font.cpp b/src/blu_cat/gra/font.cpp new file mode 100644 index 0000000..a9c2074 --- /dev/null +++ b/src/blu_cat/gra/font.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2022-2024 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 "font.hpp" + +#include "../int/core.hpp" + +namespace BluCat::GRA +{ + +Font::Font(const char* font_path, int font_size) +{ + FT_Error error; + error = FT_New_Face( + BluCat::INT::core.font_library, font_path, 0, &this->face); + if(error == FT_Err_Unknown_File_Format) throw std::invalid_argument( + "The font file could be opened and read, but it appears that its font " + "format is unsupported."); + else if(error) throw std::invalid_argument( + "The font file could not be opened or read, or it is broken."); + + error = FT_Set_Pixel_Sizes(this->face, 0, font_size); + if(error) throw std::invalid_argument("Failed to load font size."); +} + +Font::~Font() +{ + FT_Done_Face(this->face); +} + +std::shared_ptr +Font::character(uint32_t character_code) +{ + if(!this->characters.contains(character_code)) + this->characters.emplace( + character_code, std::make_shared(this->face, character_code)); + + return this->characters.at(character_code); +} + +} diff --git a/src/blu_cat/gra/font.hpp b/src/blu_cat/gra/font.hpp new file mode 100644 index 0000000..72ec6d3 --- /dev/null +++ b/src/blu_cat/gra/font.hpp @@ -0,0 +1,42 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_FONT_H +#define BLU_CAT_GRA_FONT_H 1 + +#include +#include + +#include "character.hpp" + +namespace BluCat::GRA +{ + +struct Font +{ + FT_Face face; + std::unordered_map> characters; + + Font(const char* font_path, int font_size); + ~Font(); + + std::shared_ptr + character(uint32_t character_code); +}; + +} + +#endif /* BLU_CAT_GRA_FONT_H */ diff --git a/src/blu_cat/gra/framebuffer.cpp b/src/blu_cat/gra/framebuffer.cpp new file mode 100644 index 0000000..e2d0b7c --- /dev/null +++ b/src/blu_cat/gra/framebuffer.cpp @@ -0,0 +1,200 @@ +/* + * Copyright 2022-2024 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 "framebuffer.hpp" + +#include "../com/command.hpp" +#include "../int/core.hpp" +#include "image.hpp" + +namespace +{ +void +load_depth_image(void *obj) +{ + auto self = static_cast(obj); + + VkExtent3D extent3d{}; + extent3d.width = BluCat::INT::core.display_width; + extent3d.height = BluCat::INT::core.display_height; + extent3d.depth = 1; + + try + { + BluCat::GRA::Image::create( + BluCat::INT::core.vk_device_with_swapchain, + &self->depth_image, + &self->depth_image_memory, + VK_FORMAT_D32_SFLOAT, + extent3d, + 1, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT + ); + } + catch(BluCat::GRA::Image::Error error) + { + std::string error_message{"Failed to create depth image → "}; + error_message += error.what(); + throw CommandError{error_message}; + } +} + +void +unload_depth_image(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyImage( + BluCat::INT::core.vk_device_with_swapchain->device, self->depth_image, + nullptr); + vkFreeMemory( + BluCat::INT::core.vk_device_with_swapchain->device, + self->depth_image_memory, nullptr); +} + +void +load_depth_image_view(void *obj) +{ + auto self = static_cast(obj); + + try + { + BluCat::GRA::Image::create_view( + BluCat::INT::core.vk_device_with_swapchain, &self->depth_image_view, + self->depth_image, + VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT); + } + catch(BluCat::GRA::Image::Error error) + { + std::string error_message{"Failed to create depth image view → "}; + error_message += error.what(); + throw CommandError{error_message}; + } +} + +void +unload_depth_image_view(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyImageView( + BluCat::INT::core.vk_device_with_swapchain->device, self->depth_image_view, + nullptr); +} + +void +load_3d(void *obj) +{ + auto self = static_cast(obj); + + self->pipeline_3d.resize(BluCat::INT::core.vk_swapchain->images_count); + for (auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + { + std::array attachments = { + BluCat::INT::core.vk_swapchain->image_views[i], + self->depth_image_view + }; + + VkFramebufferCreateInfo framebuffer_info{}; + framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebuffer_info.renderPass = BluCat::INT::core.vk_render_pass->pipeline_3d; + framebuffer_info.attachmentCount = attachments.size(); + framebuffer_info.pAttachments = attachments.data(); + framebuffer_info.width = BluCat::INT::core.display_width; + framebuffer_info.height = BluCat::INT::core.display_height; + + framebuffer_info.layers = 1; + + if(vkCreateFramebuffer( + BluCat::INT::core.vk_device_with_swapchain->device, &framebuffer_info, nullptr, + &self->pipeline_3d[i]) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan Framebuffer."}; + } +} + +void +unload_3d(void *obj) +{ + auto self = static_cast(obj); + + for(auto framebuffer: self->pipeline_3d) + vkDestroyFramebuffer( + BluCat::INT::core.vk_device_with_swapchain->device, framebuffer, nullptr); +} + +void +load_2d(void *obj) +{ + auto self = static_cast(obj); + + self->pipeline_2d.resize(BluCat::INT::core.vk_swapchain->images_count); + for (auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + { + std::array attachments = { + BluCat::INT::core.vk_swapchain->image_views[i] + }; + + VkFramebufferCreateInfo framebuffer_info{}; + framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebuffer_info.renderPass = BluCat::INT::core.vk_render_pass->pipeline_2d; + framebuffer_info.attachmentCount = attachments.size(); + framebuffer_info.pAttachments = attachments.data(); + framebuffer_info.width = BluCat::INT::core.display_width; + framebuffer_info.height = BluCat::INT::core.display_height; + framebuffer_info.layers = 1; + + if(vkCreateFramebuffer( + BluCat::INT::core.vk_device_with_swapchain->device, &framebuffer_info, + nullptr, &self->pipeline_2d[i]) + != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan Framebuffer."}; + } +} + +void +unload_2d(void *obj) +{ + auto self = static_cast(obj); + + for(auto framebuffer: self->pipeline_2d) + vkDestroyFramebuffer( + BluCat::INT::core.vk_device_with_swapchain->device, framebuffer, nullptr); +} + +const CommandChain loader{ + {&load_depth_image, &unload_depth_image}, + {&load_depth_image_view, &unload_depth_image_view}, + {&load_3d, &unload_3d}, + {&load_2d, &unload_2d} +}; + +} + +namespace BluCat::GRA +{ + +Framebuffer::Framebuffer() +{ + loader.execute(this); +} + +Framebuffer::~Framebuffer() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/framebuffer.hpp b/src/blu_cat/gra/framebuffer.hpp new file mode 100644 index 0000000..ddbf5c4 --- /dev/null +++ b/src/blu_cat/gra/framebuffer.hpp @@ -0,0 +1,43 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_FRAMEBUFFER_H +#define BLU_CAT_GRA_FRAMEBUFFER_H 1 + +#include + +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +struct Framebuffer +{ + // Depth image. + VkImage depth_image; + VkDeviceMemory depth_image_memory; + VkImageView depth_image_view; + + std::vector pipeline_3d; + std::vector pipeline_2d; + + Framebuffer(); + ~Framebuffer(); +}; + +} + +#endif /* BLU_CAT_GRA_FRAMEBUFFER_H */ diff --git a/src/blu_cat/gra/graphics_pipeline_2d_solid.cpp b/src/blu_cat/gra/graphics_pipeline_2d_solid.cpp new file mode 100644 index 0000000..7acca09 --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_2d_solid.cpp @@ -0,0 +1,298 @@ +/* + * Copyright 2022-2024 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_solid.hpp" + +#include + +#include "../int/core.hpp" +#include "sprite.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_pipeline(void *obj) +{ + auto self = static_cast(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 = + BluCat::INT::core.vk_device_with_swapchain->vert2d_solid_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 = + BluCat::INT::core.vk_device_with_swapchain->frag2d_solid_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 vertex_attribute{}; + // Texture coordinate. + 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(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 = BluCat::INT::core.display_width; + viewport.height = BluCat::INT::core.display_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor = {}; + scissor.offset = {0, 0}; + scissor.extent = {BluCat::INT::core.display_width, BluCat::INT::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_FILL; + 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_TRUE; + color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_blend_attachment.dstColorBlendFactor = + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + 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; + + std::array dynamic_states{ + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_LINE_WIDTH, + VK_DYNAMIC_STATE_BLEND_CONSTANTS + }; + + VkPipelineDynamicStateCreateInfo dynamic_state_info = {}; + dynamic_state_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state_info.dynamicStateCount = dynamic_states.size(); + dynamic_state_info.pDynamicStates = dynamic_states.data(); + + 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 = + BluCat::INT::core.vk_graphics_pipeline_2d_solid_layout->pipeline; + pipeline_info.renderPass = BluCat::INT::core.vk_render_pass->pipeline_2d; + pipeline_info.subpass = 0; + pipeline_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_info.basePipelineIndex = -1; + + if(vkCreateGraphicsPipelines( + BluCat::INT::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(obj); + + vkDestroyPipeline( + BluCat::INT::core.vk_device_with_swapchain->device, self->graphic_pipeline, + nullptr); +} + +const CommandChain loader{ + {&load_pipeline, &unload_pipeline} +}; + +} + +namespace BluCat::GRA +{ + +GraphicsPipeline2DSolid::GraphicsPipeline2DSolid() +{ + loader.execute(this); +} + +GraphicsPipeline2DSolid::~GraphicsPipeline2DSolid() +{ + loader.revert(this); +} + +void +GraphicsPipeline2DSolid::draw( + std::shared_ptr view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const size_t next_frame, + const uint32_t image_index) +{ + // TODO set viewport just once per view, not once per pipeline. + { // 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(view->region.x); + vk_scissor.offset.y = static_cast(view->region.y); + vk_scissor.extent.width = static_cast(view->region.z); + vk_scissor.extent.height = static_cast(view->region.w); + vkCmdSetScissor(draw_command_buffer, 0, 1, &vk_scissor); + } + + vkCmdBindPipeline( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + this->graphic_pipeline); + + // FIXME: I know sorting is expensive, but I need to figure out better what + // to do here. + std::sort(view->sprites_to_draw[current_frame].begin(), + view->sprites_to_draw[current_frame].end()); + + // Draw sprites + for(auto& sprite_to_draw: view->sprites_to_draw[current_frame]) + { + std::array vk_descriptor_sets{ + view->descriptor_sets_2d[image_index], + sprite_to_draw.sprite->texture->descriptor_sets[image_index]}; + VkDeviceSize offsets[]{0}; + + vkCmdBindDescriptorSets( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + INT::core.vk_graphics_pipeline_2d_solid_layout->pipeline, 0, + vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); + vkCmdBindVertexBuffers( + draw_command_buffer, 0, 1, &sprite_to_draw.sprite->vertex_buffer->buffer, + offsets); + + UDOVector4D position{sprite_to_draw.position}; + vkCmdPushConstants( + draw_command_buffer, + INT::core.vk_graphics_pipeline_2d_solid_layout->pipeline, + VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(UDOVector4D), &position); + vkCmdDraw(draw_command_buffer, Sprite::vertex_count, 1, 0, 0); + } + + // Prepare for the next frame. + view->sprites_to_draw[next_frame].clear(); +} + +} diff --git a/src/blu_cat/gra/graphics_pipeline_2d_solid.hpp b/src/blu_cat/gra/graphics_pipeline_2d_solid.hpp new file mode 100644 index 0000000..c1520c2 --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_2d_solid.hpp @@ -0,0 +1,44 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_SOLID_H +#define BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_SOLID_H 1 + +#include + +#include "vulkan.hpp" +#include "command_pool.hpp" +#include "view_2d.hpp" + +namespace BluCat::GRA +{ + +struct GraphicsPipeline2DSolid +{ + VkPipeline graphic_pipeline; + + GraphicsPipeline2DSolid(); + ~GraphicsPipeline2DSolid(); + + void + draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const size_t next_frame, + const uint32_t image_index); +}; + +} + +#endif /* BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_SOLID_H */ diff --git a/src/blu_cat/gra/graphics_pipeline_2d_solid_layout.cpp b/src/blu_cat/gra/graphics_pipeline_2d_solid_layout.cpp new file mode 100644 index 0000000..476bac1 --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_2d_solid_layout.cpp @@ -0,0 +1,83 @@ +/* + * Copyright 2022-2024 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_solid_layout.hpp" + +#include + +#include "../int/core.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_pipeline(void *obj) +{ + auto self = static_cast(obj); + + std::array set_layouts{ + BluCat::INT::core.vk_descriptor_set_layout->view, + BluCat::INT::core.vk_descriptor_set_layout->texture + }; + + std::array push_constants; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = 0; + push_constants[0].size = sizeof(BluCat::GRA::UDOVector4D); + + 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 = push_constants.size(); + pipeline_layout_info.pPushConstantRanges = push_constants.data(); + + if(vkCreatePipelineLayout( + BluCat::INT::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(obj); + + vkDestroyPipelineLayout( + BluCat::INT::core.vk_device_with_swapchain->device, self->pipeline, nullptr); +} + +const CommandChain loader{ + {&load_pipeline, &unload_pipeline} +}; + +} + +namespace BluCat::GRA +{ + +GraphicsPipeline2DSolidLayout::GraphicsPipeline2DSolidLayout() +{ + loader.execute(this); +} + +GraphicsPipeline2DSolidLayout::~GraphicsPipeline2DSolidLayout() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/graphics_pipeline_2d_solid_layout.hpp b/src/blu_cat/gra/graphics_pipeline_2d_solid_layout.hpp new file mode 100644 index 0000000..6abd65d --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_2d_solid_layout.hpp @@ -0,0 +1,35 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_LAYOUT_H +#define BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_LAYOUT_H 1 + +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +struct GraphicsPipeline2DSolidLayout +{ + VkPipelineLayout pipeline; + + GraphicsPipeline2DSolidLayout(); + ~GraphicsPipeline2DSolidLayout(); +}; + +} + +#endif /* BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_LAYOUT_H */ diff --git a/src/blu_cat/gra/graphics_pipeline_2d_wired.cpp b/src/blu_cat/gra/graphics_pipeline_2d_wired.cpp new file mode 100644 index 0000000..20491ed --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_2d_wired.cpp @@ -0,0 +1,314 @@ +/* + * Copyright 2022-2024 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 + +#include "../int/core.hpp" +#include "rectangle.hpp" +#include "sprite.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_indexes(void *obj) +{ + auto self = static_cast(obj); + + self->queue_family = + BluCat::INT::core.vk_device_with_swapchain->get_queue_family_with_graphics(); + + std::array indexes{0, 1, 2, 3}; + void *indexes_data{indexes.data()}; + size_t indexes_size{sizeof(indexes[0]) * indexes.size()}; + BluCat::GRA::SourceBuffer source_index_buffer{ + self->queue_family->device, indexes_data, indexes_size}; + self->index_buffer = new BluCat::GRA::DestinationBuffer{ + self->queue_family, &source_index_buffer, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT}; +} + +void +unload_indexes(void *obj) +{ + auto self = static_cast(obj); + + delete self->index_buffer; +} + +void +load_pipeline(void *obj) +{ + auto self = static_cast(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 = + BluCat::INT::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 = + BluCat::INT::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 + }; + + 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 = 0; + vertex_input_info.pVertexBindingDescriptions = nullptr; + vertex_input_info.vertexAttributeDescriptionCount = 0; + vertex_input_info.pVertexAttributeDescriptions = nullptr; + + 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 = BluCat::INT::core.display_width; + viewport.height = BluCat::INT::core.display_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor = {}; + scissor.offset = {0, 0}; + scissor.extent = {BluCat::INT::core.display_width, BluCat::INT::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 = + BluCat::INT::core.vk_graphics_pipeline_2d_wired_layout->pipeline; + pipeline_info.renderPass = BluCat::INT::core.vk_render_pass->pipeline_2d; + pipeline_info.subpass = 0; + pipeline_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_info.basePipelineIndex = -1; + + if(vkCreateGraphicsPipelines( + BluCat::INT::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(obj); + + vkDestroyPipeline( + BluCat::INT::core.vk_device_with_swapchain->device, self->graphic_pipeline, + nullptr); +} + +const CommandChain loader{ + {&load_indexes, &unload_indexes}, + {&load_pipeline, &unload_pipeline} +}; + +} + +namespace BluCat::GRA +{ + +GraphicsPipeline2DWired::GraphicsPipeline2DWired() +{ + loader.execute(this); +} + +GraphicsPipeline2DWired::~GraphicsPipeline2DWired() +{ + loader.revert(this); +} + +void +GraphicsPipeline2DWired::draw( + std::shared_ptr 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(view->region.x); + vk_scissor.offset.y = static_cast(view->region.y); + vk_scissor.extent.width = static_cast(view->region.z); + vk_scissor.extent.height = static_cast(view->region.w); + vkCmdSetScissor(draw_command_buffer, 0, 1, &vk_scissor); + } + + // Draw rectangles + { + std::array vk_descriptor_sets{ + view->descriptor_sets_2d[image_index]}; + VkDeviceSize offsets[]{0}; + + vkCmdBindDescriptorSets( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + INT::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); + vkCmdBindIndexBuffer( + draw_command_buffer, this->index_buffer->buffer, 0, + VK_INDEX_TYPE_UINT32); + + for(auto i{0}; i < view->rectangles_to_draw[current_frame].size(); i++) + { + auto &rect{view->rectangles_to_draw[current_frame][i]}; + + UDOVector4D position{rect.position}; + UDOVector3D color{rect.color}; + vkCmdPushConstants( + draw_command_buffer, + INT::core.vk_graphics_pipeline_2d_wired_layout->pipeline, + VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(UDOVector4D), &position); + vkCmdPushConstants( + draw_command_buffer, + INT::core.vk_graphics_pipeline_2d_wired_layout->pipeline, + VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UDOVector4D), sizeof(UDOVector3D), + &color); + vkCmdDrawIndexed( + draw_command_buffer, Rectangle::VertexCount, 1, 0, 0, 0); + } + } + + // Prepare for the next frame. + view->rectangles_to_draw[next_frame].clear(); +} + +} diff --git a/src/blu_cat/gra/graphics_pipeline_2d_wired.hpp b/src/blu_cat/gra/graphics_pipeline_2d_wired.hpp new file mode 100644 index 0000000..7d2752e --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_2d_wired.hpp @@ -0,0 +1,47 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_WIRED_H +#define BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_WIRED_H 1 + +#include + +#include "vulkan.hpp" +#include "view_2d.hpp" + +namespace BluCat::GRA +{ + +struct GraphicsPipeline2DWired +{ + QueueFamily *queue_family; + + VkPipeline graphic_pipeline; + + DestinationBuffer *index_buffer; + + GraphicsPipeline2DWired(); + ~GraphicsPipeline2DWired(); + + void + draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const size_t next_frame, + const uint32_t image_index); +}; + +} + +#endif /* BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_WIRED_H */ diff --git a/src/blu_cat/gra/graphics_pipeline_2d_wired_layout.cpp b/src/blu_cat/gra/graphics_pipeline_2d_wired_layout.cpp new file mode 100644 index 0000000..431a845 --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_2d_wired_layout.cpp @@ -0,0 +1,87 @@ +/* + * Copyright 2022-2024 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 + +#include "../int/core.hpp" +#include "graphics_pipeline_2d_solid_layout.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_pipeline(void *obj) +{ + auto self = static_cast(obj); + + std::array set_layouts{ + BluCat::INT::core.vk_descriptor_set_layout->view + }; + + std::array push_constants; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = 0; + push_constants[0].size = sizeof(BluCat::GRA::UDOVector4D); + + push_constants[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + push_constants[1].offset = sizeof(BluCat::GRA::UDOVector4D); + push_constants[1].size = sizeof(BluCat::GRA::UDOVector3D); + + 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 = push_constants.size(); + pipeline_layout_info.pPushConstantRanges = push_constants.data(); + + if(vkCreatePipelineLayout( + BluCat::INT::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(obj); + + vkDestroyPipelineLayout( + BluCat::INT::core.vk_device_with_swapchain->device, self->pipeline, nullptr); +} + +const CommandChain loader{ + {&load_pipeline, &unload_pipeline} +}; + +} + +namespace BluCat::GRA +{ + +GraphicsPipeline2DWiredLayout::GraphicsPipeline2DWiredLayout() +{ + loader.execute(this); +} + +GraphicsPipeline2DWiredLayout::~GraphicsPipeline2DWiredLayout() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/graphics_pipeline_2d_wired_layout.hpp b/src/blu_cat/gra/graphics_pipeline_2d_wired_layout.hpp new file mode 100644 index 0000000..16f23ea --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_2d_wired_layout.hpp @@ -0,0 +1,35 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_WIRED_LAYOUT_H +#define BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_WIRED_LAYOUT_H 1 + +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +struct GraphicsPipeline2DWiredLayout +{ + VkPipelineLayout pipeline; + + GraphicsPipeline2DWiredLayout(); + ~GraphicsPipeline2DWiredLayout(); +}; + +} + +#endif /* BLU_CAT_GRA_GRAPHICS_PIPELINE_2D_LAYOUT_H */ diff --git a/src/blu_cat/gra/graphics_pipeline_3d.cpp b/src/blu_cat/gra/graphics_pipeline_3d.cpp new file mode 100644 index 0000000..1f7324a --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_3d.cpp @@ -0,0 +1,308 @@ +/* + * Copyright 2022-2024 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_3d.hpp" + +#include +#include + +#include "../int/core.hpp" +#include "vulkan.hpp" +#include "static_mesh_vertex.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_pipeline(void *obj) +{ + auto self = static_cast(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 = + BluCat::INT::core.vk_device_with_swapchain->vert3d_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 = + BluCat::INT::core.vk_device_with_swapchain->frag3d_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(BluCat::GRA::StaticMeshVertex); + vertex_input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + std::array vertex_attribute{}; + // Position. + vertex_attribute[0].location = 0; + vertex_attribute[0].binding = 0; + vertex_attribute[0].format = VK_FORMAT_R32G32B32_SFLOAT; + vertex_attribute[0].offset = offsetof(BluCat::GRA::StaticMeshVertex, position); + // Normal. + vertex_attribute[1].location = 1; + vertex_attribute[1].binding = 0; + vertex_attribute[1].format = VK_FORMAT_R32G32B32_SFLOAT; + vertex_attribute[1].offset = offsetof(BluCat::GRA::StaticMeshVertex, normal); + // Texture coordinate. + vertex_attribute[2].location = 2; + vertex_attribute[2].binding = 0; + vertex_attribute[2].format = VK_FORMAT_R32G32_SFLOAT; + vertex_attribute[2].offset = offsetof(BluCat::GRA::StaticMeshVertex, texture_coord); + + 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(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_LIST; + input_assembly.primitiveRestartEnable = VK_FALSE; + + VkViewport viewport = {}; + viewport.x = 0; + viewport.y = 0; + viewport.width = BluCat::INT::core.display_width; + viewport.height = BluCat::INT::core.display_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor = {}; + scissor.offset = {0, 0}; + scissor.extent = {BluCat::INT::core.display_width, BluCat::INT::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_FILL; + 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; + + VkPipelineDepthStencilStateCreateInfo depth_stencil = {}; + depth_stencil.sType = + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil.depthTestEnable = VK_TRUE; + depth_stencil.depthWriteEnable = VK_TRUE; + depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; + depth_stencil.depthBoundsTestEnable = VK_FALSE; + depth_stencil.minDepthBounds = 0.0f; + depth_stencil.maxDepthBounds = 1.0f; + depth_stencil.stencilTestEnable = VK_FALSE; + depth_stencil.front = {}; + depth_stencil.back = {}; + + 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 = &depth_stencil; + pipeline_info.pColorBlendState = &color_blending; + pipeline_info.pDynamicState = &dynamic_state_info; + pipeline_info.layout = BluCat::INT::core.vk_graphics_pipeline_3d_layout->pipeline; + pipeline_info.renderPass = BluCat::INT::core.vk_render_pass->pipeline_3d; + pipeline_info.subpass = 0; + pipeline_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_info.basePipelineIndex = -1; + + if(vkCreateGraphicsPipelines( + BluCat::INT::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(obj); + + vkDestroyPipeline( + BluCat::INT::core.vk_device_with_swapchain->device, self->graphic_pipeline, + nullptr); +} + +const CommandChain loader{ + {&load_pipeline, &unload_pipeline} +}; + +} + +namespace BluCat::GRA +{ + +GraphicsPipeline3D::GraphicsPipeline3D() +{ + loader.execute(this); +} + +GraphicsPipeline3D::~GraphicsPipeline3D() +{ + loader.revert(this); +} + +void +GraphicsPipeline3D::draw( + std::shared_ptr view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const uint32_t image_index) +{ + vkCmdBindPipeline( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + this->graphic_pipeline); + + // Draw models + for(auto& [static_mesh, instances]: + INT::core.vk_renderer->static_models_to_draw[current_frame]) + { + VkBuffer vertex_buffers[]{static_mesh->vertex_buffer->buffer}; + VkDeviceSize offsets[]{0}; + + vkCmdBindVertexBuffers( + draw_command_buffer, 0, 1, vertex_buffers, offsets); + vkCmdBindIndexBuffer( + draw_command_buffer, static_mesh->index_buffer->buffer, 0, + VK_INDEX_TYPE_UINT32); + + for(auto &instance: instances) + { // Object matrix. + glm::mat4 translation_matrix{1.0f}; + translation_matrix = glm::translate( + translation_matrix, *instance->position); + glm::mat4 rotation_matrix{glm::toMat4(*instance->orientation)}; + + std::array vk_descriptor_sets{ + INT::core.vk_light->descriptor_sets_world[image_index], + view->descriptor_sets_3d[image_index], + instance->descriptor_sets[image_index], + instance->texture->descriptor_sets[image_index]}; + + vkCmdBindDescriptorSets( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + INT::core.vk_graphics_pipeline_3d_layout->pipeline, 0, + vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); + + vkCmdDrawIndexed( + draw_command_buffer, static_mesh->index_count, 1, 0, 0, 0); + + BluCat::GRA::UDOStaticModel udo_static_model{}; + udo_static_model.base_matrix = translation_matrix * rotation_matrix; + instance->uniform_buffers[image_index].copy_data(&udo_static_model); + } + } +} + +} diff --git a/src/blu_cat/gra/graphics_pipeline_3d.hpp b/src/blu_cat/gra/graphics_pipeline_3d.hpp new file mode 100644 index 0000000..0dc0b03 --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_3d.hpp @@ -0,0 +1,43 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_GRAPHICS_PIPELINE_3D_H +#define BLU_CAT_GRA_GRAPHICS_PIPELINE_3D_H 1 + +#include + +#include "vulkan.hpp" +#include "command_pool.hpp" +#include "view_3d.hpp" + +namespace BluCat::GRA +{ + +struct GraphicsPipeline3D +{ + VkPipeline graphic_pipeline; + + GraphicsPipeline3D(); + ~GraphicsPipeline3D(); + + void + draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const uint32_t image_index); +}; + +} + +#endif /* BLU_CAT_GRA_GRAPHICS_PIPELINE_3D_H */ diff --git a/src/blu_cat/gra/graphics_pipeline_3d_layout.cpp b/src/blu_cat/gra/graphics_pipeline_3d_layout.cpp new file mode 100644 index 0000000..504b46e --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_3d_layout.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2022-2024 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_3d_layout.hpp" + +#include + +#include "../int/core.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_pipeline(void *obj) +{ + auto self = static_cast(obj); + + std::array set_layouts{ + BluCat::INT::core.vk_descriptor_set_layout->world, + BluCat::INT::core.vk_descriptor_set_layout->view, + BluCat::INT::core.vk_descriptor_set_layout->model, + BluCat::INT::core.vk_descriptor_set_layout->texture}; + + 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( + BluCat::INT::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(obj); + + vkDestroyPipelineLayout( + BluCat::INT::core.vk_device_with_swapchain->device, self->pipeline, nullptr); +} + +const CommandChain loader{ + {&load_pipeline, &unload_pipeline} +}; + +} + +namespace BluCat::GRA +{ + +GraphicsPipeline3DLayout::GraphicsPipeline3DLayout() +{ + loader.execute(this); +} + +GraphicsPipeline3DLayout::~GraphicsPipeline3DLayout() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/graphics_pipeline_3d_layout.hpp b/src/blu_cat/gra/graphics_pipeline_3d_layout.hpp new file mode 100644 index 0000000..13820c4 --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_3d_layout.hpp @@ -0,0 +1,35 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_GRAPHICS_PIPELINE_3D_LAYOUT_H +#define BLU_CAT_GRA_GRAPHICS_PIPELINE_3D_LAYOUT_H 1 + +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +struct GraphicsPipeline3DLayout +{ + VkPipelineLayout pipeline; + + GraphicsPipeline3DLayout(); + ~GraphicsPipeline3DLayout(); +}; + +} + +#endif /* BLU_CAT_GRA_GRAPHICS_PIPELINE_3D_LAYOUT_H */ diff --git a/src/blu_cat/gra/graphics_pipeline_3d_skeletal.cpp b/src/blu_cat/gra/graphics_pipeline_3d_skeletal.cpp new file mode 100644 index 0000000..e8eda6b --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_3d_skeletal.cpp @@ -0,0 +1,322 @@ +/* + * Copyright 2022-2024 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_3d.hpp" + +#include +#include + +#include "../int/core.hpp" +#include "skeletal_mesh_vertex.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_pipeline(void *obj) +{ + auto self = static_cast(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 = + BluCat::INT::core.vk_device_with_swapchain->vert3d_skeletal_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 = + BluCat::INT::core.vk_device_with_swapchain->frag3d_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(BluCat::GRA::SkeletalMeshVertex); + vertex_input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + std::array vertex_attribute{}; + // Position. + vertex_attribute[0].location = 0; + vertex_attribute[0].binding = 0; + vertex_attribute[0].format = VK_FORMAT_R32G32B32_SFLOAT; + vertex_attribute[0].offset = offsetof(BluCat::GRA::SkeletalMeshVertex, position); + // Normal. + vertex_attribute[1].location = 1; + vertex_attribute[1].binding = 0; + vertex_attribute[1].format = VK_FORMAT_R32G32B32_SFLOAT; + vertex_attribute[1].offset = offsetof(BluCat::GRA::SkeletalMeshVertex, normal); + // Texture coordinate. + vertex_attribute[2].location = 2; + vertex_attribute[2].binding = 0; + vertex_attribute[2].format = VK_FORMAT_R32G32_SFLOAT; + vertex_attribute[2].offset = offsetof(BluCat::GRA::SkeletalMeshVertex, texture_coord); + // Bones ids. + vertex_attribute[3].location = 3; + vertex_attribute[3].binding = 0; + vertex_attribute[3].format = VK_FORMAT_R32G32B32A32_SINT; + vertex_attribute[3].offset = offsetof(BluCat::GRA::SkeletalMeshVertex, bone_ids); + // Bones weights. + vertex_attribute[4].location = 4; + vertex_attribute[4].binding = 0; + vertex_attribute[4].format = VK_FORMAT_R32G32B32A32_SFLOAT; + vertex_attribute[4].offset = offsetof(BluCat::GRA::SkeletalMeshVertex, bone_weights); + + 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(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_LIST; + input_assembly.primitiveRestartEnable = VK_FALSE; + + VkViewport viewport = {}; + viewport.x = 0; + viewport.y = 0; + viewport.width = BluCat::INT::core.display_width; + viewport.height = BluCat::INT::core.display_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor = {}; + scissor.offset = {0, 0}; + scissor.extent = {BluCat::INT::core.display_width, BluCat::INT::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_FILL; + 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; + + VkPipelineDepthStencilStateCreateInfo depth_stencil = {}; + depth_stencil.sType = + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil.depthTestEnable = VK_TRUE; + depth_stencil.depthWriteEnable = VK_TRUE; + depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; + depth_stencil.depthBoundsTestEnable = VK_FALSE; + depth_stencil.minDepthBounds = 0.0f; + depth_stencil.maxDepthBounds = 1.0f; + depth_stencil.stencilTestEnable = VK_FALSE; + depth_stencil.front = {}; + depth_stencil.back = {}; + + 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 = &depth_stencil; + pipeline_info.pColorBlendState = &color_blending; + pipeline_info.pDynamicState = &dynamic_state_info; + pipeline_info.layout = BluCat::INT::core.vk_graphics_pipeline_3d_layout->pipeline; + pipeline_info.renderPass = BluCat::INT::core.vk_render_pass->pipeline_3d; + pipeline_info.subpass = 0; + pipeline_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_info.basePipelineIndex = -1; + + if(vkCreateGraphicsPipelines( + BluCat::INT::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(obj); + + vkDestroyPipeline( + BluCat::INT::core.vk_device_with_swapchain->device, self->graphic_pipeline, + nullptr); +} + +const CommandChain loader{ + {&load_pipeline, &unload_pipeline} +}; + +} + +namespace BluCat::GRA +{ + +GraphicsPipeline3DSkeletal::GraphicsPipeline3DSkeletal() +{ + loader.execute(this); +} + +GraphicsPipeline3DSkeletal::~GraphicsPipeline3DSkeletal() +{ + loader.revert(this); +} + +void +GraphicsPipeline3DSkeletal::draw( + std::shared_ptr view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const uint32_t image_index) +{ + vkCmdBindPipeline( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + this->graphic_pipeline); + + // Draw models + for(auto& [skeletal_mesh, instances]: + INT::core.vk_renderer->skeletal_models_to_draw[current_frame]) + { + VkBuffer vertex_buffers[]{skeletal_mesh->vertex_buffer->buffer}; + VkDeviceSize offsets[]{0}; + + vkCmdBindVertexBuffers( + draw_command_buffer, 0, 1, vertex_buffers, offsets); + vkCmdBindIndexBuffer( + draw_command_buffer, skeletal_mesh->index_buffer->buffer, 0, + VK_INDEX_TYPE_UINT32); + + for(auto &instance: instances) + { // Object matrix. + glm::mat4 translation_matrix{1.0f}; + translation_matrix = glm::translate( + translation_matrix, *instance->position); + glm::mat4 rotation_matrix{glm::toMat4(*instance->orientation)}; + + std::array vk_descriptor_sets{ + INT::core.vk_light->descriptor_sets_world[image_index], + view->descriptor_sets_3d[image_index], + instance->descriptor_sets[image_index], + instance->texture->descriptor_sets[image_index]}; + + vkCmdBindDescriptorSets( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + INT::core.vk_graphics_pipeline_3d_layout->pipeline, 0, + vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); + + vkCmdDrawIndexed( + draw_command_buffer, skeletal_mesh->index_count, 1, 0, 0, 0); + + BluCat::GRA::UDOSkeletalModel udo_skeletal_model{}; + instance->tick(INT::core.delta_time); + udo_skeletal_model.base_matrix = translation_matrix * rotation_matrix; + std::copy(instance->bone_transforms.begin(), + instance->bone_transforms.end(), + udo_skeletal_model.bone_matrices); + instance->uniform_buffers[image_index].copy_data(&udo_skeletal_model); + } + } + +} + +} diff --git a/src/blu_cat/gra/graphics_pipeline_3d_skeletal.hpp b/src/blu_cat/gra/graphics_pipeline_3d_skeletal.hpp new file mode 100644 index 0000000..bad117d --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_3d_skeletal.hpp @@ -0,0 +1,43 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_GRAPHICS_PIPELINE_3D_SKELETAL_H +#define BLU_CAT_GRA_GRAPHICS_PIPELINE_3D_SKELETAL_H 1 + +#include + +#include "vulkan.hpp" +#include "command_pool.hpp" +#include "view_3d.hpp" + +namespace BluCat::GRA +{ + +struct GraphicsPipeline3DSkeletal +{ + VkPipeline graphic_pipeline; + + GraphicsPipeline3DSkeletal(); + ~GraphicsPipeline3DSkeletal(); + + void + draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const uint32_t image_index); +}; + +} + +#endif /* BLU_CAT_GRA_GRAPHICS_PIPELINE_SKELETAL_3D_H */ diff --git a/src/blu_cat/gra/graphics_pipeline_sprite_3d.cpp b/src/blu_cat/gra/graphics_pipeline_sprite_3d.cpp new file mode 100644 index 0000000..14796d3 --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_sprite_3d.cpp @@ -0,0 +1,315 @@ +/* + * Copyright 2022-2024 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_sprite_3d.hpp" + +#include + +#include "../int/core.hpp" +#include "sprite.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +struct Sprite3DOrder +{ + std::shared_ptr sprite_3d; + float distance; +}; + +bool +operator<(const Sprite3DOrder &a, const Sprite3DOrder &b) +{ + return a.distance < b.distance; +} + +bool +operator>(const Sprite3DOrder &a, const Sprite3DOrder &b) +{ + return a.distance > b.distance; +} + +void +load_pipeline(void *obj) +{ + auto self = static_cast(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 = + BluCat::INT::core.vk_device_with_swapchain->vert_sprite_3d_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 = + BluCat::INT::core.vk_device_with_swapchain->frag_sprite_3d_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 vertex_attribute{}; + // Texture coordinate. + 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(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 = BluCat::INT::core.display_width; + viewport.height = BluCat::INT::core.display_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor = {}; + scissor.offset = {0, 0}; + scissor.extent = {BluCat::INT::core.display_width, BluCat::INT::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_FILL; + 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; + + VkPipelineDepthStencilStateCreateInfo depth_stencil = {}; + depth_stencil.sType = + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil.depthTestEnable = VK_TRUE; + depth_stencil.depthWriteEnable = VK_TRUE; + depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; + depth_stencil.depthBoundsTestEnable = VK_FALSE; + depth_stencil.minDepthBounds = 0.0f; + depth_stencil.maxDepthBounds = 1.0f; + depth_stencil.stencilTestEnable = VK_FALSE; + depth_stencil.front = {}; + depth_stencil.back = {}; + + VkPipelineColorBlendAttachmentState color_blend_attachment = {}; + color_blend_attachment.blendEnable = VK_TRUE; + color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_blend_attachment.dstColorBlendFactor = + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + 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; + + std::array dynamic_states{ + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_LINE_WIDTH, + VK_DYNAMIC_STATE_BLEND_CONSTANTS + }; + + VkPipelineDynamicStateCreateInfo dynamic_state_info = {}; + dynamic_state_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state_info.dynamicStateCount = dynamic_states.size(); + dynamic_state_info.pDynamicStates = dynamic_states.data(); + + 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 = &depth_stencil; + pipeline_info.pColorBlendState = &color_blending; + pipeline_info.pDynamicState = &dynamic_state_info; + pipeline_info.layout = BluCat::INT::core.vk_graphics_pipeline_3d_layout->pipeline; + pipeline_info.renderPass = BluCat::INT::core.vk_render_pass->pipeline_3d; + pipeline_info.subpass = 0; + pipeline_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_info.basePipelineIndex = -1; + + if(vkCreateGraphicsPipelines( + BluCat::INT::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 sprite 3d."}; +} + +void +unload_pipeline(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyPipeline( + BluCat::INT::core.vk_device_with_swapchain->device, self->graphic_pipeline, + nullptr); +} + +const CommandChain loader{ + {&load_pipeline, &unload_pipeline} +}; + +} + +namespace BluCat::GRA +{ + +GraphicsPipelineSprite3D::GraphicsPipelineSprite3D() +{ + loader.execute(this); +} + +GraphicsPipelineSprite3D::~GraphicsPipelineSprite3D() +{ + loader.revert(this); +} + +void +GraphicsPipelineSprite3D::draw( + std::shared_ptr view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const uint32_t image_index) +{ + vkCmdBindPipeline( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + this->graphic_pipeline); + + std::vector sprite_3d_order; + { // Sort sprites 3D + sprite_3d_order.reserve( + INT::core.vk_renderer->sprites_3d_to_draw[current_frame].size()); + + for(std::shared_ptr sprite: + INT::core.vk_renderer->sprites_3d_to_draw[current_frame]) + sprite_3d_order.emplace_back( + sprite, glm::distance(*view->camera_position, *sprite->position)); + + std::sort(sprite_3d_order.rbegin(), sprite_3d_order.rend()); + } + + // Draw sprites + for(auto& sprite: sprite_3d_order) + { + std::array vk_descriptor_sets{ + INT::core.vk_light->descriptor_sets_world[image_index], + view->descriptor_sets_3d[image_index], + sprite.sprite_3d->descriptor_sets[image_index], + sprite.sprite_3d->sprite->texture->descriptor_sets[image_index]}; + VkDeviceSize offsets[]{0}; + + vkCmdBindVertexBuffers( + draw_command_buffer, 0, 1, + &sprite.sprite_3d->sprite->vertex_buffer->buffer, offsets); + vkCmdBindDescriptorSets( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + INT::core.vk_graphics_pipeline_3d_layout->pipeline, 0, + vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); + + UDOSprite3D ubo_sprite_3d{}; + ubo_sprite_3d.position = *sprite.sprite_3d->position; + ubo_sprite_3d.size = sprite.sprite_3d->size; + sprite.sprite_3d->uniform_buffers[image_index].copy_data(&ubo_sprite_3d); + + vkCmdDraw(draw_command_buffer, Sprite::vertex_count, 1, 0, 0); + } +} + +} diff --git a/src/blu_cat/gra/graphics_pipeline_sprite_3d.hpp b/src/blu_cat/gra/graphics_pipeline_sprite_3d.hpp new file mode 100644 index 0000000..325d943 --- /dev/null +++ b/src/blu_cat/gra/graphics_pipeline_sprite_3d.hpp @@ -0,0 +1,44 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_GRAPHICS_PIPELINE_SPRITE_3D_H +#define BLU_CAT_GRA_GRAPHICS_PIPELINE_SPRITE_3D_H 1 + +#include + +#include "vulkan.hpp" +#include "command_pool.hpp" +#include "sprite_3d.hpp" +#include "view_3d.hpp" + +namespace BluCat::GRA +{ + +struct GraphicsPipelineSprite3D +{ + VkPipeline graphic_pipeline; + + GraphicsPipelineSprite3D(); + ~GraphicsPipelineSprite3D(); + + void + draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, + const size_t current_frame, const uint32_t image_index); +}; + +} + +#endif /* BLU_CAT_GRA_GRAPHICS_PIPELINE_SPRITE_3D_H */ diff --git a/src/blu_cat/gra/image.cpp b/src/blu_cat/gra/image.cpp new file mode 100644 index 0000000..76e4f9d --- /dev/null +++ b/src/blu_cat/gra/image.cpp @@ -0,0 +1,149 @@ +/* + * Copyright 2022-2024 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 "image.hpp" + +#include "../int/core.hpp" + +namespace BluCat::GRA::Image +{ + +Error::Error(const std::string &m): + error(m) +{ +} + +Error::Error(const char &m): + Error{std::string{m}} +{ +} + +const char* +Error::what() const noexcept +{ + return this->error.c_str(); +} + +void +create( + BluCat::GRA::Device *device, + VkImage *image, + VkDeviceMemory *image_memory, + VkFormat format, + const VkExtent3D &extent3d, + uint32_t mip_levels, + VkImageTiling image_tiling, + VkImageUsageFlags usage) +{ + VkImageCreateInfo image_info{}; + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.pNext = nullptr; + image_info.flags = 0; + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.format = format; + image_info.extent = extent3d; + image_info.mipLevels = mip_levels; + image_info.arrayLayers = 1; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.tiling = image_tiling; + image_info.usage = usage; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_info.queueFamilyIndexCount = 0; + image_info.pQueueFamilyIndices = nullptr; + image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + if(vkCreateImage( + device->device, &image_info, nullptr, image) != VK_SUCCESS) + throw Error{"Failed to create Vulkan image."}; + + VkMemoryRequirements memory_requirements; + vkGetImageMemoryRequirements(device->device, *image, &memory_requirements); + + VkMemoryAllocateInfo memory_alloc_info{}; + memory_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_alloc_info.allocationSize = memory_requirements.size; + device->select_memory_type(&memory_alloc_info.memoryTypeIndex, + &memory_requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + if(vkAllocateMemory( + device->device, &memory_alloc_info, nullptr, image_memory) + != VK_SUCCESS) + { + vkDestroyImage(device->device, *image, nullptr); + throw Error{"Failed to allocate memory for Vulkan image."}; + } + + vkBindImageMemory(device->device, *image, *image_memory, 0); +} + +void move_image_state( + VkCommandBuffer vk_command_buffer, VkImage vk_image, VkFormat format, + VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, + VkImageLayout old_layout, VkImageLayout new_layout, + VkPipelineStageFlags source_stage, VkPipelineStageFlags destination_stage) +{ + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = src_access_mask; + barrier.dstAccessMask = dst_access_mask; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = vk_image; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + + vkCmdPipelineBarrier( + vk_command_buffer, source_stage, destination_stage, 0, 0, nullptr, + 0, nullptr, 1, &barrier); +} + +void create_view( + BluCat::GRA::Device *device, + VkImageView *image_view, + const VkImage &image, + VkFormat format, + VkImageAspectFlags image_aspect_flags) +{ + VkImageViewCreateInfo image_view_info{}; + image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_info.pNext = nullptr; + image_view_info.flags = 0; + image_view_info.image = image; + image_view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + image_view_info.format = format; + image_view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_info.subresourceRange.aspectMask = image_aspect_flags; + image_view_info.subresourceRange.baseMipLevel = 0; + image_view_info.subresourceRange.levelCount = 1; + image_view_info.subresourceRange.baseArrayLayer = 0; + image_view_info.subresourceRange.layerCount = 1; + + if(vkCreateImageView(device->device, &image_view_info, + nullptr, image_view) != VK_SUCCESS) + throw Error{"Failed to create texture view."}; + +} + +} diff --git a/src/blu_cat/gra/image.hpp b/src/blu_cat/gra/image.hpp new file mode 100644 index 0000000..ba64b76 --- /dev/null +++ b/src/blu_cat/gra/image.hpp @@ -0,0 +1,73 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_IMAGE_H +#define BLU_CAT_GRA_IMAGE_H 1 + +#include +#include + +#include "vulkan.hpp" +#include "device.hpp" + +namespace BluCat::GRA::Image +{ + +struct Error: public std::exception +{ + Error(const std::string &m); + Error(const char &m); + + const char* + what() const noexcept; + +private: + std::string error; +}; + +void +create( + BluCat::GRA::Device *device, + VkImage *image, + VkDeviceMemory *image_memory, + VkFormat format, + const VkExtent3D &extent3d, + uint32_t mip_levels, + VkImageTiling image_tiling, + VkImageUsageFlags usage); + +void +move_image_state( + VkCommandBuffer vk_command_buffer, + VkImage vk_image, + VkFormat format, + VkAccessFlags src_access_mask, + VkAccessFlags dst_access_mask, + VkImageLayout old_layout, + VkImageLayout new_layout, + VkPipelineStageFlags source_stage, + VkPipelineStageFlags destination_stage); + +void +create_view( + BluCat::GRA::Device *device, + VkImageView *image_view, + const VkImage &image, + VkFormat format, + VkImageAspectFlags image_aspect_flags); +} + +#endif /* BLU_CAT_GRA_IMAGE_H */ diff --git a/src/blu_cat/gra/light.cpp b/src/blu_cat/gra/light.cpp new file mode 100644 index 0000000..403dcf4 --- /dev/null +++ b/src/blu_cat/gra/light.cpp @@ -0,0 +1,205 @@ +/* + * Copyright 2022-2024 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 "light.hpp" + +#include + +#include "../int/core.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_world_vert_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + try + { + self->ub_world_vert.reserve(BluCat::INT::core.vk_swapchain->images_count); + for(auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + self->ub_world_vert.emplace_back( + BluCat::INT::core.vk_device_with_swapchain, sizeof(BluCat::GRA::UDOWorld3D_Vert)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_world_vert_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + self->ub_world_vert.clear(); +} + +void +load_world_frag_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + try + { + self->ub_world_frag.reserve(BluCat::INT::core.vk_swapchain->images_count); + for(auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + self->ub_world_frag.emplace_back( + BluCat::INT::core.vk_device_with_swapchain, sizeof(BluCat::GRA::UDOWorld3D_Frag)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_world_frag_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + self->ub_world_frag.clear(); +} + +void +load_descriptor_pool(void *obj) +{ + auto self = static_cast(obj); + + uint32_t uniform_buffers_count = + self->ub_world_vert.size() + self->ub_world_vert.size(); + + VkDescriptorPoolSize descriptor_pool_size{}; + descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_pool_size.descriptorCount = uniform_buffers_count; + + VkDescriptorPoolCreateInfo pool_info{}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.pNext = nullptr; + pool_info.flags = 0; + pool_info.maxSets = uniform_buffers_count; + pool_info.poolSizeCount = 1; + pool_info.pPoolSizes = &descriptor_pool_size; + + if(vkCreateDescriptorPool( + BluCat::INT::core.vk_device_with_swapchain->device, &pool_info, nullptr, + &self->descriptor_pool) != VK_SUCCESS) + throw CommandError{"Failed to create a Vulkan descriptor pool."}; +} + +void +unload_descriptor_pool(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyDescriptorPool( + BluCat::INT::core.vk_device_with_swapchain->device, self->descriptor_pool, + nullptr); +} + +void +load_descriptor_sets_world(void *obj) +{ + auto self = static_cast(obj); + + std::vector layouts( + BluCat::INT::core.vk_swapchain->images_count, + BluCat::INT::core.vk_descriptor_set_layout->world); + + 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_world.resize(layouts.size()); + if(vkAllocateDescriptorSets( + BluCat::INT::core.vk_device_with_swapchain->device, &alloc_info, + self->descriptor_sets_world.data()) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan world descriptor set."}; +} + +void +load_resources_to_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + for(auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + { + VkDescriptorBufferInfo world_vert_info{}; + world_vert_info.buffer = self->ub_world_vert[i].buffer; + world_vert_info.offset = 0; + world_vert_info.range = sizeof(BluCat::GRA::UDOWorld3D_Vert); + + VkDescriptorBufferInfo world_frag_info{}; + world_frag_info.buffer = self->ub_world_frag[i].buffer; + world_frag_info.offset = 0; + world_frag_info.range = sizeof(BluCat::GRA::UDOWorld3D_Frag); + + std::array write_descriptors{}; + write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[0].dstSet = self->descriptor_sets_world[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 = &world_vert_info; + write_descriptors[0].pImageInfo = nullptr; + write_descriptors[0].pTexelBufferView = nullptr; + + write_descriptors[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[1].dstSet = self->descriptor_sets_world[i]; + write_descriptors[1].dstBinding = 1; + write_descriptors[1].dstArrayElement = 0; + write_descriptors[1].descriptorCount = 1; + write_descriptors[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + write_descriptors[1].pBufferInfo = &world_frag_info; + write_descriptors[1].pImageInfo = nullptr; + write_descriptors[1].pTexelBufferView = nullptr; + + vkUpdateDescriptorSets( + BluCat::INT::core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); + } +} + +const CommandChain loader{ + {&load_world_vert_uniform_buffer, &unload_world_vert_uniform_buffer}, + {&load_world_frag_uniform_buffer, &unload_world_frag_uniform_buffer}, + {&load_descriptor_pool, &unload_descriptor_pool}, + // By destroying the pool the sets are also destroyed. + {&load_descriptor_sets_world, nullptr}, + {&load_resources_to_descriptor_sets, nullptr} +}; + +} + +namespace BluCat::GRA +{ + +Light::Light() +{ + loader.execute(this); +} + +Light::~Light() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/light.hpp b/src/blu_cat/gra/light.hpp new file mode 100644 index 0000000..22a9e2d --- /dev/null +++ b/src/blu_cat/gra/light.hpp @@ -0,0 +1,41 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_LIGHT_H +#define BLU_CAT_GRA_LIGHT_H 1 + +#include "vulkan.hpp" +#include "uniform_buffer.hpp" + +namespace BluCat::GRA +{ + +struct Light +{ + // FIXME: if this vector get resized, it will cause a segmentation fault! + std::vector ub_world_vert; + std::vector ub_world_frag; + + VkDescriptorPool descriptor_pool; + std::vector descriptor_sets_world; + + Light(); + ~Light(); +}; + +} + +#endif /* BLU_CAT_GRA_LIGHT_H */ diff --git a/src/blu_cat/gra/log.cpp b/src/blu_cat/gra/log.cpp new file mode 100644 index 0000000..78044c4 --- /dev/null +++ b/src/blu_cat/gra/log.cpp @@ -0,0 +1,53 @@ +/* + * 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 "log.hpp" + +#include + +namespace Log +{ + +void +Logger::message(Level lvl, const char* text) +{ + std::cout << "["; + switch(lvl) + { + case Level::Fatal: + std::cout << "\e[1;35mFatal\e[0;0m"; + break; + case Level::Error: + std::cout << "\e[1;31mError\e[0;0m"; + break; + case Level::Warning: + std::cout << "\e[1;33mWarning\e[0;0m"; + break; + case Level::Information: + std::cout << "\e[1;32mInformation\e[0;0m"; + break; + case Level::Debug: + std::cout << "\e[1;36mDebug\e[0;0m"; + break; + case Level::Trace: + std::cout << "\e[1;34mTrace\e[0;0m"; + break; + } + std::cout << "] "; + std::cout << text << std::endl; +} + +} diff --git a/src/blu_cat/gra/log.hpp b/src/blu_cat/gra/log.hpp new file mode 100644 index 0000000..2856f20 --- /dev/null +++ b/src/blu_cat/gra/log.hpp @@ -0,0 +1,54 @@ +/* + * 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_LOG_H +#define CANDY_GEAR_LOG_H 1 + +#include + +#define CANDY_GEAR_LOG_LEVEL_FATAL 0 +#define CANDY_GEAR_LOG_LEVEL_ERROR 1 +#define CANDY_GEAR_LOG_LEVEL_WARNING 2 +#define CANDY_GEAR_LOG_LEVEL_INFORMATION 3 +#define CANDY_GEAR_LOG_LEVEL_DEBUG 4 +#define CANDY_GEAR_LOG_LEVEL_TRACE 5 + +namespace Log +{ + +enum class Level +{ + Fatal = CANDY_GEAR_LOG_LEVEL_FATAL, + Error = CANDY_GEAR_LOG_LEVEL_ERROR, + Warning = CANDY_GEAR_LOG_LEVEL_WARNING, + Information = CANDY_GEAR_LOG_LEVEL_INFORMATION, + Debug = CANDY_GEAR_LOG_LEVEL_DEBUG, + Trace = CANDY_GEAR_LOG_LEVEL_TRACE +}; + +struct Logger +{ + + void + message(Level lvl, const char* text); + + inline void + message(Level lvl, const std::string &text) {message(lvl, text.c_str());} +}; + +} + +#endif /* CANDY_GEAR_LOG_H */ diff --git a/src/blu_cat/gra/qoi.cpp b/src/blu_cat/gra/qoi.cpp new file mode 100644 index 0000000..790516d --- /dev/null +++ b/src/blu_cat/gra/qoi.cpp @@ -0,0 +1,205 @@ +/* + * Copyright 2022-2024 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 "qoi.hpp" + +#include +#include + +#include "binary_reader.hpp" + +namespace +{ + +const char MAGIC[]{"qoif"}; +const int HEADER_SIZE{14}; +const uint8_t PADDING[8]{0,0,0,0,0,0,0,1}; +const unsigned int PIXELS_MAX{400000000}; + +const int OP_INDEX{0b00000000}; +const int OP_DIFF {0b01000000}; +const int OP_LUMA {0b10000000}; +const int OP_RUN {0b11000000}; +const int OP_RGB {0b11111110}; +const int OP_RGBA {0b11111111}; + +const int MASK_2_BITS{0b11000000}; + +struct RGBA +{ + uint8_t red, green, blue, alpha; + + RGBA(); + RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); +}; + +RGBA::RGBA(): + red{0}, + green{0}, + blue{0}, + alpha{0} +{ +} + +RGBA::RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha): + red{red}, + green{green}, + blue{blue}, + alpha{alpha} +{ +} + +struct Pixel +{ + union + { + RGBA colors; + uint32_t value; + }; + + Pixel(); + Pixel(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); +}; + +Pixel::Pixel(): + colors{} +{ +} + +Pixel::Pixel(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha): + colors(red, green, blue, alpha) +{ +} + +inline int +color_hash(const RGBA &colors) +{ + return colors.red*3 + colors.green*5 + colors.blue*7 + colors.alpha*11; +} + +} + +namespace BluCat::GRA::QOI +{ + +Image::Image(const char *file_path, uint8_t channels): + channels{channels} +{ + if(this->channels != 0 && this->channels != 3 && this->channels != 4) + { + throw std::invalid_argument{"invalid number of channels"}; + } + + BinaryReader input{file_path}; + if(input.size() < HEADER_SIZE + (int)sizeof(PADDING)) + { + throw std::runtime_error{"invalid QOI file"}; + } + + input.read_chars(this->header.magic, 4); + this->header.width = input.read_ui32(); + this->header.height = input.read_ui32(); + this->header.channels = input.read_ui8(); + this->header.colorspace = input.read_ui8(); + + if(this->header.width == 0 || this->header.height == 0 || + this->header.channels < 3 || this->header.channels > 4 || + this->header.colorspace > 1 || + this->header.height >= PIXELS_MAX / this->header.width) + { + throw std::runtime_error{"QOI file have an invalid header"}; + } + + if(this->channels == 0) this->channels = this->header.channels; + + uint32_t num_pixels{this->header.width * this->header.height}; + this->pixels_len = num_pixels * this->channels; + this->pixels = new uint8_t[this->pixels_len]; + + std::array index; + Pixel pixel(0, 0, 0, 255); + int chunks_len = input.size() - (int)sizeof(PADDING); + + /* + This algorithm is based on the original implementation that is in GitHub: + https://github.com/phoboslab/qoi + + For information about the QOI image format, see: https://qoiformat.org/ + */ + int pixel_p{0}; + int run{0}; + for(uint32_t decoded_pixel{0}; decoded_pixel < num_pixels; decoded_pixel++) + { + if(run > 0) + { + run--; + } + else if(input.pointer() < chunks_len) + { + int b1 = input.read_ui8(); + + if (b1 == OP_RGB) + { + pixel.colors.red = input.read_ui8(); + pixel.colors.green = input.read_ui8(); + pixel.colors.blue = input.read_ui8(); + } + else if (b1 == OP_RGBA) + { + pixel.colors.red = input.read_ui8(); + pixel.colors.green = input.read_ui8(); + pixel.colors.blue = input.read_ui8(); + pixel.colors.alpha = input.read_ui8(); + } + else if ((b1 & MASK_2_BITS) == OP_INDEX) + { + pixel = index[b1]; + } + else if ((b1 & MASK_2_BITS) == OP_DIFF) + { + pixel.colors.red += ((b1 >> 4) & 0x03) - 2; + pixel.colors.green += ((b1 >> 2) & 0x03) - 2; + pixel.colors.blue += (b1 & 0x03) - 2; + } + else if ((b1 & MASK_2_BITS) == OP_LUMA) + { + int b2 = input.read_ui8(); + int vg = (b1 & 0x3f) - 32; + pixel.colors.red += vg - 8 + ((b2 >> 4) & 0x0f); + pixel.colors.green += vg; + pixel.colors.blue += vg - 8 + (b2 & 0x0f); + } + else if ((b1 & MASK_2_BITS) == OP_RUN) + { + run = (b1 & 0x3f); + } + + index[color_hash(pixel.colors) % 64] = pixel; + } + + this->pixels[pixel_p++] = pixel.colors.red; + this->pixels[pixel_p++] = pixel.colors.green; + this->pixels[pixel_p++] = pixel.colors.blue; + if(this->channels == 4) this->pixels[pixel_p++] = pixel.colors.alpha; + } +} + +Image::~Image() +{ + delete[] this->pixels; +} + +} diff --git a/src/blu_cat/gra/qoi.hpp b/src/blu_cat/gra/qoi.hpp new file mode 100644 index 0000000..f8be4ec --- /dev/null +++ b/src/blu_cat/gra/qoi.hpp @@ -0,0 +1,41 @@ +/* + * Copyright 2022-2024 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 + +namespace BluCat::GRA::QOI +{ + struct Header + { + char magic[4]; + uint32_t width; + uint32_t height; + uint8_t channels; + uint8_t colorspace; + }; + + struct Image + { + Header header; + uint32_t pixels_len; + uint8_t channels; + uint8_t *pixels; + + Image(const char *file_path, uint8_t channels); + ~Image(); + }; + +} diff --git a/src/blu_cat/gra/queue.cpp b/src/blu_cat/gra/queue.cpp new file mode 100644 index 0000000..3f47a19 --- /dev/null +++ b/src/blu_cat/gra/queue.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2022-2024 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 "queue.hpp" + +#include "queue_family.hpp" + +namespace BluCat::GRA +{ + +Queue::Queue( + BluCat::GRA::QueueFamily *queue_family, VkQueue queue, int queue_index): + queue_family{queue_family}, + queue{queue}, + queue_index{queue_index} +{ + this->queue_family->queue_states[this->queue_index].busy = true; +} + +Queue::Queue(Queue &&that): + queue{that.queue}, + queue_family{that.queue_family}, + queue_index{that.queue_index} +{ + that.queue_family = nullptr; +} + +Queue& Queue::operator=(Queue &&that) +{ + this->queue = that.queue; + this->queue_family = that.queue_family; + this->queue_index = that.queue_index; + + that.queue_family = nullptr; + + return *this; +} + +Queue::~Queue() +{ + if(this->queue_family) + { + std::unique_lock lock{this->queue_family->queue_mutex}; + this->queue_family->queue_states[this->queue_index].busy = false; + } +} + +} diff --git a/src/blu_cat/gra/queue.hpp b/src/blu_cat/gra/queue.hpp new file mode 100644 index 0000000..3dc9833 --- /dev/null +++ b/src/blu_cat/gra/queue.hpp @@ -0,0 +1,82 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_QUEUE_H +#define BLU_CAT_GRA_QUEUE_H 1 + +#include "vulkan.hpp" + +namespace BluCat::GRA +{ +class QueueFamily; + +struct Queue +{ + friend class BluCat::GRA::QueueFamily; + + Queue(const Queue &t) = delete; + Queue& operator=(const Queue &t) = delete; + + VkQueue queue; + + template + void submit_one_time_command( + const VkCommandBuffer vk_command_buffer, T commands); + + Queue(Queue &&that); + Queue& operator=(Queue &&that); + + ~Queue(); + +private: + BluCat::GRA::QueueFamily *queue_family; + int queue_index; + + Queue(BluCat::GRA::QueueFamily *queue_family, VkQueue queue, int queue_index); +}; + +template void +Queue::submit_one_time_command( + const VkCommandBuffer vk_command_buffer, T commands) +{ + VkCommandBufferBeginInfo buffer_begin_info{}; + buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + vkBeginCommandBuffer(vk_command_buffer, &buffer_begin_info); + + commands(); + + vkEndCommandBuffer(vk_command_buffer); + + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 0; + submit_info.pWaitSemaphores = nullptr; + submit_info.pWaitDstStageMask = nullptr; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &vk_command_buffer; + submit_info.signalSemaphoreCount = 0; + submit_info.pSignalSemaphores = nullptr; + + vkQueueSubmit(this->queue, 1, &submit_info, VK_NULL_HANDLE); + vkQueueWaitIdle(this->queue); +} + +} + +#endif /* BLU_CAT_GRA_QUEUE_H */ diff --git a/src/blu_cat/gra/queue_family.cpp b/src/blu_cat/gra/queue_family.cpp new file mode 100644 index 0000000..59086b5 --- /dev/null +++ b/src/blu_cat/gra/queue_family.cpp @@ -0,0 +1,84 @@ +/* + * Copyright 2022-2024 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 "queue_family.hpp" + +#ifdef DEBUG +#include +#endif + +#include "../int/core.hpp" + +namespace BluCat::GRA +{ + +QueueFamily::QueueFamily( + BluCat::GRA::Device *device, uint32_t family_index, + const VkQueueFamilyProperties &queue_family_properties): + queue_mutex{} +{ + +#ifdef DEBUG + std::stringstream message{}; + message << "Queue quantity: " << queue_family_properties.queueCount << + std::endl; + message << "Graphics: " << + (queue_family_properties.queueFlags & VK_QUEUE_GRAPHICS_BIT ? + "true" : "false") << std::endl; + message << "Compute: " << + (queue_family_properties.queueFlags & VK_QUEUE_COMPUTE_BIT ? + "true" : "false") << std::endl; + message << "Transfer: " << + (queue_family_properties.queueFlags & VK_QUEUE_TRANSFER_BIT ? + "true" : "false") << std::endl; + message << "Sparse Binding: " << + (queue_family_properties.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT ? + "true" : "false") << std::endl; + INT::core.log.message(Log::Level::Trace, message.str()); +#endif + + this->device = device; + this->family_index = family_index; + this->family_properties = queue_family_properties; + + // Create queues + { + auto queue_count = this->family_properties.queueCount; + this->queue_states.resize(queue_count); + + for(auto i{0}; i < queue_count; i++) + { + vkGetDeviceQueue(device->device, this->family_index, i, + &this->queue_states[i].queue); + if(this->queue_states[i].queue == VK_NULL_HANDLE) + throw std::runtime_error("Failed to get Vulkan queue."); + } + } +} + +Queue +QueueFamily::get_queue() +{ + std::unique_lock lock{this->queue_mutex}; + + for(auto i{0}; i < this->queue_states.size(); i++) + if(!this->queue_states[i].busy) + return Queue(this, this->queue_states[i].queue, i); + + throw std::length_error("No free queues found."); +} + +} diff --git a/src/blu_cat/gra/queue_family.hpp b/src/blu_cat/gra/queue_family.hpp new file mode 100644 index 0000000..4673058 --- /dev/null +++ b/src/blu_cat/gra/queue_family.hpp @@ -0,0 +1,58 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_QUEUE_FAMILY_H +#define BLU_CAT_GRA_QUEUE_FAMILY_H 1 + +#include +#include + +#include "vulkan.hpp" +#include "queue.hpp" + +namespace BluCat::GRA +{ +class Device; + +struct QueueState +{ + VkQueue queue; + bool busy; +}; + +class QueueFamily +{ + friend class Queue; + + std::mutex queue_mutex; + std::vector queue_states; + +public: + BluCat::GRA::Device *device; + + uint32_t family_index; + VkQueueFamilyProperties family_properties; + + QueueFamily(BluCat::GRA::Device *device, uint32_t family_index, + const VkQueueFamilyProperties &queue_family_properties); + + Queue + get_queue(); +}; + +} + +#endif /* BLU_CAT_GRA_QUEUE_FAMILY_H */ diff --git a/src/blu_cat/gra/rectangle.cpp b/src/blu_cat/gra/rectangle.cpp new file mode 100644 index 0000000..ea01a04 --- /dev/null +++ b/src/blu_cat/gra/rectangle.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2022-2024 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" + +namespace BluCat::GRA +{ + +const int Rectangle::VertexCount{4}; + +Rectangle::Rectangle(glm::vec4 position, glm::vec3 color): + position{position}, + color{color} +{ +} + +} diff --git a/src/blu_cat/gra/rectangle.hpp b/src/blu_cat/gra/rectangle.hpp new file mode 100644 index 0000000..cd09239 --- /dev/null +++ b/src/blu_cat/gra/rectangle.hpp @@ -0,0 +1,42 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_RECTANGLE_H +#define BLU_CAT_GRA_RECTANGLE_H 1 + +#include + +#include "vulkan.hpp" +#include "destination_buffer.hpp" +#include "queue_family.hpp" +#include "uniform_buffer.hpp" + +namespace BluCat::GRA +{ + +struct Rectangle +{ + static const int VertexCount; + + glm::vec4 position; + glm::vec3 color; + + Rectangle(glm::vec4 position, glm::vec3 color); +}; + +} + +#endif /* BLU_CAT_GRA_RECTANGLE_H */ diff --git a/src/blu_cat/gra/render_pass.cpp b/src/blu_cat/gra/render_pass.cpp new file mode 100644 index 0000000..64fdf56 --- /dev/null +++ b/src/blu_cat/gra/render_pass.cpp @@ -0,0 +1,203 @@ +/* + * Copyright 2022-2024 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 "render_pass.hpp" + +#include + +#include "../int/core.hpp" + +namespace +{ + +void +load_3d(void *obj) +{ + auto self = static_cast(obj); + + std::array attachments{}; + // Color attachment. + attachments[0].flags = 0; + attachments[0].format = BluCat::INT::core.vk_swapchain->image_format; + attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + 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_UNDEFINED; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + // Depth attachment. + attachments[1].flags = 0; + attachments[1].format = VK_FORMAT_D32_SFLOAT; + attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachments[1].finalLayout = + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference color_attachment_ref{}; + color_attachment_ref.attachment = 0; + color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentReference depth_attachment_ref{}; + depth_attachment_ref.attachment = 1; + depth_attachment_ref.layout = + VK_IMAGE_LAYOUT_DEPTH_STENCIL_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 = &depth_attachment_ref; + 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( + BluCat::INT::core.vk_device_with_swapchain->device, &render_pass_info, + nullptr, &self->pipeline_3d) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan Render Pass 3D."}; +} + +void +unload_3d(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyRenderPass( + BluCat::INT::core.vk_device_with_swapchain->device, self->pipeline_3d, nullptr); +} + +void +load_2d(void *obj) +{ + auto self = static_cast(obj); + + std::array attachments{}; + // Color attachment. + attachments[0].flags = 0; + attachments[0].format = BluCat::INT::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( + BluCat::INT::core.vk_device_with_swapchain->device, &render_pass_info, + nullptr, &self->pipeline_2d) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan Render Pass 2D."}; +} + +void +unload_2d(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyRenderPass( + BluCat::INT::core.vk_device_with_swapchain->device, self->pipeline_2d, nullptr); +} + +const CommandChain loader{ + {&load_3d, &unload_3d}, + {&load_2d, &unload_2d} +}; + +} + +namespace BluCat::GRA +{ + +RenderPass::RenderPass() +{ + loader.execute(this); +} + +RenderPass::~RenderPass() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/render_pass.hpp b/src/blu_cat/gra/render_pass.hpp new file mode 100644 index 0000000..4187261 --- /dev/null +++ b/src/blu_cat/gra/render_pass.hpp @@ -0,0 +1,36 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_RENDER_PASS_H +#define BLU_CAT_GRA_RENDER_PASS_H 1 + +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +struct RenderPass +{ + VkRenderPass pipeline_2d; + VkRenderPass pipeline_3d; + + RenderPass(); + ~RenderPass(); +}; + +} + +#endif /* BLU_CAT_GRA_RENDER_PASS_H */ diff --git a/src/blu_cat/gra/renderer.cpp b/src/blu_cat/gra/renderer.cpp new file mode 100644 index 0000000..ad66003 --- /dev/null +++ b/src/blu_cat/gra/renderer.cpp @@ -0,0 +1,425 @@ +/* + * Copyright 2022-2024 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 "renderer.hpp" + +#include + +#include "../int/core.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_descriptor_pool(void *obj) +{ + auto self = static_cast(obj); + + uint32_t uniform_buffer_count = 0; + for(auto &view : self->views_3d) + uniform_buffer_count += (view->ub_3d.size() + view->ub_2d.size()); + for(auto &view : self->views_2d) + uniform_buffer_count += (view->ub_2d.size()); + + VkDescriptorPoolSize descriptor_pool_size{}; + descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_pool_size.descriptorCount = uniform_buffer_count; + + VkDescriptorPoolCreateInfo pool_info{}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.pNext = nullptr; + pool_info.flags = 0; + pool_info.maxSets = uniform_buffer_count; + pool_info.poolSizeCount = 1; + pool_info.pPoolSizes = &descriptor_pool_size; + + if(vkCreateDescriptorPool( + BluCat::INT::core.vk_device_with_swapchain->device, &pool_info, nullptr, + &self->descriptor_pool) != VK_SUCCESS) + throw CommandError{"Failed to create a Vulkan descriptor pool."}; + + for(auto &view : self->views_3d) + view->load_descriptor_sets(self->descriptor_pool); + for(auto &view : self->views_2d) + view->load_descriptor_sets(self->descriptor_pool); +} + +void +unload_descriptor_pool(void *obj) +{ + auto self = static_cast(obj); + + for(auto &view : self->views_3d) view->unload_descriptor_sets(); + for(auto &view : self->views_2d) view->unload_descriptor_sets(); + + vkDestroyDescriptorPool( + BluCat::INT::core.vk_device_with_swapchain->device, self->descriptor_pool, + nullptr); +} + +void +load_queue_family(void *obj) +{ + auto self = static_cast(obj); + + self->queue_family = + BluCat::INT::core.vk_device_with_swapchain->get_queue_family_with_presentation(); +} + +void +load_command_pool(void *obj) +{ + auto self = static_cast(obj); + + VkCommandPoolCreateInfo create_info{}; + create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + create_info.queueFamilyIndex = self->queue_family->family_index; + + vkCreateCommandPool( + self->queue_family->device->device, &create_info, nullptr, + &self->command_pool); +} + +void +unload_command_pool(void *obj) +{ + auto self = static_cast(obj); + + self->wait_frame(); + vkDestroyCommandPool( + self->queue_family->device->device, self->command_pool, nullptr); +} + +void +load_draw_command_buffer(void *obj) +{ + auto self = static_cast(obj); + + // FIXME: 3 is a magical number, triple buffering. + self->draw_command_buffers.resize(3); + + VkCommandBufferAllocateInfo allocate_info{}; + allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocate_info.pNext = nullptr; + allocate_info.commandPool = self->command_pool; + allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocate_info.commandBufferCount = self->draw_command_buffers.size(); + + if(vkAllocateCommandBuffers( + self->queue_family->device->device, &allocate_info, + self->draw_command_buffers.data()) != VK_SUCCESS) + throw CommandError{"Vulkan draw command buffers could not be allocated."}; +} + +const CommandChain loader{ + {&load_descriptor_pool, &unload_descriptor_pool}, + {&load_queue_family, nullptr}, + {&load_command_pool, &unload_command_pool}, + {&load_draw_command_buffer, nullptr} +}; + +} + +namespace BluCat::GRA +{ + +Renderer::Renderer(std::vector> views_2d, + std::vector> views_3d): + skeletal_models_to_draw{BluCat::INT::core.vk_swapchain->images_count}, + static_models_to_draw{BluCat::INT::core.vk_swapchain->images_count}, + sprites_3d_to_draw{BluCat::INT::core.vk_swapchain->images_count}, + views_2d{views_2d}, + views_3d{views_3d} +{ + loader.execute(this); +} + +Renderer::Renderer(std::initializer_list> views_2d, + std::initializer_list> views_3d): + Renderer(std::vector(views_2d), std::vector(views_3d)) +{ +} + +Renderer::~Renderer() +{ + loader.revert(this); +} + +// FIXME: this is a workaround to prevent a code to free some resource while +// it still being rendered. +void +Renderer::wait_frame() +{ + vkWaitForFences(BluCat::INT::core.vk_device_with_swapchain->device, + BluCat::GRA::Swapchain::max_frames_in_flight, + BluCat::INT::core.vk_swapchain->in_flight_fences.data(), VK_TRUE, + std::numeric_limits::max()); +} + +void +Renderer::draw() +{ + auto fence_status = vkGetFenceStatus( + BluCat::INT::core.vk_device_with_swapchain->device, + BluCat::INT::core.vk_swapchain->in_flight_fences[ + BluCat::INT::core.vk_swapchain->current_frame]); + + if(fence_status == VK_SUCCESS) + { + auto next_frame = BluCat::INT::core.vk_swapchain->current_frame + 1; + if(next_frame == Swapchain::max_frames_in_flight) next_frame = 0; + + vkResetFences(INT::core.vk_device_with_swapchain->device, 1, + &BluCat::INT::core.vk_swapchain->in_flight_fences[ + BluCat::INT::core.vk_swapchain->current_frame]); + + uint32_t image_index; + vkAcquireNextImageKHR( + BluCat::INT::core.vk_device_with_swapchain->device, + BluCat::INT::core.vk_swapchain->swapchain, + std::numeric_limits::max(), + BluCat::INT::core.vk_swapchain->image_available_semaphores[ + BluCat::INT::core.vk_swapchain->current_frame], VK_NULL_HANDLE, &image_index); + + VkCommandBuffer draw_command_buffer = + this->draw_command_buffers[BluCat::INT::core.vk_swapchain->current_frame]; + vkResetCommandBuffer(draw_command_buffer, 0); + + // Begin command buffer. + { + VkCommandBufferBeginInfo begin_info{}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags = 0; + begin_info.pInheritanceInfo = nullptr; + if (vkBeginCommandBuffer(draw_command_buffer, &begin_info) != VK_SUCCESS) + throw std::runtime_error{"Failed to beggin draw command buffer."}; + } + + // 3D drawing. + { + // Dark gray blue. + std::array clear_values{}; + clear_values[0].color = {0.12f, 0.12f, 0.18f, 1.0f}; + clear_values[1].depthStencil = {1.0f, 0}; + + { // Update world uniform buffer + UDOWorld3D_Vert ubo_world_3d_vert{}; + ubo_world_3d_vert.ambient_light_color = + glm::vec4{0.25, 0.25, 0.25, 1.0}; + BluCat::INT::core.vk_light->ub_world_vert[image_index].copy_data( + &ubo_world_3d_vert); + + UDOWorld3D_Frag ubo_world_3d_frag{}; + ubo_world_3d_frag.directional_light_direction = + glm::vec3{-0.57735, 0.57735, -0.57735}; + ubo_world_3d_frag.directional_light_color = + glm::vec4{0.8, 0.8, 0.8, 1.0}; + BluCat::INT::core.vk_light->ub_world_frag[image_index].copy_data( + &ubo_world_3d_frag); + } + + VkRenderPassBeginInfo render_pass_begin{}; + render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + render_pass_begin.pNext = nullptr; + render_pass_begin.renderPass = BluCat::INT::core.vk_render_pass->pipeline_3d; + render_pass_begin.framebuffer = + BluCat::INT::core.vk_framebuffer->pipeline_3d[image_index]; + render_pass_begin.renderArea.offset = {0, 0}; + render_pass_begin.renderArea.extent = { + static_cast(BluCat::INT::core.display_width), + static_cast(BluCat::INT::core.display_height)}; + render_pass_begin.clearValueCount = clear_values.size(); + render_pass_begin.pClearValues = clear_values.data(); + + vkCmdBeginRenderPass( + draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); + } + + for(auto &view: this->views_3d) + { + { // 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(view->region.x); + vk_scissor.offset.y = static_cast(view->region.y); + vk_scissor.extent.width = static_cast(view->region.z); + vk_scissor.extent.height = static_cast(view->region.w); + vkCmdSetScissor(draw_command_buffer, 0, 1, &vk_scissor); + } + + BluCat::INT::core.vk_graphics_pipeline_3d->draw( + view, draw_command_buffer, BluCat::INT::core.vk_swapchain->current_frame, + image_index); + + BluCat::INT::core.vk_graphics_pipeline_sprite_3d->draw( + view, draw_command_buffer, BluCat::INT::core.vk_swapchain->current_frame, + image_index); + + BluCat::INT::core.vk_graphics_pipeline_3d_skeletal->draw( + view, draw_command_buffer, BluCat::INT::core.vk_swapchain->current_frame, + image_index); + + { // Update view uniform buffers + BluCat::GRA::UDOView3D ubo_view_3d{}; + + // View matrix. + glm::mat4 translation_matrix{1.0f}; + translation_matrix = glm::translate( + translation_matrix, *view->camera_position); + glm::mat4 rotation_matrix{glm::toMat4(*view->camera_orientation)}; + ubo_view_3d.view = glm::inverse(translation_matrix * rotation_matrix); + + // Projection matrix. + ubo_view_3d.proj = glm::perspective( + glm::radians(view->field_of_view), + view->region.z / view->region.w, + 0.1f, 100.0f); + + view->ub_3d[image_index].copy_data(&ubo_view_3d); + } + } + + vkCmdEndRenderPass(draw_command_buffer); + + { // 2D render pass + VkRenderPassBeginInfo render_pass_begin{}; + render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + render_pass_begin.pNext = nullptr; + render_pass_begin.renderPass = BluCat::INT::core.vk_render_pass->pipeline_2d; + render_pass_begin.framebuffer = + BluCat::INT::core.vk_framebuffer->pipeline_2d[image_index]; + render_pass_begin.renderArea.offset = {0, 0}; + render_pass_begin.renderArea.extent = { + static_cast(BluCat::INT::core.display_width), + static_cast(BluCat::INT::core.display_height)}; + render_pass_begin.clearValueCount = 0; + render_pass_begin.pClearValues = nullptr; + + vkCmdBeginRenderPass( + draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); + + } + + { // 2D solid drawing + for(auto &view: this->views_2d) + BluCat::INT::core.vk_graphics_pipeline_2d_solid->draw( + view, draw_command_buffer, BluCat::INT::core.vk_swapchain->current_frame, + next_frame, image_index); + + for(auto &view: this->views_3d) + BluCat::INT::core.vk_graphics_pipeline_2d_solid->draw( + view, draw_command_buffer, BluCat::INT::core.vk_swapchain->current_frame, + next_frame, image_index); + } + + { // 2D wired drawing + for(auto &view: this->views_2d) + BluCat::INT::core.vk_graphics_pipeline_2d_wired->draw( + view, draw_command_buffer, BluCat::INT::core.vk_swapchain->current_frame, + next_frame, image_index); + + for(auto &view: this->views_3d) + BluCat::INT::core.vk_graphics_pipeline_2d_wired->draw( + view, draw_command_buffer, BluCat::INT::core.vk_swapchain->current_frame, + next_frame, image_index); + } + + vkCmdEndRenderPass(draw_command_buffer); + + // End command buffer. + if(vkEndCommandBuffer(draw_command_buffer) != VK_SUCCESS) + throw std::runtime_error{"Failed to end draw command buffer."}; + + // Submit drawing command. + { + auto queue{this->queue_family->get_queue()}; + + VkSemaphore wait_semaphores[]{ + BluCat::INT::core.vk_swapchain->image_available_semaphores[ + BluCat::INT::core.vk_swapchain->current_frame]}; + VkPipelineStageFlags wait_stages[] = + {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + VkSemaphore signal_semaphores[]{ + BluCat::INT::core.vk_swapchain->render_finished_semaphores[ + BluCat::INT::core.vk_swapchain->current_frame]}; + + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = wait_semaphores; + submit_info.pWaitDstStageMask = wait_stages; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &draw_command_buffer; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = signal_semaphores; + + if(vkQueueSubmit( + queue.queue, 1, &submit_info, BluCat::INT::core.vk_swapchain->in_flight_fences[ + BluCat::INT::core.vk_swapchain->current_frame]) != VK_SUCCESS) + throw std::runtime_error{"Failed to submit draw command buffer."}; + + VkSwapchainKHR swap_chains[]{BluCat::INT::core.vk_swapchain->swapchain}; + + VkPresentInfoKHR present_info{}; + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present_info.pNext = nullptr; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = signal_semaphores; + present_info.swapchainCount = 1; + present_info.pSwapchains = swap_chains; + present_info.pImageIndices = &image_index; + present_info.pResults = nullptr; + + vkQueuePresentKHR(queue.queue, &present_info); + } + + // Prepare for the next frame. + { + this->skeletal_models_to_draw[next_frame].clear(); + this->static_models_to_draw[next_frame].clear(); + this->sprites_3d_to_draw[next_frame].clear(); + BluCat::INT::core.vk_swapchain->current_frame = next_frame; + } + } + else + { + // Clear images for the current frame because we are skipping this frame. + this->skeletal_models_to_draw[ + BluCat::INT::core.vk_swapchain->current_frame].clear(); + this->static_models_to_draw[ + BluCat::INT::core.vk_swapchain->current_frame].clear(); + this->sprites_3d_to_draw[ + BluCat::INT::core.vk_swapchain->current_frame].clear(); + for(auto &view: this->views_2d) + view->sprites_to_draw[BluCat::INT::core.vk_swapchain->current_frame].clear(); + for(auto &view: this->views_3d) + view->sprites_to_draw[BluCat::INT::core.vk_swapchain->current_frame].clear(); + } +} + +} diff --git a/src/blu_cat/gra/renderer.hpp b/src/blu_cat/gra/renderer.hpp new file mode 100644 index 0000000..0a3d15f --- /dev/null +++ b/src/blu_cat/gra/renderer.hpp @@ -0,0 +1,75 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_RENDERER_H +#define BLU_CAT_GRA_RENDERER_H 1 + +#include +#include +#include + +#include "vulkan.hpp" +#include "skeletal_mesh.hpp" +#include "skeletal_model.hpp" +#include "sprite_3d.hpp" +#include "static_mesh.hpp" +#include "static_model.hpp" +#include "queue_family.hpp" +#include "view_2d.hpp" +#include "view_3d.hpp" + +namespace BluCat::GRA +{ + +struct Renderer +{ + std::vector< + std::unordered_map< + std::shared_ptr, + std::vector>>> + skeletal_models_to_draw; + + std::vector< + std::unordered_map< + std::shared_ptr, + std::vector>>> + static_models_to_draw; + + std::vector>> sprites_3d_to_draw; + + VkDescriptorPool descriptor_pool; + std::vector> views_2d; + std::vector> views_3d; + QueueFamily *queue_family; + VkCommandPool command_pool; + std::vector draw_command_buffers; + + Renderer(std::vector> views_2d, + std::vector> views_3d); + Renderer(std::initializer_list> views_2d, + std::initializer_list> views_3d); + ~Renderer(); + + void + wait_frame(); + + void + draw(); +}; + +} + +#endif /* BLU_CAT_GRA_RENDERER_H */ diff --git a/src/blu_cat/gra/skeletal_mesh.cpp b/src/blu_cat/gra/skeletal_mesh.cpp new file mode 100644 index 0000000..89d701b --- /dev/null +++ b/src/blu_cat/gra/skeletal_mesh.cpp @@ -0,0 +1,204 @@ +/* + * Copyright 2022-2024 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 "skeletal_mesh.hpp" + +#include "binary_reader.hpp" +#include "../com/command.hpp" +#include "../int/core.hpp" +#include "skeletal_mesh_vertex.hpp" + +namespace +{ + +// Data that is only needed for the command chain but not for the SkeletalMesh +// goes here. +struct MeshBuilder +{ + std::string mesh_path; + BluCat::GRA::SkeletalMesh *mesh; + + MeshBuilder(BluCat::GRA::SkeletalMesh *m, std::string mp); + MeshBuilder(BluCat::GRA::SkeletalMesh *m, const char* mp); +}; + +MeshBuilder::MeshBuilder(BluCat::GRA::SkeletalMesh *m, std::string mp): + mesh{m}, + mesh_path{mp} +{ +} + +MeshBuilder::MeshBuilder(BluCat::GRA::SkeletalMesh *m, const char *mp): + MeshBuilder{m, std::string(mp)} +{ +} + +void +load_mesh(void *obj) +{ + auto self = static_cast(obj); + + BinaryReader input{self->mesh_path}; + + self->mesh->queue_family = + BluCat::INT::core.vk_device_with_swapchain->get_queue_family_with_graphics(); + + { // Load vertexes. + auto vertex_count{input.read_ui32()}; + std::vector vertexes{vertex_count}; + + for(auto i{0}; i < vertex_count; i++) + { + vertexes[i].position = input.read_vec3(); + vertexes[i].normal = input.read_vec3(); + vertexes[i].texture_coord = input.read_vec2(); + + for(auto ii{0}; ii < BluCat::GRA::SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES; + ii++) + vertexes[i].bone_ids[ii] = input.read_ui32(); + + for(auto ii{0}; ii < BluCat::GRA::SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES; + ii++) + vertexes[i].bone_weights[ii] = input.read_float(); + } + + void *vertexes_data{vertexes.data()}; + size_t vertexes_size = sizeof(vertexes[0]) * vertexes.size(); + self->mesh->source_vertex_buffer = new BluCat::GRA::SourceBuffer{ + self->mesh->queue_family->device, vertexes_data, vertexes_size}; + self->mesh->vertex_buffer = new BluCat::GRA::DestinationBuffer{ + self->mesh->queue_family, self->mesh->source_vertex_buffer, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}; + } + + { // Load indexes. + self->mesh->index_count = input.read_ui32(); + std::vector indexes(self->mesh->index_count); + + for(auto i{0}; i < self->mesh->index_count; i++) + indexes[i] = input.read_ui32(); + + void *indexes_data{indexes.data()}; + size_t indexes_size{sizeof(indexes[0]) * indexes.size()}; + BluCat::GRA::SourceBuffer source_index_buffer{ + self->mesh->queue_family->device, indexes_data, indexes_size}; + self->mesh->index_buffer = new BluCat::GRA::DestinationBuffer{ + self->mesh->queue_family, &source_index_buffer, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT}; + } + + { // Load bones + auto bone_count{input.read_ui32()}; + self->mesh->bones.reserve(bone_count); + for(int i{0}; i < bone_count; i++) + self->mesh->bones.emplace_back(input.read_mat4()); + } + + { // Load animations + auto num_animations{input.read_ui32()}; + self->mesh->animations.resize(num_animations); + for(uint32_t i{0}; i < num_animations; i++) + { + auto duration{input.read_double()}; + self->mesh->animations[i].final_time = (float)duration; + + auto ticks_per_second{input.read_double()}; + + auto num_bone_transforms{input.read_ui32()}; + std::vector *bone_transforms = + &(self->mesh->animations[i].bone_transforms); + bone_transforms->resize(num_bone_transforms); + for(uint32_t bone_transform_index{0}; + bone_transform_index < num_bone_transforms; bone_transform_index++) + { + auto bone_id{input.read_ui32()}; + + auto num_positions{input.read_ui32()}; + BluCat::GRA::Channel *positions = + &((*bone_transforms)[bone_transform_index].positions); + for(auto position_key_index{0}; position_key_index < num_positions; + position_key_index++) + { + auto vec3{input.read_vec3()}; + auto timestamp{input.read_double()}; + positions->key_frames.emplace_back( + vec3, static_cast(timestamp)); + } + + auto num_rotations{input.read_ui32()}; + BluCat::GRA::Channel *rotations = + &((*bone_transforms)[bone_transform_index].rotations); + for(auto rotation_key_index{0}; rotation_key_index < num_rotations; + rotation_key_index++) + { + auto quat{input.read_quat()}; + auto timestamp{input.read_double()}; + rotations->key_frames.emplace_back( + quat, static_cast(timestamp)); + } + + auto num_scales{input.read_ui32()}; + BluCat::GRA::Channel *scales = + &((*bone_transforms)[bone_transform_index].scales); + for(auto scaling_key_index{0}; scaling_key_index < num_scales; + scaling_key_index++) + { + auto vec3{input.read_vec3()}; + auto timestamp{input.read_double()}; + scales->key_frames.emplace_back(vec3, static_cast(timestamp)); + } + } + } + } +} + +void +unload_mesh(void *obj) +{ + auto self = static_cast(obj); + + delete self->mesh->index_buffer; + delete self->mesh->vertex_buffer; + delete self->mesh->source_vertex_buffer; +} + +static const CommandChain loader{ + {&load_mesh, &unload_mesh} +}; + +} + +namespace BluCat::GRA +{ + +SkeletalMesh::SkeletalMesh(std::string mesh_path) +{ + MeshBuilder mesh_builder(this, mesh_path); + loader.execute(&mesh_builder); +} + +SkeletalMesh::SkeletalMesh(const char* mesh_path): + SkeletalMesh{std::string(mesh_path)} +{ +} + +SkeletalMesh::~SkeletalMesh() +{ + MeshBuilder mesh_builder(this, ""); + loader.revert(&mesh_builder); +} + +} diff --git a/src/blu_cat/gra/skeletal_mesh.hpp b/src/blu_cat/gra/skeletal_mesh.hpp new file mode 100644 index 0000000..f586ea3 --- /dev/null +++ b/src/blu_cat/gra/skeletal_mesh.hpp @@ -0,0 +1,52 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_SKELETAL_MESH_H +#define BLU_CAT_GRA_SKELETAL_MESH_H 1 + +#include +#include + +#include "animation.hpp" +#include "vulkan.hpp" +#include "destination_buffer.hpp" +#include "queue_family.hpp" +#include "uniform_buffer.hpp" +#include "texture.hpp" + +namespace BluCat::GRA +{ + +struct SkeletalMesh +{ + QueueFamily *queue_family; + + uint32_t index_count; + SourceBuffer *source_vertex_buffer; + DestinationBuffer *index_buffer; + DestinationBuffer *vertex_buffer; + + std::vector bones; + std::vector animations; + + SkeletalMesh(std::string mesh_path); + SkeletalMesh(const char* mesh_path); + ~SkeletalMesh(); +}; + +} + +#endif /* BLU_CAT_GRA_SKELETAL_MESH_H */ diff --git a/src/blu_cat/gra/skeletal_mesh_vertex.hpp b/src/blu_cat/gra/skeletal_mesh_vertex.hpp new file mode 100644 index 0000000..1bd70ad --- /dev/null +++ b/src/blu_cat/gra/skeletal_mesh_vertex.hpp @@ -0,0 +1,42 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_SKELETAL_MESH_VERTEX_H +#define BLU_CAT_GRA_SKELETAL_MESH_VERTEX_H 1 + +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +// This variable define the maximum ammount of bones that can influence a +// vertex. +const int SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES{4}; +const int SKELETAL_MESH_MAX_NUM_OF_BONES{50}; + +struct SkeletalMeshVertex +{ + glm::vec3 position; + glm::vec3 normal; + glm::vec2 texture_coord; + + uint32_t bone_ids[SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES]; + float bone_weights[SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES]; +}; + +} + +#endif /* BLU_CAT_GRA_SKELETAL_MESH_VERTEX_H */ diff --git a/src/blu_cat/gra/skeletal_model.cpp b/src/blu_cat/gra/skeletal_model.cpp new file mode 100644 index 0000000..b58982d --- /dev/null +++ b/src/blu_cat/gra/skeletal_model.cpp @@ -0,0 +1,239 @@ +/* + * Copyright 2022-2024 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 "skeletal_model.hpp" + +#include "../int/core.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_uniform_buffers(void *obj) +{ + auto self = static_cast(obj); + + try + { + self->uniform_buffers.reserve(BluCat::INT::core.vk_swapchain->images_count); + for(auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + self->uniform_buffers.emplace_back( + BluCat::INT::core.vk_device_with_swapchain, + sizeof(BluCat::GRA::UDOSkeletalModel)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_uniform_buffers(void *obj) +{ + auto self = static_cast(obj); + + self->uniform_buffers.clear(); +} + +void +load_descriptor_set_pool(void *obj) +{ + auto self = static_cast(obj); + + std::array descriptor_pool_sizes{}; + descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_pool_sizes[0].descriptorCount = + self->uniform_buffers.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->uniform_buffers.size(); + pool_info.poolSizeCount = descriptor_pool_sizes.size(); + pool_info.pPoolSizes = descriptor_pool_sizes.data(); + + if(vkCreateDescriptorPool( + self->skeletal_mesh->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(obj); + + vkDestroyDescriptorPool( + self->skeletal_mesh->queue_family->device->device, self->descriptor_pool, + nullptr); +} + +void +load_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + std::vector layouts( + BluCat::INT::core.vk_swapchain->images_count, + BluCat::INT::core.vk_descriptor_set_layout->model); + + 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->skeletal_mesh->queue_family->device->device, &alloc_info, + self->descriptor_sets.data()) != VK_SUCCESS) + CommandError{"Failed to create Vulkan descriptor set."}; +} + +void +load_buffers_to_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + for(auto i{0}; i < self->uniform_buffers.size(); i++) + { + VkDescriptorBufferInfo buffer_info{}; + buffer_info.buffer = self->uniform_buffers[i].buffer; + buffer_info.offset = 0; + buffer_info.range = sizeof(BluCat::GRA::UDOSkeletalModel); + + std::array 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( + BluCat::INT::core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); + } +} + +static const CommandChain loader{ + {&load_uniform_buffers, &unload_uniform_buffers}, + {&load_descriptor_set_pool, &unload_descriptor_set_pool}, + {&load_descriptor_sets, nullptr}, + {&load_buffers_to_descriptor_sets, nullptr} +}; + +} + +namespace BluCat::GRA +{ + +SkeletalModel::SkeletalModel( + std::shared_ptr skeletal_mesh, + std::shared_ptr texture, std::shared_ptr position, + std::shared_ptr orientation): + skeletal_mesh{skeletal_mesh}, + texture{texture}, + position{position}, + orientation{orientation}, + animation_index{0}, + animation_time{0.0f}, + bone_transforms(SKELETAL_MESH_MAX_NUM_OF_BONES) +{ + loader.execute(this); + + for(int i{0}; i < skeletal_mesh->bones.size(); i++) + this->bone_transforms[i] = skeletal_mesh->bones[i].offset_matrix; +} + +SkeletalModel::~SkeletalModel() +{ + loader.revert(this); +} + +void +SkeletalModel::tick(float delta) +{ + BluCat::GRA::Animation *current_animation = + &this->skeletal_mesh->animations[this->animation_index]; + + { // update time + this->animation_time += delta; + if(this->animation_time > current_animation->final_time) + { + this->animation_time -= current_animation->final_time; + for(BluCat::GRA::BoneTransform &bone_transform: + current_animation->bone_transforms) + { + bone_transform.positions.current_index = 0; + bone_transform.rotations.current_index = 0; + bone_transform.scales.current_index = 0; + } + } + } + + for(int i{0}; i < current_animation->bone_transforms.size(); i++) + { + BluCat::GRA::BoneTransform *bone_transform = ¤t_animation->bone_transforms[i]; + + auto position{bone_transform->positions.interpolate( + this->animation_time, + [](glm::vec3 frame) + { + return glm::translate(glm::mat4(1.0f), frame); + }, + [](glm::vec3 previous_frame, glm::vec3 next_frame, float scale_factor) + { + glm::vec3 final_position{glm::mix( + previous_frame, next_frame, scale_factor)}; + return glm::translate(glm::mat4(1.0f), final_position); + })}; + + auto rotation{bone_transform->rotations.interpolate( + this->animation_time, + [](glm::quat frame) + { + return glm::toMat4(glm::normalize(frame)); + }, + [](glm::quat previous_frame, glm::quat next_frame, float scale_factor) + { + return glm::toMat4(glm::slerp( + previous_frame, next_frame, scale_factor)); + })}; + + auto scale{bone_transform->scales.interpolate( + this->animation_time, + [](glm::vec3 frame) + { + return glm::scale(glm::mat4(1.0f), frame); + }, + [](glm::vec3 previous_frame, glm::vec3 next_frame, float scale_factor) + { + glm::vec3 scale{glm::mix( + previous_frame, next_frame, scale_factor)}; + return glm::scale(glm::mat4(1.0f), scale); + })}; + + this->bone_transforms[i] = position * rotation * scale; + } +} + +} diff --git a/src/blu_cat/gra/skeletal_model.hpp b/src/blu_cat/gra/skeletal_model.hpp new file mode 100644 index 0000000..73998cb --- /dev/null +++ b/src/blu_cat/gra/skeletal_model.hpp @@ -0,0 +1,55 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_SKELETAL_MODEL_H +#define BLU_CAT_GRA_SKELETAL_MODEL_H 1 + +#include +#include + +#include "vulkan.hpp" +#include "skeletal_mesh.hpp" + +namespace BluCat::GRA +{ + +struct SkeletalModel +{ + std::shared_ptr skeletal_mesh; + std::shared_ptr texture; + std::vector uniform_buffers; + std::shared_ptr position; + std::shared_ptr orientation; + int animation_index; + float animation_time; + std::vector bone_transforms; + + VkDescriptorPool descriptor_pool; + std::vector descriptor_sets; + + SkeletalModel( + std::shared_ptr skeletal_mesh, + std::shared_ptr texture, std::shared_ptr position, + std::shared_ptr orientation); + ~SkeletalModel(); + + void + tick(float delta); +}; + +} + +#endif /* BLU_CAT_GRA_SKELETAL_MODEL_H */ diff --git a/src/blu_cat/gra/source_buffer.cpp b/src/blu_cat/gra/source_buffer.cpp new file mode 100644 index 0000000..18f263f --- /dev/null +++ b/src/blu_cat/gra/source_buffer.cpp @@ -0,0 +1,87 @@ +/* + * Copyright 2022-2024 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 "source_buffer.hpp" + +#include + +namespace BluCat::GRA +{ + +SourceBuffer::SourceBuffer(Device *device, void *data, size_t data_size) +{ + this->device = device; + this->device_size = data_size; + this->buffer_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + this->memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + try + { + BluCat::GRA::BaseBuffer::loader.execute(static_cast(this)); + } + catch(const CommandError &command_error) + { + std::string error{"Could not initialize Vulkan source buffer → "}; + error += command_error.what(); + throw std::runtime_error{error}; + } + this->copy_data(data); +} + +SourceBuffer::SourceBuffer(SourceBuffer &&that) +{ + this->buffer = that.buffer; + this->device_memory = that.device_memory; + this->device_size = that.device_size; + this->buffer_usage = that.buffer_usage; + this->memory_properties = that.memory_properties; + + that.buffer = VK_NULL_HANDLE; + that.device_memory = VK_NULL_HANDLE; +} + +SourceBuffer& +SourceBuffer::operator=(SourceBuffer &&that) +{ + this->buffer = that.buffer; + this->device_memory = that.device_memory; + this->device_size = that.device_size; + this->buffer_usage = that.buffer_usage; + this->memory_properties = that.memory_properties; + + that.buffer = VK_NULL_HANDLE; + that.device_memory = VK_NULL_HANDLE; + + return *this; +} + +SourceBuffer::~SourceBuffer() +{ + BluCat::GRA::BaseBuffer::loader.revert(static_cast(this)); +} + +void +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, src_data, static_cast(this->device_size)); + vkUnmapMemory(this->device->device, this->device_memory); +} + +} diff --git a/src/blu_cat/gra/source_buffer.hpp b/src/blu_cat/gra/source_buffer.hpp new file mode 100644 index 0000000..4eecec9 --- /dev/null +++ b/src/blu_cat/gra/source_buffer.hpp @@ -0,0 +1,45 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_SOURCE_BUFFER_H +#define BLU_CAT_GRA_SOURCE_BUFFER_H 1 + +#include "base_buffer.hpp" + +namespace BluCat::GRA +{ + +struct SourceBuffer: public BaseBuffer +{ + SourceBuffer(const SourceBuffer &t) = delete; + SourceBuffer& + operator=(const SourceBuffer &t) = delete; + + SourceBuffer(Device *device, void *data, size_t data_size); + + SourceBuffer(SourceBuffer &&that); + SourceBuffer& + operator=(SourceBuffer &&that); + + ~SourceBuffer(); + + void + copy_data(void *src_data); +}; + +} + +#endif /* BLU_CAT_GRA_SOURCE_BUFFER_H */ diff --git a/src/blu_cat/gra/sprite.cpp b/src/blu_cat/gra/sprite.cpp new file mode 100644 index 0000000..ee64efe --- /dev/null +++ b/src/blu_cat/gra/sprite.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2022-2024 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 "sprite.hpp" + +#include + +#include "../int/core.hpp" +#include "sprite.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +struct SpriteBuilder +{ + BluCat::GRA::Sprite *sprite; + const glm::vec4 ▭ + + SpriteBuilder(BluCat::GRA::Sprite *sprite, const glm::vec4 &rect); +}; + +SpriteBuilder::SpriteBuilder(BluCat::GRA::Sprite *sprite, const glm::vec4 &rect): + sprite{sprite}, + rect{rect} +{ +} + +void +load_mesh(void *obj) +{ + auto self = static_cast(obj); + + self->sprite->queue_family = + BluCat::INT::core.vk_device_with_swapchain->get_queue_family_with_graphics(); + + glm::vec2 rect[BluCat::GRA::Sprite::vertex_count]{ + glm::vec2{self->rect.x, self->rect.y}, + glm::vec2{self->rect.x, self->rect.w}, + glm::vec2{self->rect.z, self->rect.y}, + glm::vec2{self->rect.z, self->rect.w} + }; + + void *vertexes_data{&rect}; + static const size_t vertexes_size = + sizeof(glm::vec2) * BluCat::GRA::Sprite::vertex_count; + self->sprite->source_buffer = new BluCat::GRA::SourceBuffer{ + self->sprite->queue_family->device, vertexes_data, vertexes_size}; + self->sprite->vertex_buffer = new BluCat::GRA::DestinationBuffer{ + self->sprite->queue_family, self->sprite->source_buffer, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}; +} + +void +unload_mesh(void *obj) +{ + auto self = static_cast(obj); + + delete self->sprite->vertex_buffer; + delete self->sprite->source_buffer; +} + +static const CommandChain loader{ + {&load_mesh, &unload_mesh}, +}; + +} + +namespace BluCat::GRA +{ + +Sprite::Sprite(std::shared_ptr texture, const glm::vec4 &rect): + texture{texture} +{ + SpriteBuilder sprite_builder(this, rect); + loader.execute(&sprite_builder); +} + +Sprite::~Sprite() +{ + glm::vec4 vector_4d{}; + SpriteBuilder sprite_builder(this, vector_4d); + loader.revert(&sprite_builder); +} + +} diff --git a/src/blu_cat/gra/sprite.hpp b/src/blu_cat/gra/sprite.hpp new file mode 100644 index 0000000..1834b22 --- /dev/null +++ b/src/blu_cat/gra/sprite.hpp @@ -0,0 +1,50 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_SPRITE_H +#define BLU_CAT_GRA_SPRITE_H 1 + +#include +#include +#include + +#include "vulkan.hpp" +#include "destination_buffer.hpp" +#include "queue_family.hpp" +#include "uniform_buffer.hpp" +#include "texture.hpp" + +namespace BluCat::GRA +{ + +struct Sprite +{ + static const uint32_t vertex_count{4}; + + QueueFamily *queue_family; + + SourceBuffer *source_buffer; + DestinationBuffer *vertex_buffer; + + std::shared_ptr texture; + + Sprite(std::shared_ptr texture, const glm::vec4 &rect); + ~Sprite(); +}; + +} + +#endif /* BLU_CAT_GRA_SPRITE_H */ diff --git a/src/blu_cat/gra/sprite_3d.cpp b/src/blu_cat/gra/sprite_3d.cpp new file mode 100644 index 0000000..fc994a6 --- /dev/null +++ b/src/blu_cat/gra/sprite_3d.cpp @@ -0,0 +1,168 @@ +/* + * Copyright 2022-2024 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 "sprite_3d.hpp" + +#include "../int/core.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_uniform_buffers(void *obj) +{ + auto self = static_cast(obj); + + try + { + self->uniform_buffers.reserve(BluCat::INT::core.vk_swapchain->images_count); + for(auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + self->uniform_buffers.emplace_back( + BluCat::INT::core.vk_device_with_swapchain, sizeof(BluCat::GRA::UDOSprite3D)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_uniform_buffers(void *obj) +{ + auto self = static_cast(obj); + + self->uniform_buffers.clear(); +} + +void +load_descriptor_set_pool(void *obj) +{ + auto self = static_cast(obj); + + std::array descriptor_pool_sizes{}; + descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_pool_sizes[0].descriptorCount = + self->uniform_buffers.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->uniform_buffers.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(obj); + + vkDestroyDescriptorPool( + self->queue_family->device->device, self->descriptor_pool, nullptr); +} +void +load_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + std::vector layouts( + BluCat::INT::core.vk_swapchain->images_count, + BluCat::INT::core.vk_descriptor_set_layout->model); + + 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_buffers_to_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + for(auto i{0}; i < self->uniform_buffers.size(); i++) + { + VkDescriptorBufferInfo buffer_info{}; + buffer_info.buffer = self->uniform_buffers[i].buffer; + buffer_info.offset = 0; + buffer_info.range = sizeof(BluCat::GRA::UDOSprite3D); + + VkDescriptorImageInfo image_info{}; + image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + image_info.imageView = self->sprite->texture->view; + image_info.sampler = self->sprite->texture->sampler; + + std::array 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( + BluCat::INT::core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); + } +} + +static const CommandChain loader{ + {&load_uniform_buffers, &unload_uniform_buffers}, + {&load_descriptor_set_pool, &unload_descriptor_set_pool}, + {&load_descriptor_sets, nullptr}, + {&load_buffers_to_descriptor_sets, nullptr} +}; + +} + +namespace BluCat::GRA +{ + +Sprite3D::Sprite3D( + std::shared_ptr sprite, std::shared_ptr position, + glm::vec2 size): + sprite{sprite}, + position{position}, + size{size} +{ + this->queue_family = + BluCat::INT::core.vk_device_with_swapchain->get_queue_family_with_graphics(); + loader.execute(this); +} + +Sprite3D::~Sprite3D() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/sprite_3d.hpp b/src/blu_cat/gra/sprite_3d.hpp new file mode 100644 index 0000000..0cd8c04 --- /dev/null +++ b/src/blu_cat/gra/sprite_3d.hpp @@ -0,0 +1,46 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_SPRITE_3D_H +#define BLU_CAT_GRA_SPRITE_3D_H 1 + +#include "vulkan.hpp" +#include "sprite.hpp" + +namespace BluCat::GRA +{ + +struct Sprite3D +{ + std::shared_ptr sprite; + std::shared_ptr position; + glm::vec2 size; + + QueueFamily *queue_family; + + std::vector uniform_buffers; + VkDescriptorPool descriptor_pool; + std::vector descriptor_sets; + + Sprite3D( + std::shared_ptr sprite, std::shared_ptr position, + glm::vec2 size); + ~Sprite3D(); +}; + +} + +#endif /* BLU_CAT_GRA_SPRITE_3D_H */ diff --git a/src/blu_cat/gra/sprite_to_draw.cpp b/src/blu_cat/gra/sprite_to_draw.cpp new file mode 100644 index 0000000..7645d73 --- /dev/null +++ b/src/blu_cat/gra/sprite_to_draw.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2022-2024 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 "sprite_to_draw.hpp" + +namespace BluCat::GRA +{ + SpriteToDraw::SpriteToDraw( + std::shared_ptr sprite, const glm::vec4 &position, float z_index): + sprite{sprite}, + position{position}, + z_index{z_index} + { + } + + bool + operator<(const SpriteToDraw& a, const SpriteToDraw& b) + { + return a.z_index < b.z_index; + } + + bool + operator>(const SpriteToDraw& a, const SpriteToDraw& b) + { + return a.z_index > b.z_index; + } +} diff --git a/src/blu_cat/gra/sprite_to_draw.hpp b/src/blu_cat/gra/sprite_to_draw.hpp new file mode 100644 index 0000000..e7a23c4 --- /dev/null +++ b/src/blu_cat/gra/sprite_to_draw.hpp @@ -0,0 +1,44 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_SPRITES_TO_DRAW_H +#define BLU_CAT_GRA_SPRITES_TO_DRAW_H 1 + +#include + +#include "vulkan.hpp" +#include "sprite.hpp" + +namespace BluCat::GRA +{ + struct SpriteToDraw + { + std::shared_ptr sprite; + glm::vec4 position; + float z_index; + + SpriteToDraw(std::shared_ptr sprite, const glm::vec4 &position, + float z_index); + }; + + bool + operator<(const SpriteToDraw &a, const SpriteToDraw &b); + + bool + operator>(const SpriteToDraw &a, const SpriteToDraw &b); +} + +#endif /* BLU_CAT_GRA_SPRITES_TO_DRAW_H */ diff --git a/src/blu_cat/gra/static_mesh.cpp b/src/blu_cat/gra/static_mesh.cpp new file mode 100644 index 0000000..db3a6ee --- /dev/null +++ b/src/blu_cat/gra/static_mesh.cpp @@ -0,0 +1,132 @@ +/* + * Copyright 2022-2024 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 "static_mesh.hpp" + +#include "binary_reader.hpp" +#include "../com/command.hpp" +#include "../int/core.hpp" +#include "static_mesh_vertex.hpp" + +namespace +{ + +// Data that is only needed for the command chain but not for the StaticMesh +// goes here. +struct MeshBuilder +{ + std::string mesh_path; + BluCat::GRA::StaticMesh *mesh; + + MeshBuilder(BluCat::GRA::StaticMesh *m, std::string mp); + MeshBuilder(BluCat::GRA::StaticMesh *m, const char* mp); +}; + +MeshBuilder::MeshBuilder(BluCat::GRA::StaticMesh *m, std::string mp): + mesh{m}, + mesh_path{mp} +{ +} + +MeshBuilder::MeshBuilder(BluCat::GRA::StaticMesh *m, const char *mp): + MeshBuilder{m, std::string(mp)} +{ +} + +void +load_mesh(void *obj) +{ + auto self = static_cast(obj); + + BinaryReader input{self->mesh_path}; + + self->mesh->queue_family = + BluCat::INT::core.vk_device_with_swapchain->get_queue_family_with_graphics(); + + { // Load vertexes. + auto vertex_count{input.read_ui32()}; + std::vector vertexes{vertex_count}; + + for(auto i{0}; i < vertex_count; i++) + { + vertexes[i].position = input.read_vec3(); + vertexes[i].normal = input.read_vec3(); + vertexes[i].texture_coord = input.read_vec2(); + } + + void *vertexes_data{vertexes.data()}; + size_t vertexes_size = sizeof(vertexes[0]) * vertexes.size(); + self->mesh->source_vertex_buffer = new BluCat::GRA::SourceBuffer{ + self->mesh->queue_family->device, vertexes_data, vertexes_size}; + self->mesh->vertex_buffer = new BluCat::GRA::DestinationBuffer{ + self->mesh->queue_family, self->mesh->source_vertex_buffer, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}; + } + + { // Load indexes + self->mesh->index_count = input.read_ui32(); + std::vector indexes(self->mesh->index_count); + + for(auto i{0}; i < self->mesh->index_count; i++) + indexes[i] = input.read_ui32(); + + void *indexes_data{indexes.data()}; + size_t indexes_size{sizeof(indexes[0]) * indexes.size()}; + BluCat::GRA::SourceBuffer source_index_buffer{ + self->mesh->queue_family->device, indexes_data, indexes_size}; + self->mesh->index_buffer = new BluCat::GRA::DestinationBuffer{ + self->mesh->queue_family, &source_index_buffer, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT}; + } +} + +void +unload_mesh(void *obj) +{ + auto self = static_cast(obj); + + delete self->mesh->index_buffer; + delete self->mesh->vertex_buffer; + delete self->mesh->source_vertex_buffer; +} + +static const CommandChain loader{ + {&load_mesh, &unload_mesh} +}; + +} + +namespace BluCat::GRA +{ + +StaticMesh::StaticMesh(std::string mesh_path) +{ + MeshBuilder mesh_builder(this, mesh_path); + loader.execute(&mesh_builder); +} + +StaticMesh::StaticMesh(const char* mesh_path): + StaticMesh{std::string(mesh_path)} +{ +} + +StaticMesh::~StaticMesh() +{ + MeshBuilder mesh_builder(this, ""); + loader.revert(&mesh_builder); +} + +} diff --git a/src/blu_cat/gra/static_mesh.hpp b/src/blu_cat/gra/static_mesh.hpp new file mode 100644 index 0000000..2b059fe --- /dev/null +++ b/src/blu_cat/gra/static_mesh.hpp @@ -0,0 +1,48 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_STATIC_MESH_H +#define BLU_CAT_GRA_STATIC_MESH_H 1 + +#include +#include + +#include "vulkan.hpp" +#include "destination_buffer.hpp" +#include "queue_family.hpp" +#include "uniform_buffer.hpp" +#include "texture.hpp" + +namespace BluCat::GRA +{ + +struct StaticMesh +{ + QueueFamily *queue_family; + + uint32_t index_count; + SourceBuffer *source_vertex_buffer; + DestinationBuffer *index_buffer; + DestinationBuffer *vertex_buffer; + + StaticMesh(std::string mesh_path); + StaticMesh(const char* mesh_path); + ~StaticMesh(); +}; + +} + +#endif /* BLU_CAT_GRA_STATIC_MESH_H */ diff --git a/src/blu_cat/gra/static_mesh_vertex.hpp b/src/blu_cat/gra/static_mesh_vertex.hpp new file mode 100644 index 0000000..510ce40 --- /dev/null +++ b/src/blu_cat/gra/static_mesh_vertex.hpp @@ -0,0 +1,34 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_STATIC_MESH_VERTEX_H +#define BLU_CAT_GRA_STATIC_MESH_VERTEX_H 1 + +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +struct StaticMeshVertex +{ + glm::vec3 position; + glm::vec3 normal; + glm::vec2 texture_coord; +}; + +} + +#endif /* BLU_CAT_GRA_STATIC_MESH_VERTEX_H */ diff --git a/src/blu_cat/gra/static_model.cpp b/src/blu_cat/gra/static_model.cpp new file mode 100644 index 0000000..50dc94d --- /dev/null +++ b/src/blu_cat/gra/static_model.cpp @@ -0,0 +1,165 @@ +/* + * Copyright 2022-2024 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 "static_model.hpp" + +#include "../int/core.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_uniform_buffers(void *obj) +{ + auto self = static_cast(obj); + + try + { + self->uniform_buffers.reserve(BluCat::INT::core.vk_swapchain->images_count); + for(auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + self->uniform_buffers.emplace_back( + BluCat::INT::core.vk_device_with_swapchain, sizeof(BluCat::GRA::UDOStaticModel)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_uniform_buffers(void *obj) +{ + auto self = static_cast(obj); + + self->uniform_buffers.clear(); +} + +void +load_descriptor_set_pool(void *obj) +{ + auto self = static_cast(obj); + + std::array descriptor_pool_sizes{}; + descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_pool_sizes[0].descriptorCount = + self->uniform_buffers.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->uniform_buffers.size(); + pool_info.poolSizeCount = descriptor_pool_sizes.size(); + pool_info.pPoolSizes = descriptor_pool_sizes.data(); + + if(vkCreateDescriptorPool( + self->static_mesh->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(obj); + + vkDestroyDescriptorPool( + self->static_mesh->queue_family->device->device, self->descriptor_pool, + nullptr); +} + +void +load_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + std::vector layouts( + BluCat::INT::core.vk_swapchain->images_count, + BluCat::INT::core.vk_descriptor_set_layout->model); + + 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->static_mesh->queue_family->device->device, &alloc_info, + self->descriptor_sets.data()) != VK_SUCCESS) + CommandError{"Failed to create Vulkan descriptor set."}; +} + +void +load_buffers_to_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + for(auto i{0}; i < self->uniform_buffers.size(); i++) + { + VkDescriptorBufferInfo buffer_info{}; + buffer_info.buffer = self->uniform_buffers[i].buffer; + buffer_info.offset = 0; + buffer_info.range = sizeof(BluCat::GRA::UDOStaticModel); + + std::array 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( + BluCat::INT::core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); + } +} + +static const CommandChain loader{ + {&load_uniform_buffers, &unload_uniform_buffers}, + {&load_descriptor_set_pool, &unload_descriptor_set_pool}, + {&load_descriptor_sets, nullptr}, + {&load_buffers_to_descriptor_sets, nullptr} +}; + +} + +namespace BluCat::GRA +{ + +StaticModel::StaticModel( + std::shared_ptr static_mesh, + std::shared_ptr texture, std::shared_ptr position, + std::shared_ptr orientation): + static_mesh{static_mesh}, + texture{texture}, + position{position}, + orientation{orientation} +{ + loader.execute(this); +} + +StaticModel::~StaticModel() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/static_model.hpp b/src/blu_cat/gra/static_model.hpp new file mode 100644 index 0000000..0d689d0 --- /dev/null +++ b/src/blu_cat/gra/static_model.hpp @@ -0,0 +1,49 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_STATIC_MODEL_H +#define BLU_CAT_GRA_STATIC_MODEL_H 1 + +#include +#include + +#include "vulkan.hpp" +#include "static_mesh.hpp" + +namespace BluCat::GRA +{ + +struct StaticModel +{ + std::shared_ptr static_mesh; + std::shared_ptr texture; + std::vector uniform_buffers; + std::shared_ptr position; + std::shared_ptr orientation; + + VkDescriptorPool descriptor_pool; + std::vector descriptor_sets; + + StaticModel( + std::shared_ptr static_mesh, + std::shared_ptr texture, std::shared_ptr position, + std::shared_ptr orientation); + ~StaticModel(); +}; + +} + +#endif /* BLU_CAT_GRA_STATIC_MODEL_H */ diff --git a/src/blu_cat/gra/swapchain.cpp b/src/blu_cat/gra/swapchain.cpp new file mode 100644 index 0000000..f57e3c2 --- /dev/null +++ b/src/blu_cat/gra/swapchain.cpp @@ -0,0 +1,207 @@ +/* + * Copyright 2022-2024 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 "swapchain.hpp" + +#include "../int/core.hpp" + +#include + +namespace +{ + +void +load_swapchain(void *obj) +{ + auto self = static_cast(obj); + + // Surface formats. + uint32_t vk_surface_format_count; + std::vector vk_surface_formats; + vkGetPhysicalDeviceSurfaceFormatsKHR( + BluCat::INT::core.vk_device_with_swapchain->physical_device, + BluCat::INT::core.window_surface, &vk_surface_format_count, nullptr); + vk_surface_formats.resize(vk_surface_format_count); + vkGetPhysicalDeviceSurfaceFormatsKHR( + BluCat::INT::core.vk_device_with_swapchain->physical_device, + BluCat::INT::core.window_surface, &vk_surface_format_count, + vk_surface_formats.data()); + + VkSwapchainCreateInfoKHR swapchain_create_info = {}; + swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchain_create_info.pNext = nullptr; + swapchain_create_info.flags = 0; + swapchain_create_info.surface = BluCat::INT::core.window_surface; + swapchain_create_info.minImageCount = 3; // triple buffering. + + self->image_format = vk_surface_formats[0].format; + swapchain_create_info.imageFormat = self->image_format; + swapchain_create_info.imageColorSpace = vk_surface_formats[0].colorSpace; + + swapchain_create_info.imageExtent = { + BluCat::INT::core.display_width, BluCat::INT::core.display_height}; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_create_info.queueFamilyIndexCount = 0; + swapchain_create_info.pQueueFamilyIndices = nullptr; + swapchain_create_info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; + swapchain_create_info.clipped = VK_FALSE; + swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; + + if(vkCreateSwapchainKHR( + BluCat::INT::core.vk_device_with_swapchain->device, &swapchain_create_info, + nullptr, &self->swapchain) != VK_SUCCESS) + throw CommandError{"Vulkan failed to create swapchain."}; + + vkGetSwapchainImagesKHR( + BluCat::INT::core.vk_device_with_swapchain->device, self->swapchain, + &self->images_count, nullptr); + self->images = new VkImage[self->images_count]; + vkGetSwapchainImagesKHR( + BluCat::INT::core.vk_device_with_swapchain->device, self->swapchain, + &self->images_count, self->images); +} + +void +unload_swapchain(void *obj) +{ + auto self = static_cast(obj); + + delete[] self->images; + vkDestroySwapchainKHR( + BluCat::INT::core.vk_device_with_swapchain->device, self->swapchain, nullptr); +} + +void +load_image_view(void *obj) +{ + auto self = static_cast(obj); + + self->image_views = new VkImageView[self->images_count]; + for(auto i{0}; i < self->images_count; i++) + { + VkImageViewCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info.image = self->images[i]; + create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + create_info.format = self->image_format; + create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + create_info.subresourceRange.baseMipLevel = 0; + create_info.subresourceRange.levelCount = 1; + create_info.subresourceRange.baseArrayLayer = 0; + create_info.subresourceRange.layerCount = 1; + + if(vkCreateImageView( + BluCat::INT::core.vk_device_with_swapchain->device, &create_info, nullptr, + &self->image_views[i])) + throw CommandError{"Could no create Image View for swapchain."}; + } +} + +void +unload_image_view(void *obj) +{ + auto self = static_cast(obj); + + for(auto i{0}; i < self->images_count; i++) + vkDestroyImageView( + BluCat::INT::core.vk_device_with_swapchain->device, self->image_views[i], + nullptr); +} + +void +load_frame_sync(void *obj) +{ + auto self = static_cast(obj); + + self->image_available_semaphores.resize(self->max_frames_in_flight); + self->render_finished_semaphores.resize(self->max_frames_in_flight); + self->in_flight_fences.resize(self->max_frames_in_flight); + + VkSemaphoreCreateInfo semaphore_info = {}; + semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semaphore_info.pNext = nullptr; + semaphore_info.flags = 0; + + VkFenceCreateInfo fence_info = {}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.pNext = nullptr; + fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + // FIXME: if this loop fails, it will not destroy the semaphores. + for(auto i{0}; i < self->max_frames_in_flight; i++) + { + if(vkCreateSemaphore( + BluCat::INT::core.vk_device_with_swapchain->device, &semaphore_info, + nullptr, &self->image_available_semaphores[i]) != VK_SUCCESS || + vkCreateSemaphore( + BluCat::INT::core.vk_device_with_swapchain->device, &semaphore_info, + nullptr, &self->render_finished_semaphores[i]) != VK_SUCCESS || + vkCreateFence( + BluCat::INT::core.vk_device_with_swapchain->device, &fence_info, + nullptr, &self->in_flight_fences[i]) != VK_SUCCESS) + throw CommandError{"Failed to create semaphores."}; + } +} + +void +unload_frame_sync(void *obj) +{ + auto self = static_cast(obj); + + vkDeviceWaitIdle(BluCat::INT::core.vk_device_with_swapchain->device); + + for(auto i{0}; i < self->max_frames_in_flight; i++) + { + vkDestroySemaphore(BluCat::INT::core.vk_device_with_swapchain->device, + self->render_finished_semaphores[i], nullptr); + vkDestroySemaphore(BluCat::INT::core.vk_device_with_swapchain->device, + self->image_available_semaphores[i], nullptr); + vkDestroyFence(BluCat::INT::core.vk_device_with_swapchain->device, + self->in_flight_fences[i], nullptr); + } +} + +const CommandChain loader{ + {&load_swapchain, &unload_swapchain}, + {&load_image_view, &unload_image_view}, + {&load_frame_sync, &unload_frame_sync} +}; + +} + +namespace BluCat::GRA +{ + +Swapchain::Swapchain(): + current_frame{0} +{ + loader.execute(this); +} + +Swapchain::~Swapchain() +{ + loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/swapchain.hpp b/src/blu_cat/gra/swapchain.hpp new file mode 100644 index 0000000..2b52dd6 --- /dev/null +++ b/src/blu_cat/gra/swapchain.hpp @@ -0,0 +1,47 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_SWAPCHAIN_H +#define BLU_CAT_GRA_SWAPCHAIN_H 1 + +#include "../com/command.hpp" +#include "vulkan.hpp" + +namespace BluCat::GRA +{ + +struct Swapchain +{ + VkSwapchainKHR swapchain; + VkFormat image_format; + + uint32_t images_count; + VkImage *images; + VkImageView *image_views; + + static const int max_frames_in_flight{2}; + size_t current_frame; + std::vector image_available_semaphores; + std::vector render_finished_semaphores; + std::vector in_flight_fences; + + Swapchain(); + ~Swapchain(); +}; + +} + +#endif /* BLU_CAT_GRA_SWAPCHAIN_H */ diff --git a/src/blu_cat/gra/texture.cpp b/src/blu_cat/gra/texture.cpp new file mode 100644 index 0000000..5abf751 --- /dev/null +++ b/src/blu_cat/gra/texture.cpp @@ -0,0 +1,566 @@ +/* + * Copyright 2022-2024 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 "texture.hpp" + +#include "../com/command.hpp" +#include "../int/core.hpp" +#include "image.hpp" +#include "qoi.hpp" +#include "source_buffer.hpp" + +namespace +{ + +inline void +create_vulkan_image( + VkImage *image, VkDeviceMemory *device_memory, int width, int height, + uint32_t mip_levels) +{ + VkExtent3D vk_extent3d{}; + vk_extent3d.width = width; + vk_extent3d.height = height; + vk_extent3d.depth = 1; + + BluCat::GRA::Image::create( + BluCat::INT::core.vk_device_with_swapchain, + image, + device_memory, + VK_FORMAT_R8G8B8A8_UNORM, + vk_extent3d, + mip_levels, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); +} + +struct ImageBuilder +{ + BluCat::GRA::Texture *texture; +}; + +struct ImageTextureBuilder: public ImageBuilder +{ + std::string texture_path; + + ImageTextureBuilder(BluCat::GRA::Texture *t, const std::string &tp); + ImageTextureBuilder(BluCat::GRA::Texture *t, const char* tp); +}; + +ImageTextureBuilder::ImageTextureBuilder( + BluCat::GRA::Texture *t, const std::string &tp): + texture_path{tp} +{ + this->texture = t; +} + +ImageTextureBuilder::ImageTextureBuilder(BluCat::GRA::Texture *t, const char* tp): + ImageTextureBuilder{t, std::string(tp)} +{ +} + +void +load_image(void *obj) +{ + auto self = static_cast(obj); + + const int num_channels = 4; // all images are converted to RGBA + BluCat::GRA::QOI::Image qoi_image(self->texture_path.c_str(), num_channels); + uint8_t *pixels; + + { // Load file image from file. + self->texture->width = qoi_image.header.width; + self->texture->height = qoi_image.header.height; + self->texture->mip_levels = 1; + + pixels = qoi_image.pixels; + } + + // Load file image into a vulkan buffer. + size_t image_size{static_cast( + qoi_image.header.width * qoi_image.header.height * num_channels)}; + BluCat::GRA::SourceBuffer source_image_buffer{ + BluCat::INT::core.vk_device_with_swapchain, pixels, image_size}; + + { // Create vulkan image. + try + { + create_vulkan_image( + &self->texture->image, + &self->texture->device_memory, + self->texture->width, + self->texture->height, + self->texture->mip_levels); + } + catch(BluCat::GRA::Image::Error error) + { + throw CommandError{error.what()}; + } + } + + // Copy image from vulkan buffer into vulkan image. + { + auto queue_family = self->texture->queue_family; + auto queue{queue_family->get_queue()}; + BluCat::GRA::CommandPool command_pool{queue_family, 1}; + VkCommandBuffer vk_command_buffer{command_pool.command_buffers[0]}; + + queue.submit_one_time_command(vk_command_buffer, [&](){ + BluCat::GRA::Image::move_image_state( + vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + + VkBufferImageCopy image_copy{}; + image_copy.bufferOffset = 0; + image_copy.bufferRowLength = 0; + image_copy.bufferImageHeight = 0; + image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + image_copy.imageSubresource.mipLevel = 0; + image_copy.imageSubresource.baseArrayLayer = 0; + image_copy.imageSubresource.layerCount = 1; + image_copy.imageOffset = {0, 0, 0}; + image_copy.imageExtent = { + self->texture->width, self->texture->height, 1}; + + vkCmdCopyBufferToImage( + vk_command_buffer, source_image_buffer.buffer, self->texture->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); + + BluCat::GRA::Image::move_image_state( + vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + }); + } +} + +void +unload_image(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyImage( + BluCat::INT::core.vk_device_with_swapchain->device, self->texture->image, + nullptr); + vkFreeMemory( + BluCat::INT::core.vk_device_with_swapchain->device, + self->texture->device_memory, nullptr); +} + +void +load_sampler(void *obj) +{ + auto self = static_cast(obj); + + VkSamplerCreateInfo sampler_info{}; + sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + sampler_info.pNext = nullptr; + sampler_info.flags = 0; + sampler_info.magFilter = VK_FILTER_LINEAR; + sampler_info.minFilter = VK_FILTER_LINEAR; + sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.mipLodBias = 0.0f; + sampler_info.anisotropyEnable = VK_TRUE; + sampler_info.maxAnisotropy = 16; + sampler_info.compareEnable = VK_FALSE; + sampler_info.compareOp = VK_COMPARE_OP_NEVER; + sampler_info.minLod = 0.0f; + sampler_info.maxLod = 0.0f; + sampler_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + sampler_info.unnormalizedCoordinates = VK_FALSE; + + if(vkCreateSampler( + BluCat::INT::core.vk_device_with_swapchain->device, &sampler_info, nullptr, + &self->texture->sampler) != VK_SUCCESS) + throw CommandError{"Failed to create texture sampler."}; +} + +void +unload_sampler(void *obj) +{ + auto self = static_cast(obj); + + vkDestroySampler( + BluCat::INT::core.vk_device_with_swapchain->device, self->texture->sampler, + nullptr); +} + +void +load_view(void *obj) +{ + auto self = static_cast(obj); + + try + { + BluCat::GRA::Image::create_view( + BluCat::INT::core.vk_device_with_swapchain, &self->texture->view, + self->texture->image, + VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + } + catch(BluCat::GRA::Image::Error error) + { + throw CommandError{error.what()}; + } +} + +void +unload_view(void *obj) +{ + auto self = static_cast(obj); + + vkDestroyImageView( + BluCat::INT::core.vk_device_with_swapchain->device, self->texture->view, + nullptr); +} + +const CommandChain image_loader{ + {&load_image, &unload_image}, + {&load_sampler, &unload_sampler}, + {&load_view, &unload_view} +}; + +struct CharacterToDraw +{ + int pos_x; + std::shared_ptr character; + + CharacterToDraw(int x, std::shared_ptr character): + pos_x{x}, + character{character} + {}; +}; + +struct TextTextureBuilder: public ImageBuilder +{ + BluCat::GRA::Font *font; + const char* str; + uint32_t max_bearing_y; + std::vector chars_to_draw; + + TextTextureBuilder(BluCat::GRA::Texture *texture, BluCat::GRA::Font *font, const char* str): + font{font}, + str{str} + { + this->texture = texture; + } +}; + +void +load_text_proportions(void *obj) +{ + auto self = static_cast(obj); + + uint32_t texture_width{0}, texture_descender{0}; + auto unicode_text{BluCat::GRA::Character::str_to_unicode(self->str)}; + + auto first_image{self->font->character(unicode_text[0])}; + if(first_image->bearing_x < 0) texture_width = - first_image->bearing_x; + + self->max_bearing_y = 0; + self->chars_to_draw.reserve(unicode_text.size()); + + // FIXME: I need to test several different fonts to find all bugs in this + // code. + std::shared_ptr char_image{}; + { // Calculate image size + int max_height; + for(auto char_code : unicode_text) + { + char_image = self->font->character(char_code); + uint32_t descender{char_image->height - char_image->bearing_y}; + uint32_t pos_x{texture_width + char_image->bearing_x}; + + if(char_image->image != VK_NULL_HANDLE) + self->chars_to_draw.emplace_back(pos_x, char_image); + + if(char_image->bearing_y > self->max_bearing_y) + self->max_bearing_y = char_image->bearing_y; + if(descender > texture_descender) texture_descender = descender; + + texture_width += char_image->advance; + } + } + + { // Restore image width if last character have a negative bearing. + int bearing_x_pluss_width = char_image->bearing_x + char_image->width; + if(bearing_x_pluss_width > char_image->advance) + texture_width += bearing_x_pluss_width - char_image->advance; + } + + self->texture->width = texture_width; + self->texture->height = self->max_bearing_y + texture_descender; + self->texture->mip_levels = 1; +} + +void +load_text_image(void *obj) +{ + auto self = static_cast(obj); + + const int NumChannels = 4; + + size_t image_size{static_cast( + self->texture->width * self->texture->height * NumChannels)}; + std::vector pixels(image_size); + for(auto x{0}; x < self->texture->width; x++) + { + for(auto y{0}; y < self->texture->height; y++) + { + auto image_coord = y * self->font->face->glyph->bitmap.width + + x * NumChannels; + pixels[image_coord] = 0; // Red + pixels[image_coord + 1] = 0; // Green + pixels[image_coord + 2] = 0; // Blue + pixels[image_coord + 3] = 0; // Alpha + } + } + BluCat::GRA::SourceBuffer source_image_buffer{ + BluCat::INT::core.vk_device_with_swapchain, pixels.data(), image_size}; + + { // Create vulkan image. + try + { + create_vulkan_image( + &self->texture->image, + &self->texture->device_memory, + self->texture->width, + self->texture->height, + self->texture->mip_levels); + } + catch(BluCat::GRA::Image::Error error) + { + throw CommandError{error.what()}; + } + } + + { // Render text + auto queue_family{ + BluCat::INT::core.vk_device_with_swapchain-> + get_queue_family_with_presentation()}; + auto queue{queue_family->get_queue()}; + BluCat::GRA::CommandPool command_pool{queue_family, 1}; + VkCommandBuffer vk_command_buffer{command_pool.command_buffers[0]}; + + queue.submit_one_time_command(vk_command_buffer, [&](){ + BluCat::GRA::Image::move_image_state( + vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + + VkBufferImageCopy image_copy{}; + image_copy.bufferOffset = 0; + image_copy.bufferRowLength = 0; + image_copy.bufferImageHeight = 0; + image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + image_copy.imageSubresource.mipLevel = 0; + image_copy.imageSubresource.baseArrayLayer = 0; + image_copy.imageSubresource.layerCount = 1; + image_copy.imageOffset = {0, 0, 0}; + image_copy.imageExtent = {self->texture->width, self->texture->height, 1}; + + vkCmdCopyBufferToImage( + vk_command_buffer, source_image_buffer.buffer, self->texture->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); + + for(auto &to_draw: self->chars_to_draw) + { + VkImageSubresourceLayers + source_subresources{}, destination_subresources{}; + source_subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + source_subresources.mipLevel = 0; + source_subresources.baseArrayLayer = 0; + source_subresources.layerCount = 1; + + destination_subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + destination_subresources.mipLevel = 0; + destination_subresources.baseArrayLayer = 0; + destination_subresources.layerCount = 1; + + VkImageCopy image_copy{}; + image_copy.srcSubresource = source_subresources; + image_copy.srcOffset = {0, 0, 0}; + image_copy.dstSubresource = destination_subresources; + image_copy.dstOffset = { + to_draw.pos_x, + (int)(self->max_bearing_y - to_draw.character->bearing_y), + 0}; + image_copy.extent = { + to_draw.character->width, to_draw.character->height, 1}; + + vkCmdCopyImage( + vk_command_buffer, + to_draw.character->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + self->texture->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &image_copy); + } + + BluCat::GRA::Image::move_image_state( + vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + }); + } +} + +const CommandChain text_loader{ + {&load_text_proportions, nullptr}, + {&load_text_image, &unload_image}, + {&load_sampler, &unload_sampler}, + {&load_view, &unload_view} +}; + +void +load_descriptor_set_pool(void *obj) +{ + auto self = static_cast(obj); + + std::array descriptor_pool_sizes{}; + descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptor_pool_sizes[0].descriptorCount = + BluCat::INT::core.vk_swapchain->images_count; + + VkDescriptorPoolCreateInfo pool_info{}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.pNext = nullptr; + pool_info.flags = 0; + pool_info.maxSets = BluCat::INT::core.vk_swapchain->images_count; + 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(obj); + + vkDestroyDescriptorPool( + self->queue_family->device->device, self->descriptor_pool, nullptr); +} + +void +load_descriptor_sets(void *obj) +{ + auto self = static_cast(obj); + + std::vector layouts( + BluCat::INT::core.vk_swapchain->images_count, + BluCat::INT::core.vk_descriptor_set_layout->texture); + + 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(obj); + + for(auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + { + VkDescriptorImageInfo image_info{}; + image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + image_info.imageView = self->view; + image_info.sampler = self->sampler; + + std::array 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_COMBINED_IMAGE_SAMPLER; + write_descriptors[0].pBufferInfo = nullptr; + write_descriptors[0].pImageInfo = &image_info; + write_descriptors[0].pTexelBufferView = nullptr; + + vkUpdateDescriptorSets( + BluCat::INT::core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); + } +} + +const CommandChain descriptor_loader{ + {&load_descriptor_set_pool, &unload_descriptor_set_pool}, + {&load_descriptor_sets, nullptr}, + {&load_data_to_descriptor_sets, nullptr} +}; + +} + +namespace BluCat::GRA +{ + +Texture::Texture(Font *font, const char* str) +{ + this->queue_family = + BluCat::INT::core.vk_device_with_swapchain-> + get_queue_family_with_presentation(); + + TextTextureBuilder text_builder(this, font, str); + text_loader.execute(&text_builder); + descriptor_loader.execute(this); +} + +Texture::Texture(const std::string &texture_path) +{ + this->queue_family = + BluCat::INT::core.vk_device_with_swapchain-> + get_queue_family_with_presentation(); + + ImageTextureBuilder texture_builder(this, texture_path); + image_loader.execute(&texture_builder); + descriptor_loader.execute(this); +} + +Texture::Texture(const char* texture_path): + Texture{std::string(texture_path)} +{ +} + +Texture::~Texture() +{ + ImageTextureBuilder texture_builder(this, ""); + image_loader.revert(&texture_builder); + descriptor_loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/texture.hpp b/src/blu_cat/gra/texture.hpp new file mode 100644 index 0000000..c3da8cf --- /dev/null +++ b/src/blu_cat/gra/texture.hpp @@ -0,0 +1,51 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_TEXTURE_H +#define BLU_CAT_GRA_TEXTURE_H 1 + +#include + +#include "vulkan.hpp" +#include "font.hpp" +#include "queue_family.hpp" + +namespace BluCat::GRA +{ + +struct Texture +{ + QueueFamily *queue_family; + + VkImage image; + VkSampler sampler; + VkImageView view; + VkDeviceMemory device_memory; + uint32_t width, height; + uint32_t mip_levels; + + VkDescriptorPool descriptor_pool; + std::vector descriptor_sets; + + Texture(Font *font, const char *str); + Texture(const std::string &texture_path); + Texture(const char* texture_path); + ~Texture(); +}; + +} + +#endif /* BLU_CAT_GRA_TEXTURE_H */ diff --git a/src/blu_cat/gra/uniform_buffer.cpp b/src/blu_cat/gra/uniform_buffer.cpp new file mode 100644 index 0000000..b176365 --- /dev/null +++ b/src/blu_cat/gra/uniform_buffer.cpp @@ -0,0 +1,89 @@ +/* + * Copyright 2022-2024 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 "uniform_buffer.hpp" + +#include +#include + +namespace BluCat::GRA +{ + +UniformBuffer::UniformBuffer(Device *device, VkDeviceSize data_size) +{ + this->device = device; + this->device_size = data_size; + this->buffer_usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + this->memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + try + { + BaseBuffer::loader.execute(static_cast(this)); + } + catch(const CommandError &command_error) + { + std::string error{"Could not initialize Vulkan uniform buffer → "}; + error += command_error.what(); + throw CommandError{error}; + } +} + +UniformBuffer::~UniformBuffer() +{ + BaseBuffer::loader.revert(static_cast(this)); +} + +UniformBuffer::UniformBuffer(UniformBuffer &&that) +{ + this->device = that.device; + this->buffer = that.buffer; + this->device_memory = that.device_memory; + this->device_size = that.device_size; + this->buffer_usage = that.buffer_usage; + this->memory_properties = that.memory_properties; + + that.buffer = VK_NULL_HANDLE; + that.device_memory = VK_NULL_HANDLE; +} + +UniformBuffer& +UniformBuffer::operator=(UniformBuffer &&that) +{ + this->device = that.device; + this->buffer = that.buffer; + this->device_memory = that.device_memory; + this->device_size = that.device_size; + this->buffer_usage = that.buffer_usage; + this->memory_properties = that.memory_properties; + + that.buffer = VK_NULL_HANDLE; + that.device_memory = VK_NULL_HANDLE; + + return *this; +} + +void +UniformBuffer::copy_data(void *ubo) +{ + void *data; + vkMapMemory(this->device->device, this->device_memory, 0, + this->device_size, 0, &data); + memcpy(data, ubo, this->device_size); + vkUnmapMemory(this->device->device, this->device_memory); +} + +} diff --git a/src/blu_cat/gra/uniform_buffer.hpp b/src/blu_cat/gra/uniform_buffer.hpp new file mode 100644 index 0000000..f37e100 --- /dev/null +++ b/src/blu_cat/gra/uniform_buffer.hpp @@ -0,0 +1,49 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_UNIFORM_BUFFER_H +#define BLU_CAT_GRA_UNIFORM_BUFFER_H 1 + +#include + +#include "vulkan.hpp" + +#include "base_buffer.hpp" + +namespace BluCat::GRA +{ + +// FIXME: this class need to delete or create custom copy constructors! +class UniformBuffer: public BaseBuffer +{ + UniformBuffer(const UniformBuffer &t) = delete; + UniformBuffer& + operator=(const UniformBuffer &t) = delete; + +public: + UniformBuffer(Device *device, VkDeviceSize data_size); + ~UniformBuffer(); + + UniformBuffer(UniformBuffer &&that); + UniformBuffer& + operator=(UniformBuffer &&that); + + void copy_data(void* ubo); +}; + +} + +#endif /* BLU_CAT_GRA_UNIFORM_BUFFER_H */ diff --git a/src/blu_cat/gra/uniform_data_object.hpp b/src/blu_cat/gra/uniform_data_object.hpp new file mode 100644 index 0000000..68a3fbe --- /dev/null +++ b/src/blu_cat/gra/uniform_data_object.hpp @@ -0,0 +1,80 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_UNIFORM_DATA_OBJECT_H +#define BLU_CAT_GRA_UNIFORM_DATA_OBJECT_H 1 + +#include "vulkan.hpp" +#include "skeletal_mesh_vertex.hpp" + +namespace BluCat::GRA +{ + +// UDO = "uniform data object" + +struct UDOView2D +{ + glm::mat4 proj; +}; + +struct UDOView3D +{ + glm::mat4 view; + glm::mat4 proj; +}; + +struct UDOWorld3D_Vert +{ + glm::vec4 ambient_light_color; +}; + +struct UDOWorld3D_Frag +{ + glm::vec3 directional_light_direction; + glm::vec4 directional_light_color; +}; + +struct UDOStaticModel +{ + glm::mat4 base_matrix; +}; + +struct UDOSkeletalModel +{ + glm::mat4 base_matrix; + glm::mat4 bone_matrices[SKELETAL_MESH_MAX_NUM_OF_BONES]; +}; + +struct UDOVector4D +{ + glm::vec4 vector; +}; + +struct UDOVector3D +{ + glm::vec3 vectors; +}; + +struct UDOSprite3D +{ + glm::vec3 position; + uint32_t padding; + glm::vec2 size; +}; + +} + +#endif /* BLU_CAT_GRA_UNIFORM_DATA_OBJECT_H */ diff --git a/src/blu_cat/gra/view_2d.cpp b/src/blu_cat/gra/view_2d.cpp new file mode 100644 index 0000000..948b145 --- /dev/null +++ b/src/blu_cat/gra/view_2d.cpp @@ -0,0 +1,160 @@ +/* + * Copyright 2022-2024 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 "view_2d.hpp" + +#include + +#include "../int/core.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_2d_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + try + { + self->ub_2d.reserve(BluCat::INT::core.vk_swapchain->images_count); + for(auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + self->ub_2d.emplace_back( + BluCat::INT::core.vk_device_with_swapchain, sizeof(BluCat::GRA::UDOView2D)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_2d_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + self->ub_2d.clear(); +} + +void +load_descriptor_sets_2d(void *obj) +{ + auto self = static_cast(obj); + + std::vector layouts( + BluCat::INT::core.vk_swapchain->images_count, + BluCat::INT::core.vk_descriptor_set_layout->view); + + 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_2d.resize(layouts.size()); + if(vkAllocateDescriptorSets( + BluCat::INT::core.vk_device_with_swapchain->device, &alloc_info, + self->descriptor_sets_2d.data()) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan descriptor sets for view."}; +} + +void +load_resources_to_descriptor_sets_2d(void *obj) +{ + auto self = static_cast(obj); + + for(auto i{0}; i < self->ub_2d.size(); i++) + { + VkDescriptorBufferInfo view_2d_info{}; + view_2d_info.buffer = self->ub_2d[i].buffer; + view_2d_info.offset = 0; + view_2d_info.range = sizeof(BluCat::GRA::UDOView2D); + + std::array write_descriptors{}; + write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[0].dstSet = self->descriptor_sets_2d[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 = &view_2d_info; + write_descriptors[0].pImageInfo = nullptr; + write_descriptors[0].pTexelBufferView = nullptr; + + vkUpdateDescriptorSets( + BluCat::INT::core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); + + BluCat::GRA::UDOView2D ubo_view_2d; + ubo_view_2d.proj = glm::ortho( + 0.0f, self->projection_width, + 0.0f, self->projection_height, + 0.0f, 100.0f); + self->ub_2d[i].copy_data(&ubo_view_2d); + } +} + +} + +namespace BluCat::GRA +{ + +const CommandChain View2D::loader{ + {&load_2d_uniform_buffer, &unload_2d_uniform_buffer} +}; + +const CommandChain View2D::descriptor_sets_loader{ + {&load_descriptor_sets_2d, nullptr}, + {&load_resources_to_descriptor_sets_2d, nullptr} +}; + +View2D::View2D( + glm::vec4 region, float projection_width, float projection_height): + projection_width{projection_width}, + projection_height{projection_height}, + region{region}, + descriptor_pool{VK_NULL_HANDLE}, + rectangles_to_draw{BluCat::INT::core.vk_swapchain->images_count}, + sprites_to_draw{BluCat::INT::core.vk_swapchain->images_count} +{ + loader.execute(this); +} + +View2D::~View2D() +{ + loader.revert(this); +} + +void +View2D::load_descriptor_sets(VkDescriptorPool descriptor_pool) +{ + if(this->descriptor_pool != VK_NULL_HANDLE) return; + + this->descriptor_pool = descriptor_pool; + descriptor_sets_loader.execute(this); +} + +void +View2D::unload_descriptor_sets() +{ + if(this->descriptor_pool == VK_NULL_HANDLE) return; + + this->descriptor_pool = VK_NULL_HANDLE; + descriptor_sets_loader.revert(this); +} + +} diff --git a/src/blu_cat/gra/view_2d.hpp b/src/blu_cat/gra/view_2d.hpp new file mode 100644 index 0000000..84b9f09 --- /dev/null +++ b/src/blu_cat/gra/view_2d.hpp @@ -0,0 +1,60 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_VIEW_2D_H +#define BLU_CAT_GRA_VIEW_2D_H 1 + +#include +#include +#include + +#include "vulkan.hpp" +#include "sprite_to_draw.hpp" +#include "rectangle.hpp" + +namespace BluCat::GRA +{ + +struct View2D +{ + glm::vec4 region; + float projection_width, projection_height; + + // FIXME: if these vectors get resized, they can cause a segmentation fault! + std::vector ub_2d; + + VkDescriptorPool descriptor_pool; + std::vector descriptor_sets_2d; + + std::vector> rectangles_to_draw; + std::vector> sprites_to_draw; + + View2D(glm::vec4 region, float projection_width, float projection_height); + virtual ~View2D(); + + void + virtual load_descriptor_sets(VkDescriptorPool descriptor_pool); + + void + virtual unload_descriptor_sets(); + +protected: + static const CommandChain loader, descriptor_sets_loader; +}; + +} + +#endif /* BLU_CAT_GRA_VIEW_2D_H */ diff --git a/src/blu_cat/gra/view_3d.cpp b/src/blu_cat/gra/view_3d.cpp new file mode 100644 index 0000000..dc310e3 --- /dev/null +++ b/src/blu_cat/gra/view_3d.cpp @@ -0,0 +1,155 @@ +/* + * Copyright 2022-2024 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 "view_3d.hpp" + +#include + +#include "../int/core.hpp" +#include "uniform_data_object.hpp" + +namespace +{ + +void +load_3d_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + try + { + self->ub_3d.reserve(BluCat::INT::core.vk_swapchain->images_count); + for(auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + self->ub_3d.emplace_back( + BluCat::INT::core.vk_device_with_swapchain, sizeof(BluCat::GRA::UDOView3D)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_3d_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + self->ub_3d.clear(); +} + +void +load_descriptor_sets_3d(void *obj) +{ + auto self = static_cast(obj); + + std::vector layouts( + BluCat::INT::core.vk_swapchain->images_count, + BluCat::INT::core.vk_descriptor_set_layout->view); + + 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_3d.resize(layouts.size()); + if(vkAllocateDescriptorSets( + BluCat::INT::core.vk_device_with_swapchain->device, &alloc_info, + self->descriptor_sets_3d.data()) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan descriptor sets for view."}; +} + +void +load_resources_to_descriptor_sets_3d(void *obj) +{ + auto self = static_cast(obj); + + for(auto i{0}; i < self->ub_3d.size(); i++) + { + VkDescriptorBufferInfo view_3d_info{}; + view_3d_info.buffer = self->ub_3d[i].buffer; + view_3d_info.offset = 0; + view_3d_info.range = sizeof(BluCat::GRA::UDOView3D); + + std::array write_descriptors{}; + write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[0].dstSet = self->descriptor_sets_3d[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 = &view_3d_info; + write_descriptors[0].pImageInfo = nullptr; + write_descriptors[0].pTexelBufferView = nullptr; + + vkUpdateDescriptorSets( + BluCat::INT::core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); + } +} + +const CommandChain loader{ + {&load_3d_uniform_buffer, &unload_3d_uniform_buffer} +}; + +const CommandChain descriptor_sets_loader{ + {&load_descriptor_sets_3d, nullptr}, + {&load_resources_to_descriptor_sets_3d, nullptr} +}; + +} + +namespace BluCat::GRA +{ + +View3D::View3D( + glm::vec4 region, float projection_width, float projection_height): + View2D{region, projection_width, projection_height}, + field_of_view{45.0f}, + camera_position{std::make_shared(0.0f, 0.0f, 0.0f)}, + camera_orientation{std::make_shared(0.0f, 0.0f, 0.0f, 0.0f)} +{ + ::loader.execute(this); +} + +View3D::~View3D() +{ + ::loader.revert(this); +} + +void +View3D::load_descriptor_sets(VkDescriptorPool descriptor_pool) +{ + if(this->descriptor_pool != VK_NULL_HANDLE) return; + + auto parent = dynamic_cast(this); + this->descriptor_pool = descriptor_pool; + View2D::descriptor_sets_loader.execute(parent); + ::descriptor_sets_loader.execute(this); +} + +void +View3D::unload_descriptor_sets() +{ + if(this->descriptor_pool == VK_NULL_HANDLE) return; + + auto parent = dynamic_cast(this); + this->descriptor_pool = VK_NULL_HANDLE; + ::descriptor_sets_loader.revert(this); + View2D::descriptor_sets_loader.revert(parent); +} + +} diff --git a/src/blu_cat/gra/view_3d.hpp b/src/blu_cat/gra/view_3d.hpp new file mode 100644 index 0000000..f09c70f --- /dev/null +++ b/src/blu_cat/gra/view_3d.hpp @@ -0,0 +1,48 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_VIEW_3D_H +#define BLU_CAT_GRA_VIEW_3D_H 1 + +#include "view_2d.hpp" + +namespace BluCat::GRA +{ + +struct View3D: public View2D +{ + float field_of_view; + // FIXME: if this vector get resized, it can cause a segmentation fault! + std::vector ub_3d; + + std::vector descriptor_sets_3d; + + std::shared_ptr camera_position; + std::shared_ptr camera_orientation; + + View3D(glm::vec4 region, float projection_width, float projection_height); + ~View3D(); + + void + load_descriptor_sets(VkDescriptorPool descriptor_pool); + + void + unload_descriptor_sets(); +}; + +} + +#endif /* BLU_CAT_GRA_VIEW_3D_H */ diff --git a/src/blu_cat/gra/vulkan.hpp b/src/blu_cat/gra/vulkan.hpp new file mode 100644 index 0000000..fcf6628 --- /dev/null +++ b/src/blu_cat/gra/vulkan.hpp @@ -0,0 +1,34 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_GRA_VULKAN_H +#define BLU_CAT_GRA_VULKAN_H 1 + +// GLM uses some definitions to control their behavior, so you should not +// include it directly. Instead, use this header. +#define GLM_ENABLE_EXPERIMENTAL +#define GLM_FORCE_RADIANS +#define GLM_FORCE_DEPTH_ZERO_TO_ONE + +#include +#include +#include +#include +#include + +#include + +#endif /* BLU_CAT_GRA_VULKAN_H */ diff --git a/src/blu_cat/int/core.cpp b/src/blu_cat/int/core.cpp new file mode 100644 index 0000000..eafdab7 --- /dev/null +++ b/src/blu_cat/int/core.cpp @@ -0,0 +1,503 @@ +/* + * Copyright 2022-2024 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 "core.hpp" + +namespace +{ + +#ifdef DEBUG +VKAPI_ATTR VkBool32 VKAPI_CALL +vk_debug_callback( + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_type, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, + void* _obj) +{ + // Set level. + Log::Level log_level; + switch(message_severity) + { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + log_level = Log::Level::Trace; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + log_level = Log::Level::Information; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + log_level = Log::Level::Warning; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + default: + log_level = Log::Level::Error; + break; + } + + // Log message. + BluCat::INT::core.log.message(log_level, callback_data->pMessage); + + return VK_FALSE; +} +#endif + +void +load_threads(void *obj) +{ + auto num_threads{std::thread::hardware_concurrency() - 1}; + for(auto i{0}; i < num_threads; i++) + BluCat::INT::core.threads.emplace_back( + BluCat::INT::core.workers.emplace_back(&BluCat::INT::core.job_queue)); +} + +void +unload_threads(void *obj) +{ + BluCat::INT::core.job_queue.stop(); + for(auto &t: BluCat::INT::core.threads) t.join(); +} + +void +load_fps(void *obj) +{ + using namespace std::chrono; + + BluCat::INT::core.max_frame_duration = + duration(1000 / BluCat::INT::core.fps); + // FIXME: actually calculates the real delta time. + BluCat::INT::core.delta_time = 1.0f / BluCat::INT::core.fps; +} + +void +load_font_library(void *obj) +{ + FT_Error error{FT_Init_FreeType(&BluCat::INT::core.font_library)}; + if(error) throw CommandError{"Failed to open the FreeType library."}; +} + +void +unload_font_library(void *obj) +{ + FT_Done_FreeType(BluCat::INT::core.font_library); +} + +#ifdef DEBUG +void +load_vk_debug_callback(void *obj) +{ + PFN_vkCreateDebugUtilsMessengerEXT debug_messenger; + + // A Vulkan instance extension named VK_EXT_debug_utils and a Vulkan instance + // layer named VK_LAYER_LUNARG_standard_validation are required to enable + // this callback. These instance extension and instance layer are loaded at + // Instance::load_blucat_instance. + VkDebugUtilsMessengerCreateInfoEXT create_info; + create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + create_info.pNext = nullptr; + create_info.messageSeverity = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + create_info.pfnUserCallback = vk_debug_callback; + create_info.pUserData = nullptr; + create_info.flags = 0; + + debug_messenger = (PFN_vkCreateDebugUtilsMessengerEXT) + vkGetInstanceProcAddr(BluCat::INT::core.vk_instance, + "vkCreateDebugUtilsMessengerEXT"); + + if(debug_messenger(BluCat::INT::core.vk_instance, &create_info, nullptr, + &BluCat::INT::core.vk_callback) != VK_SUCCESS) + CommandError{"Failed to setup debug callback for Vulkan."}; +} + +void +unload_vk_debug_callback(void *obj) +{ + PFN_vkDestroyDebugUtilsMessengerEXT debug_messenger; + + debug_messenger = (PFN_vkDestroyDebugUtilsMessengerEXT) + vkGetInstanceProcAddr(BluCat::INT::core.vk_instance, + "vkDestroyDebugUtilsMessengerEXT"); + + debug_messenger(BluCat::INT::core.vk_instance, BluCat::INT::core.vk_callback, nullptr); +} +#endif + +void +load_devices(void *obj) +{ + uint32_t devices_count; + std::vector vk_physical_devices; + + // Enumerate physical devices + { + vkEnumeratePhysicalDevices( + BluCat::INT::core.vk_instance, &devices_count, nullptr); + if(devices_count < 1) + CommandError{"Failed to find GPUs with Vulkan support."}; + vk_physical_devices.resize(devices_count); + vkEnumeratePhysicalDevices( + BluCat::INT::core.vk_instance, &devices_count, vk_physical_devices.data()); + } + +#ifdef DEBUG + BluCat::INT::core.log.message(Log::Level::Trace, "Physical devices properties"); +#endif + + BluCat::INT::core.vk_devices.reserve(devices_count); + for(auto i = 0; i < devices_count; i++) + { + // Use swapchain on first device. + if(i == 0) + { + BluCat::INT::core.vk_devices.emplace_back(vk_physical_devices[i], true); + BluCat::INT::core.vk_device_with_swapchain = &BluCat::INT::core.vk_devices[i]; + } + else + BluCat::INT::core.vk_devices.emplace_back(vk_physical_devices[i], false); + } +} + +void +unload_devices(void *obj) +{ + BluCat::INT::core.vk_devices.clear(); +} + +static void +load_swapchain(void *obj) +{ + try { BluCat::INT::core.vk_swapchain = new BluCat::GRA::Swapchain(); } + catch(const CommandError &error) + { + std::string error_message{"Failed to create swapchain → "}; + error_message += error.what(); + throw CommandError{error_message}; + } +} + +void +unload_swapchain(void *obj) +{ + delete BluCat::INT::core.vk_swapchain; +} + +void +load_framebuffer(void *obj) +{ + try + { + BluCat::INT::core.vk_framebuffer = new BluCat::GRA::Framebuffer(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create framebuffer."}; + } +} + +void +unload_framebuffer(void *obj) +{ + delete BluCat::INT::core.vk_framebuffer; +} + +void +load_render_pass(void *obj) +{ + try + { + BluCat::INT::core.vk_render_pass = new BluCat::GRA::RenderPass(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create render pass."}; + } +} + +void +unload_render_pass(void *obj) +{ + delete BluCat::INT::core.vk_render_pass; +} + +void +load_descriptor_set_layout(void *obj) +{ + try + { + BluCat::INT::core.vk_descriptor_set_layout = new BluCat::GRA::DescriptorSetLayout(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create descriptor set layouts."}; + } +} + +void +unload_descriptor_set_layout(void *obj) +{ + delete BluCat::INT::core.vk_descriptor_set_layout; +} + +void +load_graphics_pipeline_3d_layout(void *obj) +{ + try + { + BluCat::INT::core.vk_graphics_pipeline_3d_layout = + new BluCat::GRA::GraphicsPipeline3DLayout(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 3d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_3d_layout(void *obj) +{ + delete BluCat::INT::core.vk_graphics_pipeline_3d_layout; +} + +void +load_graphics_pipeline_2d_solid_layout(void *obj) +{ + try + { + BluCat::INT::core.vk_graphics_pipeline_2d_solid_layout = + new BluCat::GRA::GraphicsPipeline2DSolidLayout(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_2d_solid_layout(void *obj) +{ + delete BluCat::INT::core.vk_graphics_pipeline_2d_solid_layout; +} + +void +load_graphics_pipeline_2d_wired_layout(void *obj) +{ + try + { + BluCat::INT::core.vk_graphics_pipeline_2d_wired_layout = + new BluCat::GRA::GraphicsPipeline2DWiredLayout(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_2d_wired_layout(void *obj) +{ + delete BluCat::INT::core.vk_graphics_pipeline_2d_wired_layout; +} + +void +load_light(void *obj) +{ + try + { + BluCat::INT::core.vk_light = new BluCat::GRA::Light(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to descriptor sets for light."}; + } +} + +void +unload_light(void *obj) +{ + delete BluCat::INT::core.vk_light; +} + +void +load_graphics_pipeline_3d(void *obj) +{ + try + { + BluCat::INT::core.vk_graphics_pipeline_3d = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 3d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_3d(void *obj) +{ + BluCat::INT::core.vk_graphics_pipeline_3d = nullptr; +} + +void +load_graphics_pipeline_3d_skeletal(void *obj) +{ + try + { + BluCat::INT::core.vk_graphics_pipeline_3d_skeletal = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 3d skeletal graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_3d_skeletal(void *obj) +{ + BluCat::INT::core.vk_graphics_pipeline_3d_skeletal = nullptr; +} + +void +load_graphics_pipeline_sprite_3d(void *obj) +{ + try + { + BluCat::INT::core.vk_graphics_pipeline_sprite_3d = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create sprite 3d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_sprite_3d(void *obj) +{ + BluCat::INT::core.vk_graphics_pipeline_sprite_3d = nullptr; +} + +void +load_graphics_pipeline_2d_solid(void *obj) +{ + try + { + BluCat::INT::core.vk_graphics_pipeline_2d_solid = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_2d_solid(void *obj) +{ + BluCat::INT::core.vk_graphics_pipeline_2d_solid = nullptr; +} + +void +load_graphics_pipeline_2d_wired(void *obj) +{ + try + { + BluCat::INT::core.vk_graphics_pipeline_2d_wired = + std::make_unique(); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create 2d graphics pipeline."}; + } +} + +void +unload_graphics_pipeline_2d_wired(void *obj) +{ + BluCat::INT::core.vk_graphics_pipeline_2d_wired = nullptr; +} + +void +load_renderer(void *obj) +{ + try + { + glm::vec4 region( + 0.f, 0.f, + static_cast(BluCat::INT::core.display_width), + static_cast(BluCat::INT::core.display_height)); + BluCat::INT::core.vk_renderer = new BluCat::GRA::Renderer( + {}, + {std::make_shared(region, region.z, region.w)}); + } + catch(const CommandError &e) + { + throw CommandError{"Failed to create renderer."}; + } +} + +void +unload_renderer(void *obj) +{ + delete BluCat::INT::core.vk_renderer; +} + +} + +namespace BluCat::INT +{ + +std::random_device random_seed; +std::mt19937 random_number_generator; + +const CommandChain Core::loader{ + {&load_threads, &unload_threads}, + {&load_fps, nullptr}, + {&load_font_library, &unload_font_library}, +#ifdef DEBUG + {&load_vk_debug_callback, &unload_vk_debug_callback}, +#endif + {&load_devices, &unload_devices}, + {&load_swapchain, &unload_swapchain}, + + {&load_render_pass, &unload_render_pass}, + {&load_framebuffer, &unload_framebuffer}, + {&load_descriptor_set_layout, &unload_descriptor_set_layout}, + {&load_graphics_pipeline_3d_layout, + &unload_graphics_pipeline_3d_layout}, + {&load_graphics_pipeline_2d_solid_layout, + &unload_graphics_pipeline_2d_solid_layout}, + {&load_graphics_pipeline_2d_wired_layout, + &unload_graphics_pipeline_2d_wired_layout}, + {&load_light, &unload_light}, + {&load_graphics_pipeline_3d_skeletal, + &unload_graphics_pipeline_3d_skeletal}, + {&load_graphics_pipeline_3d, &unload_graphics_pipeline_3d}, + {&load_graphics_pipeline_sprite_3d, + &unload_graphics_pipeline_sprite_3d}, + {&load_graphics_pipeline_2d_solid, &unload_graphics_pipeline_2d_solid}, + {&load_graphics_pipeline_2d_wired, &unload_graphics_pipeline_2d_wired}, + {&load_renderer, &unload_renderer}, +}; + +Core core; + +} diff --git a/src/blu_cat/int/core.hpp b/src/blu_cat/int/core.hpp new file mode 100644 index 0000000..0900b81 --- /dev/null +++ b/src/blu_cat/int/core.hpp @@ -0,0 +1,123 @@ +/* + * Copyright 2022-2024 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 BLU_CAT_INT_CORE_H +#define BLU_CAT_INT_CORE_H 1 + +#define BLU_CAT_VERSION_MAJOR 0 +#define BLU_CAT_VERSION_MINOR 1 +#define BLU_CAT_VERSION_PATCH 0 + +#include +#include +#include +#include + +#include "../com/command.hpp" +#include "../com/job_queue.hpp" +#include "../com/worker.hpp" +#include "../gra/device.hpp" +#include "../gra/descriptor_set_layout.hpp" +#include "../gra/framebuffer.hpp" +#include "../gra/graphics_pipeline_2d_solid_layout.hpp" +#include "../gra/graphics_pipeline_2d_wired_layout.hpp" +#include "../gra/graphics_pipeline_2d_solid.hpp" +#include "../gra/graphics_pipeline_2d_wired.hpp" +#include "../gra/graphics_pipeline_3d_layout.hpp" +#include "../gra/graphics_pipeline_3d.hpp" +#include "../gra/graphics_pipeline_3d_skeletal.hpp" +#include "../gra/graphics_pipeline_sprite_3d.hpp" +#include "../gra/light.hpp" +#include "../gra/log.hpp" +#include "../gra/render_pass.hpp" +#include "../gra/renderer.hpp" +#include "../gra/swapchain.hpp" +#include "../gra/vulkan.hpp" + +namespace BluCat::INT +{ + +extern std::random_device random_seed; +extern std::mt19937 random_number_generator; + +struct Core +{ + static const CommandChain loader; + + Log::Logger log; + + COM::JobQueue job_queue; + std::vector workers; + std::vector threads; + + /// Text displayed in the game window. + std::string game_name; + + /** + * @{ + * This is the ammount of pixel that the games uses when rendering to the + * screen. + */ + uint32_t display_width, display_height; + /// @} + + int game_version_major, game_version_minor, game_version_patch; + + uint32_t fps; + std::chrono::duration max_frame_duration; + float delta_time; + + FT_Library font_library; + + VkSurfaceKHR window_surface; + VkInstance vk_instance; + +#ifdef DEBUG + VkDebugUtilsMessengerEXT vk_callback; +#endif + + // Vulkan devices. + std::vector vk_devices; + BluCat::GRA::Device *vk_device_with_swapchain; + BluCat::GRA::Swapchain *vk_swapchain; + + BluCat::GRA::Framebuffer *vk_framebuffer; + BluCat::GRA::RenderPass *vk_render_pass; + BluCat::GRA::DescriptorSetLayout *vk_descriptor_set_layout; + BluCat::GRA::GraphicsPipeline3DLayout *vk_graphics_pipeline_3d_layout; + BluCat::GRA::GraphicsPipeline2DSolidLayout + *vk_graphics_pipeline_2d_solid_layout; + BluCat::GRA::GraphicsPipeline2DWiredLayout + *vk_graphics_pipeline_2d_wired_layout; + BluCat::GRA::Light *vk_light; + std::unique_ptr vk_graphics_pipeline_3d; + std::unique_ptr + vk_graphics_pipeline_3d_skeletal; + std::unique_ptr + vk_graphics_pipeline_sprite_3d; + std::unique_ptr + vk_graphics_pipeline_2d_solid; + std::unique_ptr + vk_graphics_pipeline_2d_wired; + + BluCat::GRA::Renderer *vk_renderer; +}; + +extern Core core; + +} + +#endif /* BLU_CAT_INT_CORE_H */ diff --git a/src/blucat/animation.cpp b/src/blucat/animation.cpp deleted file mode 100644 index b4daeef..0000000 --- a/src/blucat/animation.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2022-2024 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 "animation.hpp" - -namespace BluCat -{ - -Bone::Bone(glm::mat4 offset_matrix): - offset_matrix{offset_matrix} -{ -} - -} diff --git a/src/blucat/animation.hpp b/src/blucat/animation.hpp deleted file mode 100644 index b1ddd06..0000000 --- a/src/blucat/animation.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_ANIMATION_H -#define CANDY_GEAR_BLUCAT_ANIMATION_H 1 - -#include - -#include "vulkan.hpp" -#include "animation/frame.hpp" - -namespace BluCat -{ - -struct Bone -{ - glm::mat4x4 offset_matrix; - - Bone(glm::mat4 offset_matrix); -}; - -struct BoneTransform -{ - uint32_t bone_id; - Channel positions; - Channel rotations; - Channel scales; -}; - -struct Animation -{ - std::vector bone_transforms; - float final_time; -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_ANIMATION_H */ diff --git a/src/blucat/animation/frame.hpp b/src/blucat/animation/frame.hpp deleted file mode 100644 index 663483d..0000000 --- a/src/blucat/animation/frame.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_FRAME_H -#define CANDY_GEAR_BLUCAT_FRAME_H 1 - -#include - -#include "../vulkan.hpp" - -namespace BluCat -{ - -template -struct Frame -{ - const T value; - const float timestamp; - - Frame(T value, float timestamp): - value{value}, - timestamp{timestamp} - { - } - -}; - -template -struct Channel -{ - int current_index{0}; - std::vector> key_frames; - - inline glm::mat4 - interpolate( - float animation_time, - glm::mat4 (*single_frame)(T frame), - glm::mat4 (*multiple_frames)(T current_frame, T next_frame, float scale)) - { - if(this->key_frames.size() == 1) - return single_frame(this->key_frames[0].value); - else - { - while(animation_time > this->key_frames[current_index].timestamp) - this->current_index++; - - float scale_factor; - Frame *previous_frame; - Frame *next_frame{&(this->key_frames[this->current_index])}; - if(this->current_index == 0) - { - previous_frame = &(this->key_frames[this->key_frames.size() - 1]); - float midway_length{animation_time - 0}; - float frames_diff{next_frame->timestamp - 0}; - scale_factor = midway_length / frames_diff; - } - else - { - previous_frame = &(this->key_frames[this->current_index - 1]); - float midway_length{animation_time - previous_frame->timestamp}; - float frames_diff{next_frame->timestamp - previous_frame->timestamp}; - scale_factor = midway_length / frames_diff; - } - - return multiple_frames( - previous_frame->value, next_frame->value, scale_factor); - } - }; -}; - -} -#endif /* CANDY_GEAR_BLUCAT_FRAME_H */ diff --git a/src/blucat/base_buffer.cpp b/src/blucat/base_buffer.cpp deleted file mode 100644 index 762c89a..0000000 --- a/src/blucat/base_buffer.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2022-2024 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 "base_buffer.hpp" - -namespace BluCat -{ - -const CommandChain BaseBuffer::loader{ - {&BaseBuffer::load_buffer, &BaseBuffer::unload_buffer}, - {&BaseBuffer::load_memory, &BaseBuffer::unload_memory} -}; - -void -BaseBuffer::load_buffer(void *obj) -{ - auto self = static_cast(obj); - - VkBufferCreateInfo buffer_info = {}; - buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.pNext = nullptr; - buffer_info.flags = 0; - buffer_info.size = self->device_size; - buffer_info.usage = self->buffer_usage; - buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - buffer_info.queueFamilyIndexCount = 0; - buffer_info.pQueueFamilyIndices = nullptr; - - if(vkCreateBuffer( - self->device->device, &buffer_info, nullptr, &self->buffer) - != VK_SUCCESS) - throw CommandError{"Failed to create vertex buffer."}; -} - -void -BaseBuffer::unload_buffer(void *obj) -{ - auto self = static_cast(obj); - - if(self->buffer != VK_NULL_HANDLE) - vkDestroyBuffer(self->device->device, self->buffer, nullptr); -} - -void -BaseBuffer::load_memory(void *obj) -{ - auto self = static_cast(obj); - - VkMemoryRequirements memory_requirements; - vkGetBufferMemoryRequirements( - self->device->device, self->buffer, &memory_requirements); - - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties( - self->device->physical_device, &memory_properties); - - VkMemoryAllocateInfo alloc_info = {}; - alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc_info.pNext = nullptr; - alloc_info.allocationSize = memory_requirements.size; - if(!self->device->select_memory_type( - &alloc_info.memoryTypeIndex, &memory_requirements, - self->memory_properties)) - throw CommandError{"Could not allocate memory for Vulkan vertex buffer."}; - - if(vkAllocateMemory(self->device->device, &alloc_info, nullptr, - &self->device_memory) != VK_SUCCESS) - throw CommandError{"Could not allocate memory for Vulkan vertex buffer."}; - - vkBindBufferMemory( - self->device->device, self->buffer, self->device_memory, 0); -} - -void -BaseBuffer::unload_memory(void *obj) -{ - auto self = static_cast(obj); - - if(self->device_memory != VK_NULL_HANDLE) - vkFreeMemory(self->device->device, self->device_memory, nullptr); -} - -} diff --git a/src/blucat/base_buffer.hpp b/src/blucat/base_buffer.hpp deleted file mode 100644 index cdc9f9c..0000000 --- a/src/blucat/base_buffer.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_BASE_BUFFER_H -#define CANDY_GEAR_BLUCAT_BASE_BUFFER_H 1 - -#include "command.hpp" -#include "vulkan.hpp" -#include "device.hpp" - -namespace BluCat -{ - -class BaseBuffer -{ - public: - virtual ~BaseBuffer(){}; - - VkBuffer buffer; - VkDeviceMemory device_memory; - VkDeviceSize device_size; - VkBufferUsageFlags buffer_usage; - VkMemoryPropertyFlags memory_properties; - - protected: - static const CommandChain loader; - - Device *device; - - static void - load_buffer(void *obj); - static void - unload_buffer(void *obj); - - static void - load_memory(void *obj); - static void - unload_memory(void *obj); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_BASE_BUFFER_H */ diff --git a/src/blucat/binary_reader.cpp b/src/blucat/binary_reader.cpp deleted file mode 100644 index 14fc39c..0000000 --- a/src/blucat/binary_reader.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2022-2024 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 "binary_reader.hpp" - -#include - -namespace -{ - -union IntAndFloat32bit{ - uint32_t i; - float f; -}; - -union IntAndFloat64bit{ - uint64_t i; - double f; -}; - -} - -BinaryReader::BinaryReader(std::string file_path): - _pointer{0} -{ - std::ifstream file(file_path, std::ios::binary | std::ios::ate); - if(!file.is_open()) - { - std::string error{"failed to open file: "}; - error += file_path; - throw std::runtime_error{error}; - } - - this->_size = file.tellg(); - file.seekg(0); - this->data = new uint8_t[this->_size]; - file.read((char*)data, this->_size); -} - -BinaryReader::BinaryReader(const char *file_path): - BinaryReader{std::string(file_path)} -{ -} - -BinaryReader::~BinaryReader() -{ - delete[] this->data; -} - -uint8_t -BinaryReader::read_ui8() -{ - return this->data[this->_pointer++]; -} - -uint32_t -BinaryReader::read_ui32() -{ - uint8_t b1{this->data[_pointer++]}, b2{this->data[_pointer++]}, - b3{this->data[_pointer++]}, b4{this->data[_pointer++]}; - - return b1 << 24 | b2 << 16 | b3 << 8 | b4; -} - -uint64_t -BinaryReader::read_ui64() -{ - uint8_t b1{this->data[_pointer++]}, b2{this->data[_pointer++]}, - b3{this->data[_pointer++]}, b4{this->data[_pointer++]}, - b5{this->data[_pointer++]}, b6{this->data[_pointer++]}, - b7{this->data[_pointer++]}, b8{this->data[_pointer++]}; - - return (uint64_t)b1 << 56 | (uint64_t)b2 << 48 | (uint64_t)b3 << 40 | - (uint64_t)b4 << 32 | (uint64_t)b5 << 24 | (uint64_t)b6 << 16 | - (uint64_t)b7 << 8 | (uint64_t)b8; -} - -float -BinaryReader::read_float() -{ - IntAndFloat32bit num; - num.i = read_ui32(); - - return num.f; -} - -double -BinaryReader::read_double() -{ - IntAndFloat64bit num; - num.i = read_ui64(); - - return num.f; -} - -glm::vec2 -BinaryReader::read_vec2() -{ - IntAndFloat32bit x{read_ui32()}, y{read_ui32()}; - - return glm::vec2{x.f, y.f}; -} - -glm::vec3 -BinaryReader::read_vec3() -{ - IntAndFloat32bit x{read_ui32()}, y{read_ui32()}, z{read_ui32()}; - - return glm::vec3{x.f, y.f, z.f}; -} - -glm::quat -BinaryReader::read_quat() -{ - IntAndFloat32bit w{read_ui32()}, x{read_ui32()}, y{read_ui32()}, - z{read_ui32()}; - - return glm::quat{w.f, x.f, y.f, z.f}; -} - -glm::mat4 -BinaryReader::read_mat4() -{ - glm::mat4 matrix; - float *offset_matrix_data{glm::value_ptr(matrix)}; - - for(int i{0}; i < 16; i++) - { - IntAndFloat32bit num; - num.i = read_ui32(); - offset_matrix_data[i] = num.f; - } - - return matrix; -} - -void -BinaryReader::read_chars(char *str, int size) -{ - for(int i{0}; i < size; i++) - str[i] = (char)data[this->_pointer++]; -} - diff --git a/src/blucat/binary_reader.hpp b/src/blucat/binary_reader.hpp deleted file mode 100644 index 1995402..0000000 --- a/src/blucat/binary_reader.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2022-2024 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 -#include - -#include "vulkan.hpp" - -class BinaryReader -{ - int _pointer; - int _size; - uint8_t *data; - -public: - - BinaryReader(const std::string file_path); - BinaryReader(const char *file_path); - ~BinaryReader(); - - inline int - pointer(){return this->_pointer;}; - - inline int - size(){return this->_size;}; - - uint8_t - read_ui8(); - - uint32_t - read_ui32(); - - uint64_t - read_ui64(); - - float - read_float(); - - double - read_double(); - - glm::vec2 - read_vec2(); - - glm::vec3 - read_vec3(); - - glm::quat - read_quat(); - - glm::mat4 - read_mat4(); - - void - read_chars(char *str, int size); -}; diff --git a/src/blucat/character.cpp b/src/blucat/character.cpp deleted file mode 100644 index 220295d..0000000 --- a/src/blucat/character.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2022-2024 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 "character.hpp" - -#include "command.hpp" -#include "core.hpp" -#include "font.hpp" -#include "image.hpp" -#include "source_buffer.hpp" - -namespace -{ - -struct CharacterBuilder -{ - BluCat::Character *character; - FT_Face face; - uint32_t character_code; - - CharacterBuilder( - BluCat::Character *character, FT_Face face, uint32_t character_code); -}; - -CharacterBuilder::CharacterBuilder( - BluCat::Character *character, FT_Face face, uint32_t character_code): - character{character}, - face{face}, - character_code{character_code} -{ -} - -// TODO: creating one image with one device memory for each character is -// ineficient -void -load_image(void *obj) -{ - auto self = static_cast(obj); - - FT_Error error; - std::vector source_image_raw; - const int num_channels = 4; // all images are converted to RGBA - auto glyph_index{FT_Get_Char_Index(self->face, self->character_code)}; - - error = FT_Load_Glyph(self->face, glyph_index, FT_LOAD_DEFAULT); - if(error) throw CommandError{"failed to load glyph"}; - - error = FT_Render_Glyph(self->face->glyph, FT_RENDER_MODE_NORMAL); - if(error) throw CommandError{"failed to render glyph"}; - - self->character->bearing_x = self->face->glyph->bitmap_left; - self->character->bearing_y = self->face->glyph->bitmap_top; - self->character->advance = (self->face->glyph->advance.x >> 6); - self->character->width = self->face->glyph->bitmap.width; - self->character->height = self->face->glyph->bitmap.rows; - self->character->mip_levels = 1; - - // Character is a white-space. - if(self->character->width <= 0) - { - self->character->image = VK_NULL_HANDLE; - self->character->device_memory = VK_NULL_HANDLE; - - return; - } - - auto image_size{static_cast( - self->face->glyph->bitmap.width * - self->face->glyph->bitmap.rows * num_channels)}; - - { // Create the data for the image buffer - source_image_raw.resize(image_size, 0); - - for(auto y{0}; y < self->face->glyph->bitmap.width; y++) - { - for(auto x{0}; x < self->face->glyph->bitmap.rows; x++) - { - auto image_coord = y * self->face->glyph->bitmap.rows * num_channels + - x * num_channels; - auto glyph_coord = y * self->face->glyph->bitmap.rows + x; - // Red - source_image_raw[image_coord] = 255; - // Green - source_image_raw[image_coord + 1] = 255; - // Blue - source_image_raw[image_coord + 2] = 255; - // Alpha - source_image_raw[image_coord + 3] = - self->face->glyph->bitmap.buffer[glyph_coord]; - } - } - } - - BluCat::SourceBuffer source_image_buffer{ - BluCat::core.vk_device_with_swapchain, source_image_raw.data(), - image_size}; - - { // Create Vulkan image. - try - { - VkExtent3D vk_extent3d; - vk_extent3d.width = self->face->glyph->bitmap.width; - vk_extent3d.height = self->face->glyph->bitmap.rows; - vk_extent3d.depth = 1; - - BluCat::Image::create( - BluCat::core.vk_device_with_swapchain, - &self->character->image, - &self->character->device_memory, - VK_FORMAT_R8G8B8A8_UNORM, - vk_extent3d, - self->character->mip_levels, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - } - catch(BluCat::Image::Error error) - { - throw CommandError{error.what()}; - } - } - - { // Copy image from buffer into image. - auto queue_family{BluCat::core.vk_device_with_swapchain-> - get_queue_family_with_presentation()}; - auto queue{queue_family->get_queue()}; - BluCat::CommandPool command_pool{queue_family, 1}; - VkCommandBuffer vk_command_buffer{command_pool.command_buffers[0]}; - - queue.submit_one_time_command(vk_command_buffer, [&](){ - BluCat::Image::move_image_state( - vk_command_buffer, self->character->image, VK_FORMAT_R8G8B8A8_UNORM, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT); - - VkBufferImageCopy image_copy; - image_copy.bufferOffset = 0; - image_copy.bufferRowLength = 0; - image_copy.bufferImageHeight = 0; - image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_copy.imageSubresource.mipLevel = 0; - image_copy.imageSubresource.baseArrayLayer = 0; - image_copy.imageSubresource.layerCount = 1; - image_copy.imageOffset = {0, 0, 0}; - image_copy.imageExtent = { - self->character->width, self->character->height, 1}; - - vkCmdCopyBufferToImage( - vk_command_buffer, source_image_buffer.buffer, self->character->image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); - - BluCat::Image::move_image_state( - vk_command_buffer, self->character->image, VK_FORMAT_R8G8B8A8_UNORM, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - }); - } -} - -void -unload_image(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyImage( - BluCat::core.vk_device_with_swapchain->device, self->character->image, - nullptr); - vkFreeMemory( - BluCat::core.vk_device_with_swapchain->device, - self->character->device_memory, nullptr); -} - -const CommandChain loader{ - {&load_image, &unload_image} -}; - -} - -namespace BluCat -{ - -Character::Character(FT_Face face, uint32_t character_code) -{ - CharacterBuilder character_builder(this, face, character_code); - loader.execute(&character_builder); -} - -Character::~Character() -{ - CharacterBuilder character_builder(this, nullptr, 0); - loader.revert(&character_builder); -} - -std::vector -Character::str_to_unicode(const char* str) -{ - std::vector unicode_text; - int text_width{0}; - int text_height{0}; - - { // Reserve memory - int size{0}; - for(auto i{0}; str[i] != '\0'; i++) - if((str[i] & 0b11000000) != 0b10000000) size++; - unicode_text.reserve(size); - } - - for(auto i{0}; str[i] != '\0'; i++) - { - int num_bytes; - uint32_t codepoint{0}; - - if(str[i] >= 0 && str[i] < 127) - { // Normal ASCI character, 1-byte. - num_bytes = 1; - codepoint = str[i]; - } - else if((str[i] & 0xE0) == 0xC0) - { // 2-byte character. - num_bytes = 2; - codepoint += ((str[i] & 0b00011111) << 6); - } - else if((str[i] & 0xF0) == 0xE0) - { // 3-byte character. - num_bytes = 3; - codepoint += ((str[i] & 0b00001111) << 12); - } - else if((str[i] & 0xF8) == 0xF0) - { // 4-byte character. - num_bytes = 4; - codepoint += ((str[i] & 0b00000111) << 18); - } - else - { // FIXME: Add support to 5-byte and 6-byte characters. - } - - switch (num_bytes) - { - case 4: - i++; - codepoint += ((str[i] & 0b00111111) << 12); - case 3: - i++; - codepoint += ((str[i] & 0b00111111) << 6); - case 2: - i++; - codepoint += (str[i] & 0b00111111); - case 1: - default: - break; - } - - unicode_text.push_back(codepoint); - } - - return unicode_text; -} - -} diff --git a/src/blucat/character.hpp b/src/blucat/character.hpp deleted file mode 100644 index 9d0829f..0000000 --- a/src/blucat/character.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_CHARACTER_H -#define CANDY_GEAR_BLUCAT_CHARACTER_H 1 - -#include -#include FT_FREETYPE_H - -#include "vulkan.hpp" - -#include - -namespace BluCat -{ - -struct Character -{ - VkImage image; - VkDeviceMemory device_memory; - int32_t bearing_y, bearing_x; - uint32_t width, height, advance, mip_levels; - - Character(FT_Face face, uint32_t character_code); - ~Character(); - - Character(Character const&) = delete; - Character& operator=(Character const&) = delete; - - static std::vector - str_to_unicode(const char* str); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_CHARACTER_H */ diff --git a/src/blucat/command.cpp b/src/blucat/command.cpp deleted file mode 100644 index a1d3240..0000000 --- a/src/blucat/command.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 - -#include "command.hpp" - -CommandError::CommandError(const std::string &m): - error(m) -{ -} - -CommandError::CommandError(const char &m): - CommandError{std::string{m}} -{ -} - -const char* CommandError::what() const noexcept -{ - return this->error.c_str(); -} - -CommandChain::CommandChain(std::initializer_list commands) -{ - for(auto c: commands) this->add(c); -} - -void -CommandChain::partial_revert(void *obj, int32_t step) const -{ - // Already unloaded, nothing to do. - if(step <= 0) return; - - for(; step > 0; step--) - { - auto command = this->_commands[step -1].undo_command; - if(command != nullptr) command(obj); - } -} - -void -CommandChain::add(const Command &c) -{ - this->_commands.push_back(c); -} - -void -CommandChain::execute(void *obj) const -{ - for(auto i{0}; i < this->_commands.size(); i++) - { - try { this->_commands[i].do_command(obj); } - catch(const CommandError &error) - { - this->partial_revert(obj, i); - throw; - } - } -} - -void -CommandChain::revert(void *obj) const -{ - this->partial_revert(obj, this->_commands.size()); -} diff --git a/src/blucat/command.hpp b/src/blucat/command.hpp deleted file mode 100644 index 47552a5..0000000 --- a/src/blucat/command.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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_COMMAND_CHAIN_H -#define CANDY_GEAR_COMMAND_CHAIN_H 1 - -#include -#include -#include -#include -#include - -class CommandChain; - -struct CommandError: public std::exception -{ - CommandError(const std::string &m); - CommandError(const char &m); - - const char* what() const noexcept; - -private: - std::string error; -}; - -/** - * Stores a reversible action. - */ -struct Command -{ - void (*do_command)(void *obj); - void (*undo_command)(void *obj); -}; - -/** - * Stores a sequence of functions that must be executed and rolled back in - * order. - * - * For example, if the variable _commands contain A→B→C→D→E, it will load A, - * then B, then C, etc. If D fails, it unloads C, then B, then A. - */ -class CommandChain -{ - std::vector _commands; - - void - partial_revert(void *obj, int32_t step) const; - -public: - CommandChain(std::initializer_list commands); - -/** - * Adds a reversible action to the command. The first action added is the first - * to de executed the last rolled back, and so on. Those functions are stored - * inside _commands. - * - * @param[unload] the undo/rollback action, if the action do not need a - * rollback, this pointer can be set to null. - */ - void - add(const Command &c); - -/** - * Execute all of the load functions in the _commands. If one of them fails, - * roll back everything inside _commands. - * @return true on success and false on fail. - */ - void - execute(void *obj) const; - -/** - * Roll back all loaded function inside commands, if there are any. - */ - void - revert(void *obj) const; - -}; - -#endif /* CANDY_GEAR_COMMAND_CHAIN_H */ diff --git a/src/blucat/command_pool.cpp b/src/blucat/command_pool.cpp deleted file mode 100644 index 898d7ae..0000000 --- a/src/blucat/command_pool.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2022-2024 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 "command_pool.hpp" - -namespace BluCat -{ - -const CommandChain CommandPool::loader{ - {&CommandPool::load_command_pool, &CommandPool::unload_command_pool}, - {&CommandPool::load_command_buffers, nullptr} -}; - -CommandPool::CommandPool(QueueFamily *queue_family, uint32_t buffers_quantity): - queue_family{queue_family} -{ - this->command_buffers.resize(buffers_quantity); - - CommandPool::loader.execute(this); -} - -CommandPool::~CommandPool() -{ - CommandPool::loader.revert(this); -} - -void -CommandPool::load_command_pool(void *obj) -{ - auto *self = static_cast(obj); - - VkCommandPoolCreateInfo command_pool_create_info; - - command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - command_pool_create_info.pNext = nullptr; - command_pool_create_info.flags = - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - command_pool_create_info.queueFamilyIndex = self->queue_family->family_index; - - if(vkCreateCommandPool( - self->queue_family->device->device, &command_pool_create_info, - nullptr, &self->command_pool) != VK_SUCCESS) - throw CommandError{"Vulkan command pool could not be created."}; -} - -void -CommandPool::unload_command_pool(void *obj) -{ - auto *self = static_cast(obj); - - vkDestroyCommandPool( - self->queue_family->device->device, self->command_pool, nullptr); -} - -void -CommandPool::load_command_buffers(void *obj) -{ - auto *self = static_cast(obj); - - VkCommandBufferAllocateInfo command_buffer_info; - command_buffer_info.sType = - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_info.pNext = nullptr; - command_buffer_info.commandPool = self->command_pool; - command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - command_buffer_info.commandBufferCount = self->command_buffers.size(); - - if(vkAllocateCommandBuffers( - self->queue_family->device->device, - &command_buffer_info, self->command_buffers.data()) != VK_SUCCESS) - throw CommandError{"Vulkan command buffers could not be allocated."}; -} - -} diff --git a/src/blucat/command_pool.hpp b/src/blucat/command_pool.hpp deleted file mode 100644 index 92451d8..0000000 --- a/src/blucat/command_pool.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_COMMAND_POOL_H -#define CANDY_GEAR_BLUCAT_COMMAND_POOL_H 1 - -#include - -#include "command.hpp" -#include "device.hpp" -#include "vulkan.hpp" - -namespace BluCat -{ - -class CommandPool -{ - CommandPool(const CommandPool &t) = delete; - CommandPool& operator=(const CommandPool &t) = delete; - CommandPool(const CommandPool &&t) = delete; - CommandPool& operator=(const CommandPool &&t) = delete; - -public: - std::vector command_buffers; - - CommandPool(QueueFamily *queue_family, uint32_t buffers_quantity); - ~CommandPool(); - -private: - static const CommandChain loader; - - QueueFamily *queue_family; - VkCommandPool command_pool; - - static void - load_command_pool(void *obj); - static void - unload_command_pool(void *obj); - - static void - load_command_buffers(void *obj); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_COMMAND_POOL_H */ diff --git a/src/blucat/core.cpp b/src/blucat/core.cpp deleted file mode 100644 index 8478f86..0000000 --- a/src/blucat/core.cpp +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Copyright 2022-2024 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 "core.hpp" - -namespace -{ - -#ifdef DEBUG -VKAPI_ATTR VkBool32 VKAPI_CALL -vk_debug_callback( - VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, - VkDebugUtilsMessageTypeFlagsEXT message_type, - const VkDebugUtilsMessengerCallbackDataEXT* callback_data, - void* _obj) -{ - // Set level. - Log::Level log_level; - switch(message_severity) - { - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: - log_level = Log::Level::Trace; - break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: - log_level = Log::Level::Information; - break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: - log_level = Log::Level::Warning; - break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: - default: - log_level = Log::Level::Error; - break; - } - - // Log message. - BluCat::core.log.message(log_level, callback_data->pMessage); - - return VK_FALSE; -} -#endif - -void -load_threads(void *obj) -{ - auto num_threads{std::thread::hardware_concurrency() - 1}; - for(auto i{0}; i < num_threads; i++) - BluCat::core.threads.emplace_back( - BluCat::core.workers.emplace_back(&BluCat::core.job_queue)); -} - -void -unload_threads(void *obj) -{ - BluCat::core.job_queue.stop(); - for(auto &t: BluCat::core.threads) t.join(); -} - -void -load_fps(void *obj) -{ - using namespace std::chrono; - - BluCat::core.max_frame_duration = - duration(1000 / BluCat::core.fps); - // FIXME: actually calculates the real delta time. - BluCat::core.delta_time = 1.0f / BluCat::core.fps; -} - -void -load_font_library(void *obj) -{ - FT_Error error{FT_Init_FreeType(&BluCat::core.font_library)}; - if(error) throw CommandError{"Failed to open the FreeType library."}; -} - -void -unload_font_library(void *obj) -{ - FT_Done_FreeType(BluCat::core.font_library); -} - -#ifdef DEBUG -void -load_vk_debug_callback(void *obj) -{ - PFN_vkCreateDebugUtilsMessengerEXT debug_messenger; - - // A Vulkan instance extension named VK_EXT_debug_utils and a Vulkan instance - // layer named VK_LAYER_LUNARG_standard_validation are required to enable - // this callback. These instance extension and instance layer are loaded at - // Instance::load_blucat_instance. - VkDebugUtilsMessengerCreateInfoEXT create_info; - create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - create_info.pNext = nullptr; - create_info.messageSeverity = - VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; - create_info.pfnUserCallback = vk_debug_callback; - create_info.pUserData = nullptr; - create_info.flags = 0; - - debug_messenger = (PFN_vkCreateDebugUtilsMessengerEXT) - vkGetInstanceProcAddr(BluCat::core.vk_instance, - "vkCreateDebugUtilsMessengerEXT"); - - if(debug_messenger(BluCat::core.vk_instance, &create_info, nullptr, - &BluCat::core.vk_callback) != VK_SUCCESS) - CommandError{"Failed to setup debug callback for Vulkan."}; -} - -void -unload_vk_debug_callback(void *obj) -{ - PFN_vkDestroyDebugUtilsMessengerEXT debug_messenger; - - debug_messenger = (PFN_vkDestroyDebugUtilsMessengerEXT) - vkGetInstanceProcAddr(BluCat::core.vk_instance, - "vkDestroyDebugUtilsMessengerEXT"); - - debug_messenger(BluCat::core.vk_instance, BluCat::core.vk_callback, nullptr); -} -#endif - -void -load_devices(void *obj) -{ - uint32_t devices_count; - std::vector vk_physical_devices; - - // Enumerate physical devices - { - vkEnumeratePhysicalDevices( - BluCat::core.vk_instance, &devices_count, nullptr); - if(devices_count < 1) - CommandError{"Failed to find GPUs with Vulkan support."}; - vk_physical_devices.resize(devices_count); - vkEnumeratePhysicalDevices( - BluCat::core.vk_instance, &devices_count, vk_physical_devices.data()); - } - -#ifdef DEBUG - BluCat::core.log.message(Log::Level::Trace, "Physical devices properties"); -#endif - - BluCat::core.vk_devices.reserve(devices_count); - for(auto i = 0; i < devices_count; i++) - { - // Use swapchain on first device. - if(i == 0) - { - BluCat::core.vk_devices.emplace_back(vk_physical_devices[i], true); - BluCat::core.vk_device_with_swapchain = &BluCat::core.vk_devices[i]; - } - else - BluCat::core.vk_devices.emplace_back(vk_physical_devices[i], false); - } -} - -void -unload_devices(void *obj) -{ - BluCat::core.vk_devices.clear(); -} - -static void -load_swapchain(void *obj) -{ - try { BluCat::core.vk_swapchain = new BluCat::Swapchain(); } - catch(const CommandError &error) - { - std::string error_message{"Failed to create swapchain → "}; - error_message += error.what(); - throw CommandError{error_message}; - } -} - -void -unload_swapchain(void *obj) -{ - delete BluCat::core.vk_swapchain; -} - -void -load_framebuffer(void *obj) -{ - try - { - BluCat::core.vk_framebuffer = new BluCat::Framebuffer(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create framebuffer."}; - } -} - -void -unload_framebuffer(void *obj) -{ - delete BluCat::core.vk_framebuffer; -} - -void -load_render_pass(void *obj) -{ - try - { - BluCat::core.vk_render_pass = new BluCat::RenderPass(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create render pass."}; - } -} - -void -unload_render_pass(void *obj) -{ - delete BluCat::core.vk_render_pass; -} - -void -load_descriptor_set_layout(void *obj) -{ - try - { - BluCat::core.vk_descriptor_set_layout = new BluCat::DescriptorSetLayout(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create descriptor set layouts."}; - } -} - -void -unload_descriptor_set_layout(void *obj) -{ - delete BluCat::core.vk_descriptor_set_layout; -} - -void -load_graphics_pipeline_3d_layout(void *obj) -{ - try - { - BluCat::core.vk_graphics_pipeline_3d_layout = - new BluCat::GraphicsPipeline3DLayout(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create 3d graphics pipeline."}; - } -} - -void -unload_graphics_pipeline_3d_layout(void *obj) -{ - delete BluCat::core.vk_graphics_pipeline_3d_layout; -} - -void -load_graphics_pipeline_2d_solid_layout(void *obj) -{ - try - { - BluCat::core.vk_graphics_pipeline_2d_solid_layout = - new BluCat::GraphicsPipeline2DSolidLayout(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create 2d graphics pipeline."}; - } -} - -void -unload_graphics_pipeline_2d_solid_layout(void *obj) -{ - delete BluCat::core.vk_graphics_pipeline_2d_solid_layout; -} - -void -load_graphics_pipeline_2d_wired_layout(void *obj) -{ - try - { - BluCat::core.vk_graphics_pipeline_2d_wired_layout = - new BluCat::GraphicsPipeline2DWiredLayout(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create 2d graphics pipeline."}; - } -} - -void -unload_graphics_pipeline_2d_wired_layout(void *obj) -{ - delete BluCat::core.vk_graphics_pipeline_2d_wired_layout; -} - -void -load_light(void *obj) -{ - try - { - BluCat::core.vk_light = new BluCat::Light(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to descriptor sets for light."}; - } -} - -void -unload_light(void *obj) -{ - delete BluCat::core.vk_light; -} - -void -load_graphics_pipeline_3d(void *obj) -{ - try - { - BluCat::core.vk_graphics_pipeline_3d = - std::make_unique(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create 3d graphics pipeline."}; - } -} - -void -unload_graphics_pipeline_3d(void *obj) -{ - BluCat::core.vk_graphics_pipeline_3d = nullptr; -} - -void -load_graphics_pipeline_3d_skeletal(void *obj) -{ - try - { - BluCat::core.vk_graphics_pipeline_3d_skeletal = - std::make_unique(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create 3d skeletal graphics pipeline."}; - } -} - -void -unload_graphics_pipeline_3d_skeletal(void *obj) -{ - BluCat::core.vk_graphics_pipeline_3d_skeletal = nullptr; -} - -void -load_graphics_pipeline_sprite_3d(void *obj) -{ - try - { - BluCat::core.vk_graphics_pipeline_sprite_3d = - std::make_unique(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create sprite 3d graphics pipeline."}; - } -} - -void -unload_graphics_pipeline_sprite_3d(void *obj) -{ - BluCat::core.vk_graphics_pipeline_sprite_3d = nullptr; -} - -void -load_graphics_pipeline_2d_solid(void *obj) -{ - try - { - BluCat::core.vk_graphics_pipeline_2d_solid = - std::make_unique(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create 2d graphics pipeline."}; - } -} - -void -unload_graphics_pipeline_2d_solid(void *obj) -{ - BluCat::core.vk_graphics_pipeline_2d_solid = nullptr; -} - -void -load_graphics_pipeline_2d_wired(void *obj) -{ - try - { - BluCat::core.vk_graphics_pipeline_2d_wired = - std::make_unique(); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create 2d graphics pipeline."}; - } -} - -void -unload_graphics_pipeline_2d_wired(void *obj) -{ - BluCat::core.vk_graphics_pipeline_2d_wired = nullptr; -} - -void -load_renderer(void *obj) -{ - try - { - glm::vec4 region( - 0.f, 0.f, - static_cast(BluCat::core.display_width), - static_cast(BluCat::core.display_height)); - BluCat::core.vk_renderer = new BluCat::Renderer( - {}, - {std::make_shared(region, region.z, region.w)}); - } - catch(const CommandError &e) - { - throw CommandError{"Failed to create renderer."}; - } -} - -void -unload_renderer(void *obj) -{ - delete BluCat::core.vk_renderer; -} - -} - -namespace BluCat -{ - -std::random_device random_seed; -std::mt19937 random_number_generator; - -const CommandChain Core::loader{ - {&load_threads, &unload_threads}, - {&load_fps, nullptr}, - {&load_font_library, &unload_font_library}, -#ifdef DEBUG - {&load_vk_debug_callback, &unload_vk_debug_callback}, -#endif - {&load_devices, &unload_devices}, - {&load_swapchain, &unload_swapchain}, - - {&load_render_pass, &unload_render_pass}, - {&load_framebuffer, &unload_framebuffer}, - {&load_descriptor_set_layout, &unload_descriptor_set_layout}, - {&load_graphics_pipeline_3d_layout, - &unload_graphics_pipeline_3d_layout}, - {&load_graphics_pipeline_2d_solid_layout, - &unload_graphics_pipeline_2d_solid_layout}, - {&load_graphics_pipeline_2d_wired_layout, - &unload_graphics_pipeline_2d_wired_layout}, - {&load_light, &unload_light}, - {&load_graphics_pipeline_3d_skeletal, - &unload_graphics_pipeline_3d_skeletal}, - {&load_graphics_pipeline_3d, &unload_graphics_pipeline_3d}, - {&load_graphics_pipeline_sprite_3d, - &unload_graphics_pipeline_sprite_3d}, - {&load_graphics_pipeline_2d_solid, &unload_graphics_pipeline_2d_solid}, - {&load_graphics_pipeline_2d_wired, &unload_graphics_pipeline_2d_wired}, - {&load_renderer, &unload_renderer}, -}; - -Core core; - -} diff --git a/src/blucat/core.hpp b/src/blucat/core.hpp deleted file mode 100644 index decf319..0000000 --- a/src/blucat/core.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_CORE_H -#define CANDY_GEAR_BLUCAT_CORE_H 1 - -#define BLU_CAT_VERSION_MAJOR 0 -#define BLU_CAT_VERSION_MINOR 1 -#define BLU_CAT_VERSION_PATCH 0 - -#include -#include -#include -#include - -#include "command.hpp" -#include "device.hpp" -#include "descriptor_set_layout.hpp" -#include "framebuffer.hpp" -#include "graphics_pipeline_2d_solid_layout.hpp" -#include "graphics_pipeline_2d_wired_layout.hpp" -#include "graphics_pipeline_2d_solid.hpp" -#include "graphics_pipeline_2d_wired.hpp" -#include "graphics_pipeline_3d_layout.hpp" -#include "graphics_pipeline_3d.hpp" -#include "graphics_pipeline_3d_skeletal.hpp" -#include "graphics_pipeline_sprite_3d.hpp" -#include "job_queue.hpp" -#include "light.hpp" -#include "log.hpp" -#include "render_pass.hpp" -#include "renderer.hpp" -#include "swapchain.hpp" -#include "vulkan.hpp" -#include "worker.hpp" - -namespace BluCat -{ - -extern std::random_device random_seed; -extern std::mt19937 random_number_generator; - -struct Core -{ - static const CommandChain loader; - - Log::Logger log; - - JobQueue job_queue; - std::vector workers; - std::vector threads; - - /// Text displayed in the game window. - std::string game_name; - - /** - * @{ - * This is the ammount of pixel that the games uses when rendering to the - * screen. - */ - uint32_t display_width, display_height; - /// @} - - int game_version_major, game_version_minor, game_version_patch; - - uint32_t fps; - std::chrono::duration max_frame_duration; - float delta_time; - - FT_Library font_library; - - VkSurfaceKHR window_surface; - VkInstance vk_instance; - -#ifdef DEBUG - VkDebugUtilsMessengerEXT vk_callback; -#endif - - // Vulkan devices. - std::vector vk_devices; - Device *vk_device_with_swapchain; - Swapchain *vk_swapchain; - - Framebuffer *vk_framebuffer; - RenderPass *vk_render_pass; - DescriptorSetLayout *vk_descriptor_set_layout; - GraphicsPipeline3DLayout *vk_graphics_pipeline_3d_layout; - GraphicsPipeline2DSolidLayout *vk_graphics_pipeline_2d_solid_layout; - GraphicsPipeline2DWiredLayout *vk_graphics_pipeline_2d_wired_layout; - Light *vk_light; - std::unique_ptr vk_graphics_pipeline_3d; - std::unique_ptr - vk_graphics_pipeline_3d_skeletal; - std::unique_ptr vk_graphics_pipeline_sprite_3d; - std::unique_ptr vk_graphics_pipeline_2d_solid; - std::unique_ptr vk_graphics_pipeline_2d_wired; - - Renderer *vk_renderer; -}; - -extern Core core; - -} - -#endif /* CANDY_GEAR_BLUCAT_CORE_H */ diff --git a/src/blucat/descriptor_set_layout.cpp b/src/blucat/descriptor_set_layout.cpp deleted file mode 100644 index 7d32346..0000000 --- a/src/blucat/descriptor_set_layout.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2022-2024 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 "descriptor_set_layout.hpp" - -#include - -#include "core.hpp" - -namespace -{ - -void -load_world(void *obj) -{ - auto self = static_cast(obj); - - std::array set_layouts{}; - set_layouts[0].binding = 0; - set_layouts[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - set_layouts[0].descriptorCount = 1; - set_layouts[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - set_layouts[0].pImmutableSamplers = nullptr; - - set_layouts[1].binding = 1; - set_layouts[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - set_layouts[1].descriptorCount = 1; - set_layouts[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - set_layouts[1].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 = set_layouts.size(); - layout_info.pBindings = set_layouts.data(); - - if(vkCreateDescriptorSetLayout( - BluCat::core.vk_device_with_swapchain->device, &layout_info, nullptr, - &self->world) != VK_SUCCESS) - throw CommandError{ - "Failed to create Vulkan descriptor set layout for world view."}; -} - -void -unload_world(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyDescriptorSetLayout( - BluCat::core.vk_device_with_swapchain->device, self->world, nullptr); -} - -void -load_view(void *obj) -{ - auto self = static_cast(obj); - - std::array 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(layout_bindings.size()); - layout_info.pBindings = layout_bindings.data(); - - if(vkCreateDescriptorSetLayout( - BluCat::core.vk_device_with_swapchain->device, &layout_info, nullptr, - &self->view) != VK_SUCCESS) - throw CommandError{ - "Failed to create Vulkan descriptor set layout for view."}; -} - -void -unload_view(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyDescriptorSetLayout( - BluCat::core.vk_device_with_swapchain->device, self->view, nullptr); -} - -void -load_texture(void *obj) -{ - auto self = static_cast(obj); - - std::array layout_bindings{}; - - layout_bindings[0].binding = 0; - layout_bindings[0].descriptorType = - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - 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(layout_bindings.size()); - layout_info.pBindings = layout_bindings.data(); - - if(vkCreateDescriptorSetLayout( - BluCat::core.vk_device_with_swapchain->device, &layout_info, nullptr, - &self->texture) != VK_SUCCESS) - throw CommandError{ - "Failed to create Vulkan descriptor set layout for textures."}; -} - -void -unload_texture(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyDescriptorSetLayout( - BluCat::core.vk_device_with_swapchain->device, self->texture, nullptr); -} - -void -load_model(void *obj) -{ - auto self = static_cast(obj); - - std::array 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(layout_bindings.size()); - layout_info.pBindings = layout_bindings.data(); - - if(vkCreateDescriptorSetLayout( - BluCat::core.vk_device_with_swapchain->device, &layout_info, nullptr, - &self->model) != VK_SUCCESS) - throw CommandError{ - "Failed to create Vulkan descriptor set layout for model instance."}; -} - -void -unload_model(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyDescriptorSetLayout( - BluCat::core.vk_device_with_swapchain->device, self->model, nullptr); -} - -const CommandChain loader{ - {&load_world, &unload_world}, - {&load_view, &unload_view}, - {&load_texture, &unload_texture}, - {&load_model, &unload_model}, -}; - -} - -namespace BluCat -{ - -DescriptorSetLayout::DescriptorSetLayout() -{ - loader.execute(this); -} - -DescriptorSetLayout::~DescriptorSetLayout() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/descriptor_set_layout.hpp b/src/blucat/descriptor_set_layout.hpp deleted file mode 100644 index 0724e40..0000000 --- a/src/blucat/descriptor_set_layout.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_DESCRIPTOR_SET_LAYOUT_H -#define CANDY_GEAR_BLUCAT_DESCRIPTOR_SET_LAYOUT_H 1 - -#include "vulkan.hpp" - -namespace BluCat -{ - -struct DescriptorSetLayout -{ - VkDescriptorSetLayout world; - VkDescriptorSetLayout view; - VkDescriptorSetLayout texture; - VkDescriptorSetLayout model; - - DescriptorSetLayout(); - ~DescriptorSetLayout(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_DESCRIPTOR_SET_LAYOUT_H */ diff --git a/src/blucat/destination_buffer.cpp b/src/blucat/destination_buffer.cpp deleted file mode 100644 index ea5f31e..0000000 --- a/src/blucat/destination_buffer.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2022-2024 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 "destination_buffer.hpp" - -#include "command_pool.hpp" - -namespace BluCat -{ - -DestinationBuffer::DestinationBuffer( - QueueFamily *queue_family, SourceBuffer *source_buffer, - VkBufferUsageFlags buffer_usage) -{ - this->device = queue_family->device; - this->device_size = source_buffer->device_size; - this->buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | buffer_usage; - this->memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - this->queue_family = queue_family; - this->source_buffer = source_buffer; - - BaseBuffer::loader.execute(dynamic_cast(this)); - - this->copy_data(); -} - -DestinationBuffer::DestinationBuffer( - DestinationBuffer &&that) -{ - this->buffer = that.buffer; - this->device_memory = that.device_memory; - this->device_size = that.device_size; - this->buffer_usage = that.buffer_usage; - this->memory_properties = that.memory_properties; - - that.buffer = VK_NULL_HANDLE; - that.device_memory = VK_NULL_HANDLE; -} - -DestinationBuffer& -DestinationBuffer::operator=(DestinationBuffer &&that) -{ - this->buffer = that.buffer; - this->device_memory = that.device_memory; - this->device_size = that.device_size; - this->buffer_usage = that.buffer_usage; - this->memory_properties = that.memory_properties; - - that.buffer = VK_NULL_HANDLE; - that.device_memory = VK_NULL_HANDLE; - - return *this; -} - -DestinationBuffer::~DestinationBuffer() -{ - BaseBuffer::loader.revert(dynamic_cast(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/blucat/destination_buffer.hpp b/src/blucat/destination_buffer.hpp deleted file mode 100644 index 7f5fb4b..0000000 --- a/src/blucat/destination_buffer.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_DESTINATION_BUFFER_H -#define CANDY_GEAR_BLUCAT_DESTINATION_BUFFER_H 1 - -#include "base_buffer.hpp" -#include "vulkan.hpp" -#include "source_buffer.hpp" -#include "queue_family.hpp" - -namespace BluCat -{ - -struct DestinationBuffer: public BaseBuffer -{ - DestinationBuffer(const DestinationBuffer &t) = delete; - DestinationBuffer& - operator=(const DestinationBuffer &t) = delete; - - QueueFamily *queue_family; - SourceBuffer *source_buffer; - VkCommandBuffer vk_command_buffer; - - DestinationBuffer( - QueueFamily *queue_family, SourceBuffer *source_buffer, - VkBufferUsageFlags buffer_usage); - - DestinationBuffer(DestinationBuffer &&that); - DestinationBuffer& - operator=(DestinationBuffer &&that); - - ~DestinationBuffer(); - - void - copy_data(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_DESTINATION_BUFFER_H */ diff --git a/src/blucat/device.cpp b/src/blucat/device.cpp deleted file mode 100644 index 8ce6d17..0000000 --- a/src/blucat/device.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright 2022-2024 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 "device.hpp" - -#include -#include -#include -#ifdef DEBUG -#include -#endif - -#include "core.hpp" - -namespace -{ -VkShaderModule -create_shader_module(VkDevice vk_device, const char *filename) -{ - std::ifstream file(filename, std::ios::ate | std::ios::binary); - - if (!file.is_open()) - { - throw std::runtime_error("Failed to open shader module file."); - } - - size_t file_size = (size_t) file.tellg(); - std::vector code(file_size); - - file.seekg(0); - file.read(code.data(), file_size); - - file.close(); - - VkShaderModuleCreateInfo create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - create_info.codeSize = code.size(); - create_info.pCode = reinterpret_cast(code.data()); - - VkShaderModule shader_module; - if (vkCreateShaderModule(vk_device, &create_info, nullptr, - &shader_module) != VK_SUCCESS) - { - throw std::runtime_error("Failed to create shader module."); - } - - return shader_module; -} -} - -namespace BluCat -{ - -Device::Device(VkPhysicalDevice vk_physical_device, bool with_swapchain) -{ - this->physical_device = vk_physical_device; - - std::vector queue_family_properties; - - // Get queue families. - { - vkGetPhysicalDeviceQueueFamilyProperties( - vk_physical_device, &this->queue_families_count, nullptr); - queue_family_properties.resize(this->queue_families_count); - vkGetPhysicalDeviceQueueFamilyProperties( - vk_physical_device, &this->queue_families_count, - queue_family_properties.data()); - } - - // Get information from physical device. - { - VkPhysicalDeviceProperties physical_properties = {}; - vkGetPhysicalDeviceProperties(vk_physical_device, &physical_properties); - VkPhysicalDeviceFeatures supported_features = {}; - vkGetPhysicalDeviceFeatures(vk_physical_device, &supported_features); - -#ifdef DEBUG - std::stringstream message{}; - message << "Name: " << physical_properties.deviceName << std::endl; - message << "API version: " << physical_properties.apiVersion << - std::endl; - message << "Driver version: " << physical_properties.driverVersion << - std::endl; - message << "Vendor ID: " << physical_properties.vendorID << std::endl; - message << "Device ID: " << physical_properties.deviceID << std::endl; - message << "Device type: " << physical_properties.deviceType << - std::endl; - core.log.message(Log::Level::Trace, message.str()); -#endif - - std::vector device_queue_create_infos; - std::vector> queue_priorities( - queue_family_properties.size()); - device_queue_create_infos.resize(queue_family_properties.size()); - for(auto i{0}; i < queue_family_properties.size(); i++) - { - // Give different priorities to queues. - int queue_count = queue_family_properties[i].queueCount; - queue_priorities[i].resize(queue_count); - float priority_unity = 1.0f/queue_count; - for(auto ii{0}; ii < queue_count; ii++) - queue_priorities[i][ii] = priority_unity * (queue_count - ii); - - device_queue_create_infos[i].sType = - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - device_queue_create_infos[i].pNext = nullptr; - device_queue_create_infos[i].flags = 0; - device_queue_create_infos[i].queueFamilyIndex = i; - device_queue_create_infos[i].queueCount = queue_priorities[i].size(); - device_queue_create_infos[i].pQueuePriorities = - queue_priorities[i].data(); - } - - 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; - - std::vector device_extensions; - if(with_swapchain) - device_extensions.emplace_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); - - VkDeviceCreateInfo device_create_info = {}; - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - device_create_info.pNext = nullptr; - device_create_info.flags = 0; - device_create_info.queueCreateInfoCount = device_queue_create_infos.size(); - device_create_info.pQueueCreateInfos = device_queue_create_infos.data(); - device_create_info.enabledLayerCount = 0; - device_create_info.ppEnabledLayerNames = nullptr; - device_create_info.enabledExtensionCount = device_extensions.size(); - if(device_extensions.size() == 0) - device_create_info.ppEnabledExtensionNames = nullptr; - else - device_create_info.ppEnabledExtensionNames = device_extensions.data(); - - device_create_info.pEnabledFeatures = &required_features; - - if(vkCreateDevice(this->physical_device, &device_create_info, nullptr, - &this->device) != VK_SUCCESS) - throw std::runtime_error("Failed to create Vulkan physical device."); - } - - // Load Shaders - { - std::string data_dir{""}; -#ifdef _WIN64 - HKEY hKey; - LPCSTR lpSubKey = "SOFTWARE\\CandyGear"; - LPCSTR lpValueName = "InstallLocation"; - DWORD dwType = REG_SZ; - DWORD dwSize = 0; - LPBYTE lpData = NULL; - - if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ, &hKey) == - ERROR_SUCCESS) - { - if(RegQueryValueEx(hKey, lpValueName, NULL, &dwType, NULL, &dwSize) == - ERROR_SUCCESS) - { - lpData = new BYTE[dwSize]; - if(RegQueryValueEx( - hKey, lpValueName, NULL, &dwType, lpData, &dwSize) == - ERROR_SUCCESS) - { - data_dir = reinterpret_cast(lpData); - } - delete[] lpData; - } - RegCloseKey(hKey); - } - - if(data_dir == "") - throw std::runtime_error("Failed to read CandyGear registry."); - - std::string vert_sprite_3d_shader_module{data_dir}; - vert_sprite_3d_shader_module.append("\\glsl\\shader_sprite_3d.vert.spv"); - this->vert_sprite_3d_shader_module = create_shader_module( - this->device, vert_sprite_3d_shader_module.c_str()); - - std::string frag_sprite_3d_shader_module{data_dir}; - frag_sprite_3d_shader_module.append("\\glsl\\shader_sprite_3d.frag.spv"); - this->frag_sprite_3d_shader_module = create_shader_module( - this->device, frag_sprite_3d_shader_module.c_str()); - - std::string vert3d_shader_module{data_dir}; - vert3d_shader_module.append("\\glsl\\shader_3d.vert.spv"); - this->vert3d_shader_module = create_shader_module( - this->device, vert3d_shader_module.c_str()); - - std::string vert3d_skeletal_shader_module{data_dir}; - vert3d_skeletal_shader_module.append( - "\\glsl\\shader_3d_skeletal.vert.spv"); - this->vert3d_skeletal_shader_module = create_shader_module( - this->device, vert3d_skeletal_shader_module.c_str()); - - std::string frag3d_shader_module{data_dir}; - frag3d_shader_module.append("\\glsl\\shader_3d.frag.spv"); - this->frag3d_shader_module = create_shader_module( - this->device, frag3d_shader_module.c_str()); - - std::string vert2d_solid_shader_module{data_dir}; - vert2d_solid_shader_module.append("\\glsl\\shader_2d_solid.vert.spv"); - this->vert2d_solid_shader_module = create_shader_module( - this->device, vert2d_solid_shader_module.c_str()); - - std::string frag2d_solid_shader_module{data_dir}; - frag2d_solid_shader_module.append("\\glsl\\shader_2d_solid.frag.spv"); - this->frag2d_solid_shader_module = create_shader_module( - this->device, frag2d_solid_shader_module.c_str()); - - std::string vert2d_wired_shader_module{data_dir}; - vert2d_wired_shader_module.append("\\glsl\\shader_2d_wired.vert.spv"); - this->vert2d_wired_shader_module = create_shader_module( - this->device, vert2d_wired_shader_module.c_str()); - - std::string frag2d_wired_shader_module{data_dir}; - frag2d_wired_shader_module.append("\\glsl\\shader_2d_wired.frag.spv"); - this->frag2d_wired_shader_module = create_shader_module( - this->device, frag2d_wired_shader_module.c_str()); -#else - data_dir = "/usr/local/share/candy_gear"; - - std::string vert_sprite_3d_shader_module{data_dir}; - vert_sprite_3d_shader_module.append("/glsl/shader_sprite_3d.vert.spv"); - this->vert_sprite_3d_shader_module = create_shader_module( - this->device, vert_sprite_3d_shader_module.c_str()); - - std::string frag_sprite_3d_shader_module{data_dir}; - frag_sprite_3d_shader_module.append("/glsl/shader_sprite_3d.frag.spv"); - this->frag_sprite_3d_shader_module = create_shader_module( - this->device, frag_sprite_3d_shader_module.c_str()); - - std::string vert3d_shader_module{data_dir}; - vert3d_shader_module.append("/glsl/shader_3d.vert.spv"); - this->vert3d_shader_module = create_shader_module( - this->device, vert3d_shader_module.c_str()); - - std::string vert3d_skeletal_shader_module{data_dir}; - vert3d_skeletal_shader_module.append("/glsl/shader_3d_skeletal.vert.spv"); - this->vert3d_skeletal_shader_module = create_shader_module( - this->device, vert3d_skeletal_shader_module.c_str()); - - std::string frag3d_shader_module{data_dir}; - frag3d_shader_module.append("/glsl/shader_3d.frag.spv"); - this->frag3d_shader_module = create_shader_module( - this->device, frag3d_shader_module.c_str()); - - std::string vert2d_solid_shader_module{data_dir}; - vert2d_solid_shader_module.append("/glsl/shader_2d_solid.vert.spv"); - this->vert2d_solid_shader_module = create_shader_module( - this->device, vert2d_solid_shader_module.c_str()); - - std::string frag2d_solid_shader_module{data_dir}; - frag2d_solid_shader_module.append("/glsl/shader_2d_solid.frag.spv"); - this->frag2d_solid_shader_module = create_shader_module( - this->device, frag2d_solid_shader_module.c_str()); - - std::string vert2d_wired_shader_module{data_dir}; - vert2d_wired_shader_module.append("/glsl/shader_2d_wired.vert.spv"); - this->vert2d_wired_shader_module = create_shader_module( - this->device, vert2d_wired_shader_module.c_str()); - - std::string frag2d_wired_shader_module{data_dir}; - frag2d_wired_shader_module.append("/glsl/shader_2d_wired.frag.spv"); - this->frag2d_wired_shader_module = create_shader_module( - this->device, frag2d_wired_shader_module.c_str()); -#endif - } - - this->queue_families = static_cast( - std::malloc(this->queue_families_count * sizeof(QueueFamily))); - for(auto i{0}; i < this->queue_families_count; i++) - { - new(&this->queue_families[i])QueueFamily( - this, i, queue_family_properties[i]); - - // Select families with graphics support. - auto &family_properties = this->queue_families[i].family_properties; - if(family_properties.queueCount > 0 && - family_properties.queueFlags & VK_QUEUE_GRAPHICS_BIT) - this->queue_families_with_graphics.push_back( - &this->queue_families[i]); - - // Select families with presentation support. - VkBool32 present_supported; - vkGetPhysicalDeviceSurfaceSupportKHR( - vk_physical_device, i, core.window_surface, &present_supported); - if(present_supported) - this->queue_families_with_presentation.push_back( - &this->queue_families[i]); - } -} - -Device::~Device() -{ - for(auto i{0}; i < this->queue_families_count; i++) - this->queue_families[i].~QueueFamily(); - std::free(this->queue_families); - - // Destroy shaders - vkDestroyShaderModule( - this->device, this->vert_sprite_3d_shader_module, nullptr); - vkDestroyShaderModule( - this->device, this->frag_sprite_3d_shader_module, nullptr); - vkDestroyShaderModule(this->device, this->vert3d_shader_module, nullptr); - vkDestroyShaderModule( - this->device, this->vert3d_skeletal_shader_module, nullptr); - vkDestroyShaderModule(this->device, this->frag3d_shader_module, nullptr); - vkDestroyShaderModule( - this->device, this->vert2d_solid_shader_module, nullptr); - vkDestroyShaderModule( - this->device, this->frag2d_solid_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); -} - -bool -Device::select_memory_type( - uint32_t *memory_type_index, VkMemoryRequirements *vk_memory_requirements, - VkMemoryPropertyFlags vk_property_flags) -{ - VkPhysicalDeviceMemoryProperties vk_memory_properties; - vkGetPhysicalDeviceMemoryProperties( - this->physical_device, &vk_memory_properties); - - for (auto i{0}; i < vk_memory_properties.memoryTypeCount; i++) - { - if(vk_memory_requirements->memoryTypeBits & (1 << i)) - { - const VkMemoryType& type = vk_memory_properties.memoryTypes[i]; - - if ((type.propertyFlags & vk_property_flags) == vk_property_flags) - { - *memory_type_index = i; - return true; - } - } - } - - return false; -} - -QueueFamily* -Device::get_queue_family_with_graphics() const -{ - /* - Returns a random queue family, so not all commands in the engine use the - same queue. - TODO: There must be a better way of doing this. - */ - std::uniform_int_distribution random_distribution{ - 0, this->queue_families_with_graphics.size() -1}; - auto random = random_distribution(random_number_generator); - return this->queue_families_with_graphics[0]; -} - -QueueFamily* -Device::get_queue_family_with_presentation() const -{ - /* - Returns a random queue family, so not all commands in the engine use the - same queue. - TODO: There must be a better way of doing this. - */ - std::uniform_int_distribution random_distribution{ - 0, this->queue_families_with_presentation.size() -1}; - auto random = random_distribution(random_number_generator); - return this->queue_families_with_presentation[0]; -} - -} diff --git a/src/blucat/device.hpp b/src/blucat/device.hpp deleted file mode 100644 index 61e87a4..0000000 --- a/src/blucat/device.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_DEVICE_H -#define CANDY_GEAR_BLUCAT_DEVICE_H 1 - -#include -#include - -#include "vulkan.hpp" -#include "queue_family.hpp" - -namespace BluCat -{ - -struct Device -{ - uint32_t queue_families_count; - QueueFamily *queue_families; - std::vector queue_families_with_graphics; - std::vector queue_families_with_presentation; - -public: - VkDevice device; - VkPhysicalDevice physical_device; - - VkShaderModule vert_sprite_3d_shader_module; - VkShaderModule frag_sprite_3d_shader_module; - VkShaderModule vert3d_shader_module; - VkShaderModule vert3d_skeletal_shader_module; - VkShaderModule frag3d_shader_module; - VkShaderModule vert2d_solid_shader_module; - VkShaderModule frag2d_solid_shader_module; - VkShaderModule vert2d_wired_shader_module; - VkShaderModule frag2d_wired_shader_module; - - bool with_swapchain; - - Device(VkPhysicalDevice vk_physical_device, bool with_swapchain); - ~Device(); - - bool - select_memory_type( - uint32_t *memoryTypeIndex, VkMemoryRequirements *vk_memory_requirements, - VkMemoryPropertyFlags vk_property_flags); - - QueueFamily* - get_queue_family_with_graphics() const; - - QueueFamily* - get_queue_family_with_presentation() const; -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_DEVICE_H */ diff --git a/src/blucat/font.cpp b/src/blucat/font.cpp deleted file mode 100644 index 603dda1..0000000 --- a/src/blucat/font.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2022-2024 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 "font.hpp" - -#include "core.hpp" - -namespace BluCat -{ - -Font::Font(const char* font_path, int font_size) -{ - FT_Error error; - error = FT_New_Face(core.font_library, font_path, 0, &this->face); - if(error == FT_Err_Unknown_File_Format) throw std::invalid_argument( - "The font file could be opened and read, but it appears that its font " - "format is unsupported."); - else if(error) throw std::invalid_argument( - "The font file could not be opened or read, or it is broken."); - - error = FT_Set_Pixel_Sizes(this->face, 0, font_size); - if(error) throw std::invalid_argument("Failed to load font size."); -} - -Font::~Font() -{ - FT_Done_Face(this->face); -} - -std::shared_ptr -Font::character(uint32_t character_code) -{ - if(!this->characters.contains(character_code)) - this->characters.emplace( - character_code, std::make_shared(this->face, character_code)); - - return this->characters.at(character_code); -} - -} diff --git a/src/blucat/font.hpp b/src/blucat/font.hpp deleted file mode 100644 index 1b9be69..0000000 --- a/src/blucat/font.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_FONT_H -#define CANDY_GEAR_BLUCAT_FONT_H 1 - -#include -#include - -#include "character.hpp" - -namespace BluCat -{ - -struct Font -{ - FT_Face face; - std::unordered_map> characters; - - Font(const char* font_path, int font_size); - ~Font(); - - std::shared_ptr - character(uint32_t character_code); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_FONT_H */ diff --git a/src/blucat/framebuffer.cpp b/src/blucat/framebuffer.cpp deleted file mode 100644 index c4d3230..0000000 --- a/src/blucat/framebuffer.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2022-2024 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 "framebuffer.hpp" - -#include "command.hpp" -#include "core.hpp" -#include "image.hpp" - -namespace -{ -void -load_depth_image(void *obj) -{ - auto self = static_cast(obj); - - VkExtent3D extent3d{}; - extent3d.width = BluCat::core.display_width; - extent3d.height = BluCat::core.display_height; - extent3d.depth = 1; - - try - { - BluCat::Image::create( - BluCat::core.vk_device_with_swapchain, - &self->depth_image, - &self->depth_image_memory, - VK_FORMAT_D32_SFLOAT, - extent3d, - 1, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT - ); - } - catch(BluCat::Image::Error error) - { - std::string error_message{"Failed to create depth image → "}; - error_message += error.what(); - throw CommandError{error_message}; - } -} - -void -unload_depth_image(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyImage( - BluCat::core.vk_device_with_swapchain->device, self->depth_image, - nullptr); - vkFreeMemory( - BluCat::core.vk_device_with_swapchain->device, - self->depth_image_memory, nullptr); -} - -void -load_depth_image_view(void *obj) -{ - auto self = static_cast(obj); - - try - { - BluCat::Image::create_view( - BluCat::core.vk_device_with_swapchain, &self->depth_image_view, - self->depth_image, - VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT); - } - catch(BluCat::Image::Error error) - { - std::string error_message{"Failed to create depth image view → "}; - error_message += error.what(); - throw CommandError{error_message}; - } -} - -void -unload_depth_image_view(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyImageView( - BluCat::core.vk_device_with_swapchain->device, self->depth_image_view, - nullptr); -} - -void -load_3d(void *obj) -{ - auto self = static_cast(obj); - - self->pipeline_3d.resize(BluCat::core.vk_swapchain->images_count); - for (auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - { - std::array attachments = { - BluCat::core.vk_swapchain->image_views[i], - self->depth_image_view - }; - - VkFramebufferCreateInfo framebuffer_info{}; - framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebuffer_info.renderPass = BluCat::core.vk_render_pass->pipeline_3d; - framebuffer_info.attachmentCount = attachments.size(); - framebuffer_info.pAttachments = attachments.data(); - framebuffer_info.width = BluCat::core.display_width; - framebuffer_info.height = BluCat::core.display_height; - - framebuffer_info.layers = 1; - - if(vkCreateFramebuffer( - BluCat::core.vk_device_with_swapchain->device, &framebuffer_info, nullptr, - &self->pipeline_3d[i]) != VK_SUCCESS) - throw CommandError{"Failed to create Vulkan Framebuffer."}; - } -} - -void -unload_3d(void *obj) -{ - auto self = static_cast(obj); - - for(auto framebuffer: self->pipeline_3d) - vkDestroyFramebuffer( - BluCat::core.vk_device_with_swapchain->device, framebuffer, nullptr); -} - -void -load_2d(void *obj) -{ - auto self = static_cast(obj); - - self->pipeline_2d.resize(BluCat::core.vk_swapchain->images_count); - for (auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - { - std::array attachments = { - BluCat::core.vk_swapchain->image_views[i] - }; - - VkFramebufferCreateInfo framebuffer_info{}; - framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebuffer_info.renderPass = BluCat::core.vk_render_pass->pipeline_2d; - framebuffer_info.attachmentCount = attachments.size(); - framebuffer_info.pAttachments = attachments.data(); - framebuffer_info.width = BluCat::core.display_width; - framebuffer_info.height = BluCat::core.display_height; - framebuffer_info.layers = 1; - - if(vkCreateFramebuffer( - BluCat::core.vk_device_with_swapchain->device, &framebuffer_info, - nullptr, &self->pipeline_2d[i]) - != VK_SUCCESS) - throw CommandError{"Failed to create Vulkan Framebuffer."}; - } -} - -void -unload_2d(void *obj) -{ - auto self = static_cast(obj); - - for(auto framebuffer: self->pipeline_2d) - vkDestroyFramebuffer( - BluCat::core.vk_device_with_swapchain->device, framebuffer, nullptr); -} - -const CommandChain loader{ - {&load_depth_image, &unload_depth_image}, - {&load_depth_image_view, &unload_depth_image_view}, - {&load_3d, &unload_3d}, - {&load_2d, &unload_2d} -}; - -} - -namespace BluCat -{ - -Framebuffer::Framebuffer() -{ - loader.execute(this); -} - -Framebuffer::~Framebuffer() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/framebuffer.hpp b/src/blucat/framebuffer.hpp deleted file mode 100644 index e9303f8..0000000 --- a/src/blucat/framebuffer.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_FRAMEBUFFER_H -#define CANDY_GEAR_BLUCAT_FRAMEBUFFER_H 1 - -#include - -#include "vulkan.hpp" - -namespace BluCat -{ - -struct Framebuffer -{ - // Depth image. - VkImage depth_image; - VkDeviceMemory depth_image_memory; - VkImageView depth_image_view; - - std::vector pipeline_3d; - std::vector pipeline_2d; - - Framebuffer(); - ~Framebuffer(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_FRAMEBUFFER_H */ diff --git a/src/blucat/graphics_pipeline_2d_solid.cpp b/src/blucat/graphics_pipeline_2d_solid.cpp deleted file mode 100644 index afd8a2e..0000000 --- a/src/blucat/graphics_pipeline_2d_solid.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright 2022-2024 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_solid.hpp" - -#include - -#include "core.hpp" -#include "sprite.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_pipeline(void *obj) -{ - auto self = static_cast(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 = - BluCat::core.vk_device_with_swapchain->vert2d_solid_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 = - BluCat::core.vk_device_with_swapchain->frag2d_solid_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 vertex_attribute{}; - // Texture coordinate. - 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(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 = BluCat::core.display_width; - viewport.height = BluCat::core.display_height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor = {}; - scissor.offset = {0, 0}; - scissor.extent = {BluCat::core.display_width, BluCat::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_FILL; - 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_TRUE; - color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - color_blend_attachment.dstColorBlendFactor = - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - 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; - - std::array dynamic_states{ - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_LINE_WIDTH, - VK_DYNAMIC_STATE_BLEND_CONSTANTS - }; - - VkPipelineDynamicStateCreateInfo dynamic_state_info = {}; - dynamic_state_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state_info.dynamicStateCount = dynamic_states.size(); - dynamic_state_info.pDynamicStates = dynamic_states.data(); - - 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 = - BluCat::core.vk_graphics_pipeline_2d_solid_layout->pipeline; - pipeline_info.renderPass = BluCat::core.vk_render_pass->pipeline_2d; - pipeline_info.subpass = 0; - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_info.basePipelineIndex = -1; - - if(vkCreateGraphicsPipelines( - BluCat::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(obj); - - vkDestroyPipeline( - BluCat::core.vk_device_with_swapchain->device, self->graphic_pipeline, - nullptr); -} - -const CommandChain loader{ - {&load_pipeline, &unload_pipeline} -}; - -} - -namespace BluCat -{ - -GraphicsPipeline2DSolid::GraphicsPipeline2DSolid() -{ - loader.execute(this); -} - -GraphicsPipeline2DSolid::~GraphicsPipeline2DSolid() -{ - loader.revert(this); -} - -void -GraphicsPipeline2DSolid::draw( - std::shared_ptr view, const VkCommandBuffer draw_command_buffer, - const size_t current_frame, const size_t next_frame, - const uint32_t image_index) -{ - // TODO set viewport just once per view, not once per pipeline. - { // 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(view->region.x); - vk_scissor.offset.y = static_cast(view->region.y); - vk_scissor.extent.width = static_cast(view->region.z); - vk_scissor.extent.height = static_cast(view->region.w); - vkCmdSetScissor(draw_command_buffer, 0, 1, &vk_scissor); - } - - vkCmdBindPipeline( - draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - this->graphic_pipeline); - - // FIXME: I know sorting is expensive, but I need to figure out better what - // to do here. - std::sort(view->sprites_to_draw[current_frame].begin(), - view->sprites_to_draw[current_frame].end()); - - // Draw sprites - for(auto& sprite_to_draw: view->sprites_to_draw[current_frame]) - { - std::array vk_descriptor_sets{ - view->descriptor_sets_2d[image_index], - sprite_to_draw.sprite->texture->descriptor_sets[image_index]}; - VkDeviceSize offsets[]{0}; - - vkCmdBindDescriptorSets( - draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - core.vk_graphics_pipeline_2d_solid_layout->pipeline, 0, - vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); - vkCmdBindVertexBuffers( - draw_command_buffer, 0, 1, &sprite_to_draw.sprite->vertex_buffer->buffer, - offsets); - - UDOVector4D position{sprite_to_draw.position}; - vkCmdPushConstants( - draw_command_buffer, - core.vk_graphics_pipeline_2d_solid_layout->pipeline, - VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(UDOVector4D), &position); - vkCmdDraw(draw_command_buffer, Sprite::vertex_count, 1, 0, 0); - } - - // Prepare for the next frame. - view->sprites_to_draw[next_frame].clear(); -} - -} diff --git a/src/blucat/graphics_pipeline_2d_solid.hpp b/src/blucat/graphics_pipeline_2d_solid.hpp deleted file mode 100644 index 753e9d8..0000000 --- a/src/blucat/graphics_pipeline_2d_solid.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_GRAPHICS_PIPELINE_2D_SOLID_H -#define CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_2D_SOLID_H 1 - -#include - -#include "vulkan.hpp" -#include "command_pool.hpp" -#include "view_2d.hpp" - -namespace BluCat -{ - -struct GraphicsPipeline2DSolid -{ - VkPipeline graphic_pipeline; - - GraphicsPipeline2DSolid(); - ~GraphicsPipeline2DSolid(); - - void - draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, - const size_t current_frame, const size_t next_frame, - const uint32_t image_index); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_2D_SOLID_H */ diff --git a/src/blucat/graphics_pipeline_2d_solid_layout.cpp b/src/blucat/graphics_pipeline_2d_solid_layout.cpp deleted file mode 100644 index 666556d..0000000 --- a/src/blucat/graphics_pipeline_2d_solid_layout.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2022-2024 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_solid_layout.hpp" - -#include - -#include "core.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_pipeline(void *obj) -{ - auto self = static_cast(obj); - - std::array set_layouts{ - BluCat::core.vk_descriptor_set_layout->view, - BluCat::core.vk_descriptor_set_layout->texture - }; - - std::array push_constants; - push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - push_constants[0].offset = 0; - push_constants[0].size = sizeof(BluCat::UDOVector4D); - - 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 = push_constants.size(); - pipeline_layout_info.pPushConstantRanges = push_constants.data(); - - if(vkCreatePipelineLayout( - BluCat::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(obj); - - vkDestroyPipelineLayout( - BluCat::core.vk_device_with_swapchain->device, self->pipeline, nullptr); -} - -const CommandChain loader{ - {&load_pipeline, &unload_pipeline} -}; - -} - -namespace BluCat -{ - -GraphicsPipeline2DSolidLayout::GraphicsPipeline2DSolidLayout() -{ - loader.execute(this); -} - -GraphicsPipeline2DSolidLayout::~GraphicsPipeline2DSolidLayout() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/graphics_pipeline_2d_solid_layout.hpp b/src/blucat/graphics_pipeline_2d_solid_layout.hpp deleted file mode 100644 index f6a8960..0000000 --- a/src/blucat/graphics_pipeline_2d_solid_layout.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_GRAPHICS_PIPELINE_2D_LAYOUT_H -#define CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_2D_LAYOUT_H 1 - -#include "vulkan.hpp" - -namespace BluCat -{ - -struct GraphicsPipeline2DSolidLayout -{ - VkPipelineLayout pipeline; - - GraphicsPipeline2DSolidLayout(); - ~GraphicsPipeline2DSolidLayout(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_2D_LAYOUT_H */ diff --git a/src/blucat/graphics_pipeline_2d_wired.cpp b/src/blucat/graphics_pipeline_2d_wired.cpp deleted file mode 100644 index 9cd3a86..0000000 --- a/src/blucat/graphics_pipeline_2d_wired.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 2022-2024 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 - -#include "core.hpp" -#include "rectangle.hpp" -#include "sprite.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_indexes(void *obj) -{ - auto self = static_cast(obj); - - self->queue_family = - BluCat::core.vk_device_with_swapchain->get_queue_family_with_graphics(); - - std::array indexes{0, 1, 2, 3}; - void *indexes_data{indexes.data()}; - size_t indexes_size{sizeof(indexes[0]) * indexes.size()}; - BluCat::SourceBuffer source_index_buffer{ - self->queue_family->device, indexes_data, indexes_size}; - self->index_buffer = new BluCat::DestinationBuffer{ - self->queue_family, &source_index_buffer, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT}; -} - -void -unload_indexes(void *obj) -{ - auto self = static_cast(obj); - - delete self->index_buffer; -} - -void -load_pipeline(void *obj) -{ - auto self = static_cast(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 = - BluCat::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 = - BluCat::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 - }; - - 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 = 0; - vertex_input_info.pVertexBindingDescriptions = nullptr; - vertex_input_info.vertexAttributeDescriptionCount = 0; - vertex_input_info.pVertexAttributeDescriptions = nullptr; - - 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 = BluCat::core.display_width; - viewport.height = BluCat::core.display_height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor = {}; - scissor.offset = {0, 0}; - scissor.extent = {BluCat::core.display_width, BluCat::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 = - BluCat::core.vk_graphics_pipeline_2d_wired_layout->pipeline; - pipeline_info.renderPass = BluCat::core.vk_render_pass->pipeline_2d; - pipeline_info.subpass = 0; - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_info.basePipelineIndex = -1; - - if(vkCreateGraphicsPipelines( - BluCat::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(obj); - - vkDestroyPipeline( - BluCat::core.vk_device_with_swapchain->device, self->graphic_pipeline, - nullptr); -} - -const CommandChain loader{ - {&load_indexes, &unload_indexes}, - {&load_pipeline, &unload_pipeline} -}; - -} - -namespace BluCat -{ - -GraphicsPipeline2DWired::GraphicsPipeline2DWired() -{ - loader.execute(this); -} - -GraphicsPipeline2DWired::~GraphicsPipeline2DWired() -{ - loader.revert(this); -} - -void -GraphicsPipeline2DWired::draw( - std::shared_ptr 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(view->region.x); - vk_scissor.offset.y = static_cast(view->region.y); - vk_scissor.extent.width = static_cast(view->region.z); - vk_scissor.extent.height = static_cast(view->region.w); - vkCmdSetScissor(draw_command_buffer, 0, 1, &vk_scissor); - } - - // Draw rectangles - { - std::array vk_descriptor_sets{ - view->descriptor_sets_2d[image_index]}; - VkDeviceSize offsets[]{0}; - - vkCmdBindDescriptorSets( - draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - 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); - vkCmdBindIndexBuffer( - draw_command_buffer, this->index_buffer->buffer, 0, - VK_INDEX_TYPE_UINT32); - - for(auto i{0}; i < view->rectangles_to_draw[current_frame].size(); i++) - { - auto &rect{view->rectangles_to_draw[current_frame][i]}; - - UDOVector4D position{rect.position}; - UDOVector3D color{rect.color}; - vkCmdPushConstants( - draw_command_buffer, - core.vk_graphics_pipeline_2d_wired_layout->pipeline, - VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(UDOVector4D), &position); - vkCmdPushConstants( - draw_command_buffer, - core.vk_graphics_pipeline_2d_wired_layout->pipeline, - VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UDOVector4D), sizeof(UDOVector3D), - &color); - vkCmdDrawIndexed( - draw_command_buffer, Rectangle::VertexCount, 1, 0, 0, 0); - } - } - - // Prepare for the next frame. - view->rectangles_to_draw[next_frame].clear(); -} - -} diff --git a/src/blucat/graphics_pipeline_2d_wired.hpp b/src/blucat/graphics_pipeline_2d_wired.hpp deleted file mode 100644 index a351aee..0000000 --- a/src/blucat/graphics_pipeline_2d_wired.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_GRAPHICS_PIPELINE_2D_WIRED_H -#define CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_2D_WIRED_H 1 - -#include - -#include "vulkan.hpp" -#include "view_2d.hpp" - -namespace BluCat -{ - -struct GraphicsPipeline2DWired -{ - QueueFamily *queue_family; - - VkPipeline graphic_pipeline; - - DestinationBuffer *index_buffer; - - GraphicsPipeline2DWired(); - ~GraphicsPipeline2DWired(); - - void - draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, - const size_t current_frame, const size_t next_frame, - const uint32_t image_index); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_2D_WIRED_H */ diff --git a/src/blucat/graphics_pipeline_2d_wired_layout.cpp b/src/blucat/graphics_pipeline_2d_wired_layout.cpp deleted file mode 100644 index 104c599..0000000 --- a/src/blucat/graphics_pipeline_2d_wired_layout.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2022-2024 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 - -#include "core.hpp" -#include "graphics_pipeline_2d_solid_layout.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_pipeline(void *obj) -{ - auto self = static_cast(obj); - - std::array set_layouts{ - BluCat::core.vk_descriptor_set_layout->view - }; - - std::array push_constants; - push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - push_constants[0].offset = 0; - push_constants[0].size = sizeof(BluCat::UDOVector4D); - - push_constants[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - push_constants[1].offset = sizeof(BluCat::UDOVector4D); - push_constants[1].size = sizeof(BluCat::UDOVector3D); - - 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 = push_constants.size(); - pipeline_layout_info.pPushConstantRanges = push_constants.data(); - - if(vkCreatePipelineLayout( - BluCat::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(obj); - - vkDestroyPipelineLayout( - BluCat::core.vk_device_with_swapchain->device, self->pipeline, nullptr); -} - -const CommandChain loader{ - {&load_pipeline, &unload_pipeline} -}; - -} - -namespace BluCat -{ - -GraphicsPipeline2DWiredLayout::GraphicsPipeline2DWiredLayout() -{ - loader.execute(this); -} - -GraphicsPipeline2DWiredLayout::~GraphicsPipeline2DWiredLayout() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/graphics_pipeline_2d_wired_layout.hpp b/src/blucat/graphics_pipeline_2d_wired_layout.hpp deleted file mode 100644 index 402e7dc..0000000 --- a/src/blucat/graphics_pipeline_2d_wired_layout.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_GRAPHICS_PIPELINE_2D_WIRED_LAYOUT_H -#define CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_2D_WIRED_LAYOUT_H 1 - -#include "vulkan.hpp" - -namespace BluCat -{ - -struct GraphicsPipeline2DWiredLayout -{ - VkPipelineLayout pipeline; - - GraphicsPipeline2DWiredLayout(); - ~GraphicsPipeline2DWiredLayout(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_2D_LAYOUT_H */ diff --git a/src/blucat/graphics_pipeline_3d.cpp b/src/blucat/graphics_pipeline_3d.cpp deleted file mode 100644 index bd64ebc..0000000 --- a/src/blucat/graphics_pipeline_3d.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright 2022-2024 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_3d.hpp" - -#include -#include - -#include "core.hpp" -#include "vulkan.hpp" -#include "static_mesh_vertex.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_pipeline(void *obj) -{ - auto self = static_cast(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 = - BluCat::core.vk_device_with_swapchain->vert3d_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 = - BluCat::core.vk_device_with_swapchain->frag3d_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(BluCat::StaticMeshVertex); - vertex_input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - std::array vertex_attribute{}; - // Position. - vertex_attribute[0].location = 0; - vertex_attribute[0].binding = 0; - vertex_attribute[0].format = VK_FORMAT_R32G32B32_SFLOAT; - vertex_attribute[0].offset = offsetof(BluCat::StaticMeshVertex, position); - // Normal. - vertex_attribute[1].location = 1; - vertex_attribute[1].binding = 0; - vertex_attribute[1].format = VK_FORMAT_R32G32B32_SFLOAT; - vertex_attribute[1].offset = offsetof(BluCat::StaticMeshVertex, normal); - // Texture coordinate. - vertex_attribute[2].location = 2; - vertex_attribute[2].binding = 0; - vertex_attribute[2].format = VK_FORMAT_R32G32_SFLOAT; - vertex_attribute[2].offset = offsetof(BluCat::StaticMeshVertex, texture_coord); - - 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(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_LIST; - input_assembly.primitiveRestartEnable = VK_FALSE; - - VkViewport viewport = {}; - viewport.x = 0; - viewport.y = 0; - viewport.width = BluCat::core.display_width; - viewport.height = BluCat::core.display_height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor = {}; - scissor.offset = {0, 0}; - scissor.extent = {BluCat::core.display_width, BluCat::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_FILL; - 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; - - VkPipelineDepthStencilStateCreateInfo depth_stencil = {}; - depth_stencil.sType = - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depth_stencil.depthTestEnable = VK_TRUE; - depth_stencil.depthWriteEnable = VK_TRUE; - depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; - depth_stencil.depthBoundsTestEnable = VK_FALSE; - depth_stencil.minDepthBounds = 0.0f; - depth_stencil.maxDepthBounds = 1.0f; - depth_stencil.stencilTestEnable = VK_FALSE; - depth_stencil.front = {}; - depth_stencil.back = {}; - - 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 = &depth_stencil; - pipeline_info.pColorBlendState = &color_blending; - pipeline_info.pDynamicState = &dynamic_state_info; - pipeline_info.layout = BluCat::core.vk_graphics_pipeline_3d_layout->pipeline; - pipeline_info.renderPass = BluCat::core.vk_render_pass->pipeline_3d; - pipeline_info.subpass = 0; - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_info.basePipelineIndex = -1; - - if(vkCreateGraphicsPipelines( - BluCat::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(obj); - - vkDestroyPipeline( - BluCat::core.vk_device_with_swapchain->device, self->graphic_pipeline, - nullptr); -} - -const CommandChain loader{ - {&load_pipeline, &unload_pipeline} -}; - -} - -namespace BluCat -{ - -GraphicsPipeline3D::GraphicsPipeline3D() -{ - loader.execute(this); -} - -GraphicsPipeline3D::~GraphicsPipeline3D() -{ - loader.revert(this); -} - -void -GraphicsPipeline3D::draw( - std::shared_ptr view, const VkCommandBuffer draw_command_buffer, - const size_t current_frame, const uint32_t image_index) -{ - vkCmdBindPipeline( - draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - this->graphic_pipeline); - - // Draw models - for(auto& [static_mesh, instances]: - core.vk_renderer->static_models_to_draw[current_frame]) - { - VkBuffer vertex_buffers[]{static_mesh->vertex_buffer->buffer}; - VkDeviceSize offsets[]{0}; - - vkCmdBindVertexBuffers( - draw_command_buffer, 0, 1, vertex_buffers, offsets); - vkCmdBindIndexBuffer( - draw_command_buffer, static_mesh->index_buffer->buffer, 0, - VK_INDEX_TYPE_UINT32); - - for(auto &instance: instances) - { // Object matrix. - glm::mat4 translation_matrix{1.0f}; - translation_matrix = glm::translate( - translation_matrix, *instance->position); - glm::mat4 rotation_matrix{glm::toMat4(*instance->orientation)}; - - std::array vk_descriptor_sets{ - core.vk_light->descriptor_sets_world[image_index], - view->descriptor_sets_3d[image_index], - instance->descriptor_sets[image_index], - instance->texture->descriptor_sets[image_index]}; - - vkCmdBindDescriptorSets( - draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - core.vk_graphics_pipeline_3d_layout->pipeline, 0, - vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); - - vkCmdDrawIndexed( - draw_command_buffer, static_mesh->index_count, 1, 0, 0, 0); - - BluCat::UDOStaticModel udo_static_model{}; - udo_static_model.base_matrix = translation_matrix * rotation_matrix; - instance->uniform_buffers[image_index].copy_data(&udo_static_model); - } - } -} - -} diff --git a/src/blucat/graphics_pipeline_3d.hpp b/src/blucat/graphics_pipeline_3d.hpp deleted file mode 100644 index 6942955..0000000 --- a/src/blucat/graphics_pipeline_3d.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_GRAPHICS_PIPELINE_3D_H -#define CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_3D_H 1 - -#include - -#include "vulkan.hpp" -#include "command_pool.hpp" -#include "view_3d.hpp" - -namespace BluCat -{ - -struct GraphicsPipeline3D -{ - VkPipeline graphic_pipeline; - - GraphicsPipeline3D(); - ~GraphicsPipeline3D(); - - void - draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, - const size_t current_frame, const uint32_t image_index); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_3D_H */ diff --git a/src/blucat/graphics_pipeline_3d_layout.cpp b/src/blucat/graphics_pipeline_3d_layout.cpp deleted file mode 100644 index 6bac1bb..0000000 --- a/src/blucat/graphics_pipeline_3d_layout.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2022-2024 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_3d_layout.hpp" - -#include - -#include "core.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_pipeline(void *obj) -{ - auto self = static_cast(obj); - - std::array set_layouts{ - BluCat::core.vk_descriptor_set_layout->world, - BluCat::core.vk_descriptor_set_layout->view, - BluCat::core.vk_descriptor_set_layout->model, - BluCat::core.vk_descriptor_set_layout->texture}; - - 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( - BluCat::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(obj); - - vkDestroyPipelineLayout( - BluCat::core.vk_device_with_swapchain->device, self->pipeline, nullptr); -} - -const CommandChain loader{ - {&load_pipeline, &unload_pipeline} -}; - -} - -namespace BluCat -{ - -GraphicsPipeline3DLayout::GraphicsPipeline3DLayout() -{ - loader.execute(this); -} - -GraphicsPipeline3DLayout::~GraphicsPipeline3DLayout() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/graphics_pipeline_3d_layout.hpp b/src/blucat/graphics_pipeline_3d_layout.hpp deleted file mode 100644 index bc86646..0000000 --- a/src/blucat/graphics_pipeline_3d_layout.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_GRAPHICS_PIPELINE_3D_LAYOUT_H -#define CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_3D_LAYOUT_H 1 - -#include "vulkan.hpp" - -namespace BluCat -{ - -struct GraphicsPipeline3DLayout -{ - VkPipelineLayout pipeline; - - GraphicsPipeline3DLayout(); - ~GraphicsPipeline3DLayout(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_3D_LAYOUT_H */ diff --git a/src/blucat/graphics_pipeline_3d_skeletal.cpp b/src/blucat/graphics_pipeline_3d_skeletal.cpp deleted file mode 100644 index 6b56221..0000000 --- a/src/blucat/graphics_pipeline_3d_skeletal.cpp +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright 2022-2024 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_3d.hpp" - -#include -#include - -#include "core.hpp" -#include "skeletal_mesh_vertex.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_pipeline(void *obj) -{ - auto self = static_cast(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 = - BluCat::core.vk_device_with_swapchain->vert3d_skeletal_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 = - BluCat::core.vk_device_with_swapchain->frag3d_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(BluCat::SkeletalMeshVertex); - vertex_input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - std::array vertex_attribute{}; - // Position. - vertex_attribute[0].location = 0; - vertex_attribute[0].binding = 0; - vertex_attribute[0].format = VK_FORMAT_R32G32B32_SFLOAT; - vertex_attribute[0].offset = offsetof(BluCat::SkeletalMeshVertex, position); - // Normal. - vertex_attribute[1].location = 1; - vertex_attribute[1].binding = 0; - vertex_attribute[1].format = VK_FORMAT_R32G32B32_SFLOAT; - vertex_attribute[1].offset = offsetof(BluCat::SkeletalMeshVertex, normal); - // Texture coordinate. - vertex_attribute[2].location = 2; - vertex_attribute[2].binding = 0; - vertex_attribute[2].format = VK_FORMAT_R32G32_SFLOAT; - vertex_attribute[2].offset = offsetof(BluCat::SkeletalMeshVertex, texture_coord); - // Bones ids. - vertex_attribute[3].location = 3; - vertex_attribute[3].binding = 0; - vertex_attribute[3].format = VK_FORMAT_R32G32B32A32_SINT; - vertex_attribute[3].offset = offsetof(BluCat::SkeletalMeshVertex, bone_ids); - // Bones weights. - vertex_attribute[4].location = 4; - vertex_attribute[4].binding = 0; - vertex_attribute[4].format = VK_FORMAT_R32G32B32A32_SFLOAT; - vertex_attribute[4].offset = offsetof(BluCat::SkeletalMeshVertex, bone_weights); - - 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(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_LIST; - input_assembly.primitiveRestartEnable = VK_FALSE; - - VkViewport viewport = {}; - viewport.x = 0; - viewport.y = 0; - viewport.width = BluCat::core.display_width; - viewport.height = BluCat::core.display_height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor = {}; - scissor.offset = {0, 0}; - scissor.extent = {BluCat::core.display_width, BluCat::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_FILL; - 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; - - VkPipelineDepthStencilStateCreateInfo depth_stencil = {}; - depth_stencil.sType = - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depth_stencil.depthTestEnable = VK_TRUE; - depth_stencil.depthWriteEnable = VK_TRUE; - depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; - depth_stencil.depthBoundsTestEnable = VK_FALSE; - depth_stencil.minDepthBounds = 0.0f; - depth_stencil.maxDepthBounds = 1.0f; - depth_stencil.stencilTestEnable = VK_FALSE; - depth_stencil.front = {}; - depth_stencil.back = {}; - - 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 = &depth_stencil; - pipeline_info.pColorBlendState = &color_blending; - pipeline_info.pDynamicState = &dynamic_state_info; - pipeline_info.layout = BluCat::core.vk_graphics_pipeline_3d_layout->pipeline; - pipeline_info.renderPass = BluCat::core.vk_render_pass->pipeline_3d; - pipeline_info.subpass = 0; - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_info.basePipelineIndex = -1; - - if(vkCreateGraphicsPipelines( - BluCat::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(obj); - - vkDestroyPipeline( - BluCat::core.vk_device_with_swapchain->device, self->graphic_pipeline, - nullptr); -} - -const CommandChain loader{ - {&load_pipeline, &unload_pipeline} -}; - -} - -namespace BluCat -{ - -GraphicsPipeline3DSkeletal::GraphicsPipeline3DSkeletal() -{ - loader.execute(this); -} - -GraphicsPipeline3DSkeletal::~GraphicsPipeline3DSkeletal() -{ - loader.revert(this); -} - -void -GraphicsPipeline3DSkeletal::draw( - std::shared_ptr view, const VkCommandBuffer draw_command_buffer, - const size_t current_frame, const uint32_t image_index) -{ - vkCmdBindPipeline( - draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - this->graphic_pipeline); - - // Draw models - for(auto& [skeletal_mesh, instances]: - core.vk_renderer->skeletal_models_to_draw[current_frame]) - { - VkBuffer vertex_buffers[]{skeletal_mesh->vertex_buffer->buffer}; - VkDeviceSize offsets[]{0}; - - vkCmdBindVertexBuffers( - draw_command_buffer, 0, 1, vertex_buffers, offsets); - vkCmdBindIndexBuffer( - draw_command_buffer, skeletal_mesh->index_buffer->buffer, 0, - VK_INDEX_TYPE_UINT32); - - for(auto &instance: instances) - { // Object matrix. - glm::mat4 translation_matrix{1.0f}; - translation_matrix = glm::translate( - translation_matrix, *instance->position); - glm::mat4 rotation_matrix{glm::toMat4(*instance->orientation)}; - - std::array vk_descriptor_sets{ - core.vk_light->descriptor_sets_world[image_index], - view->descriptor_sets_3d[image_index], - instance->descriptor_sets[image_index], - instance->texture->descriptor_sets[image_index]}; - - vkCmdBindDescriptorSets( - draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - core.vk_graphics_pipeline_3d_layout->pipeline, 0, - vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); - - vkCmdDrawIndexed( - draw_command_buffer, skeletal_mesh->index_count, 1, 0, 0, 0); - - BluCat::UDOSkeletalModel udo_skeletal_model{}; - instance->tick(core.delta_time); - udo_skeletal_model.base_matrix = translation_matrix * rotation_matrix; - std::copy(instance->bone_transforms.begin(), - instance->bone_transforms.end(), - udo_skeletal_model.bone_matrices); - instance->uniform_buffers[image_index].copy_data(&udo_skeletal_model); - } - } - -} - -} diff --git a/src/blucat/graphics_pipeline_3d_skeletal.hpp b/src/blucat/graphics_pipeline_3d_skeletal.hpp deleted file mode 100644 index 52810f6..0000000 --- a/src/blucat/graphics_pipeline_3d_skeletal.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_GRAPHICS_PIPELINE_3D_SKELETAL_H -#define CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_3D_SKELETAL_H 1 - -#include - -#include "vulkan.hpp" -#include "command_pool.hpp" -#include "view_3d.hpp" - -namespace BluCat -{ - -struct GraphicsPipeline3DSkeletal -{ - VkPipeline graphic_pipeline; - - GraphicsPipeline3DSkeletal(); - ~GraphicsPipeline3DSkeletal(); - - void - draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, - const size_t current_frame, const uint32_t image_index); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_SKELETAL_3D_H */ diff --git a/src/blucat/graphics_pipeline_sprite_3d.cpp b/src/blucat/graphics_pipeline_sprite_3d.cpp deleted file mode 100644 index f87b7e1..0000000 --- a/src/blucat/graphics_pipeline_sprite_3d.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright 2022-2024 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_sprite_3d.hpp" - -#include - -#include "core.hpp" -#include "sprite.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -struct Sprite3DOrder -{ - std::shared_ptr sprite_3d; - float distance; -}; - -bool -operator<(const Sprite3DOrder &a, const Sprite3DOrder &b) -{ - return a.distance < b.distance; -} - -bool -operator>(const Sprite3DOrder &a, const Sprite3DOrder &b) -{ - return a.distance > b.distance; -} - -void -load_pipeline(void *obj) -{ - auto self = static_cast(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 = - BluCat::core.vk_device_with_swapchain->vert_sprite_3d_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 = - BluCat::core.vk_device_with_swapchain->frag_sprite_3d_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 vertex_attribute{}; - // Texture coordinate. - 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(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 = BluCat::core.display_width; - viewport.height = BluCat::core.display_height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor = {}; - scissor.offset = {0, 0}; - scissor.extent = {BluCat::core.display_width, BluCat::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_FILL; - 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; - - VkPipelineDepthStencilStateCreateInfo depth_stencil = {}; - depth_stencil.sType = - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depth_stencil.depthTestEnable = VK_TRUE; - depth_stencil.depthWriteEnable = VK_TRUE; - depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; - depth_stencil.depthBoundsTestEnable = VK_FALSE; - depth_stencil.minDepthBounds = 0.0f; - depth_stencil.maxDepthBounds = 1.0f; - depth_stencil.stencilTestEnable = VK_FALSE; - depth_stencil.front = {}; - depth_stencil.back = {}; - - VkPipelineColorBlendAttachmentState color_blend_attachment = {}; - color_blend_attachment.blendEnable = VK_TRUE; - color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - color_blend_attachment.dstColorBlendFactor = - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - 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; - - std::array dynamic_states{ - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_LINE_WIDTH, - VK_DYNAMIC_STATE_BLEND_CONSTANTS - }; - - VkPipelineDynamicStateCreateInfo dynamic_state_info = {}; - dynamic_state_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state_info.dynamicStateCount = dynamic_states.size(); - dynamic_state_info.pDynamicStates = dynamic_states.data(); - - 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 = &depth_stencil; - pipeline_info.pColorBlendState = &color_blending; - pipeline_info.pDynamicState = &dynamic_state_info; - pipeline_info.layout = BluCat::core.vk_graphics_pipeline_3d_layout->pipeline; - pipeline_info.renderPass = BluCat::core.vk_render_pass->pipeline_3d; - pipeline_info.subpass = 0; - pipeline_info.basePipelineHandle = VK_NULL_HANDLE; - pipeline_info.basePipelineIndex = -1; - - if(vkCreateGraphicsPipelines( - BluCat::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 sprite 3d."}; -} - -void -unload_pipeline(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyPipeline( - BluCat::core.vk_device_with_swapchain->device, self->graphic_pipeline, - nullptr); -} - -const CommandChain loader{ - {&load_pipeline, &unload_pipeline} -}; - -} - -namespace BluCat -{ - -GraphicsPipelineSprite3D::GraphicsPipelineSprite3D() -{ - loader.execute(this); -} - -GraphicsPipelineSprite3D::~GraphicsPipelineSprite3D() -{ - loader.revert(this); -} - -void -GraphicsPipelineSprite3D::draw( - std::shared_ptr view, const VkCommandBuffer draw_command_buffer, - const size_t current_frame, const uint32_t image_index) -{ - vkCmdBindPipeline( - draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - this->graphic_pipeline); - - std::vector sprite_3d_order; - { // Sort sprites 3D - sprite_3d_order.reserve( - core.vk_renderer->sprites_3d_to_draw[current_frame].size()); - - for(std::shared_ptr sprite: - core.vk_renderer->sprites_3d_to_draw[current_frame]) - sprite_3d_order.emplace_back( - sprite, glm::distance(*view->camera_position, *sprite->position)); - - std::sort(sprite_3d_order.rbegin(), sprite_3d_order.rend()); - } - - // Draw sprites - for(auto& sprite: sprite_3d_order) - { - std::array vk_descriptor_sets{ - core.vk_light->descriptor_sets_world[image_index], - view->descriptor_sets_3d[image_index], - sprite.sprite_3d->descriptor_sets[image_index], - sprite.sprite_3d->sprite->texture->descriptor_sets[image_index]}; - VkDeviceSize offsets[]{0}; - - vkCmdBindVertexBuffers( - draw_command_buffer, 0, 1, - &sprite.sprite_3d->sprite->vertex_buffer->buffer, offsets); - vkCmdBindDescriptorSets( - draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - core.vk_graphics_pipeline_3d_layout->pipeline, 0, - vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr); - - UDOSprite3D ubo_sprite_3d{}; - ubo_sprite_3d.position = *sprite.sprite_3d->position; - ubo_sprite_3d.size = sprite.sprite_3d->size; - sprite.sprite_3d->uniform_buffers[image_index].copy_data(&ubo_sprite_3d); - - vkCmdDraw(draw_command_buffer, Sprite::vertex_count, 1, 0, 0); - } -} - -} diff --git a/src/blucat/graphics_pipeline_sprite_3d.hpp b/src/blucat/graphics_pipeline_sprite_3d.hpp deleted file mode 100644 index 237094d..0000000 --- a/src/blucat/graphics_pipeline_sprite_3d.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_GRAPHICS_PIPELINE_SPRITE_3D_H -#define CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_SPRITE_3D_H 1 - -#include - -#include "vulkan.hpp" -#include "command_pool.hpp" -#include "sprite_3d.hpp" -#include "view_3d.hpp" - -namespace BluCat -{ - -struct GraphicsPipelineSprite3D -{ - VkPipeline graphic_pipeline; - - GraphicsPipelineSprite3D(); - ~GraphicsPipelineSprite3D(); - - void - draw(std::shared_ptr view, const VkCommandBuffer draw_command_buffer, - const size_t current_frame, const uint32_t image_index); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_GRAPHICS_PIPELINE_SPRITE_3D_H */ diff --git a/src/blucat/image.cpp b/src/blucat/image.cpp deleted file mode 100644 index 81b1563..0000000 --- a/src/blucat/image.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2022-2024 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 "image.hpp" - -#include "core.hpp" - -namespace BluCat::Image -{ - -Error::Error(const std::string &m): - error(m) -{ -} - -Error::Error(const char &m): - Error{std::string{m}} -{ -} - -const char* -Error::what() const noexcept -{ - return this->error.c_str(); -} - -void -create( - BluCat::Device *device, - VkImage *image, - VkDeviceMemory *image_memory, - VkFormat format, - const VkExtent3D &extent3d, - uint32_t mip_levels, - VkImageTiling image_tiling, - VkImageUsageFlags usage) -{ - VkImageCreateInfo image_info{}; - image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_info.pNext = nullptr; - image_info.flags = 0; - image_info.imageType = VK_IMAGE_TYPE_2D; - image_info.format = format; - image_info.extent = extent3d; - image_info.mipLevels = mip_levels; - image_info.arrayLayers = 1; - image_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_info.tiling = image_tiling; - image_info.usage = usage; - image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.queueFamilyIndexCount = 0; - image_info.pQueueFamilyIndices = nullptr; - image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - if(vkCreateImage( - device->device, &image_info, nullptr, image) != VK_SUCCESS) - throw Error{"Failed to create Vulkan image."}; - - VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(device->device, *image, &memory_requirements); - - VkMemoryAllocateInfo memory_alloc_info{}; - memory_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_alloc_info.allocationSize = memory_requirements.size; - device->select_memory_type(&memory_alloc_info.memoryTypeIndex, - &memory_requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - if(vkAllocateMemory( - device->device, &memory_alloc_info, nullptr, image_memory) - != VK_SUCCESS) - { - vkDestroyImage(device->device, *image, nullptr); - throw Error{"Failed to allocate memory for Vulkan image."}; - } - - vkBindImageMemory(device->device, *image, *image_memory, 0); -} - -void move_image_state( - VkCommandBuffer vk_command_buffer, VkImage vk_image, VkFormat format, - VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, - VkImageLayout old_layout, VkImageLayout new_layout, - VkPipelineStageFlags source_stage, VkPipelineStageFlags destination_stage) -{ - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.pNext = nullptr; - barrier.srcAccessMask = src_access_mask; - barrier.dstAccessMask = dst_access_mask; - barrier.oldLayout = old_layout; - barrier.newLayout = new_layout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = vk_image; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - - vkCmdPipelineBarrier( - vk_command_buffer, source_stage, destination_stage, 0, 0, nullptr, - 0, nullptr, 1, &barrier); -} - -void create_view( - BluCat::Device *device, - VkImageView *image_view, - const VkImage &image, - VkFormat format, - VkImageAspectFlags image_aspect_flags) -{ - VkImageViewCreateInfo image_view_info{}; - image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_info.pNext = nullptr; - image_view_info.flags = 0; - image_view_info.image = image; - image_view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_info.format = format; - image_view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_info.subresourceRange.aspectMask = image_aspect_flags; - image_view_info.subresourceRange.baseMipLevel = 0; - image_view_info.subresourceRange.levelCount = 1; - image_view_info.subresourceRange.baseArrayLayer = 0; - image_view_info.subresourceRange.layerCount = 1; - - if(vkCreateImageView(device->device, &image_view_info, - nullptr, image_view) != VK_SUCCESS) - throw Error{"Failed to create texture view."}; - -} - -} diff --git a/src/blucat/image.hpp b/src/blucat/image.hpp deleted file mode 100644 index 67c1933..0000000 --- a/src/blucat/image.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2022-2024 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 BLUE_KITTY_BLUCAT_IMAGE_H -#define BLUE_KITTY_BLUCAT_IMAGE_H 1 - -#include -#include - -#include "vulkan.hpp" -#include "device.hpp" - -namespace BluCat::Image -{ - -struct Error: public std::exception -{ - Error(const std::string &m); - Error(const char &m); - - const char* - what() const noexcept; - -private: - std::string error; -}; - -void -create( - BluCat::Device *device, - VkImage *image, - VkDeviceMemory *image_memory, - VkFormat format, - const VkExtent3D &extent3d, - uint32_t mip_levels, - VkImageTiling image_tiling, - VkImageUsageFlags usage); - -void -move_image_state( - VkCommandBuffer vk_command_buffer, - VkImage vk_image, - VkFormat format, - VkAccessFlags src_access_mask, - VkAccessFlags dst_access_mask, - VkImageLayout old_layout, - VkImageLayout new_layout, - VkPipelineStageFlags source_stage, - VkPipelineStageFlags destination_stage); - -void -create_view( - BluCat::Device *device, - VkImageView *image_view, - const VkImage &image, - VkFormat format, - VkImageAspectFlags image_aspect_flags); -} - -#endif /* CANDY_GEAR_BLUCAT_IMAGE_H */ diff --git a/src/blucat/job_queue.cpp b/src/blucat/job_queue.cpp deleted file mode 100644 index 49bf34f..0000000 --- a/src/blucat/job_queue.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 "job_queue.hpp" - -#include - -JobQueue::JobQueue(): - jobs{}, - _stop{false} -{ -} - -void -JobQueue::stop() -{ - using namespace std::chrono_literals; - - while(!this->jobs.empty()) std::this_thread::sleep_for(1000ms); - this->_stop = true; - this->condition.notify_all(); -} - -void -JobQueue::push(Job job) -{ - std::unique_lock lock{this->access}; - this->jobs.push_back(job); - this->condition.notify_one(); -} - -Job -JobQueue::pop() -{ - std::unique_lock lock{this->access}; - this->condition.wait(lock, [this]{ - return !this->jobs.empty() || this->_stop;}); - if(!this->jobs.empty()) - { - auto job{std::move(this->jobs.front())}; - this->jobs.pop_front(); - return job; - } - else - { - return Job{nullptr}; - } -} diff --git a/src/blucat/job_queue.hpp b/src/blucat/job_queue.hpp deleted file mode 100644 index 2a7735b..0000000 --- a/src/blucat/job_queue.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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_JOB_QUEUE_H -#define CANDY_GEAR_JOB_QUEUE_H 1 - -#include -#include -#include -#include -#include - -class Worker; - -typedef std::function Job; - -class JobQueue -{ - friend Worker; - - std::mutex access; - std::condition_variable condition; - std::atomic _stop; - std::deque jobs; - - Job - pop(); - -public: - JobQueue(); - - void - stop(); - - void - push(Job job); -}; - -#endif /* CANDY_GEAR_JOB_QUEUE_H */ diff --git a/src/blucat/light.cpp b/src/blucat/light.cpp deleted file mode 100644 index 43611a1..0000000 --- a/src/blucat/light.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2022-2024 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 "light.hpp" - -#include - -#include "core.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_world_vert_uniform_buffer(void *obj) -{ - auto self = static_cast(obj); - - try - { - self->ub_world_vert.reserve(BluCat::core.vk_swapchain->images_count); - for(auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - self->ub_world_vert.emplace_back( - BluCat::core.vk_device_with_swapchain, sizeof(BluCat::UDOWorld3D_Vert)); - } - catch(const std::exception& e) - { - throw CommandError{e.what()}; - } -} - -void -unload_world_vert_uniform_buffer(void *obj) -{ - auto self = static_cast(obj); - - self->ub_world_vert.clear(); -} - -void -load_world_frag_uniform_buffer(void *obj) -{ - auto self = static_cast(obj); - - try - { - self->ub_world_frag.reserve(BluCat::core.vk_swapchain->images_count); - for(auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - self->ub_world_frag.emplace_back( - BluCat::core.vk_device_with_swapchain, sizeof(BluCat::UDOWorld3D_Frag)); - } - catch(const std::exception& e) - { - throw CommandError{e.what()}; - } -} - -void -unload_world_frag_uniform_buffer(void *obj) -{ - auto self = static_cast(obj); - - self->ub_world_frag.clear(); -} - -void -load_descriptor_pool(void *obj) -{ - auto self = static_cast(obj); - - uint32_t uniform_buffers_count = - self->ub_world_vert.size() + self->ub_world_vert.size(); - - VkDescriptorPoolSize descriptor_pool_size{}; - descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_pool_size.descriptorCount = uniform_buffers_count; - - VkDescriptorPoolCreateInfo pool_info{}; - pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - pool_info.pNext = nullptr; - pool_info.flags = 0; - pool_info.maxSets = uniform_buffers_count; - pool_info.poolSizeCount = 1; - pool_info.pPoolSizes = &descriptor_pool_size; - - if(vkCreateDescriptorPool( - BluCat::core.vk_device_with_swapchain->device, &pool_info, nullptr, - &self->descriptor_pool) != VK_SUCCESS) - throw CommandError{"Failed to create a Vulkan descriptor pool."}; -} - -void -unload_descriptor_pool(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyDescriptorPool( - BluCat::core.vk_device_with_swapchain->device, self->descriptor_pool, - nullptr); -} - -void -load_descriptor_sets_world(void *obj) -{ - auto self = static_cast(obj); - - std::vector layouts( - BluCat::core.vk_swapchain->images_count, - BluCat::core.vk_descriptor_set_layout->world); - - 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_world.resize(layouts.size()); - if(vkAllocateDescriptorSets( - BluCat::core.vk_device_with_swapchain->device, &alloc_info, - self->descriptor_sets_world.data()) != VK_SUCCESS) - throw CommandError{"Failed to create Vulkan world descriptor set."}; -} - -void -load_resources_to_descriptor_sets(void *obj) -{ - auto self = static_cast(obj); - - for(auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - { - VkDescriptorBufferInfo world_vert_info{}; - world_vert_info.buffer = self->ub_world_vert[i].buffer; - world_vert_info.offset = 0; - world_vert_info.range = sizeof(BluCat::UDOWorld3D_Vert); - - VkDescriptorBufferInfo world_frag_info{}; - world_frag_info.buffer = self->ub_world_frag[i].buffer; - world_frag_info.offset = 0; - world_frag_info.range = sizeof(BluCat::UDOWorld3D_Frag); - - std::array write_descriptors{}; - write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_descriptors[0].dstSet = self->descriptor_sets_world[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 = &world_vert_info; - write_descriptors[0].pImageInfo = nullptr; - write_descriptors[0].pTexelBufferView = nullptr; - - write_descriptors[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_descriptors[1].dstSet = self->descriptor_sets_world[i]; - write_descriptors[1].dstBinding = 1; - write_descriptors[1].dstArrayElement = 0; - write_descriptors[1].descriptorCount = 1; - write_descriptors[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - write_descriptors[1].pBufferInfo = &world_frag_info; - write_descriptors[1].pImageInfo = nullptr; - write_descriptors[1].pTexelBufferView = nullptr; - - vkUpdateDescriptorSets( - BluCat::core.vk_device_with_swapchain->device, write_descriptors.size(), - write_descriptors.data(), 0, nullptr); - } -} - -const CommandChain loader{ - {&load_world_vert_uniform_buffer, &unload_world_vert_uniform_buffer}, - {&load_world_frag_uniform_buffer, &unload_world_frag_uniform_buffer}, - {&load_descriptor_pool, &unload_descriptor_pool}, - // By destroying the pool the sets are also destroyed. - {&load_descriptor_sets_world, nullptr}, - {&load_resources_to_descriptor_sets, nullptr} -}; - -} - -namespace BluCat -{ - -Light::Light() -{ - loader.execute(this); -} - -Light::~Light() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/light.hpp b/src/blucat/light.hpp deleted file mode 100644 index f5f153e..0000000 --- a/src/blucat/light.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_LIGHT_H -#define CANDY_GEAR_BLUCAT_LIGHT_H 1 - -#include "vulkan.hpp" -#include "uniform_buffer.hpp" - -namespace BluCat -{ - -struct Light -{ - // FIXME: if this vector get resized, it will cause a segmentation fault! - std::vector ub_world_vert; - std::vector ub_world_frag; - - VkDescriptorPool descriptor_pool; - std::vector descriptor_sets_world; - - Light(); - ~Light(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_LIGHT_H */ diff --git a/src/blucat/log.cpp b/src/blucat/log.cpp deleted file mode 100644 index 78044c4..0000000 --- a/src/blucat/log.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 "log.hpp" - -#include - -namespace Log -{ - -void -Logger::message(Level lvl, const char* text) -{ - std::cout << "["; - switch(lvl) - { - case Level::Fatal: - std::cout << "\e[1;35mFatal\e[0;0m"; - break; - case Level::Error: - std::cout << "\e[1;31mError\e[0;0m"; - break; - case Level::Warning: - std::cout << "\e[1;33mWarning\e[0;0m"; - break; - case Level::Information: - std::cout << "\e[1;32mInformation\e[0;0m"; - break; - case Level::Debug: - std::cout << "\e[1;36mDebug\e[0;0m"; - break; - case Level::Trace: - std::cout << "\e[1;34mTrace\e[0;0m"; - break; - } - std::cout << "] "; - std::cout << text << std::endl; -} - -} diff --git a/src/blucat/log.hpp b/src/blucat/log.hpp deleted file mode 100644 index 2856f20..0000000 --- a/src/blucat/log.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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_LOG_H -#define CANDY_GEAR_LOG_H 1 - -#include - -#define CANDY_GEAR_LOG_LEVEL_FATAL 0 -#define CANDY_GEAR_LOG_LEVEL_ERROR 1 -#define CANDY_GEAR_LOG_LEVEL_WARNING 2 -#define CANDY_GEAR_LOG_LEVEL_INFORMATION 3 -#define CANDY_GEAR_LOG_LEVEL_DEBUG 4 -#define CANDY_GEAR_LOG_LEVEL_TRACE 5 - -namespace Log -{ - -enum class Level -{ - Fatal = CANDY_GEAR_LOG_LEVEL_FATAL, - Error = CANDY_GEAR_LOG_LEVEL_ERROR, - Warning = CANDY_GEAR_LOG_LEVEL_WARNING, - Information = CANDY_GEAR_LOG_LEVEL_INFORMATION, - Debug = CANDY_GEAR_LOG_LEVEL_DEBUG, - Trace = CANDY_GEAR_LOG_LEVEL_TRACE -}; - -struct Logger -{ - - void - message(Level lvl, const char* text); - - inline void - message(Level lvl, const std::string &text) {message(lvl, text.c_str());} -}; - -} - -#endif /* CANDY_GEAR_LOG_H */ diff --git a/src/blucat/qoi.cpp b/src/blucat/qoi.cpp deleted file mode 100644 index 3169ecc..0000000 --- a/src/blucat/qoi.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2022-2024 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 "qoi.hpp" - -#include -#include - -#include "binary_reader.hpp" - -namespace -{ - -const char MAGIC[]{"qoif"}; -const int HEADER_SIZE{14}; -const uint8_t PADDING[8]{0,0,0,0,0,0,0,1}; -const unsigned int PIXELS_MAX{400000000}; - -const int OP_INDEX{0b00000000}; -const int OP_DIFF {0b01000000}; -const int OP_LUMA {0b10000000}; -const int OP_RUN {0b11000000}; -const int OP_RGB {0b11111110}; -const int OP_RGBA {0b11111111}; - -const int MASK_2_BITS{0b11000000}; - -struct RGBA -{ - uint8_t red, green, blue, alpha; - - RGBA(); - RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); -}; - -RGBA::RGBA(): - red{0}, - green{0}, - blue{0}, - alpha{0} -{ -} - -RGBA::RGBA(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha): - red{red}, - green{green}, - blue{blue}, - alpha{alpha} -{ -} - -struct Pixel -{ - union - { - RGBA colors; - uint32_t value; - }; - - Pixel(); - Pixel(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); -}; - -Pixel::Pixel(): - colors{} -{ -} - -Pixel::Pixel(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha): - colors(red, green, blue, alpha) -{ -} - -inline int -color_hash(const RGBA &colors) -{ - return colors.red*3 + colors.green*5 + colors.blue*7 + colors.alpha*11; -} - -} - -namespace BluCat::QOI -{ - -Image::Image(const char *file_path, uint8_t channels): - channels{channels} -{ - if(this->channels != 0 && this->channels != 3 && this->channels != 4) - { - throw std::invalid_argument{"invalid number of channels"}; - } - - BinaryReader input{file_path}; - if(input.size() < HEADER_SIZE + (int)sizeof(PADDING)) - { - throw std::runtime_error{"invalid QOI file"}; - } - - input.read_chars(this->header.magic, 4); - this->header.width = input.read_ui32(); - this->header.height = input.read_ui32(); - this->header.channels = input.read_ui8(); - this->header.colorspace = input.read_ui8(); - - if(this->header.width == 0 || this->header.height == 0 || - this->header.channels < 3 || this->header.channels > 4 || - this->header.colorspace > 1 || - this->header.height >= PIXELS_MAX / this->header.width) - { - throw std::runtime_error{"QOI file have an invalid header"}; - } - - if(this->channels == 0) this->channels = this->header.channels; - - uint32_t num_pixels{this->header.width * this->header.height}; - this->pixels_len = num_pixels * this->channels; - this->pixels = new uint8_t[this->pixels_len]; - - std::array index; - Pixel pixel(0, 0, 0, 255); - int chunks_len = input.size() - (int)sizeof(PADDING); - - /* - This algorithm is based on the original implementation that is in GitHub: - https://github.com/phoboslab/qoi - - For information about the QOI image format, see: https://qoiformat.org/ - */ - int pixel_p{0}; - int run{0}; - for(uint32_t decoded_pixel{0}; decoded_pixel < num_pixels; decoded_pixel++) - { - if(run > 0) - { - run--; - } - else if(input.pointer() < chunks_len) - { - int b1 = input.read_ui8(); - - if (b1 == OP_RGB) - { - pixel.colors.red = input.read_ui8(); - pixel.colors.green = input.read_ui8(); - pixel.colors.blue = input.read_ui8(); - } - else if (b1 == OP_RGBA) - { - pixel.colors.red = input.read_ui8(); - pixel.colors.green = input.read_ui8(); - pixel.colors.blue = input.read_ui8(); - pixel.colors.alpha = input.read_ui8(); - } - else if ((b1 & MASK_2_BITS) == OP_INDEX) - { - pixel = index[b1]; - } - else if ((b1 & MASK_2_BITS) == OP_DIFF) - { - pixel.colors.red += ((b1 >> 4) & 0x03) - 2; - pixel.colors.green += ((b1 >> 2) & 0x03) - 2; - pixel.colors.blue += (b1 & 0x03) - 2; - } - else if ((b1 & MASK_2_BITS) == OP_LUMA) - { - int b2 = input.read_ui8(); - int vg = (b1 & 0x3f) - 32; - pixel.colors.red += vg - 8 + ((b2 >> 4) & 0x0f); - pixel.colors.green += vg; - pixel.colors.blue += vg - 8 + (b2 & 0x0f); - } - else if ((b1 & MASK_2_BITS) == OP_RUN) - { - run = (b1 & 0x3f); - } - - index[color_hash(pixel.colors) % 64] = pixel; - } - - this->pixels[pixel_p++] = pixel.colors.red; - this->pixels[pixel_p++] = pixel.colors.green; - this->pixels[pixel_p++] = pixel.colors.blue; - if(this->channels == 4) this->pixels[pixel_p++] = pixel.colors.alpha; - } -} - -Image::~Image() -{ - delete[] this->pixels; -} - -} diff --git a/src/blucat/qoi.hpp b/src/blucat/qoi.hpp deleted file mode 100644 index cd33205..0000000 --- a/src/blucat/qoi.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2022-2024 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 - -namespace BluCat::QOI -{ - struct Header - { - char magic[4]; - uint32_t width; - uint32_t height; - uint8_t channels; - uint8_t colorspace; - }; - - struct Image - { - Header header; - uint32_t pixels_len; - uint8_t channels; - uint8_t *pixels; - - Image(const char *file_path, uint8_t channels); - ~Image(); - }; - -} diff --git a/src/blucat/queue.cpp b/src/blucat/queue.cpp deleted file mode 100644 index c00d874..0000000 --- a/src/blucat/queue.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2022-2024 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 "queue.hpp" - -#include "queue_family.hpp" - -namespace BluCat -{ - -Queue::Queue( - BluCat::QueueFamily *queue_family, VkQueue queue, int queue_index): - queue_family{queue_family}, - queue{queue}, - queue_index{queue_index} -{ - this->queue_family->queue_states[this->queue_index].busy = true; -} - -Queue::Queue(Queue &&that): - queue{that.queue}, - queue_family{that.queue_family}, - queue_index{that.queue_index} -{ - that.queue_family = nullptr; -} - -Queue& Queue::operator=(Queue &&that) -{ - this->queue = that.queue; - this->queue_family = that.queue_family; - this->queue_index = that.queue_index; - - that.queue_family = nullptr; - - return *this; -} - -Queue::~Queue() -{ - if(this->queue_family) - { - std::unique_lock lock{this->queue_family->queue_mutex}; - this->queue_family->queue_states[this->queue_index].busy = false; - } -} - -} diff --git a/src/blucat/queue.hpp b/src/blucat/queue.hpp deleted file mode 100644 index 3be1a94..0000000 --- a/src/blucat/queue.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_QUEUE_H -#define CANDY_GEAR_BLUCAT_QUEUE_H 1 - -#include "vulkan.hpp" - -namespace BluCat -{ -class QueueFamily; - -struct Queue -{ - friend class BluCat::QueueFamily; - - Queue(const Queue &t) = delete; - Queue& operator=(const Queue &t) = delete; - - VkQueue queue; - - template - void submit_one_time_command( - const VkCommandBuffer vk_command_buffer, T commands); - - Queue(Queue &&that); - Queue& operator=(Queue &&that); - - ~Queue(); - -private: - BluCat::QueueFamily *queue_family; - int queue_index; - - Queue(BluCat::QueueFamily *queue_family, VkQueue queue, int queue_index); -}; - -template void -Queue::submit_one_time_command( - const VkCommandBuffer vk_command_buffer, T commands) -{ - VkCommandBufferBeginInfo buffer_begin_info{}; - buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - - vkBeginCommandBuffer(vk_command_buffer, &buffer_begin_info); - - commands(); - - vkEndCommandBuffer(vk_command_buffer); - - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = nullptr; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = nullptr; - submit_info.pWaitDstStageMask = nullptr; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &vk_command_buffer; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = nullptr; - - vkQueueSubmit(this->queue, 1, &submit_info, VK_NULL_HANDLE); - vkQueueWaitIdle(this->queue); -} - -} - -#endif /* CANDY_GEAR_BLUCAT_QUEUE_H */ diff --git a/src/blucat/queue_family.cpp b/src/blucat/queue_family.cpp deleted file mode 100644 index da799c0..0000000 --- a/src/blucat/queue_family.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2022-2024 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 "queue_family.hpp" - -#ifdef DEBUG -#include -#endif - -#include "core.hpp" - -namespace BluCat -{ - -QueueFamily::QueueFamily( - BluCat::Device *device, uint32_t family_index, - const VkQueueFamilyProperties &queue_family_properties): - queue_mutex{} -{ - -#ifdef DEBUG - std::stringstream message{}; - message << "Queue quantity: " << queue_family_properties.queueCount << - std::endl; - message << "Graphics: " << - (queue_family_properties.queueFlags & VK_QUEUE_GRAPHICS_BIT ? - "true" : "false") << std::endl; - message << "Compute: " << - (queue_family_properties.queueFlags & VK_QUEUE_COMPUTE_BIT ? - "true" : "false") << std::endl; - message << "Transfer: " << - (queue_family_properties.queueFlags & VK_QUEUE_TRANSFER_BIT ? - "true" : "false") << std::endl; - message << "Sparse Binding: " << - (queue_family_properties.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT ? - "true" : "false") << std::endl; - core.log.message(Log::Level::Trace, message.str()); -#endif - - this->device = device; - this->family_index = family_index; - this->family_properties = queue_family_properties; - - // Create queues - { - auto queue_count = this->family_properties.queueCount; - this->queue_states.resize(queue_count); - - for(auto i{0}; i < queue_count; i++) - { - vkGetDeviceQueue(device->device, this->family_index, i, - &this->queue_states[i].queue); - if(this->queue_states[i].queue == VK_NULL_HANDLE) - throw std::runtime_error("Failed to get Vulkan queue."); - } - } -} - -Queue -QueueFamily::get_queue() -{ - std::unique_lock lock{this->queue_mutex}; - - for(auto i{0}; i < this->queue_states.size(); i++) - if(!this->queue_states[i].busy) - return Queue(this, this->queue_states[i].queue, i); - - throw std::length_error("No free queues found."); -} - -} diff --git a/src/blucat/queue_family.hpp b/src/blucat/queue_family.hpp deleted file mode 100644 index 988748f..0000000 --- a/src/blucat/queue_family.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_QUEUE_FAMILY_H -#define CANDY_GEAR_BLUCAT_QUEUE_FAMILY_H 1 - -#include -#include - -#include "vulkan.hpp" -#include "queue.hpp" - -namespace BluCat -{ -class Device; - -struct QueueState -{ - VkQueue queue; - bool busy; -}; - -class QueueFamily -{ - friend class Queue; - - std::mutex queue_mutex; - std::vector queue_states; - -public: - BluCat::Device *device; - - uint32_t family_index; - VkQueueFamilyProperties family_properties; - - QueueFamily(BluCat::Device *device, uint32_t family_index, - const VkQueueFamilyProperties &queue_family_properties); - - Queue - get_queue(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_QUEUE_FAMILY_H */ diff --git a/src/blucat/rectangle.cpp b/src/blucat/rectangle.cpp deleted file mode 100644 index 34f844d..0000000 --- a/src/blucat/rectangle.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2022-2024 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" - -namespace BluCat -{ - -const int Rectangle::VertexCount{4}; - -Rectangle::Rectangle(glm::vec4 position, glm::vec3 color): - position{position}, - color{color} -{ -} - -} diff --git a/src/blucat/rectangle.hpp b/src/blucat/rectangle.hpp deleted file mode 100644 index 57c9d4f..0000000 --- a/src/blucat/rectangle.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_RECTANGLE_H -#define CANDY_GEAR_BLUCAT_RECTANGLE_H 1 - -#include - -#include "vulkan.hpp" -#include "destination_buffer.hpp" -#include "queue_family.hpp" -#include "uniform_buffer.hpp" - -namespace BluCat -{ - -struct Rectangle -{ - static const int VertexCount; - - glm::vec4 position; - glm::vec3 color; - - Rectangle(glm::vec4 position, glm::vec3 color); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_RECTANGLE_H */ diff --git a/src/blucat/render_pass.cpp b/src/blucat/render_pass.cpp deleted file mode 100644 index 2effe6b..0000000 --- a/src/blucat/render_pass.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2022-2024 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 "render_pass.hpp" - -#include - -#include "core.hpp" - -namespace -{ - -void -load_3d(void *obj) -{ - auto self = static_cast(obj); - - std::array attachments{}; - // Color attachment. - attachments[0].flags = 0; - attachments[0].format = BluCat::core.vk_swapchain->image_format; - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - 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_UNDEFINED; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - // Depth attachment. - attachments[1].flags = 0; - attachments[1].format = VK_FORMAT_D32_SFLOAT; - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments[1].finalLayout = - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference color_attachment_ref{}; - color_attachment_ref.attachment = 0; - color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkAttachmentReference depth_attachment_ref{}; - depth_attachment_ref.attachment = 1; - depth_attachment_ref.layout = - VK_IMAGE_LAYOUT_DEPTH_STENCIL_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 = &depth_attachment_ref; - 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( - BluCat::core.vk_device_with_swapchain->device, &render_pass_info, - nullptr, &self->pipeline_3d) != VK_SUCCESS) - throw CommandError{"Failed to create Vulkan Render Pass 3D."}; -} - -void -unload_3d(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyRenderPass( - BluCat::core.vk_device_with_swapchain->device, self->pipeline_3d, nullptr); -} - -void -load_2d(void *obj) -{ - auto self = static_cast(obj); - - std::array attachments{}; - // Color attachment. - attachments[0].flags = 0; - attachments[0].format = BluCat::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( - BluCat::core.vk_device_with_swapchain->device, &render_pass_info, - nullptr, &self->pipeline_2d) != VK_SUCCESS) - throw CommandError{"Failed to create Vulkan Render Pass 2D."}; -} - -void -unload_2d(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyRenderPass( - BluCat::core.vk_device_with_swapchain->device, self->pipeline_2d, nullptr); -} - -const CommandChain loader{ - {&load_3d, &unload_3d}, - {&load_2d, &unload_2d} -}; - -} - -namespace BluCat -{ - -RenderPass::RenderPass() -{ - loader.execute(this); -} - -RenderPass::~RenderPass() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/render_pass.hpp b/src/blucat/render_pass.hpp deleted file mode 100644 index d55f908..0000000 --- a/src/blucat/render_pass.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_RENDER_PASS_H -#define CANDY_GEAR_BLUCAT_RENDER_PASS_H 1 - -#include "vulkan.hpp" - -namespace BluCat -{ - -struct RenderPass -{ - VkRenderPass pipeline_2d; - VkRenderPass pipeline_3d; - - RenderPass(); - ~RenderPass(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_RENDER_PASS_H */ diff --git a/src/blucat/renderer.cpp b/src/blucat/renderer.cpp deleted file mode 100644 index 18d3976..0000000 --- a/src/blucat/renderer.cpp +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright 2022-2024 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 "renderer.hpp" - -#include - -#include "core.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_descriptor_pool(void *obj) -{ - auto self = static_cast(obj); - - uint32_t uniform_buffer_count = 0; - for(auto &view : self->views_3d) - uniform_buffer_count += (view->ub_3d.size() + view->ub_2d.size()); - for(auto &view : self->views_2d) - uniform_buffer_count += (view->ub_2d.size()); - - VkDescriptorPoolSize descriptor_pool_size{}; - descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_pool_size.descriptorCount = uniform_buffer_count; - - VkDescriptorPoolCreateInfo pool_info{}; - pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - pool_info.pNext = nullptr; - pool_info.flags = 0; - pool_info.maxSets = uniform_buffer_count; - pool_info.poolSizeCount = 1; - pool_info.pPoolSizes = &descriptor_pool_size; - - if(vkCreateDescriptorPool( - BluCat::core.vk_device_with_swapchain->device, &pool_info, nullptr, - &self->descriptor_pool) != VK_SUCCESS) - throw CommandError{"Failed to create a Vulkan descriptor pool."}; - - for(auto &view : self->views_3d) - view->load_descriptor_sets(self->descriptor_pool); - for(auto &view : self->views_2d) - view->load_descriptor_sets(self->descriptor_pool); -} - -void -unload_descriptor_pool(void *obj) -{ - auto self = static_cast(obj); - - for(auto &view : self->views_3d) view->unload_descriptor_sets(); - for(auto &view : self->views_2d) view->unload_descriptor_sets(); - - vkDestroyDescriptorPool( - BluCat::core.vk_device_with_swapchain->device, self->descriptor_pool, - nullptr); -} - -void -load_queue_family(void *obj) -{ - auto self = static_cast(obj); - - self->queue_family = - BluCat::core.vk_device_with_swapchain->get_queue_family_with_presentation(); -} - -void -load_command_pool(void *obj) -{ - auto self = static_cast(obj); - - VkCommandPoolCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - create_info.pNext = nullptr; - create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - create_info.queueFamilyIndex = self->queue_family->family_index; - - vkCreateCommandPool( - self->queue_family->device->device, &create_info, nullptr, - &self->command_pool); -} - -void -unload_command_pool(void *obj) -{ - auto self = static_cast(obj); - - self->wait_frame(); - vkDestroyCommandPool( - self->queue_family->device->device, self->command_pool, nullptr); -} - -void -load_draw_command_buffer(void *obj) -{ - auto self = static_cast(obj); - - // FIXME: 3 is a magical number, triple buffering. - self->draw_command_buffers.resize(3); - - VkCommandBufferAllocateInfo allocate_info{}; - allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocate_info.pNext = nullptr; - allocate_info.commandPool = self->command_pool; - allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocate_info.commandBufferCount = self->draw_command_buffers.size(); - - if(vkAllocateCommandBuffers( - self->queue_family->device->device, &allocate_info, - self->draw_command_buffers.data()) != VK_SUCCESS) - throw CommandError{"Vulkan draw command buffers could not be allocated."}; -} - -const CommandChain loader{ - {&load_descriptor_pool, &unload_descriptor_pool}, - {&load_queue_family, nullptr}, - {&load_command_pool, &unload_command_pool}, - {&load_draw_command_buffer, nullptr} -}; - -} - -namespace BluCat -{ - -Renderer::Renderer(std::vector> views_2d, - std::vector> views_3d): - skeletal_models_to_draw{BluCat::core.vk_swapchain->images_count}, - static_models_to_draw{BluCat::core.vk_swapchain->images_count}, - sprites_3d_to_draw{BluCat::core.vk_swapchain->images_count}, - views_2d{views_2d}, - views_3d{views_3d} -{ - loader.execute(this); -} - -Renderer::Renderer(std::initializer_list> views_2d, - std::initializer_list> views_3d): - Renderer(std::vector(views_2d), std::vector(views_3d)) -{ -} - -Renderer::~Renderer() -{ - loader.revert(this); -} - -// FIXME: this is a workaround to prevent a code to free some resource while -// it still being rendered. -void -Renderer::wait_frame() -{ - vkWaitForFences(BluCat::core.vk_device_with_swapchain->device, - BluCat::Swapchain::max_frames_in_flight, - BluCat::core.vk_swapchain->in_flight_fences.data(), VK_TRUE, - std::numeric_limits::max()); -} - -void -Renderer::draw() -{ - auto fence_status = vkGetFenceStatus( - BluCat::core.vk_device_with_swapchain->device, - BluCat::core.vk_swapchain->in_flight_fences[ - BluCat::core.vk_swapchain->current_frame]); - - if(fence_status == VK_SUCCESS) - { - auto next_frame = BluCat::core.vk_swapchain->current_frame + 1; - if(next_frame == Swapchain::max_frames_in_flight) next_frame = 0; - - vkResetFences(core.vk_device_with_swapchain->device, 1, - &BluCat::core.vk_swapchain->in_flight_fences[ - BluCat::core.vk_swapchain->current_frame]); - - uint32_t image_index; - vkAcquireNextImageKHR( - BluCat::core.vk_device_with_swapchain->device, - BluCat::core.vk_swapchain->swapchain, - std::numeric_limits::max(), - BluCat::core.vk_swapchain->image_available_semaphores[ - BluCat::core.vk_swapchain->current_frame], VK_NULL_HANDLE, &image_index); - - VkCommandBuffer draw_command_buffer = - this->draw_command_buffers[BluCat::core.vk_swapchain->current_frame]; - vkResetCommandBuffer(draw_command_buffer, 0); - - // Begin command buffer. - { - VkCommandBufferBeginInfo begin_info{}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.flags = 0; - begin_info.pInheritanceInfo = nullptr; - if (vkBeginCommandBuffer(draw_command_buffer, &begin_info) != VK_SUCCESS) - throw std::runtime_error{"Failed to beggin draw command buffer."}; - } - - // 3D drawing. - { - // Dark gray blue. - std::array clear_values{}; - clear_values[0].color = {0.12f, 0.12f, 0.18f, 1.0f}; - clear_values[1].depthStencil = {1.0f, 0}; - - { // Update world uniform buffer - UDOWorld3D_Vert ubo_world_3d_vert{}; - ubo_world_3d_vert.ambient_light_color = - glm::vec4{0.25, 0.25, 0.25, 1.0}; - BluCat::core.vk_light->ub_world_vert[image_index].copy_data( - &ubo_world_3d_vert); - - UDOWorld3D_Frag ubo_world_3d_frag{}; - ubo_world_3d_frag.directional_light_direction = - glm::vec3{-0.57735, 0.57735, -0.57735}; - ubo_world_3d_frag.directional_light_color = - glm::vec4{0.8, 0.8, 0.8, 1.0}; - BluCat::core.vk_light->ub_world_frag[image_index].copy_data( - &ubo_world_3d_frag); - } - - VkRenderPassBeginInfo render_pass_begin{}; - render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_begin.pNext = nullptr; - render_pass_begin.renderPass = BluCat::core.vk_render_pass->pipeline_3d; - render_pass_begin.framebuffer = - BluCat::core.vk_framebuffer->pipeline_3d[image_index]; - render_pass_begin.renderArea.offset = {0, 0}; - render_pass_begin.renderArea.extent = { - static_cast(BluCat::core.display_width), - static_cast(BluCat::core.display_height)}; - render_pass_begin.clearValueCount = clear_values.size(); - render_pass_begin.pClearValues = clear_values.data(); - - vkCmdBeginRenderPass( - draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); - } - - for(auto &view: this->views_3d) - { - { // 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(view->region.x); - vk_scissor.offset.y = static_cast(view->region.y); - vk_scissor.extent.width = static_cast(view->region.z); - vk_scissor.extent.height = static_cast(view->region.w); - vkCmdSetScissor(draw_command_buffer, 0, 1, &vk_scissor); - } - - BluCat::core.vk_graphics_pipeline_3d->draw( - view, draw_command_buffer, BluCat::core.vk_swapchain->current_frame, - image_index); - - BluCat::core.vk_graphics_pipeline_sprite_3d->draw( - view, draw_command_buffer, BluCat::core.vk_swapchain->current_frame, - image_index); - - BluCat::core.vk_graphics_pipeline_3d_skeletal->draw( - view, draw_command_buffer, BluCat::core.vk_swapchain->current_frame, - image_index); - - { // Update view uniform buffers - BluCat::UDOView3D ubo_view_3d{}; - - // View matrix. - glm::mat4 translation_matrix{1.0f}; - translation_matrix = glm::translate( - translation_matrix, *view->camera_position); - glm::mat4 rotation_matrix{glm::toMat4(*view->camera_orientation)}; - ubo_view_3d.view = glm::inverse(translation_matrix * rotation_matrix); - - // Projection matrix. - ubo_view_3d.proj = glm::perspective( - glm::radians(view->field_of_view), - view->region.z / view->region.w, - 0.1f, 100.0f); - - view->ub_3d[image_index].copy_data(&ubo_view_3d); - } - } - - vkCmdEndRenderPass(draw_command_buffer); - - { // 2D render pass - VkRenderPassBeginInfo render_pass_begin{}; - render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_begin.pNext = nullptr; - render_pass_begin.renderPass = BluCat::core.vk_render_pass->pipeline_2d; - render_pass_begin.framebuffer = - BluCat::core.vk_framebuffer->pipeline_2d[image_index]; - render_pass_begin.renderArea.offset = {0, 0}; - render_pass_begin.renderArea.extent = { - static_cast(BluCat::core.display_width), - static_cast(BluCat::core.display_height)}; - render_pass_begin.clearValueCount = 0; - render_pass_begin.pClearValues = nullptr; - - vkCmdBeginRenderPass( - draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); - - } - - { // 2D solid drawing - for(auto &view: this->views_2d) - BluCat::core.vk_graphics_pipeline_2d_solid->draw( - view, draw_command_buffer, BluCat::core.vk_swapchain->current_frame, - next_frame, image_index); - - for(auto &view: this->views_3d) - BluCat::core.vk_graphics_pipeline_2d_solid->draw( - view, draw_command_buffer, BluCat::core.vk_swapchain->current_frame, - next_frame, image_index); - } - - { // 2D wired drawing - for(auto &view: this->views_2d) - BluCat::core.vk_graphics_pipeline_2d_wired->draw( - view, draw_command_buffer, BluCat::core.vk_swapchain->current_frame, - next_frame, image_index); - - for(auto &view: this->views_3d) - BluCat::core.vk_graphics_pipeline_2d_wired->draw( - view, draw_command_buffer, BluCat::core.vk_swapchain->current_frame, - next_frame, image_index); - } - - vkCmdEndRenderPass(draw_command_buffer); - - // End command buffer. - if(vkEndCommandBuffer(draw_command_buffer) != VK_SUCCESS) - throw std::runtime_error{"Failed to end draw command buffer."}; - - // Submit drawing command. - { - auto queue{this->queue_family->get_queue()}; - - VkSemaphore wait_semaphores[]{ - BluCat::core.vk_swapchain->image_available_semaphores[ - BluCat::core.vk_swapchain->current_frame]}; - VkPipelineStageFlags wait_stages[] = - {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; - VkSemaphore signal_semaphores[]{ - BluCat::core.vk_swapchain->render_finished_semaphores[ - BluCat::core.vk_swapchain->current_frame]}; - - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = nullptr; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = wait_semaphores; - submit_info.pWaitDstStageMask = wait_stages; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &draw_command_buffer; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = signal_semaphores; - - if(vkQueueSubmit( - queue.queue, 1, &submit_info, BluCat::core.vk_swapchain->in_flight_fences[ - BluCat::core.vk_swapchain->current_frame]) != VK_SUCCESS) - throw std::runtime_error{"Failed to submit draw command buffer."}; - - VkSwapchainKHR swap_chains[]{BluCat::core.vk_swapchain->swapchain}; - - VkPresentInfoKHR present_info{}; - present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - present_info.pNext = nullptr; - present_info.waitSemaphoreCount = 1; - present_info.pWaitSemaphores = signal_semaphores; - present_info.swapchainCount = 1; - present_info.pSwapchains = swap_chains; - present_info.pImageIndices = &image_index; - present_info.pResults = nullptr; - - vkQueuePresentKHR(queue.queue, &present_info); - } - - // Prepare for the next frame. - { - this->skeletal_models_to_draw[next_frame].clear(); - this->static_models_to_draw[next_frame].clear(); - this->sprites_3d_to_draw[next_frame].clear(); - BluCat::core.vk_swapchain->current_frame = next_frame; - } - } - else - { - // Clear images for the current frame because we are skipping this frame. - this->skeletal_models_to_draw[ - BluCat::core.vk_swapchain->current_frame].clear(); - this->static_models_to_draw[ - BluCat::core.vk_swapchain->current_frame].clear(); - this->sprites_3d_to_draw[ - BluCat::core.vk_swapchain->current_frame].clear(); - for(auto &view: this->views_2d) - view->sprites_to_draw[BluCat::core.vk_swapchain->current_frame].clear(); - for(auto &view: this->views_3d) - view->sprites_to_draw[BluCat::core.vk_swapchain->current_frame].clear(); - } -} - -} diff --git a/src/blucat/renderer.hpp b/src/blucat/renderer.hpp deleted file mode 100644 index 55b0727..0000000 --- a/src/blucat/renderer.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_RENDERER_H -#define CANDY_GEAR_BLUCAT_RENDERER_H 1 - -#include -#include -#include - -#include "vulkan.hpp" -#include "skeletal_mesh.hpp" -#include "skeletal_model.hpp" -#include "sprite_3d.hpp" -#include "static_mesh.hpp" -#include "static_model.hpp" -#include "queue_family.hpp" -#include "view_2d.hpp" -#include "view_3d.hpp" - -namespace BluCat -{ - -struct Renderer -{ - std::vector< - std::unordered_map< - std::shared_ptr, - std::vector>>> - skeletal_models_to_draw; - - std::vector< - std::unordered_map< - std::shared_ptr, - std::vector>>> - static_models_to_draw; - - std::vector>> sprites_3d_to_draw; - - VkDescriptorPool descriptor_pool; - std::vector> views_2d; - std::vector> views_3d; - QueueFamily *queue_family; - VkCommandPool command_pool; - std::vector draw_command_buffers; - - Renderer(std::vector> views_2d, - std::vector> views_3d); - Renderer(std::initializer_list> views_2d, - std::initializer_list> views_3d); - ~Renderer(); - - void - wait_frame(); - - void - draw(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_RENDERER_H */ diff --git a/src/blucat/skeletal_mesh.cpp b/src/blucat/skeletal_mesh.cpp deleted file mode 100644 index d4fbfe7..0000000 --- a/src/blucat/skeletal_mesh.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2022-2024 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 "skeletal_mesh.hpp" - -#include "binary_reader.hpp" -#include "command.hpp" -#include "core.hpp" -#include "skeletal_mesh_vertex.hpp" - -namespace -{ - -// Data that is only needed for the command chain but not for the SkeletalMesh -// goes here. -struct MeshBuilder -{ - std::string mesh_path; - BluCat::SkeletalMesh *mesh; - - MeshBuilder(BluCat::SkeletalMesh *m, std::string mp); - MeshBuilder(BluCat::SkeletalMesh *m, const char* mp); -}; - -MeshBuilder::MeshBuilder(BluCat::SkeletalMesh *m, std::string mp): - mesh{m}, - mesh_path{mp} -{ -} - -MeshBuilder::MeshBuilder(BluCat::SkeletalMesh *m, const char *mp): - MeshBuilder{m, std::string(mp)} -{ -} - -void -load_mesh(void *obj) -{ - auto self = static_cast(obj); - - BinaryReader input{self->mesh_path}; - - self->mesh->queue_family = - BluCat::core.vk_device_with_swapchain->get_queue_family_with_graphics(); - - { // Load vertexes. - auto vertex_count{input.read_ui32()}; - std::vector vertexes{vertex_count}; - - for(auto i{0}; i < vertex_count; i++) - { - vertexes[i].position = input.read_vec3(); - vertexes[i].normal = input.read_vec3(); - vertexes[i].texture_coord = input.read_vec2(); - - for(auto ii{0}; ii < BluCat::SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES; - ii++) - vertexes[i].bone_ids[ii] = input.read_ui32(); - - for(auto ii{0}; ii < BluCat::SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES; - ii++) - vertexes[i].bone_weights[ii] = input.read_float(); - } - - void *vertexes_data{vertexes.data()}; - size_t vertexes_size = sizeof(vertexes[0]) * vertexes.size(); - self->mesh->source_vertex_buffer = new BluCat::SourceBuffer{ - self->mesh->queue_family->device, vertexes_data, vertexes_size}; - self->mesh->vertex_buffer = new BluCat::DestinationBuffer{ - self->mesh->queue_family, self->mesh->source_vertex_buffer, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}; - } - - { // Load indexes. - self->mesh->index_count = input.read_ui32(); - std::vector indexes(self->mesh->index_count); - - for(auto i{0}; i < self->mesh->index_count; i++) - indexes[i] = input.read_ui32(); - - void *indexes_data{indexes.data()}; - size_t indexes_size{sizeof(indexes[0]) * indexes.size()}; - BluCat::SourceBuffer source_index_buffer{ - self->mesh->queue_family->device, indexes_data, indexes_size}; - self->mesh->index_buffer = new BluCat::DestinationBuffer{ - self->mesh->queue_family, &source_index_buffer, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT}; - } - - { // Load bones - auto bone_count{input.read_ui32()}; - self->mesh->bones.reserve(bone_count); - for(int i{0}; i < bone_count; i++) - self->mesh->bones.emplace_back(input.read_mat4()); - } - - { // Load animations - auto num_animations{input.read_ui32()}; - self->mesh->animations.resize(num_animations); - for(uint32_t i{0}; i < num_animations; i++) - { - auto duration{input.read_double()}; - self->mesh->animations[i].final_time = (float)duration; - - auto ticks_per_second{input.read_double()}; - - auto num_bone_transforms{input.read_ui32()}; - std::vector *bone_transforms = - &(self->mesh->animations[i].bone_transforms); - bone_transforms->resize(num_bone_transforms); - for(uint32_t bone_transform_index{0}; - bone_transform_index < num_bone_transforms; bone_transform_index++) - { - auto bone_id{input.read_ui32()}; - - auto num_positions{input.read_ui32()}; - BluCat::Channel *positions = - &((*bone_transforms)[bone_transform_index].positions); - for(auto position_key_index{0}; position_key_index < num_positions; - position_key_index++) - { - auto vec3{input.read_vec3()}; - auto timestamp{input.read_double()}; - positions->key_frames.emplace_back( - vec3, static_cast(timestamp)); - } - - auto num_rotations{input.read_ui32()}; - BluCat::Channel *rotations = - &((*bone_transforms)[bone_transform_index].rotations); - for(auto rotation_key_index{0}; rotation_key_index < num_rotations; - rotation_key_index++) - { - auto quat{input.read_quat()}; - auto timestamp{input.read_double()}; - rotations->key_frames.emplace_back( - quat, static_cast(timestamp)); - } - - auto num_scales{input.read_ui32()}; - BluCat::Channel *scales = - &((*bone_transforms)[bone_transform_index].scales); - for(auto scaling_key_index{0}; scaling_key_index < num_scales; - scaling_key_index++) - { - auto vec3{input.read_vec3()}; - auto timestamp{input.read_double()}; - scales->key_frames.emplace_back(vec3, static_cast(timestamp)); - } - } - } - } -} - -void -unload_mesh(void *obj) -{ - auto self = static_cast(obj); - - delete self->mesh->index_buffer; - delete self->mesh->vertex_buffer; - delete self->mesh->source_vertex_buffer; -} - -static const CommandChain loader{ - {&load_mesh, &unload_mesh} -}; - -} - -namespace BluCat -{ - -SkeletalMesh::SkeletalMesh(std::string mesh_path) -{ - MeshBuilder mesh_builder(this, mesh_path); - loader.execute(&mesh_builder); -} - -SkeletalMesh::SkeletalMesh(const char* mesh_path): - SkeletalMesh{std::string(mesh_path)} -{ -} - -SkeletalMesh::~SkeletalMesh() -{ - MeshBuilder mesh_builder(this, ""); - loader.revert(&mesh_builder); -} - -} diff --git a/src/blucat/skeletal_mesh.hpp b/src/blucat/skeletal_mesh.hpp deleted file mode 100644 index 98506d7..0000000 --- a/src/blucat/skeletal_mesh.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_SKELETAL_MESH_H -#define CANDY_GEAR_BLUCAT_SKELETAL_MESH_H 1 - -#include -#include - -#include "animation.hpp" -#include "vulkan.hpp" -#include "destination_buffer.hpp" -#include "queue_family.hpp" -#include "uniform_buffer.hpp" -#include "texture.hpp" - -namespace BluCat -{ - -struct SkeletalMesh -{ - QueueFamily *queue_family; - - uint32_t index_count; - SourceBuffer *source_vertex_buffer; - DestinationBuffer *index_buffer; - DestinationBuffer *vertex_buffer; - - std::vector bones; - std::vector animations; - - SkeletalMesh(std::string mesh_path); - SkeletalMesh(const char* mesh_path); - ~SkeletalMesh(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_SKELETAL_MESH_H */ diff --git a/src/blucat/skeletal_mesh_vertex.hpp b/src/blucat/skeletal_mesh_vertex.hpp deleted file mode 100644 index 2e8a56f..0000000 --- a/src/blucat/skeletal_mesh_vertex.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_SKELETAL_MESH_VERTEX_H -#define CANDY_GEAR_BLUCAT_SKELETAL_MESH_VERTEX_H 1 - -#include "vulkan.hpp" - -namespace BluCat -{ - -// This variable define the maximum ammount of bones that can influence a -// vertex. -const int SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES{4}; -const int SKELETAL_MESH_MAX_NUM_OF_BONES{50}; - -struct SkeletalMeshVertex -{ - glm::vec3 position; - glm::vec3 normal; - glm::vec2 texture_coord; - - uint32_t bone_ids[SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES]; - float bone_weights[SKELETAL_MESH_MAX_NUM_OF_INFLUENCING_BONES]; -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_SKELETAL_MESH_VERTEX_H */ diff --git a/src/blucat/skeletal_model.cpp b/src/blucat/skeletal_model.cpp deleted file mode 100644 index fa46044..0000000 --- a/src/blucat/skeletal_model.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2022-2024 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 "skeletal_model.hpp" - -#include "core.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_uniform_buffers(void *obj) -{ - auto self = static_cast(obj); - - try - { - self->uniform_buffers.reserve(BluCat::core.vk_swapchain->images_count); - for(auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - self->uniform_buffers.emplace_back( - BluCat::core.vk_device_with_swapchain, - sizeof(BluCat::UDOSkeletalModel)); - } - catch(const std::exception& e) - { - throw CommandError{e.what()}; - } -} - -void -unload_uniform_buffers(void *obj) -{ - auto self = static_cast(obj); - - self->uniform_buffers.clear(); -} - -void -load_descriptor_set_pool(void *obj) -{ - auto self = static_cast(obj); - - std::array descriptor_pool_sizes{}; - descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_pool_sizes[0].descriptorCount = - self->uniform_buffers.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->uniform_buffers.size(); - pool_info.poolSizeCount = descriptor_pool_sizes.size(); - pool_info.pPoolSizes = descriptor_pool_sizes.data(); - - if(vkCreateDescriptorPool( - self->skeletal_mesh->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(obj); - - vkDestroyDescriptorPool( - self->skeletal_mesh->queue_family->device->device, self->descriptor_pool, - nullptr); -} - -void -load_descriptor_sets(void *obj) -{ - auto self = static_cast(obj); - - std::vector layouts( - BluCat::core.vk_swapchain->images_count, - BluCat::core.vk_descriptor_set_layout->model); - - 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->skeletal_mesh->queue_family->device->device, &alloc_info, - self->descriptor_sets.data()) != VK_SUCCESS) - CommandError{"Failed to create Vulkan descriptor set."}; -} - -void -load_buffers_to_descriptor_sets(void *obj) -{ - auto self = static_cast(obj); - - for(auto i{0}; i < self->uniform_buffers.size(); i++) - { - VkDescriptorBufferInfo buffer_info{}; - buffer_info.buffer = self->uniform_buffers[i].buffer; - buffer_info.offset = 0; - buffer_info.range = sizeof(BluCat::UDOSkeletalModel); - - std::array 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( - BluCat::core.vk_device_with_swapchain->device, write_descriptors.size(), - write_descriptors.data(), 0, nullptr); - } -} - -static const CommandChain loader{ - {&load_uniform_buffers, &unload_uniform_buffers}, - {&load_descriptor_set_pool, &unload_descriptor_set_pool}, - {&load_descriptor_sets, nullptr}, - {&load_buffers_to_descriptor_sets, nullptr} -}; - -} - -namespace BluCat -{ - -SkeletalModel::SkeletalModel( - std::shared_ptr skeletal_mesh, - std::shared_ptr texture, std::shared_ptr position, - std::shared_ptr orientation): - skeletal_mesh{skeletal_mesh}, - texture{texture}, - position{position}, - orientation{orientation}, - animation_index{0}, - animation_time{0.0f}, - bone_transforms(SKELETAL_MESH_MAX_NUM_OF_BONES) -{ - loader.execute(this); - - for(int i{0}; i < skeletal_mesh->bones.size(); i++) - this->bone_transforms[i] = skeletal_mesh->bones[i].offset_matrix; -} - -SkeletalModel::~SkeletalModel() -{ - loader.revert(this); -} - -void -SkeletalModel::tick(float delta) -{ - BluCat::Animation *current_animation = - &this->skeletal_mesh->animations[this->animation_index]; - - { // update time - this->animation_time += delta; - if(this->animation_time > current_animation->final_time) - { - this->animation_time -= current_animation->final_time; - for(BluCat::BoneTransform &bone_transform: - current_animation->bone_transforms) - { - bone_transform.positions.current_index = 0; - bone_transform.rotations.current_index = 0; - bone_transform.scales.current_index = 0; - } - } - } - - for(int i{0}; i < current_animation->bone_transforms.size(); i++) - { - BluCat::BoneTransform *bone_transform = ¤t_animation->bone_transforms[i]; - - auto position{bone_transform->positions.interpolate( - this->animation_time, - [](glm::vec3 frame) - { - return glm::translate(glm::mat4(1.0f), frame); - }, - [](glm::vec3 previous_frame, glm::vec3 next_frame, float scale_factor) - { - glm::vec3 final_position{glm::mix( - previous_frame, next_frame, scale_factor)}; - return glm::translate(glm::mat4(1.0f), final_position); - })}; - - auto rotation{bone_transform->rotations.interpolate( - this->animation_time, - [](glm::quat frame) - { - return glm::toMat4(glm::normalize(frame)); - }, - [](glm::quat previous_frame, glm::quat next_frame, float scale_factor) - { - return glm::toMat4(glm::slerp( - previous_frame, next_frame, scale_factor)); - })}; - - auto scale{bone_transform->scales.interpolate( - this->animation_time, - [](glm::vec3 frame) - { - return glm::scale(glm::mat4(1.0f), frame); - }, - [](glm::vec3 previous_frame, glm::vec3 next_frame, float scale_factor) - { - glm::vec3 scale{glm::mix( - previous_frame, next_frame, scale_factor)}; - return glm::scale(glm::mat4(1.0f), scale); - })}; - - this->bone_transforms[i] = position * rotation * scale; - } -} - -} diff --git a/src/blucat/skeletal_model.hpp b/src/blucat/skeletal_model.hpp deleted file mode 100644 index 03be8e5..0000000 --- a/src/blucat/skeletal_model.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_SKELETAL_MODEL_H -#define CANDY_GEAR_BLUCAT_SKELETAL_MODEL_H 1 - -#include -#include - -#include "vulkan.hpp" -#include "skeletal_mesh.hpp" - -namespace BluCat -{ - -struct SkeletalModel -{ - std::shared_ptr skeletal_mesh; - std::shared_ptr texture; - std::vector uniform_buffers; - std::shared_ptr position; - std::shared_ptr orientation; - int animation_index; - float animation_time; - std::vector bone_transforms; - - VkDescriptorPool descriptor_pool; - std::vector descriptor_sets; - - SkeletalModel( - std::shared_ptr skeletal_mesh, - std::shared_ptr texture, std::shared_ptr position, - std::shared_ptr orientation); - ~SkeletalModel(); - - void - tick(float delta); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_SKELETAL_MODEL_H */ diff --git a/src/blucat/source_buffer.cpp b/src/blucat/source_buffer.cpp deleted file mode 100644 index 41c40b9..0000000 --- a/src/blucat/source_buffer.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2022-2024 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 "source_buffer.hpp" - -#include - -namespace BluCat -{ - -SourceBuffer::SourceBuffer(Device *device, void *data, size_t data_size) -{ - this->device = device; - this->device_size = data_size; - this->buffer_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - this->memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - - try - { - BluCat::BaseBuffer::loader.execute(static_cast(this)); - } - catch(const CommandError &command_error) - { - std::string error{"Could not initialize Vulkan source buffer → "}; - error += command_error.what(); - throw std::runtime_error{error}; - } - this->copy_data(data); -} - -SourceBuffer::SourceBuffer(SourceBuffer &&that) -{ - this->buffer = that.buffer; - this->device_memory = that.device_memory; - this->device_size = that.device_size; - this->buffer_usage = that.buffer_usage; - this->memory_properties = that.memory_properties; - - that.buffer = VK_NULL_HANDLE; - that.device_memory = VK_NULL_HANDLE; -} - -SourceBuffer& -SourceBuffer::operator=(SourceBuffer &&that) -{ - this->buffer = that.buffer; - this->device_memory = that.device_memory; - this->device_size = that.device_size; - this->buffer_usage = that.buffer_usage; - this->memory_properties = that.memory_properties; - - that.buffer = VK_NULL_HANDLE; - that.device_memory = VK_NULL_HANDLE; - - return *this; -} - -SourceBuffer::~SourceBuffer() -{ - BluCat::BaseBuffer::loader.revert(static_cast(this)); -} - -void -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, src_data, static_cast(this->device_size)); - vkUnmapMemory(this->device->device, this->device_memory); -} - -} diff --git a/src/blucat/source_buffer.hpp b/src/blucat/source_buffer.hpp deleted file mode 100644 index dd52acc..0000000 --- a/src/blucat/source_buffer.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_SOURCE_BUFFER_H -#define CANDY_GEAR_BLUCAT_SOURCE_BUFFER_H 1 - -#include "base_buffer.hpp" - -namespace BluCat -{ - -struct SourceBuffer: public BaseBuffer -{ - SourceBuffer(const SourceBuffer &t) = delete; - SourceBuffer& - operator=(const SourceBuffer &t) = delete; - - SourceBuffer(Device *device, void *data, size_t data_size); - - SourceBuffer(SourceBuffer &&that); - SourceBuffer& - operator=(SourceBuffer &&that); - - ~SourceBuffer(); - - void - copy_data(void *src_data); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_SOURCE_BUFFER_H */ diff --git a/src/blucat/sprite.cpp b/src/blucat/sprite.cpp deleted file mode 100644 index 0c66a27..0000000 --- a/src/blucat/sprite.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2022-2024 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 "sprite.hpp" - -#include - -#include "core.hpp" -#include "sprite.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -struct SpriteBuilder -{ - BluCat::Sprite *sprite; - const glm::vec4 ▭ - - SpriteBuilder(BluCat::Sprite *sprite, const glm::vec4 &rect); -}; - -SpriteBuilder::SpriteBuilder(BluCat::Sprite *sprite, const glm::vec4 &rect): - sprite{sprite}, - rect{rect} -{ -} - -void -load_mesh(void *obj) -{ - auto self = static_cast(obj); - - self->sprite->queue_family = - BluCat::core.vk_device_with_swapchain->get_queue_family_with_graphics(); - - glm::vec2 rect[BluCat::Sprite::vertex_count]{ - glm::vec2{self->rect.x, self->rect.y}, - glm::vec2{self->rect.x, self->rect.w}, - glm::vec2{self->rect.z, self->rect.y}, - glm::vec2{self->rect.z, self->rect.w} - }; - - void *vertexes_data{&rect}; - static const size_t vertexes_size = - sizeof(glm::vec2) * BluCat::Sprite::vertex_count; - self->sprite->source_buffer = new BluCat::SourceBuffer{ - self->sprite->queue_family->device, vertexes_data, vertexes_size}; - self->sprite->vertex_buffer = new BluCat::DestinationBuffer{ - self->sprite->queue_family, self->sprite->source_buffer, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}; -} - -void -unload_mesh(void *obj) -{ - auto self = static_cast(obj); - - delete self->sprite->vertex_buffer; - delete self->sprite->source_buffer; -} - -static const CommandChain loader{ - {&load_mesh, &unload_mesh}, -}; - -} - -namespace BluCat -{ - -Sprite::Sprite(std::shared_ptr texture, const glm::vec4 &rect): - texture{texture} -{ - SpriteBuilder sprite_builder(this, rect); - loader.execute(&sprite_builder); -} - -Sprite::~Sprite() -{ - glm::vec4 vector_4d{}; - SpriteBuilder sprite_builder(this, vector_4d); - loader.revert(&sprite_builder); -} - -} diff --git a/src/blucat/sprite.hpp b/src/blucat/sprite.hpp deleted file mode 100644 index 303beca..0000000 --- a/src/blucat/sprite.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_SPRITE_H -#define CANDY_GEAR_BLUCAT_SPRITE_H 1 - -#include -#include -#include - -#include "vulkan.hpp" -#include "destination_buffer.hpp" -#include "queue_family.hpp" -#include "uniform_buffer.hpp" -#include "texture.hpp" - -namespace BluCat -{ - -struct Sprite -{ - static const uint32_t vertex_count{4}; - - QueueFamily *queue_family; - - SourceBuffer *source_buffer; - DestinationBuffer *vertex_buffer; - - std::shared_ptr texture; - - Sprite(std::shared_ptr texture, const glm::vec4 &rect); - ~Sprite(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_SPRITE_H */ diff --git a/src/blucat/sprite_3d.cpp b/src/blucat/sprite_3d.cpp deleted file mode 100644 index dab97e2..0000000 --- a/src/blucat/sprite_3d.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2022-2024 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 "sprite_3d.hpp" - -#include "core.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_uniform_buffers(void *obj) -{ - auto self = static_cast(obj); - - try - { - self->uniform_buffers.reserve(BluCat::core.vk_swapchain->images_count); - for(auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - self->uniform_buffers.emplace_back( - BluCat::core.vk_device_with_swapchain, sizeof(BluCat::UDOSprite3D)); - } - catch(const std::exception& e) - { - throw CommandError{e.what()}; - } -} - -void -unload_uniform_buffers(void *obj) -{ - auto self = static_cast(obj); - - self->uniform_buffers.clear(); -} - -void -load_descriptor_set_pool(void *obj) -{ - auto self = static_cast(obj); - - std::array descriptor_pool_sizes{}; - descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_pool_sizes[0].descriptorCount = - self->uniform_buffers.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->uniform_buffers.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(obj); - - vkDestroyDescriptorPool( - self->queue_family->device->device, self->descriptor_pool, nullptr); -} -void -load_descriptor_sets(void *obj) -{ - auto self = static_cast(obj); - - std::vector layouts( - BluCat::core.vk_swapchain->images_count, - BluCat::core.vk_descriptor_set_layout->model); - - 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_buffers_to_descriptor_sets(void *obj) -{ - auto self = static_cast(obj); - - for(auto i{0}; i < self->uniform_buffers.size(); i++) - { - VkDescriptorBufferInfo buffer_info{}; - buffer_info.buffer = self->uniform_buffers[i].buffer; - buffer_info.offset = 0; - buffer_info.range = sizeof(BluCat::UDOSprite3D); - - VkDescriptorImageInfo image_info{}; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_info.imageView = self->sprite->texture->view; - image_info.sampler = self->sprite->texture->sampler; - - std::array 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( - BluCat::core.vk_device_with_swapchain->device, write_descriptors.size(), - write_descriptors.data(), 0, nullptr); - } -} - -static const CommandChain loader{ - {&load_uniform_buffers, &unload_uniform_buffers}, - {&load_descriptor_set_pool, &unload_descriptor_set_pool}, - {&load_descriptor_sets, nullptr}, - {&load_buffers_to_descriptor_sets, nullptr} -}; - -} - -namespace BluCat -{ - -Sprite3D::Sprite3D( - std::shared_ptr sprite, std::shared_ptr position, - glm::vec2 size): - sprite{sprite}, - position{position}, - size{size} -{ - this->queue_family = - BluCat::core.vk_device_with_swapchain->get_queue_family_with_graphics(); - loader.execute(this); -} - -Sprite3D::~Sprite3D() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/sprite_3d.hpp b/src/blucat/sprite_3d.hpp deleted file mode 100644 index 03a13f4..0000000 --- a/src/blucat/sprite_3d.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_SPRITE_3D_H -#define CANDY_GEAR_BLUCAT_SPRITE_3D_H 1 - -#include "vulkan.hpp" -#include "sprite.hpp" - -namespace BluCat -{ - -struct Sprite3D -{ - std::shared_ptr sprite; - std::shared_ptr position; - glm::vec2 size; - - QueueFamily *queue_family; - - std::vector uniform_buffers; - VkDescriptorPool descriptor_pool; - std::vector descriptor_sets; - - Sprite3D( - std::shared_ptr sprite, std::shared_ptr position, - glm::vec2 size); - ~Sprite3D(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_SPRITE_3D_H */ diff --git a/src/blucat/sprite_to_draw.cpp b/src/blucat/sprite_to_draw.cpp deleted file mode 100644 index 9013adb..0000000 --- a/src/blucat/sprite_to_draw.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2022-2024 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 "sprite_to_draw.hpp" - -namespace BluCat -{ - SpriteToDraw::SpriteToDraw( - std::shared_ptr sprite, const glm::vec4 &position, float z_index): - sprite{sprite}, - position{position}, - z_index{z_index} - { - } - - bool - operator<(const SpriteToDraw& a, const SpriteToDraw& b) - { - return a.z_index < b.z_index; - } - - bool - operator>(const SpriteToDraw& a, const SpriteToDraw& b) - { - return a.z_index > b.z_index; - } -} diff --git a/src/blucat/sprite_to_draw.hpp b/src/blucat/sprite_to_draw.hpp deleted file mode 100644 index c122437..0000000 --- a/src/blucat/sprite_to_draw.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_SPRITES_TO_DRAW_H -#define CANDY_GEAR_BLUCAT_SPRITES_TO_DRAW_H 1 - -#include - -#include "vulkan.hpp" -#include "sprite.hpp" - -namespace BluCat -{ - struct SpriteToDraw - { - std::shared_ptr sprite; - glm::vec4 position; - float z_index; - - SpriteToDraw(std::shared_ptr sprite, const glm::vec4 &position, - float z_index); - }; - - bool - operator<(const SpriteToDraw &a, const SpriteToDraw &b); - - bool - operator>(const SpriteToDraw &a, const SpriteToDraw &b); -} - -#endif /* CANDY_GEAR_BLUCAT_SPRITES_TO_DRAW_H */ diff --git a/src/blucat/static_mesh.cpp b/src/blucat/static_mesh.cpp deleted file mode 100644 index a7c1c53..0000000 --- a/src/blucat/static_mesh.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2022-2024 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 "static_mesh.hpp" - -#include "binary_reader.hpp" -#include "command.hpp" -#include "core.hpp" -#include "static_mesh_vertex.hpp" - -namespace -{ - -// Data that is only needed for the command chain but not for the StaticMesh -// goes here. -struct MeshBuilder -{ - std::string mesh_path; - BluCat::StaticMesh *mesh; - - MeshBuilder(BluCat::StaticMesh *m, std::string mp); - MeshBuilder(BluCat::StaticMesh *m, const char* mp); -}; - -MeshBuilder::MeshBuilder(BluCat::StaticMesh *m, std::string mp): - mesh{m}, - mesh_path{mp} -{ -} - -MeshBuilder::MeshBuilder(BluCat::StaticMesh *m, const char *mp): - MeshBuilder{m, std::string(mp)} -{ -} - -void -load_mesh(void *obj) -{ - auto self = static_cast(obj); - - BinaryReader input{self->mesh_path}; - - self->mesh->queue_family = - BluCat::core.vk_device_with_swapchain->get_queue_family_with_graphics(); - - { // Load vertexes. - auto vertex_count{input.read_ui32()}; - std::vector vertexes{vertex_count}; - - for(auto i{0}; i < vertex_count; i++) - { - vertexes[i].position = input.read_vec3(); - vertexes[i].normal = input.read_vec3(); - vertexes[i].texture_coord = input.read_vec2(); - } - - void *vertexes_data{vertexes.data()}; - size_t vertexes_size = sizeof(vertexes[0]) * vertexes.size(); - self->mesh->source_vertex_buffer = new BluCat::SourceBuffer{ - self->mesh->queue_family->device, vertexes_data, vertexes_size}; - self->mesh->vertex_buffer = new BluCat::DestinationBuffer{ - self->mesh->queue_family, self->mesh->source_vertex_buffer, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}; - } - - { // Load indexes - self->mesh->index_count = input.read_ui32(); - std::vector indexes(self->mesh->index_count); - - for(auto i{0}; i < self->mesh->index_count; i++) - indexes[i] = input.read_ui32(); - - void *indexes_data{indexes.data()}; - size_t indexes_size{sizeof(indexes[0]) * indexes.size()}; - BluCat::SourceBuffer source_index_buffer{ - self->mesh->queue_family->device, indexes_data, indexes_size}; - self->mesh->index_buffer = new BluCat::DestinationBuffer{ - self->mesh->queue_family, &source_index_buffer, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT}; - } -} - -void -unload_mesh(void *obj) -{ - auto self = static_cast(obj); - - delete self->mesh->index_buffer; - delete self->mesh->vertex_buffer; - delete self->mesh->source_vertex_buffer; -} - -static const CommandChain loader{ - {&load_mesh, &unload_mesh} -}; - -} - -namespace BluCat -{ - -StaticMesh::StaticMesh(std::string mesh_path) -{ - MeshBuilder mesh_builder(this, mesh_path); - loader.execute(&mesh_builder); -} - -StaticMesh::StaticMesh(const char* mesh_path): - StaticMesh{std::string(mesh_path)} -{ -} - -StaticMesh::~StaticMesh() -{ - MeshBuilder mesh_builder(this, ""); - loader.revert(&mesh_builder); -} - -} diff --git a/src/blucat/static_mesh.hpp b/src/blucat/static_mesh.hpp deleted file mode 100644 index 04c5e3b..0000000 --- a/src/blucat/static_mesh.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_STATIC_MESH_H -#define CANDY_GEAR_BLUCAT_STATIC_MESH_H 1 - -#include -#include - -#include "vulkan.hpp" -#include "destination_buffer.hpp" -#include "queue_family.hpp" -#include "uniform_buffer.hpp" -#include "texture.hpp" - -namespace BluCat -{ - -struct StaticMesh -{ - QueueFamily *queue_family; - - uint32_t index_count; - SourceBuffer *source_vertex_buffer; - DestinationBuffer *index_buffer; - DestinationBuffer *vertex_buffer; - - StaticMesh(std::string mesh_path); - StaticMesh(const char* mesh_path); - ~StaticMesh(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_STATIC_MESH_H */ diff --git a/src/blucat/static_mesh_vertex.hpp b/src/blucat/static_mesh_vertex.hpp deleted file mode 100644 index 4f7c6d4..0000000 --- a/src/blucat/static_mesh_vertex.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_STATIC_MESH_VERTEX_H -#define CANDY_GEAR_BLUCAT_STATIC_MESH_VERTEX_H 1 - -#include "vulkan.hpp" - -namespace BluCat -{ - -struct StaticMeshVertex -{ - glm::vec3 position; - glm::vec3 normal; - glm::vec2 texture_coord; -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_STATIC_MESH_VERTEX_H */ diff --git a/src/blucat/static_model.cpp b/src/blucat/static_model.cpp deleted file mode 100644 index 60c2536..0000000 --- a/src/blucat/static_model.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2022-2024 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 "static_model.hpp" - -#include "core.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_uniform_buffers(void *obj) -{ - auto self = static_cast(obj); - - try - { - self->uniform_buffers.reserve(BluCat::core.vk_swapchain->images_count); - for(auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - self->uniform_buffers.emplace_back( - BluCat::core.vk_device_with_swapchain, sizeof(BluCat::UDOStaticModel)); - } - catch(const std::exception& e) - { - throw CommandError{e.what()}; - } -} - -void -unload_uniform_buffers(void *obj) -{ - auto self = static_cast(obj); - - self->uniform_buffers.clear(); -} - -void -load_descriptor_set_pool(void *obj) -{ - auto self = static_cast(obj); - - std::array descriptor_pool_sizes{}; - descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_pool_sizes[0].descriptorCount = - self->uniform_buffers.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->uniform_buffers.size(); - pool_info.poolSizeCount = descriptor_pool_sizes.size(); - pool_info.pPoolSizes = descriptor_pool_sizes.data(); - - if(vkCreateDescriptorPool( - self->static_mesh->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(obj); - - vkDestroyDescriptorPool( - self->static_mesh->queue_family->device->device, self->descriptor_pool, - nullptr); -} - -void -load_descriptor_sets(void *obj) -{ - auto self = static_cast(obj); - - std::vector layouts( - BluCat::core.vk_swapchain->images_count, - BluCat::core.vk_descriptor_set_layout->model); - - 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->static_mesh->queue_family->device->device, &alloc_info, - self->descriptor_sets.data()) != VK_SUCCESS) - CommandError{"Failed to create Vulkan descriptor set."}; -} - -void -load_buffers_to_descriptor_sets(void *obj) -{ - auto self = static_cast(obj); - - for(auto i{0}; i < self->uniform_buffers.size(); i++) - { - VkDescriptorBufferInfo buffer_info{}; - buffer_info.buffer = self->uniform_buffers[i].buffer; - buffer_info.offset = 0; - buffer_info.range = sizeof(BluCat::UDOStaticModel); - - std::array 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( - BluCat::core.vk_device_with_swapchain->device, write_descriptors.size(), - write_descriptors.data(), 0, nullptr); - } -} - -static const CommandChain loader{ - {&load_uniform_buffers, &unload_uniform_buffers}, - {&load_descriptor_set_pool, &unload_descriptor_set_pool}, - {&load_descriptor_sets, nullptr}, - {&load_buffers_to_descriptor_sets, nullptr} -}; - -} - -namespace BluCat -{ - -StaticModel::StaticModel( - std::shared_ptr static_mesh, - std::shared_ptr texture, std::shared_ptr position, - std::shared_ptr orientation): - static_mesh{static_mesh}, - texture{texture}, - position{position}, - orientation{orientation} -{ - loader.execute(this); -} - -StaticModel::~StaticModel() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/static_model.hpp b/src/blucat/static_model.hpp deleted file mode 100644 index c300c8f..0000000 --- a/src/blucat/static_model.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_STATIC_MODEL_H -#define CANDY_GEAR_BLUCAT_STATIC_MODEL_H 1 - -#include -#include - -#include "vulkan.hpp" -#include "static_mesh.hpp" - -namespace BluCat -{ - -struct StaticModel -{ - std::shared_ptr static_mesh; - std::shared_ptr texture; - std::vector uniform_buffers; - std::shared_ptr position; - std::shared_ptr orientation; - - VkDescriptorPool descriptor_pool; - std::vector descriptor_sets; - - StaticModel( - std::shared_ptr static_mesh, - std::shared_ptr texture, std::shared_ptr position, - std::shared_ptr orientation); - ~StaticModel(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_STATIC_MODEL_H */ diff --git a/src/blucat/swapchain.cpp b/src/blucat/swapchain.cpp deleted file mode 100644 index 613cf9b..0000000 --- a/src/blucat/swapchain.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2022-2024 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 "swapchain.hpp" - -#include "core.hpp" - -#include - -namespace -{ - -void -load_swapchain(void *obj) -{ - auto self = static_cast(obj); - - // Surface formats. - uint32_t vk_surface_format_count; - std::vector vk_surface_formats; - vkGetPhysicalDeviceSurfaceFormatsKHR( - BluCat::core.vk_device_with_swapchain->physical_device, - BluCat::core.window_surface, &vk_surface_format_count, nullptr); - vk_surface_formats.resize(vk_surface_format_count); - vkGetPhysicalDeviceSurfaceFormatsKHR( - BluCat::core.vk_device_with_swapchain->physical_device, - BluCat::core.window_surface, &vk_surface_format_count, - vk_surface_formats.data()); - - VkSwapchainCreateInfoKHR swapchain_create_info = {}; - swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - swapchain_create_info.pNext = nullptr; - swapchain_create_info.flags = 0; - swapchain_create_info.surface = BluCat::core.window_surface; - swapchain_create_info.minImageCount = 3; // triple buffering. - - self->image_format = vk_surface_formats[0].format; - swapchain_create_info.imageFormat = self->image_format; - swapchain_create_info.imageColorSpace = vk_surface_formats[0].colorSpace; - - swapchain_create_info.imageExtent = { - BluCat::core.display_width, BluCat::core.display_height}; - swapchain_create_info.imageArrayLayers = 1; - swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapchain_create_info.queueFamilyIndexCount = 0; - swapchain_create_info.pQueueFamilyIndices = nullptr; - swapchain_create_info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; - swapchain_create_info.clipped = VK_FALSE; - swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; - - if(vkCreateSwapchainKHR( - BluCat::core.vk_device_with_swapchain->device, &swapchain_create_info, - nullptr, &self->swapchain) != VK_SUCCESS) - throw CommandError{"Vulkan failed to create swapchain."}; - - vkGetSwapchainImagesKHR( - BluCat::core.vk_device_with_swapchain->device, self->swapchain, - &self->images_count, nullptr); - self->images = new VkImage[self->images_count]; - vkGetSwapchainImagesKHR( - BluCat::core.vk_device_with_swapchain->device, self->swapchain, - &self->images_count, self->images); -} - -void -unload_swapchain(void *obj) -{ - auto self = static_cast(obj); - - delete[] self->images; - vkDestroySwapchainKHR( - BluCat::core.vk_device_with_swapchain->device, self->swapchain, nullptr); -} - -void -load_image_view(void *obj) -{ - auto self = static_cast(obj); - - self->image_views = new VkImageView[self->images_count]; - for(auto i{0}; i < self->images_count; i++) - { - VkImageViewCreateInfo create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - create_info.image = self->images[i]; - create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - create_info.format = self->image_format; - create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - create_info.subresourceRange.baseMipLevel = 0; - create_info.subresourceRange.levelCount = 1; - create_info.subresourceRange.baseArrayLayer = 0; - create_info.subresourceRange.layerCount = 1; - - if(vkCreateImageView( - BluCat::core.vk_device_with_swapchain->device, &create_info, nullptr, - &self->image_views[i])) - throw CommandError{"Could no create Image View for swapchain."}; - } -} - -void -unload_image_view(void *obj) -{ - auto self = static_cast(obj); - - for(auto i{0}; i < self->images_count; i++) - vkDestroyImageView( - BluCat::core.vk_device_with_swapchain->device, self->image_views[i], - nullptr); -} - -void -load_frame_sync(void *obj) -{ - auto self = static_cast(obj); - - self->image_available_semaphores.resize(self->max_frames_in_flight); - self->render_finished_semaphores.resize(self->max_frames_in_flight); - self->in_flight_fences.resize(self->max_frames_in_flight); - - VkSemaphoreCreateInfo semaphore_info = {}; - semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - semaphore_info.pNext = nullptr; - semaphore_info.flags = 0; - - VkFenceCreateInfo fence_info = {}; - fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_info.pNext = nullptr; - fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - // FIXME: if this loop fails, it will not destroy the semaphores. - for(auto i{0}; i < self->max_frames_in_flight; i++) - { - if(vkCreateSemaphore( - BluCat::core.vk_device_with_swapchain->device, &semaphore_info, - nullptr, &self->image_available_semaphores[i]) != VK_SUCCESS || - vkCreateSemaphore( - BluCat::core.vk_device_with_swapchain->device, &semaphore_info, - nullptr, &self->render_finished_semaphores[i]) != VK_SUCCESS || - vkCreateFence( - BluCat::core.vk_device_with_swapchain->device, &fence_info, - nullptr, &self->in_flight_fences[i]) != VK_SUCCESS) - throw CommandError{"Failed to create semaphores."}; - } -} - -void -unload_frame_sync(void *obj) -{ - auto self = static_cast(obj); - - vkDeviceWaitIdle(BluCat::core.vk_device_with_swapchain->device); - - for(auto i{0}; i < self->max_frames_in_flight; i++) - { - vkDestroySemaphore(BluCat::core.vk_device_with_swapchain->device, - self->render_finished_semaphores[i], nullptr); - vkDestroySemaphore(BluCat::core.vk_device_with_swapchain->device, - self->image_available_semaphores[i], nullptr); - vkDestroyFence(BluCat::core.vk_device_with_swapchain->device, - self->in_flight_fences[i], nullptr); - } -} - -const CommandChain loader{ - {&load_swapchain, &unload_swapchain}, - {&load_image_view, &unload_image_view}, - {&load_frame_sync, &unload_frame_sync} -}; - -} - -namespace BluCat -{ - -Swapchain::Swapchain(): - current_frame{0} -{ - loader.execute(this); -} - -Swapchain::~Swapchain() -{ - loader.revert(this); -} - -} diff --git a/src/blucat/swapchain.hpp b/src/blucat/swapchain.hpp deleted file mode 100644 index a6f588d..0000000 --- a/src/blucat/swapchain.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_SWAPCHAIN_H -#define CANDY_GEAR_BLUCAT_SWAPCHAIN_H 1 - -#include "command.hpp" -#include "vulkan.hpp" - -namespace BluCat -{ - -struct Swapchain -{ - VkSwapchainKHR swapchain; - VkFormat image_format; - - uint32_t images_count; - VkImage *images; - VkImageView *image_views; - - static const int max_frames_in_flight{2}; - size_t current_frame; - std::vector image_available_semaphores; - std::vector render_finished_semaphores; - std::vector in_flight_fences; - - Swapchain(); - ~Swapchain(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_SWAPCHAIN_H */ diff --git a/src/blucat/texture.cpp b/src/blucat/texture.cpp deleted file mode 100644 index afab950..0000000 --- a/src/blucat/texture.cpp +++ /dev/null @@ -1,566 +0,0 @@ -/* - * Copyright 2022-2024 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 "texture.hpp" - -#include "command.hpp" -#include "core.hpp" -#include "image.hpp" -#include "qoi.hpp" -#include "source_buffer.hpp" - -namespace -{ - -inline void -create_vulkan_image( - VkImage *image, VkDeviceMemory *device_memory, int width, int height, - uint32_t mip_levels) -{ - VkExtent3D vk_extent3d{}; - vk_extent3d.width = width; - vk_extent3d.height = height; - vk_extent3d.depth = 1; - - BluCat::Image::create( - BluCat::core.vk_device_with_swapchain, - image, - device_memory, - VK_FORMAT_R8G8B8A8_UNORM, - vk_extent3d, - mip_levels, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); -} - -struct ImageBuilder -{ - BluCat::Texture *texture; -}; - -struct ImageTextureBuilder: public ImageBuilder -{ - std::string texture_path; - - ImageTextureBuilder(BluCat::Texture *t, const std::string &tp); - ImageTextureBuilder(BluCat::Texture *t, const char* tp); -}; - -ImageTextureBuilder::ImageTextureBuilder( - BluCat::Texture *t, const std::string &tp): - texture_path{tp} -{ - this->texture = t; -} - -ImageTextureBuilder::ImageTextureBuilder(BluCat::Texture *t, const char* tp): - ImageTextureBuilder{t, std::string(tp)} -{ -} - -void -load_image(void *obj) -{ - auto self = static_cast(obj); - - const int num_channels = 4; // all images are converted to RGBA - BluCat::QOI::Image qoi_image(self->texture_path.c_str(), num_channels); - uint8_t *pixels; - - { // Load file image from file. - self->texture->width = qoi_image.header.width; - self->texture->height = qoi_image.header.height; - self->texture->mip_levels = 1; - - pixels = qoi_image.pixels; - } - - // Load file image into a vulkan buffer. - size_t image_size{static_cast( - qoi_image.header.width * qoi_image.header.height * num_channels)}; - BluCat::SourceBuffer source_image_buffer{ - BluCat::core.vk_device_with_swapchain, pixels, image_size}; - - { // Create vulkan image. - try - { - create_vulkan_image( - &self->texture->image, - &self->texture->device_memory, - self->texture->width, - self->texture->height, - self->texture->mip_levels); - } - catch(BluCat::Image::Error error) - { - throw CommandError{error.what()}; - } - } - - // Copy image from vulkan buffer into vulkan image. - { - auto queue_family = self->texture->queue_family; - auto queue{queue_family->get_queue()}; - BluCat::CommandPool command_pool{queue_family, 1}; - VkCommandBuffer vk_command_buffer{command_pool.command_buffers[0]}; - - queue.submit_one_time_command(vk_command_buffer, [&](){ - BluCat::Image::move_image_state( - vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - - VkBufferImageCopy image_copy{}; - image_copy.bufferOffset = 0; - image_copy.bufferRowLength = 0; - image_copy.bufferImageHeight = 0; - image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_copy.imageSubresource.mipLevel = 0; - image_copy.imageSubresource.baseArrayLayer = 0; - image_copy.imageSubresource.layerCount = 1; - image_copy.imageOffset = {0, 0, 0}; - image_copy.imageExtent = { - self->texture->width, self->texture->height, 1}; - - vkCmdCopyBufferToImage( - vk_command_buffer, source_image_buffer.buffer, self->texture->image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); - - BluCat::Image::move_image_state( - vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - }); - } -} - -void -unload_image(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyImage( - BluCat::core.vk_device_with_swapchain->device, self->texture->image, - nullptr); - vkFreeMemory( - BluCat::core.vk_device_with_swapchain->device, - self->texture->device_memory, nullptr); -} - -void -load_sampler(void *obj) -{ - auto self = static_cast(obj); - - VkSamplerCreateInfo sampler_info{}; - sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - sampler_info.pNext = nullptr; - sampler_info.flags = 0; - sampler_info.magFilter = VK_FILTER_LINEAR; - sampler_info.minFilter = VK_FILTER_LINEAR; - sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.mipLodBias = 0.0f; - sampler_info.anisotropyEnable = VK_TRUE; - sampler_info.maxAnisotropy = 16; - sampler_info.compareEnable = VK_FALSE; - sampler_info.compareOp = VK_COMPARE_OP_NEVER; - sampler_info.minLod = 0.0f; - sampler_info.maxLod = 0.0f; - sampler_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - sampler_info.unnormalizedCoordinates = VK_FALSE; - - if(vkCreateSampler( - BluCat::core.vk_device_with_swapchain->device, &sampler_info, nullptr, - &self->texture->sampler) != VK_SUCCESS) - throw CommandError{"Failed to create texture sampler."}; -} - -void -unload_sampler(void *obj) -{ - auto self = static_cast(obj); - - vkDestroySampler( - BluCat::core.vk_device_with_swapchain->device, self->texture->sampler, - nullptr); -} - -void -load_view(void *obj) -{ - auto self = static_cast(obj); - - try - { - BluCat::Image::create_view( - BluCat::core.vk_device_with_swapchain, &self->texture->view, - self->texture->image, - VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); - } - catch(BluCat::Image::Error error) - { - throw CommandError{error.what()}; - } -} - -void -unload_view(void *obj) -{ - auto self = static_cast(obj); - - vkDestroyImageView( - BluCat::core.vk_device_with_swapchain->device, self->texture->view, - nullptr); -} - -const CommandChain image_loader{ - {&load_image, &unload_image}, - {&load_sampler, &unload_sampler}, - {&load_view, &unload_view} -}; - -struct CharacterToDraw -{ - int pos_x; - std::shared_ptr character; - - CharacterToDraw(int x, std::shared_ptr character): - pos_x{x}, - character{character} - {}; -}; - -struct TextTextureBuilder: public ImageBuilder -{ - BluCat::Font *font; - const char* str; - uint32_t max_bearing_y; - std::vector chars_to_draw; - - TextTextureBuilder(BluCat::Texture *texture, BluCat::Font *font, const char* str): - font{font}, - str{str} - { - this->texture = texture; - } -}; - -void -load_text_proportions(void *obj) -{ - auto self = static_cast(obj); - - uint32_t texture_width{0}, texture_descender{0}; - auto unicode_text{BluCat::Character::str_to_unicode(self->str)}; - - auto first_image{self->font->character(unicode_text[0])}; - if(first_image->bearing_x < 0) texture_width = - first_image->bearing_x; - - self->max_bearing_y = 0; - self->chars_to_draw.reserve(unicode_text.size()); - - // FIXME: I need to test several different fonts to find all bugs in this - // code. - std::shared_ptr char_image{}; - { // Calculate image size - int max_height; - for(auto char_code : unicode_text) - { - char_image = self->font->character(char_code); - uint32_t descender{char_image->height - char_image->bearing_y}; - uint32_t pos_x{texture_width + char_image->bearing_x}; - - if(char_image->image != VK_NULL_HANDLE) - self->chars_to_draw.emplace_back(pos_x, char_image); - - if(char_image->bearing_y > self->max_bearing_y) - self->max_bearing_y = char_image->bearing_y; - if(descender > texture_descender) texture_descender = descender; - - texture_width += char_image->advance; - } - } - - { // Restore image width if last character have a negative bearing. - int bearing_x_pluss_width = char_image->bearing_x + char_image->width; - if(bearing_x_pluss_width > char_image->advance) - texture_width += bearing_x_pluss_width - char_image->advance; - } - - self->texture->width = texture_width; - self->texture->height = self->max_bearing_y + texture_descender; - self->texture->mip_levels = 1; -} - -void -load_text_image(void *obj) -{ - auto self = static_cast(obj); - - const int NumChannels = 4; - - size_t image_size{static_cast( - self->texture->width * self->texture->height * NumChannels)}; - std::vector pixels(image_size); - for(auto x{0}; x < self->texture->width; x++) - { - for(auto y{0}; y < self->texture->height; y++) - { - auto image_coord = y * self->font->face->glyph->bitmap.width + - x * NumChannels; - pixels[image_coord] = 0; // Red - pixels[image_coord + 1] = 0; // Green - pixels[image_coord + 2] = 0; // Blue - pixels[image_coord + 3] = 0; // Alpha - } - } - BluCat::SourceBuffer source_image_buffer{ - BluCat::core.vk_device_with_swapchain, pixels.data(), image_size}; - - { // Create vulkan image. - try - { - create_vulkan_image( - &self->texture->image, - &self->texture->device_memory, - self->texture->width, - self->texture->height, - self->texture->mip_levels); - } - catch(BluCat::Image::Error error) - { - throw CommandError{error.what()}; - } - } - - { // Render text - auto queue_family{ - BluCat::core.vk_device_with_swapchain-> - get_queue_family_with_presentation()}; - auto queue{queue_family->get_queue()}; - BluCat::CommandPool command_pool{queue_family, 1}; - VkCommandBuffer vk_command_buffer{command_pool.command_buffers[0]}; - - queue.submit_one_time_command(vk_command_buffer, [&](){ - BluCat::Image::move_image_state( - vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - - VkBufferImageCopy image_copy{}; - image_copy.bufferOffset = 0; - image_copy.bufferRowLength = 0; - image_copy.bufferImageHeight = 0; - image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_copy.imageSubresource.mipLevel = 0; - image_copy.imageSubresource.baseArrayLayer = 0; - image_copy.imageSubresource.layerCount = 1; - image_copy.imageOffset = {0, 0, 0}; - image_copy.imageExtent = {self->texture->width, self->texture->height, 1}; - - vkCmdCopyBufferToImage( - vk_command_buffer, source_image_buffer.buffer, self->texture->image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); - - for(auto &to_draw: self->chars_to_draw) - { - VkImageSubresourceLayers - source_subresources{}, destination_subresources{}; - source_subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - source_subresources.mipLevel = 0; - source_subresources.baseArrayLayer = 0; - source_subresources.layerCount = 1; - - destination_subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - destination_subresources.mipLevel = 0; - destination_subresources.baseArrayLayer = 0; - destination_subresources.layerCount = 1; - - VkImageCopy image_copy{}; - image_copy.srcSubresource = source_subresources; - image_copy.srcOffset = {0, 0, 0}; - image_copy.dstSubresource = destination_subresources; - image_copy.dstOffset = { - to_draw.pos_x, - (int)(self->max_bearing_y - to_draw.character->bearing_y), - 0}; - image_copy.extent = { - to_draw.character->width, to_draw.character->height, 1}; - - vkCmdCopyImage( - vk_command_buffer, - to_draw.character->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - self->texture->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, &image_copy); - } - - BluCat::Image::move_image_state( - vk_command_buffer, self->texture->image, VK_FORMAT_R8G8B8A8_UNORM, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - }); - } -} - -const CommandChain text_loader{ - {&load_text_proportions, nullptr}, - {&load_text_image, &unload_image}, - {&load_sampler, &unload_sampler}, - {&load_view, &unload_view} -}; - -void -load_descriptor_set_pool(void *obj) -{ - auto self = static_cast(obj); - - std::array descriptor_pool_sizes{}; - descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_pool_sizes[0].descriptorCount = - BluCat::core.vk_swapchain->images_count; - - VkDescriptorPoolCreateInfo pool_info{}; - pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - pool_info.pNext = nullptr; - pool_info.flags = 0; - pool_info.maxSets = BluCat::core.vk_swapchain->images_count; - 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(obj); - - vkDestroyDescriptorPool( - self->queue_family->device->device, self->descriptor_pool, nullptr); -} - -void -load_descriptor_sets(void *obj) -{ - auto self = static_cast(obj); - - std::vector layouts( - BluCat::core.vk_swapchain->images_count, - BluCat::core.vk_descriptor_set_layout->texture); - - 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(obj); - - for(auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - { - VkDescriptorImageInfo image_info{}; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_info.imageView = self->view; - image_info.sampler = self->sampler; - - std::array 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_COMBINED_IMAGE_SAMPLER; - write_descriptors[0].pBufferInfo = nullptr; - write_descriptors[0].pImageInfo = &image_info; - write_descriptors[0].pTexelBufferView = nullptr; - - vkUpdateDescriptorSets( - BluCat::core.vk_device_with_swapchain->device, write_descriptors.size(), - write_descriptors.data(), 0, nullptr); - } -} - -const CommandChain descriptor_loader{ - {&load_descriptor_set_pool, &unload_descriptor_set_pool}, - {&load_descriptor_sets, nullptr}, - {&load_data_to_descriptor_sets, nullptr} -}; - -} - -namespace BluCat -{ - -Texture::Texture(Font *font, const char* str) -{ - this->queue_family = - BluCat::core.vk_device_with_swapchain-> - get_queue_family_with_presentation(); - - TextTextureBuilder text_builder(this, font, str); - text_loader.execute(&text_builder); - descriptor_loader.execute(this); -} - -Texture::Texture(const std::string &texture_path) -{ - this->queue_family = - BluCat::core.vk_device_with_swapchain-> - get_queue_family_with_presentation(); - - ImageTextureBuilder texture_builder(this, texture_path); - image_loader.execute(&texture_builder); - descriptor_loader.execute(this); -} - -Texture::Texture(const char* texture_path): - Texture{std::string(texture_path)} -{ -} - -Texture::~Texture() -{ - ImageTextureBuilder texture_builder(this, ""); - image_loader.revert(&texture_builder); - descriptor_loader.revert(this); -} - -} diff --git a/src/blucat/texture.hpp b/src/blucat/texture.hpp deleted file mode 100644 index 4bf0350..0000000 --- a/src/blucat/texture.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_TEXTURE_H -#define CANDY_GEAR_BLUCAT_TEXTURE_H 1 - -#include - -#include "vulkan.hpp" -#include "font.hpp" -#include "queue_family.hpp" - -namespace BluCat -{ - -struct Texture -{ - QueueFamily *queue_family; - - VkImage image; - VkSampler sampler; - VkImageView view; - VkDeviceMemory device_memory; - uint32_t width, height; - uint32_t mip_levels; - - VkDescriptorPool descriptor_pool; - std::vector descriptor_sets; - - Texture(Font *font, const char *str); - Texture(const std::string &texture_path); - Texture(const char* texture_path); - ~Texture(); -}; - -} - -#endif /* CANDY_GEAR_TEXTURE_H */ diff --git a/src/blucat/uniform_buffer.cpp b/src/blucat/uniform_buffer.cpp deleted file mode 100644 index 4b6194a..0000000 --- a/src/blucat/uniform_buffer.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2022-2024 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 "uniform_buffer.hpp" - -#include -#include - -namespace BluCat -{ - -UniformBuffer::UniformBuffer(Device *device, VkDeviceSize data_size) -{ - this->device = device; - this->device_size = data_size; - this->buffer_usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - this->memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - - try - { - BaseBuffer::loader.execute(static_cast(this)); - } - catch(const CommandError &command_error) - { - std::string error{"Could not initialize Vulkan uniform buffer → "}; - error += command_error.what(); - throw CommandError{error}; - } -} - -UniformBuffer::~UniformBuffer() -{ - BaseBuffer::loader.revert(static_cast(this)); -} - -UniformBuffer::UniformBuffer(UniformBuffer &&that) -{ - this->device = that.device; - this->buffer = that.buffer; - this->device_memory = that.device_memory; - this->device_size = that.device_size; - this->buffer_usage = that.buffer_usage; - this->memory_properties = that.memory_properties; - - that.buffer = VK_NULL_HANDLE; - that.device_memory = VK_NULL_HANDLE; -} - -UniformBuffer& -UniformBuffer::operator=(UniformBuffer &&that) -{ - this->device = that.device; - this->buffer = that.buffer; - this->device_memory = that.device_memory; - this->device_size = that.device_size; - this->buffer_usage = that.buffer_usage; - this->memory_properties = that.memory_properties; - - that.buffer = VK_NULL_HANDLE; - that.device_memory = VK_NULL_HANDLE; - - return *this; -} - -void -UniformBuffer::copy_data(void *ubo) -{ - void *data; - vkMapMemory(this->device->device, this->device_memory, 0, - this->device_size, 0, &data); - memcpy(data, ubo, this->device_size); - vkUnmapMemory(this->device->device, this->device_memory); -} - -} diff --git a/src/blucat/uniform_buffer.hpp b/src/blucat/uniform_buffer.hpp deleted file mode 100644 index 1dd7788..0000000 --- a/src/blucat/uniform_buffer.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_UNIFORM_BUFFER_H -#define CANDY_GEAR_BLUCAT_UNIFORM_BUFFER_H 1 - -#include - -#include "vulkan.hpp" - -#include "base_buffer.hpp" - -namespace BluCat -{ - -// FIXME: this class need to delete or create custom copy constructors! -class UniformBuffer: public BaseBuffer -{ - UniformBuffer(const UniformBuffer &t) = delete; - UniformBuffer& - operator=(const UniformBuffer &t) = delete; - -public: - UniformBuffer(Device *device, VkDeviceSize data_size); - ~UniformBuffer(); - - UniformBuffer(UniformBuffer &&that); - UniformBuffer& - operator=(UniformBuffer &&that); - - void copy_data(void* ubo); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_UNIFORM_BUFFER_H */ diff --git a/src/blucat/uniform_data_object.hpp b/src/blucat/uniform_data_object.hpp deleted file mode 100644 index 0549e4e..0000000 --- a/src/blucat/uniform_data_object.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_UNIFORM_DATA_OBJECT_H -#define CANDY_GEAR_BLUCAT_UNIFORM_DATA_OBJECT_H 1 - -#include "vulkan.hpp" -#include "skeletal_mesh_vertex.hpp" - -namespace BluCat -{ - -// UDO = "uniform data object" - -struct UDOView2D -{ - glm::mat4 proj; -}; - -struct UDOView3D -{ - glm::mat4 view; - glm::mat4 proj; -}; - -struct UDOWorld3D_Vert -{ - glm::vec4 ambient_light_color; -}; - -struct UDOWorld3D_Frag -{ - glm::vec3 directional_light_direction; - glm::vec4 directional_light_color; -}; - -struct UDOStaticModel -{ - glm::mat4 base_matrix; -}; - -struct UDOSkeletalModel -{ - glm::mat4 base_matrix; - glm::mat4 bone_matrices[SKELETAL_MESH_MAX_NUM_OF_BONES]; -}; - -struct UDOVector4D -{ - glm::vec4 vector; -}; - -struct UDOVector3D -{ - glm::vec3 vectors; -}; - -struct UDOSprite3D -{ - glm::vec3 position; - uint32_t padding; - glm::vec2 size; -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_UNIFORM_DATA_OBJECT_H */ diff --git a/src/blucat/view_2d.cpp b/src/blucat/view_2d.cpp deleted file mode 100644 index de764ce..0000000 --- a/src/blucat/view_2d.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2022-2024 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 "view_2d.hpp" - -#include - -#include "core.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_2d_uniform_buffer(void *obj) -{ - auto self = static_cast(obj); - - try - { - self->ub_2d.reserve(BluCat::core.vk_swapchain->images_count); - for(auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - self->ub_2d.emplace_back( - BluCat::core.vk_device_with_swapchain, sizeof(BluCat::UDOView2D)); - } - catch(const std::exception& e) - { - throw CommandError{e.what()}; - } -} - -void -unload_2d_uniform_buffer(void *obj) -{ - auto self = static_cast(obj); - - self->ub_2d.clear(); -} - -void -load_descriptor_sets_2d(void *obj) -{ - auto self = static_cast(obj); - - std::vector layouts( - BluCat::core.vk_swapchain->images_count, - BluCat::core.vk_descriptor_set_layout->view); - - 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_2d.resize(layouts.size()); - if(vkAllocateDescriptorSets( - BluCat::core.vk_device_with_swapchain->device, &alloc_info, - self->descriptor_sets_2d.data()) != VK_SUCCESS) - throw CommandError{"Failed to create Vulkan descriptor sets for view."}; -} - -void -load_resources_to_descriptor_sets_2d(void *obj) -{ - auto self = static_cast(obj); - - for(auto i{0}; i < self->ub_2d.size(); i++) - { - VkDescriptorBufferInfo view_2d_info{}; - view_2d_info.buffer = self->ub_2d[i].buffer; - view_2d_info.offset = 0; - view_2d_info.range = sizeof(BluCat::UDOView2D); - - std::array write_descriptors{}; - write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_descriptors[0].dstSet = self->descriptor_sets_2d[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 = &view_2d_info; - write_descriptors[0].pImageInfo = nullptr; - write_descriptors[0].pTexelBufferView = nullptr; - - vkUpdateDescriptorSets( - BluCat::core.vk_device_with_swapchain->device, write_descriptors.size(), - write_descriptors.data(), 0, nullptr); - - BluCat::UDOView2D ubo_view_2d; - ubo_view_2d.proj = glm::ortho( - 0.0f, self->projection_width, - 0.0f, self->projection_height, - 0.0f, 100.0f); - self->ub_2d[i].copy_data(&ubo_view_2d); - } -} - -} - -namespace BluCat -{ - -const CommandChain View2D::loader{ - {&load_2d_uniform_buffer, &unload_2d_uniform_buffer} -}; - -const CommandChain View2D::descriptor_sets_loader{ - {&load_descriptor_sets_2d, nullptr}, - {&load_resources_to_descriptor_sets_2d, nullptr} -}; - -View2D::View2D( - glm::vec4 region, float projection_width, float projection_height): - projection_width{projection_width}, - projection_height{projection_height}, - region{region}, - descriptor_pool{VK_NULL_HANDLE}, - rectangles_to_draw{BluCat::core.vk_swapchain->images_count}, - sprites_to_draw{BluCat::core.vk_swapchain->images_count} -{ - loader.execute(this); -} - -View2D::~View2D() -{ - loader.revert(this); -} - -void -View2D::load_descriptor_sets(VkDescriptorPool descriptor_pool) -{ - if(this->descriptor_pool != VK_NULL_HANDLE) return; - - this->descriptor_pool = descriptor_pool; - descriptor_sets_loader.execute(this); -} - -void -View2D::unload_descriptor_sets() -{ - if(this->descriptor_pool == VK_NULL_HANDLE) return; - - this->descriptor_pool = VK_NULL_HANDLE; - descriptor_sets_loader.revert(this); -} - -} diff --git a/src/blucat/view_2d.hpp b/src/blucat/view_2d.hpp deleted file mode 100644 index b798f19..0000000 --- a/src/blucat/view_2d.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_VIEW_2D_H -#define CANDY_GEAR_BLUCAT_VIEW_2D_H 1 - -#include -#include -#include - -#include "vulkan.hpp" -#include "sprite_to_draw.hpp" -#include "rectangle.hpp" - -namespace BluCat -{ - -struct View2D -{ - glm::vec4 region; - float projection_width, projection_height; - - // FIXME: if these vectors get resized, they can cause a segmentation fault! - std::vector ub_2d; - - VkDescriptorPool descriptor_pool; - std::vector descriptor_sets_2d; - - std::vector> rectangles_to_draw; - std::vector> sprites_to_draw; - - View2D(glm::vec4 region, float projection_width, float projection_height); - virtual ~View2D(); - - void - virtual load_descriptor_sets(VkDescriptorPool descriptor_pool); - - void - virtual unload_descriptor_sets(); - -protected: - static const CommandChain loader, descriptor_sets_loader; -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_VIEW_2D_H */ diff --git a/src/blucat/view_3d.cpp b/src/blucat/view_3d.cpp deleted file mode 100644 index be9970c..0000000 --- a/src/blucat/view_3d.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2022-2024 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 "view_3d.hpp" - -#include - -#include "core.hpp" -#include "uniform_data_object.hpp" - -namespace -{ - -void -load_3d_uniform_buffer(void *obj) -{ - auto self = static_cast(obj); - - try - { - self->ub_3d.reserve(BluCat::core.vk_swapchain->images_count); - for(auto i{0}; i < BluCat::core.vk_swapchain->images_count; i++) - self->ub_3d.emplace_back( - BluCat::core.vk_device_with_swapchain, sizeof(BluCat::UDOView3D)); - } - catch(const std::exception& e) - { - throw CommandError{e.what()}; - } -} - -void -unload_3d_uniform_buffer(void *obj) -{ - auto self = static_cast(obj); - - self->ub_3d.clear(); -} - -void -load_descriptor_sets_3d(void *obj) -{ - auto self = static_cast(obj); - - std::vector layouts( - BluCat::core.vk_swapchain->images_count, - BluCat::core.vk_descriptor_set_layout->view); - - 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_3d.resize(layouts.size()); - if(vkAllocateDescriptorSets( - BluCat::core.vk_device_with_swapchain->device, &alloc_info, - self->descriptor_sets_3d.data()) != VK_SUCCESS) - throw CommandError{"Failed to create Vulkan descriptor sets for view."}; -} - -void -load_resources_to_descriptor_sets_3d(void *obj) -{ - auto self = static_cast(obj); - - for(auto i{0}; i < self->ub_3d.size(); i++) - { - VkDescriptorBufferInfo view_3d_info{}; - view_3d_info.buffer = self->ub_3d[i].buffer; - view_3d_info.offset = 0; - view_3d_info.range = sizeof(BluCat::UDOView3D); - - std::array write_descriptors{}; - write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_descriptors[0].dstSet = self->descriptor_sets_3d[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 = &view_3d_info; - write_descriptors[0].pImageInfo = nullptr; - write_descriptors[0].pTexelBufferView = nullptr; - - vkUpdateDescriptorSets( - BluCat::core.vk_device_with_swapchain->device, write_descriptors.size(), - write_descriptors.data(), 0, nullptr); - } -} - -const CommandChain loader{ - {&load_3d_uniform_buffer, &unload_3d_uniform_buffer} -}; - -const CommandChain descriptor_sets_loader{ - {&load_descriptor_sets_3d, nullptr}, - {&load_resources_to_descriptor_sets_3d, nullptr} -}; - -} - -namespace BluCat -{ - -View3D::View3D( - glm::vec4 region, float projection_width, float projection_height): - View2D{region, projection_width, projection_height}, - field_of_view{45.0f}, - camera_position{std::make_shared(0.0f, 0.0f, 0.0f)}, - camera_orientation{std::make_shared(0.0f, 0.0f, 0.0f, 0.0f)} -{ - ::loader.execute(this); -} - -View3D::~View3D() -{ - ::loader.revert(this); -} - -void -View3D::load_descriptor_sets(VkDescriptorPool descriptor_pool) -{ - if(this->descriptor_pool != VK_NULL_HANDLE) return; - - auto parent = dynamic_cast(this); - this->descriptor_pool = descriptor_pool; - View2D::descriptor_sets_loader.execute(parent); - ::descriptor_sets_loader.execute(this); -} - -void -View3D::unload_descriptor_sets() -{ - if(this->descriptor_pool == VK_NULL_HANDLE) return; - - auto parent = dynamic_cast(this); - this->descriptor_pool = VK_NULL_HANDLE; - ::descriptor_sets_loader.revert(this); - View2D::descriptor_sets_loader.revert(parent); -} - -} diff --git a/src/blucat/view_3d.hpp b/src/blucat/view_3d.hpp deleted file mode 100644 index 05cae6b..0000000 --- a/src/blucat/view_3d.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2022-2024 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_BLUCAT_VIEW_3D_H -#define CANDY_GEAR_BLUCAT_VIEW_3D_H 1 - -#include "view_2d.hpp" - -namespace BluCat -{ - -struct View3D: public View2D -{ - float field_of_view; - // FIXME: if this vector get resized, it can cause a segmentation fault! - std::vector ub_3d; - - std::vector descriptor_sets_3d; - - std::shared_ptr camera_position; - std::shared_ptr camera_orientation; - - View3D(glm::vec4 region, float projection_width, float projection_height); - ~View3D(); - - void - load_descriptor_sets(VkDescriptorPool descriptor_pool); - - void - unload_descriptor_sets(); -}; - -} - -#endif /* CANDY_GEAR_BLUCAT_VIEW_3D_H */ diff --git a/src/blucat/vulkan.hpp b/src/blucat/vulkan.hpp deleted file mode 100644 index 24c35f5..0000000 --- a/src/blucat/vulkan.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2022-2024 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 BLU_CAT_VULKAN_H -#define BLU_CAT_VULKAN_H 1 - -// GLM uses some definitions to control their behavior, so you should not -// include it directly. Instead, use this header. -#define GLM_ENABLE_EXPERIMENTAL -#define GLM_FORCE_RADIANS -#define GLM_FORCE_DEPTH_ZERO_TO_ONE - -#include -#include -#include -#include -#include - -#include - -#endif /* BLU_CAT_VULKAN_H */ diff --git a/src/blucat/worker.cpp b/src/blucat/worker.cpp deleted file mode 100644 index bcf654e..0000000 --- a/src/blucat/worker.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 "worker.hpp" - -#include - -Worker::Worker(JobQueue *job_queue): - job_queue{job_queue} -{ -} - -void -Worker::operator()() -{ - while(!this->job_queue->_stop) - { - auto job{this->job_queue->pop()}; - if(job) job(); - } -} diff --git a/src/blucat/worker.hpp b/src/blucat/worker.hpp deleted file mode 100644 index 449e1b0..0000000 --- a/src/blucat/worker.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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_WORKER_H -#define CANDY_GEAR_WORKER_H 1 - -#include "job_queue.hpp" - -class Worker -{ - JobQueue *job_queue; - -public: - Worker(JobQueue *job_queue); - - void - operator()(); -}; - -#endif /* CANDY_GEAR_WORKER_H */ diff --git a/src/candy_gear.cpp b/src/candy_gear.cpp deleted file mode 100644 index e8add70..0000000 --- a/src/candy_gear.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2022-2024 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 "candy_gear.hpp" - -#include -#include -#include - -#include "core.hpp" -#include "view_2d.hpp" -#include "view_3d.hpp" - -static mrb_value -cg_mCandyGear_set_game_name(mrb_state *mrb, mrb_value self) -{ - mrb_value name; - - mrb_get_args(mrb, "S", &name); - BluCat::core.game_name = RSTRING_PTR(name); - - return self; -} - -static mrb_value -cg_mCandyGear_set_views(mrb_state *mrb, mrb_value self) -{ - struct RClass *cg_m, *cg_cView2D, *cg_cView3D; - mrb_value *array; - mrb_int array_len; - - std::vector> views_2d; - std::vector> views_3d; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cView2D = mrb_class_get_under(mrb, cg_m, "View2D"); - cg_cView3D = mrb_class_get_under(mrb, cg_m, "View3D"); - - mrb_get_args(mrb, "a", &array, &array_len); - for(mrb_int i{0}; i < array_len; i++) - { - if(mrb_obj_is_kind_of(mrb, array[i], cg_cView2D)) - { - auto v = (std::shared_ptr*)DATA_PTR(array[i]); - views_2d.push_back(*v); - } - else if(mrb_obj_is_kind_of(mrb, array[i], cg_cView3D)) - { - auto v = (std::shared_ptr*)DATA_PTR(array[i]); - views_3d.push_back(*v); - } - } - - // A Renderer need at least one view to work. - if(views_2d.size() > 0 || views_3d.size() > 0) - { - delete BluCat::core.vk_renderer; - BluCat::core.vk_renderer = new BluCat::Renderer({views_2d, views_3d}); - } - - return self; -} - -static mrb_value -cg_mCandyGear_log(mrb_state *mrb, mrb_value self) -{ - const char *message; - mrb_sym sym_log_level; - Log::Level log_lvl; - - mrb_get_args(mrb, "nz", &sym_log_level, &message); - - if(sym_log_level == cg_core.sym_trace) - log_lvl = Log::Level::Trace; - else if(sym_log_level == cg_core.sym_debug) - log_lvl = Log::Level::Debug; - else if(sym_log_level == cg_core.sym_information) - log_lvl = Log::Level::Information; - else if(sym_log_level == cg_core.sym_warning) - log_lvl = Log::Level::Warning; - else if(sym_log_level == cg_core.sym_error) - log_lvl = Log::Level::Error; - else - log_lvl = Log::Level::Fatal; - - BluCat::core.log.message(log_lvl, message); - - return self; -} - -static mrb_value -cg_mCandyGear_quit(mrb_state *mrb, mrb_value self) -{ - cg_core.quit_game = true; - - return self; -} - -void -cg_candy_gear_init_config(mrb_state *mrb) -{ - struct RClass *cg_m; - - cg_m = mrb_module_get(mrb, "CandyGear"); - - mrb_define_class_method( - mrb, cg_m, "game_name=", cg_mCandyGear_set_game_name, MRB_ARGS_REQ(1)); -} - -void -cg_candy_gear_finish_config(mrb_state *mrb) -{ - struct RClass *cg_m; - - cg_m = mrb_module_get(mrb, "CandyGear"); - - mrb_undef_class_method(mrb, cg_m, "game_name="); -} - -void -cg_candy_gear_init(mrb_state *mrb) -{ - struct RClass *cg_m; - - cg_m = mrb_module_get(mrb, "CandyGear"); - - mrb_define_class_method( - mrb, cg_m, "views=", cg_mCandyGear_set_views, MRB_ARGS_REQ(1)); - mrb_define_class_method( - mrb, cg_m, "log", cg_mCandyGear_log, MRB_ARGS_REQ(2)); - mrb_define_class_method( - mrb, cg_m, "quit", cg_mCandyGear_quit, MRB_ARGS_NONE()); -} diff --git a/src/candy_gear.hpp b/src/candy_gear.hpp deleted file mode 100644 index 3ec92b3..0000000 --- a/src/candy_gear.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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_CANDY_GEAR_H -#define CANDY_GEAR_CANDY_GEAR_H 1 - -#include "core.hpp" - -// Provides the basic interface the game needs to configure the engine's -// initialization. -void -cg_candy_gear_init_config(mrb_state *mrb); -void -cg_candy_gear_finish_config(mrb_state *mrb); - -void -cg_candy_gear_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_CANDY_GEAR_H */ diff --git a/src/candy_gear/candy_gear.cpp b/src/candy_gear/candy_gear.cpp new file mode 100644 index 0000000..b1758a4 --- /dev/null +++ b/src/candy_gear/candy_gear.cpp @@ -0,0 +1,146 @@ +/* + * Copyright 2022-2024 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 "candy_gear.hpp" + +#include +#include +#include + +#include "core.hpp" +#include "view_2d.hpp" +#include "view_3d.hpp" + +static mrb_value +cg_mCandyGear_set_game_name(mrb_state *mrb, mrb_value self) +{ + mrb_value name; + + mrb_get_args(mrb, "S", &name); + BluCat::INT::core.game_name = RSTRING_PTR(name); + + return self; +} + +static mrb_value +cg_mCandyGear_set_views(mrb_state *mrb, mrb_value self) +{ + struct RClass *cg_m, *cg_cView2D, *cg_cView3D; + mrb_value *array; + mrb_int array_len; + + std::vector> views_2d; + std::vector> views_3d; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cView2D = mrb_class_get_under(mrb, cg_m, "View2D"); + cg_cView3D = mrb_class_get_under(mrb, cg_m, "View3D"); + + mrb_get_args(mrb, "a", &array, &array_len); + for(mrb_int i{0}; i < array_len; i++) + { + if(mrb_obj_is_kind_of(mrb, array[i], cg_cView2D)) + { + auto v = (std::shared_ptr*)DATA_PTR(array[i]); + views_2d.push_back(*v); + } + else if(mrb_obj_is_kind_of(mrb, array[i], cg_cView3D)) + { + auto v = (std::shared_ptr*)DATA_PTR(array[i]); + views_3d.push_back(*v); + } + } + + // A Renderer need at least one view to work. + if(views_2d.size() > 0 || views_3d.size() > 0) + { + delete BluCat::INT::core.vk_renderer; + BluCat::INT::core.vk_renderer = new BluCat::GRA::Renderer({views_2d, views_3d}); + } + + return self; +} + +static mrb_value +cg_mCandyGear_log(mrb_state *mrb, mrb_value self) +{ + const char *message; + mrb_sym sym_log_level; + Log::Level log_lvl; + + mrb_get_args(mrb, "nz", &sym_log_level, &message); + + if(sym_log_level == cg_core.sym_trace) + log_lvl = Log::Level::Trace; + else if(sym_log_level == cg_core.sym_debug) + log_lvl = Log::Level::Debug; + else if(sym_log_level == cg_core.sym_information) + log_lvl = Log::Level::Information; + else if(sym_log_level == cg_core.sym_warning) + log_lvl = Log::Level::Warning; + else if(sym_log_level == cg_core.sym_error) + log_lvl = Log::Level::Error; + else + log_lvl = Log::Level::Fatal; + + BluCat::INT::core.log.message(log_lvl, message); + + return self; +} + +static mrb_value +cg_mCandyGear_quit(mrb_state *mrb, mrb_value self) +{ + cg_core.quit_game = true; + + return self; +} + +void +cg_candy_gear_init_config(mrb_state *mrb) +{ + struct RClass *cg_m; + + cg_m = mrb_module_get(mrb, "CandyGear"); + + mrb_define_class_method( + mrb, cg_m, "game_name=", cg_mCandyGear_set_game_name, MRB_ARGS_REQ(1)); +} + +void +cg_candy_gear_finish_config(mrb_state *mrb) +{ + struct RClass *cg_m; + + cg_m = mrb_module_get(mrb, "CandyGear"); + + mrb_undef_class_method(mrb, cg_m, "game_name="); +} + +void +cg_candy_gear_init(mrb_state *mrb) +{ + struct RClass *cg_m; + + cg_m = mrb_module_get(mrb, "CandyGear"); + + mrb_define_class_method( + mrb, cg_m, "views=", cg_mCandyGear_set_views, MRB_ARGS_REQ(1)); + mrb_define_class_method( + mrb, cg_m, "log", cg_mCandyGear_log, MRB_ARGS_REQ(2)); + mrb_define_class_method( + mrb, cg_m, "quit", cg_mCandyGear_quit, MRB_ARGS_NONE()); +} diff --git a/src/candy_gear/candy_gear.hpp b/src/candy_gear/candy_gear.hpp new file mode 100644 index 0000000..3ec92b3 --- /dev/null +++ b/src/candy_gear/candy_gear.hpp @@ -0,0 +1,32 @@ +/* + * 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_CANDY_GEAR_H +#define CANDY_GEAR_CANDY_GEAR_H 1 + +#include "core.hpp" + +// Provides the basic interface the game needs to configure the engine's +// initialization. +void +cg_candy_gear_init_config(mrb_state *mrb); +void +cg_candy_gear_finish_config(mrb_state *mrb); + +void +cg_candy_gear_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_CANDY_GEAR_H */ diff --git a/src/candy_gear/core.cpp b/src/candy_gear/core.cpp new file mode 100644 index 0000000..28f5a15 --- /dev/null +++ b/src/candy_gear/core.cpp @@ -0,0 +1,398 @@ +/* + * Copyright 2022-2024 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 "core.hpp" + +#include "candy_gear.hpp" +#include "font.hpp" +#include "graphic.hpp" +#include "key.hpp" +#include "orientation_3d.hpp" +#include "skeletal_model.hpp" +#include "skeletal_mesh.hpp" +#include "static_model.hpp" +#include "static_mesh.hpp" +#include "sound.hpp" +#include "sprite.hpp" +#include "sprite_3d.hpp" +#include "texture.hpp" +#include "vector_3d.hpp" +#include "vector_4d.hpp" +#include "view_2d.hpp" +#include "view_3d.hpp" + +#ifdef DEBUG +#include +#endif + +namespace +{ + +void +load_mruby_symbols(void *obj) +{ + cg_core.sym_config = mrb_intern_cstr(cg_core.mrb, "config"); + cg_core.sym_debug = mrb_intern_cstr(cg_core.mrb, "debug"); + cg_core.sym_error = mrb_intern_cstr(cg_core.mrb, "error"); + cg_core.sym_fatal = mrb_intern_cstr(cg_core.mrb, "fatal"); + cg_core.sym_information = mrb_intern_cstr(cg_core.mrb, "information"); + cg_core.sym_init = mrb_intern_cstr(cg_core.mrb, "init"); + cg_core.sym_key_down = mrb_intern_cstr(cg_core.mrb, "key_down"); + cg_core.sym_key_up = mrb_intern_cstr(cg_core.mrb, "key_up"); + cg_core.sym_quit = mrb_intern_cstr(cg_core.mrb, "quit"); + cg_core.sym_tick = mrb_intern_cstr(cg_core.mrb, "tick"); + cg_core.sym_trace = mrb_intern_cstr(cg_core.mrb, "trace"); + cg_core.sym_warning = mrb_intern_cstr(cg_core.mrb, "warning"); +} + +void +load_game(void *obj) +{ + FILE *fp; + mrb_value main_obj{mrb_top_self(cg_core.mrb)}; + + BluCat::INT::core.game_name = "CandyGear Game"; + + BluCat::INT::core.display_width = 800; + BluCat::INT::core.display_height = 600; + + BluCat::INT::core.game_version_major = 0; + BluCat::INT::core.game_version_minor = 1; + BluCat::INT::core.game_version_patch = 0; + + BluCat::INT::core.fps = 30; + + mrb_define_module(cg_core.mrb, "CandyGear"); + cg_candy_gear_init_config(cg_core.mrb); + cg_graphic_init_config(cg_core.mrb); + + fp = fopen(cg_core.game_file.c_str(), "rb"); + mrb_load_irep_file(cg_core.mrb, fp); + fclose(fp); + if (cg_core.mrb->exc) + { + mrb_print_error(cg_core.mrb); + throw CommandError{"Error loading game."}; + } + + mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_config, 0); + if (cg_core.mrb->exc) + { + mrb_print_error(cg_core.mrb); + throw CommandError{"Error configuring game."}; + } + + cg_candy_gear_finish_config(cg_core.mrb); + cg_graphic_finish_config(cg_core.mrb); +} + +void +load_sdl(void *obj) +{ + if(SDL_Init(SDL_INIT_EVERYTHING) < 0) + { + std::string error{"SDL could not initialize! SDL Error → "}; + error += SDL_GetError(); + throw error; + } + + if(SDL_Vulkan_LoadLibrary(nullptr) != 0) + { + SDL_Quit(); + std::string error{"SDL could not initialize Vulkan! SDL_Error → "}; + error += SDL_GetError(); + throw CommandError{error}; + } +} + +void +unload_sdl(void *obj) +{ + SDL_Vulkan_UnloadLibrary(); + SDL_Quit(); +} + +void +load_sdl_mixer(void *obj) +{ + int flags = MIX_INIT_OGG|MIX_INIT_MOD; + int initted = Mix_Init(flags); + if(initted&flags != flags) + { + std::string error{"Could not initialize SDL mixer → "}; + error += Mix_GetError(); + throw CommandError{error}; + } +} + +void +unload_sdl_mixer(void *obj) +{ + while(Mix_Init(0)) Mix_Quit(); +} + +void +load_sdl_open_audio(void *obj) +{ + if(Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 1024) == -1) + { + std::string error{"Could not open SDL mixer audio → "}; + error += Mix_GetError(); + throw CommandError{error}; + } +} + +void +unload_sdl_open_audio(void *obj) +{ + Mix_CloseAudio(); +} + +void +load_window(void *obj) +{ + cg_core.window = NULL; + cg_core.window = SDL_CreateWindow( + BluCat::INT::core.game_name.c_str(), + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + BluCat::INT::core.display_width, BluCat::INT::core.display_height, + SDL_WINDOW_VULKAN); + if(cg_core.window == NULL) + { + std::string error{"Window could not be created! SDL_Error → "}; + error += SDL_GetError(); + throw CommandError{error}; + } +} + +void +unload_window(void *obj) +{ + SDL_DestroyWindow(cg_core.window); +} + +void +load_vk_instance(void *obj) +{ + std::vector vk_extensions; + std::vector vk_required_layers_names; + + // Get extensions. + { + uint32_t vk_extensions_count; + std::vector vk_required_extensions; + + // Load debuging layers. +#ifdef DEBUG + vk_required_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + vk_required_layers_names.push_back("VK_LAYER_KHRONOS_validation"); +#endif + + // Get extensions for SDL. + { + uint32_t vk_sdl_extension_count; + std::vector vk_sdl_extensions; + + if(!SDL_Vulkan_GetInstanceExtensions( + cg_core.window, &vk_sdl_extension_count, nullptr)) + { + std::string error{ + "Vulkan extensions could not be loaded by SDL! SDL_Error: "}; + error += SDL_GetError(); + throw CommandError{error}; + } + + vk_sdl_extensions.resize(vk_sdl_extension_count); + SDL_Vulkan_GetInstanceExtensions( + cg_core.window, &vk_sdl_extension_count, vk_sdl_extensions.data()); + + // Combine all extensions. + vk_extensions_count = vk_sdl_extension_count + + vk_required_extensions.size(); + vk_extensions.resize(vk_extensions_count); + for(auto i{0}; i < vk_sdl_extension_count; i++) + vk_extensions[i] = vk_sdl_extensions[i]; + for(auto i{0}; i < vk_required_extensions.size(); i++) + vk_extensions[i + vk_sdl_extension_count] = vk_required_extensions[i]; + } + +#ifdef DEBUG + BluCat::INT::core.log.message(Log::Level::Trace, "Enabled VK extensions."); + for(auto vk_extension: vk_extensions) + { + std::string message{"Extension name: "}; + message += vk_extension; + BluCat::INT::core.log.message(Log::Level::Trace, message); + } +#endif + } + + // Get available instance layers. + { + uint32_t vk_available_layers_count; + std::vector vk_available_layers; + std::vector vk_available_layers_names; + + vkEnumerateInstanceLayerProperties(&vk_available_layers_count, nullptr); + vk_available_layers.resize(vk_available_layers_count); + vkEnumerateInstanceLayerProperties(&vk_available_layers_count, + vk_available_layers.data()); + vk_available_layers_names.resize(vk_available_layers_count); +#ifdef DEBUG + BluCat::INT::core.log.message( + Log::Level::Trace, "Available VK instance layers."); +#endif + for(uint32_t i = 0; i < vk_available_layers_count; i++) + { +#ifdef DEBUG + std::stringstream message{}; + message << "\nname: " << vk_available_layers[i].layerName << std::endl; + message << "Description: " << vk_available_layers[i].description << + std::endl; + message << "Spec version: " << vk_available_layers[i].specVersion << + std::endl; + message << "Implementation version: " << + vk_available_layers[i].implementationVersion << std::endl; + BluCat::INT::core.log.message(Log::Level::Trace, message.str()); +#endif + + vk_available_layers_names[i] = vk_available_layers[i].layerName; + } + + // If required layers are not all available. + if(!std::includes( + vk_available_layers_names.begin(), vk_available_layers_names.end(), + vk_required_layers_names.begin(), vk_required_layers_names.begin())) + throw CommandError{"Some required Vulkan layers are not available."}; + } + + { + VkApplicationInfo app_info; + app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + app_info.pNext = nullptr; + app_info.pApplicationName = BluCat::INT::core.game_name.c_str(); + app_info.applicationVersion = VK_MAKE_VERSION( + BluCat::INT::core.game_version_major, + BluCat::INT::core.game_version_minor, + BluCat::INT::core.game_version_patch); + app_info.pEngineName = "BluCat::GRA"; + app_info.engineVersion = VK_MAKE_VERSION( + BLU_CAT_VERSION_MAJOR, + BLU_CAT_VERSION_MINOR, + BLU_CAT_VERSION_PATCH); + app_info.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo create_info; + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.pApplicationInfo = &app_info; + create_info.enabledExtensionCount = vk_extensions.size(); + create_info.ppEnabledExtensionNames = vk_extensions.data(); + create_info.enabledLayerCount = vk_required_layers_names.size(); + create_info.ppEnabledLayerNames = vk_required_layers_names.data(); + + VkResult result = + vkCreateInstance(&create_info, nullptr, &BluCat::INT::core.vk_instance); + if(result != VK_SUCCESS) + { + std::string error{""}; + switch(result) + { + case VK_ERROR_LAYER_NOT_PRESENT: + error = " Layer not present."; + break; + case VK_ERROR_EXTENSION_NOT_PRESENT: + error = " Extension not present."; + } + error = "Failed to create Vulkan instance." + error; + throw CommandError{error}; + } + } +} + +void +unload_vk_instance(void *obj) +{ + vkDestroyInstance(BluCat::INT::core.vk_instance, nullptr); +} + +void +load_window_surface(void *obj) +{ + if(!SDL_Vulkan_CreateSurface( + cg_core.window, BluCat::INT::core.vk_instance, &BluCat::INT::core.window_surface)) + { + std::string error{"Failed to create a window surface → "}; + error += SDL_GetError(); + throw CommandError{error}; + } +} + +void +unload_window_surface(void *obj) +{ + vkDestroySurfaceKHR( + BluCat::INT::core.vk_instance, BluCat::INT::core.window_surface, nullptr); +} + +void +load_blucat(void *obj) +{ + BluCat::INT::core.loader.execute(nullptr); +} + +void +unload_blucat(void *obj) +{ + BluCat::INT::core.loader.revert(nullptr); +} + +void +load_mruby_interface(void *obj) +{ + cg_candy_gear_init(cg_core.mrb); + cg_font_init(cg_core.mrb); + cg_key_init(cg_core.mrb); + cg_orientation_3d_init(cg_core.mrb); + cg_skeletal_model_init(cg_core.mrb); + cg_skeletal_mesh_init(cg_core.mrb); + cg_static_model_init(cg_core.mrb); + cg_static_mesh_init(cg_core.mrb); + cg_sound_init(cg_core.mrb); + cg_sprite_init(cg_core.mrb); + cg_sprite_3d_init(cg_core.mrb); + cg_texture_init(cg_core.mrb); + cg_vector_3d_init(cg_core.mrb); + cg_vector_4d_init(cg_core.mrb); + cg_view_2d_init(cg_core.mrb); + cg_view_3d_init(cg_core.mrb); +} + +} + +const CommandChain cg_sCore::loader{ + {&load_mruby_symbols, nullptr}, + {&load_game, nullptr}, + {&load_sdl, &unload_sdl}, + {&load_sdl_mixer, &unload_sdl_mixer}, + {&load_sdl_open_audio, &unload_sdl_open_audio}, + {&load_window, &unload_window}, + {&load_vk_instance, &unload_vk_instance}, + {&load_window_surface, &unload_window_surface}, + {&load_blucat, &unload_blucat}, + {&load_mruby_interface, nullptr} +}; diff --git a/src/candy_gear/core.hpp b/src/candy_gear/core.hpp new file mode 100644 index 0000000..60d8339 --- /dev/null +++ b/src/candy_gear/core.hpp @@ -0,0 +1,66 @@ +/* + * Copyright 2022-2024 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_CORE_H +#define CANDY_GEAR_CORE_H 1 + +#include +#include +#include +#include +#include +#include + +#define SDL_MAIN_HANDLED + +#ifdef _WIN64 +#include +#endif + +#include +#include +#include + +#include +#include FT_FREETYPE_H + +#include "../blu_cat/int/core.hpp" + +/** + * The Core class stores all global states that the engine needs to work. + * Global variables are not evil if you use them carefully. + */ +struct cg_sCore +{ + static const CommandChain loader; + + mrb_state *mrb; + + std::string game_file; + + /// mruby symbols + mrb_sym sym_config, sym_debug, sym_error, sym_fatal, sym_information, + sym_init, sym_key_down, sym_key_up, sym_quit, sym_tick, sym_trace, + sym_warning; + + bool quit_game; + + SDL_Window *window; +}; + +extern cg_sCore cg_core; + +#endif /* CANDY_GEAR_CORE_H */ diff --git a/src/candy_gear/font.cpp b/src/candy_gear/font.cpp new file mode 100644 index 0000000..f9cbf44 --- /dev/null +++ b/src/candy_gear/font.cpp @@ -0,0 +1,68 @@ +/* + * Copyright 2022-2024 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 "font.hpp" + +#include "../blu_cat/gra/font.hpp" + +void +cg_free_font(mrb_state *mrb, void *obj) +{ + auto ptr = static_cast(obj); + + ptr->~Font(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type +cg_font_type = {"CG_Font", cg_free_font}; + +static mrb_value +cg_cFont_initialize(mrb_state *mrb, mrb_value self) +{ + BluCat::GRA::Font *ptr; + const char *font_path; + mrb_int font_size; + + mrb_get_args(mrb, "zi", &font_path, &font_size); + ptr = (BluCat::GRA::Font*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (BluCat::GRA::Font*)mrb_malloc(mrb, sizeof(BluCat::GRA::Font)); + + try + { + new(ptr)BluCat::GRA::Font(font_path, font_size); + } + catch(const std::invalid_argument &e) + { + mrb_raise(mrb, E_RUNTIME_ERROR, e.what()); + } + + mrb_data_init(self, ptr, &cg_font_type); + return self; +} + +void +cg_font_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cFont; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cFont = mrb_define_class_under(mrb, cg_m, "Font", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cFont, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cFont, "initialize", cg_cFont_initialize, MRB_ARGS_REQ(2)); +} diff --git a/src/candy_gear/font.hpp b/src/candy_gear/font.hpp new file mode 100644 index 0000000..0128ea0 --- /dev/null +++ b/src/candy_gear/font.hpp @@ -0,0 +1,28 @@ +/* + * Copyright 2022-2023 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_FONT_H +#define CANDY_GEAR_FONT_H 1 + +#include "core.hpp" + +extern const struct mrb_data_type +cg_font_type; + +void +cg_font_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_FONT_H */ diff --git a/src/candy_gear/graphic.cpp b/src/candy_gear/graphic.cpp new file mode 100644 index 0000000..ad701d1 --- /dev/null +++ b/src/candy_gear/graphic.cpp @@ -0,0 +1,83 @@ +/* + * 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 "graphic.hpp" + +#include "core.hpp" + +static mrb_value +cg_mCandyGear_set_display_width(mrb_state *mrb, mrb_value self) +{ + mrb_int width; + + mrb_get_args(mrb, "i", &width); + BluCat::INT::core.display_width = width; + + return self; +} + +static mrb_value +cg_mCandyGear_set_display_height(mrb_state *mrb, mrb_value self) +{ + mrb_int height; + + mrb_get_args(mrb, "i", &height); + BluCat::INT::core.display_height = height; + + return self; +} + +static mrb_value +cg_mCandyGear_set_fps(mrb_state *mrb, mrb_value self) +{ + mrb_int fps; + + mrb_get_args(mrb, "i", &fps); + BluCat::INT::core.fps = fps; + + return self; +} + +void +cg_graphic_init_config(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_mGraphic; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_mGraphic = mrb_define_module_under(mrb, cg_m, "Graphic"); + + mrb_define_class_method( + mrb, cg_mGraphic, "display_width=", cg_mCandyGear_set_display_width, + MRB_ARGS_REQ(1)); + mrb_define_class_method( + mrb, cg_mGraphic, "display_height=", cg_mCandyGear_set_display_height, + MRB_ARGS_REQ(1)); + mrb_define_class_method( + mrb, cg_mGraphic, "fps=", cg_mCandyGear_set_fps, MRB_ARGS_REQ(1)); +} + +void +cg_graphic_finish_config(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_mGraphic; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_mGraphic = mrb_module_get_under(mrb, cg_m, "Graphic"); + + mrb_undef_class_method(mrb, cg_mGraphic, "display_width="); + mrb_undef_class_method(mrb, cg_mGraphic, "display_height="); + mrb_undef_class_method(mrb, cg_mGraphic, "fps="); +} diff --git a/src/candy_gear/graphic.hpp b/src/candy_gear/graphic.hpp new file mode 100644 index 0000000..fbd9df8 --- /dev/null +++ b/src/candy_gear/graphic.hpp @@ -0,0 +1,29 @@ +/* + * 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_GRAPHIC_H +#define CANDY_GEAR_GRAPHIC_H 1 + +#include "core.hpp" + +// Provides the basic interface the game needs to configure the engine's +// initialization. +void +cg_graphic_init_config(mrb_state *mrb); +void +cg_graphic_finish_config(mrb_state *mrb); + +#endif /* CANDY_GEAR_GRAPHIC_H */ diff --git a/src/candy_gear/key.cpp b/src/candy_gear/key.cpp new file mode 100644 index 0000000..615119c --- /dev/null +++ b/src/candy_gear/key.cpp @@ -0,0 +1,71 @@ +/* + * 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 "key.hpp" + +void +cg_key_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_mKey; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_mKey = mrb_define_module_under(mrb, cg_m, "Key"); + + mrb_define_const(mrb, cg_mKey, "A", mrb_int_value(mrb, SDLK_a)); + mrb_define_const(mrb, cg_mKey, "B", mrb_int_value(mrb, SDLK_b)); + mrb_define_const(mrb, cg_mKey, "C", mrb_int_value(mrb, SDLK_c)); + mrb_define_const(mrb, cg_mKey, "D", mrb_int_value(mrb, SDLK_d)); + mrb_define_const(mrb, cg_mKey, "E", mrb_int_value(mrb, SDLK_e)); + mrb_define_const(mrb, cg_mKey, "F", mrb_int_value(mrb, SDLK_f)); + mrb_define_const(mrb, cg_mKey, "G", mrb_int_value(mrb, SDLK_g)); + mrb_define_const(mrb, cg_mKey, "H", mrb_int_value(mrb, SDLK_h)); + mrb_define_const(mrb, cg_mKey, "I", mrb_int_value(mrb, SDLK_i)); + mrb_define_const(mrb, cg_mKey, "J", mrb_int_value(mrb, SDLK_j)); + mrb_define_const(mrb, cg_mKey, "K", mrb_int_value(mrb, SDLK_k)); + mrb_define_const(mrb, cg_mKey, "L", mrb_int_value(mrb, SDLK_l)); + mrb_define_const(mrb, cg_mKey, "M", mrb_int_value(mrb, SDLK_m)); + mrb_define_const(mrb, cg_mKey, "N", mrb_int_value(mrb, SDLK_n)); + mrb_define_const(mrb, cg_mKey, "O", mrb_int_value(mrb, SDLK_o)); + mrb_define_const(mrb, cg_mKey, "P", mrb_int_value(mrb, SDLK_p)); + mrb_define_const(mrb, cg_mKey, "Q", mrb_int_value(mrb, SDLK_q)); + mrb_define_const(mrb, cg_mKey, "R", mrb_int_value(mrb, SDLK_r)); + mrb_define_const(mrb, cg_mKey, "S", mrb_int_value(mrb, SDLK_s)); + mrb_define_const(mrb, cg_mKey, "T", mrb_int_value(mrb, SDLK_t)); + mrb_define_const(mrb, cg_mKey, "U", mrb_int_value(mrb, SDLK_u)); + mrb_define_const(mrb, cg_mKey, "V", mrb_int_value(mrb, SDLK_v)); + mrb_define_const(mrb, cg_mKey, "W", mrb_int_value(mrb, SDLK_w)); + mrb_define_const(mrb, cg_mKey, "X", mrb_int_value(mrb, SDLK_x)); + mrb_define_const(mrb, cg_mKey, "Y", mrb_int_value(mrb, SDLK_y)); + mrb_define_const(mrb, cg_mKey, "Z", mrb_int_value(mrb, SDLK_z)); + + mrb_define_const(mrb, cg_mKey, "UP", mrb_int_value(mrb, SDLK_UP)); + mrb_define_const(mrb, cg_mKey, "DOWN", mrb_int_value(mrb, SDLK_DOWN)); + mrb_define_const(mrb, cg_mKey, "LEFT", mrb_int_value(mrb, SDLK_LEFT)); + mrb_define_const(mrb, cg_mKey, "RIGHT", mrb_int_value(mrb, SDLK_RIGHT)); + + mrb_define_const( + mrb, cg_mKey, "BACKSPACE", mrb_int_value(mrb, SDLK_BACKSPACE)); + mrb_define_const(mrb, cg_mKey, "TAB", mrb_int_value(mrb, SDLK_TAB)); + mrb_define_const( + mrb, cg_mKey, "LEFT_SHIFT", mrb_int_value(mrb, SDLK_LSHIFT)); + mrb_define_const( + mrb, cg_mKey, "RIGHT_SHIFT", mrb_int_value(mrb, SDLK_RSHIFT)); + mrb_define_const(mrb, cg_mKey, "SPACE", mrb_int_value(mrb, SDLK_SPACE)); + mrb_define_const(mrb, cg_mKey, "LEFT_ALT", mrb_int_value(mrb, SDLK_LALT)); + mrb_define_const(mrb, cg_mKey, "RIGHT_ALT", mrb_int_value(mrb, SDLK_RALT)); + mrb_define_const(mrb, cg_mKey, "LEFT_CTRL", mrb_int_value(mrb, SDLK_LCTRL)); + mrb_define_const(mrb, cg_mKey, "RIGHT_CTRL", mrb_int_value(mrb, SDLK_RCTRL)); +} diff --git a/src/candy_gear/key.hpp b/src/candy_gear/key.hpp new file mode 100644 index 0000000..d3f4f5f --- /dev/null +++ b/src/candy_gear/key.hpp @@ -0,0 +1,25 @@ +/* + * 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_KEY_H +#define CANDY_GEAR_KEY_H 1 + +#include "core.hpp" + +void +cg_key_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_KEY_H */ diff --git a/src/candy_gear/main.cpp b/src/candy_gear/main.cpp new file mode 100644 index 0000000..353b6bf --- /dev/null +++ b/src/candy_gear/main.cpp @@ -0,0 +1,115 @@ +/* + * Copyright 2022-2024 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 +#include + +#include "core.hpp" + +cg_sCore cg_core; + +int main(int argc, char *argv[]) +{ + using namespace std::chrono; + using namespace std::this_thread; + + SDL_Event event; + + // Random numbers + BluCat::INT::random_number_generator.seed(BluCat::INT::random_seed()); + + cg_core.game_file = argv[1]; + cg_core.mrb = mrb_open(); + if (!cg_core.mrb) throw CommandError{"Failed to initialize mruby."}; + try{ cg_sCore::loader.execute(nullptr); } + catch(const CommandError &error) + { + BluCat::INT::core.log.message(Log::Level::Fatal, error.what()); + mrb_close(cg_core.mrb); + return 1; + } + + mrb_value main_obj{mrb_top_self(cg_core.mrb)}; + + mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_init, 0); + if (cg_core.mrb->exc) + { + mrb_print_error(cg_core.mrb); + mrb_close(cg_core.mrb); + cg_sCore::loader.revert(nullptr); + return 1; + } + + auto frame_start = steady_clock::now(); + + // Game main loop. + while(!cg_core.quit_game) + { + // Get input. + while(SDL_PollEvent(&event) != 0) + { + switch(event.type) + { + case SDL_KEYDOWN: + mrb_funcall_id( + cg_core.mrb, main_obj, cg_core.sym_key_down, 1, + mrb_int_value(cg_core.mrb, event.key.keysym.sym)); + break; + case SDL_KEYUP: + mrb_funcall_id( + cg_core.mrb, main_obj, cg_core.sym_key_up, 1, + mrb_int_value(cg_core.mrb, event.key.keysym.sym)); + break; + case SDL_MOUSEMOTION: + break; + case SDL_MOUSEBUTTONDOWN: + break; + case SDL_MOUSEBUTTONUP: + break; + case SDL_QUIT: + mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_quit, 0); + break; + } + } + + mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_tick, 0); + if (cg_core.mrb->exc) + { + mrb_print_error(cg_core.mrb); + cg_core.quit_game = true; + } + else + { + BluCat::INT::core.vk_renderer->draw(); + + { // Timer + auto frame_stop = steady_clock::now(); + auto frame_duration = frame_stop - frame_start; + + // If frame take less time than maximum allowed. + if(BluCat::INT::core.max_frame_duration > frame_duration) + sleep_for(BluCat::INT::core.max_frame_duration - frame_duration); + + frame_start = frame_stop; + } + } + } + + mrb_close(cg_core.mrb); + cg_sCore::loader.revert(nullptr); + + return 0; +} diff --git a/src/candy_gear/orientation_3d.cpp b/src/candy_gear/orientation_3d.cpp new file mode 100644 index 0000000..cb42984 --- /dev/null +++ b/src/candy_gear/orientation_3d.cpp @@ -0,0 +1,135 @@ +/* + * Copyright 2022-2024 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. + */ + +#define _USE_MATH_DEFINES + +#include "orientation_3d.hpp" + +#include "vector_3d.hpp" + +void +cg_free_orientation_3d(mrb_state *mrb, void* obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_orientation_3d_type = { + "CG_Orientation3D", cg_free_orientation_3d}; + +static mrb_value +cg_cOrientation3D_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_float x, y, z; + std::shared_ptr *ptr; + + mrb_get_args(mrb, "fff", &x, &y, &z); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + glm::vec3 angles(x, y, z); + new(ptr)std::shared_ptr( + std::make_shared(angles)); + (**ptr) = glm::normalize(**ptr); + + mrb_data_init(self, ptr, &cg_orientation_3d_type); + return self; +} + +static mrb_value +cg_cOrientation3D_get_w(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->w); +} + +static mrb_value +cg_cOrientation3D_get_x(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->x); +} + +static mrb_value +cg_cOrientation3D_get_y(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->y); +} + +static mrb_value +cg_cOrientation3D_get_z(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->z); +} + +static mrb_value +cg_cOrientation3D_rotate(mrb_state *mrb, mrb_value self) +{ + mrb_float x, y, z; + auto *ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "fff", &x, &y, &z); + + glm::vec3 angles(x, y, z); + glm::quat rot(angles); + (**ptr) *= rot; + + // TODO: calling normalize for every rotation is expensive. + (**ptr) = glm::normalize(**ptr); + + return self; +} + +void +cg_orientation_3d_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cOrientation3D; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cOrientation3D = mrb_define_class_under( + mrb, cg_m, "Orientation3D", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cOrientation3D, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cOrientation3D, "initialize", cg_cOrientation3D_initialize, + MRB_ARGS_REQ(3)); + + mrb_define_method( + mrb, cg_cOrientation3D, "w", cg_cOrientation3D_get_w, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cOrientation3D, "x", cg_cOrientation3D_get_x, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cOrientation3D, "y", cg_cOrientation3D_get_y, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cOrientation3D, "z", cg_cOrientation3D_get_z, MRB_ARGS_NONE()); + + mrb_define_method( + mrb, cg_cOrientation3D, "rotate", cg_cOrientation3D_rotate, + MRB_ARGS_REQ(3)); +} diff --git a/src/candy_gear/orientation_3d.hpp b/src/candy_gear/orientation_3d.hpp new file mode 100644 index 0000000..45a8ab2 --- /dev/null +++ b/src/candy_gear/orientation_3d.hpp @@ -0,0 +1,27 @@ +/* + * Copyright 2022-2024 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_ORIENTATION_3D_H +#define CANDY_GEAR_ORIENTATION_3D_H 1 + +#include "core.hpp" + +extern const struct mrb_data_type cg_orientation_3d_type; + +void +cg_orientation_3d_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_ORIENTATION_3D_H */ diff --git a/src/candy_gear/skeletal_mesh.cpp b/src/candy_gear/skeletal_mesh.cpp new file mode 100644 index 0000000..4af4419 --- /dev/null +++ b/src/candy_gear/skeletal_mesh.cpp @@ -0,0 +1,67 @@ +/* + * Copyright 2022-2024 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 "skeletal_mesh.hpp" + +#include "orientation_3d.hpp" +#include "vector_3d.hpp" +#include "../blu_cat/gra/skeletal_mesh.hpp" + +void +cg_free_skeletal_mesh(mrb_state *mrb, void* obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_skeletal_mesh_type = { + "CG_SkeletalMesh", cg_free_skeletal_mesh }; + +static mrb_value +cg_cSkeletalMesh_initialize(mrb_state *mrb, mrb_value self) +{ + const char *file_path; + + std::shared_ptr *ptr; + + mrb_get_args(mrb, "z", &file_path); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + new(ptr)std::shared_ptr( + std::make_shared(file_path)); + + mrb_data_init(self, ptr, &cg_skeletal_mesh_type); + return self; +} + +void +cg_skeletal_mesh_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cSkeletalMesh; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cSkeletalMesh = mrb_define_class_under( + mrb, cg_m, "SkeletalMesh", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cSkeletalMesh, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cSkeletalMesh, "initialize", cg_cSkeletalMesh_initialize, + MRB_ARGS_REQ(1)); +} diff --git a/src/candy_gear/skeletal_mesh.hpp b/src/candy_gear/skeletal_mesh.hpp new file mode 100644 index 0000000..476aa9b --- /dev/null +++ b/src/candy_gear/skeletal_mesh.hpp @@ -0,0 +1,27 @@ +/* + * Copyright 2022-2023 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_SKELETAL_MESH_H +#define CANDY_GEAR_SKELETAL_MESH_H 1 + +#include "core.hpp" + +extern const struct mrb_data_type cg_skeletal_mesh_type; + +void +cg_skeletal_mesh_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_SKELETAL_MESH_H */ diff --git a/src/candy_gear/skeletal_model.cpp b/src/candy_gear/skeletal_model.cpp new file mode 100644 index 0000000..41d0c9a --- /dev/null +++ b/src/candy_gear/skeletal_model.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2022-2024 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 "skeletal_model.hpp" + +#include "orientation_3d.hpp" +#include "vector_3d.hpp" +#include "skeletal_mesh.hpp" +#include "texture.hpp" +#include "../blu_cat/gra/skeletal_model.hpp" + +void +cg_free_skeletal_model(mrb_state *mrb, void *obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_skeletal_model_type = { + "CG_SkeletalModel", cg_free_skeletal_model }; + +static mrb_value +cg_cSkeletalModel_initialize(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *skeletal_mesh; + std::shared_ptr *texture; + std::shared_ptr *position; + std::shared_ptr *orientation; + std::shared_ptr *ptr; + + mrb_get_args( + mrb, "dddd", &skeletal_mesh, &cg_skeletal_mesh_type, &texture, + &cg_texture_type, &position, &cg_vector_3d_type, &orientation, + &cg_orientation_3d_type); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + new(ptr)std::shared_ptr( + std::make_shared( + *skeletal_mesh, *texture, *position, *orientation)); + + mrb_data_init(self, ptr, &cg_skeletal_model_type); + return self; +} + +static mrb_value +cg_cSkeletalModel_set_orientation(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + std::shared_ptr *orientation; + + mrb_get_args(mrb, "d", &orientation, &cg_orientation_3d_type); + (*ptr)->orientation = *orientation; + + return self; +} + +static mrb_value +cg_cSkeletalModel_set_position(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + std::shared_ptr *position; + + mrb_get_args(mrb, "d", &position, &cg_vector_3d_type); + (*ptr)->position = *position; + + return self; +} + +static mrb_value +cg_cSkeletalModel_set_animation(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + mrb_int animation_index; + + mrb_get_args(mrb, "i", &animation_index); + (*ptr)->animation_index = animation_index; + + return self; +} + +static mrb_value +cg_cSkeletalModel_draw(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + auto &instances = BluCat::INT::core.vk_renderer->skeletal_models_to_draw[ + BluCat::INT::core.vk_swapchain->current_frame][(*ptr)->skeletal_mesh]; + instances.push_back(*ptr); + + return self; +} + +void +cg_skeletal_model_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cSkeletalModel; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cSkeletalModel = mrb_define_class_under( + mrb, cg_m, "SkeletalModel", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cSkeletalModel, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cSkeletalModel, "initialize", cg_cSkeletalModel_initialize, + MRB_ARGS_REQ(4)); + mrb_define_method( + mrb, cg_cSkeletalModel, "position=", cg_cSkeletalModel_set_position, + MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cSkeletalModel, "orientation=", cg_cSkeletalModel_set_orientation, + MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cSkeletalModel, "animation=", cg_cSkeletalModel_set_animation, + MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cSkeletalModel, "draw", cg_cSkeletalModel_draw, MRB_ARGS_NONE()); +} diff --git a/src/candy_gear/skeletal_model.hpp b/src/candy_gear/skeletal_model.hpp new file mode 100644 index 0000000..05f9c2e --- /dev/null +++ b/src/candy_gear/skeletal_model.hpp @@ -0,0 +1,25 @@ +/* + * Copyright 2022-2023 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_SKELETAL_MODEL_H +#define CANDY_GEAR_SKELETAL_MODEL_H 1 + +#include "core.hpp" + +void +cg_skeletal_model_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_SKELETAL_MODEL_H */ diff --git a/src/candy_gear/sound.cpp b/src/candy_gear/sound.cpp new file mode 100644 index 0000000..0b3518f --- /dev/null +++ b/src/candy_gear/sound.cpp @@ -0,0 +1,73 @@ +/* + * 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 "sound.hpp" + +void +cg_free_sound(mrb_state *mrb, void* obj) +{ + struct cg_sound *ptr = static_cast(obj); + + Mix_FreeChunk(ptr->chunk); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_sound_type = { + "CG_Sound", cg_free_sound }; + +static mrb_value +cg_cSound_initialize(mrb_state *mrb, mrb_value self) +{ + const char *file_path; + + struct cg_sound *ptr; + + mrb_get_args(mrb, "z", &file_path); + ptr = (struct cg_sound *)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (struct cg_sound *)mrb_malloc(mrb, sizeof(struct cg_sound)); + + ptr->chunk = Mix_LoadWAV(file_path); + if(ptr->chunk == NULL) mrb_raise(mrb, E_RUNTIME_ERROR, Mix_GetError()); + + mrb_data_init(self, ptr, &cg_sound_type); + return self; +} + +static mrb_value +cg_cSound_play(mrb_state *mrb, mrb_value self) +{ + struct cg_sound *ptr; + + ptr = (struct cg_sound *)DATA_PTR(self); + + Mix_PlayChannel(-1, ptr->chunk, 0); + + return self; +} + +void +cg_sound_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cSound; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cSound = mrb_define_class_under(mrb, cg_m, "Sound", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cSound, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cSound, "initialize", cg_cSound_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, cg_cSound, "play", cg_cSound_play, MRB_ARGS_NONE()); +} diff --git a/src/candy_gear/sound.hpp b/src/candy_gear/sound.hpp new file mode 100644 index 0000000..2f483e3 --- /dev/null +++ b/src/candy_gear/sound.hpp @@ -0,0 +1,32 @@ +/* + * 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_SOUND_H +#define CANDY_GEAR_SOUND_H 1 + +#include "core.hpp" + +struct cg_sound +{ + Mix_Chunk *chunk; +}; + +extern const struct mrb_data_type cg_sound_type; + +void +cg_sound_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_SOUND_H */ diff --git a/src/candy_gear/sprite.cpp b/src/candy_gear/sprite.cpp new file mode 100644 index 0000000..daf96a8 --- /dev/null +++ b/src/candy_gear/sprite.cpp @@ -0,0 +1,93 @@ +/* + * Copyright 2022-2024 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 "sprite.hpp" + +#include "texture.hpp" +#include "vector_4d.hpp" +#include "view_2d.hpp" +#include "../blu_cat/gra/sprite.hpp" + +void +cg_free_sprite(mrb_state *mrb, void* obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_sprite_type = { "CG_Sprite", cg_free_sprite }; + +static mrb_value +cg_cSprite_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_float x, y, w, h; + glm::vec4 vector_4d; + std::shared_ptr *texture; + std::shared_ptr *ptr; + + mrb_get_args( + mrb, "dffff", &texture, &cg_texture_type, &x, &y, &w, &h); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + vector_4d.x = x; + vector_4d.y = y; + vector_4d.z = w; + vector_4d.w = h; + new(ptr)std::shared_ptr( + std::make_shared(*texture, vector_4d)); + + mrb_data_init(self, ptr, &cg_sprite_type); + return self; +} + +static mrb_value +cg_cSprite_draw(mrb_state *mrb, mrb_value self) +{ + mrb_value view_value; + BluCat::GRA::View2D *view_2d; + mrb_float x, y, w, h, z_index{0.0}; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "offff|f", &view_value, &x, &y, &w, &h, &z_index); + + view_2d = cg_cView_to_view_2d(mrb, view_value); + + glm::vec4 rect(x, y, x + w, y + h); + auto &sprites_to_draw = view_2d->sprites_to_draw[ + BluCat::INT::core.vk_swapchain->current_frame]; + sprites_to_draw.emplace_back(*ptr, rect, z_index); + + return self; +} + +void +cg_sprite_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cSprite; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cSprite = mrb_define_class_under(mrb, cg_m, "Sprite", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cSprite, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cSprite, "initialize", cg_cSprite_initialize, MRB_ARGS_REQ(5)); + mrb_define_method(mrb, cg_cSprite, "draw", cg_cSprite_draw, MRB_ARGS_REQ(5)| + MRB_ARGS_OPT(1)); +} diff --git a/src/candy_gear/sprite.hpp b/src/candy_gear/sprite.hpp new file mode 100644 index 0000000..528f2f7 --- /dev/null +++ b/src/candy_gear/sprite.hpp @@ -0,0 +1,27 @@ +/* + * 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_SPRITE_H +#define CANDY_GEAR_SPRITE_H 1 + +#include "core.hpp" + +extern const struct mrb_data_type cg_sprite_type; + +void +cg_sprite_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_SPRITE_H */ diff --git a/src/candy_gear/sprite_3d.cpp b/src/candy_gear/sprite_3d.cpp new file mode 100644 index 0000000..d03b585 --- /dev/null +++ b/src/candy_gear/sprite_3d.cpp @@ -0,0 +1,82 @@ +/* + * Copyright 2022-2024 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 "sprite_3d.hpp" + +#include "sprite.hpp" +#include "vector_3d.hpp" + +void +cg_free_sprite_3d(mrb_state *mrb, void *obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_sprite_3d_type = { + "CG_Sprite3D", cg_free_sprite_3d }; + +static mrb_value +cg_cSprite3D_initialize(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *sprite; + std::shared_ptr *position; + mrb_float w, h; + std::shared_ptr *ptr; + + mrb_get_args(mrb, "ddff", &sprite, &cg_sprite_type, + &position, &cg_vector_3d_type, &w, &h); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + glm::vec3 size{w, h, 0.0}; + new(ptr)std::shared_ptr( + std::make_shared(*sprite, *position, size)); + + mrb_data_init(self, ptr, &cg_sprite_3d_type); + return self; +} + +static mrb_value +cg_cSprite3D_draw(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + auto &sprites_3d_to_draw = BluCat::INT::core.vk_renderer->sprites_3d_to_draw[ + BluCat::INT::core.vk_swapchain->current_frame]; + sprites_3d_to_draw.emplace_back(*ptr); + + return self; +} + +void +cg_sprite_3d_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cSprite3D; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cSprite3D = mrb_define_class_under( + mrb, cg_m, "Sprite3D", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cSprite3D, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cSprite3D, "initialize", cg_cSprite3D_initialize, MRB_ARGS_REQ(3)); + mrb_define_method( + mrb, cg_cSprite3D, "draw", cg_cSprite3D_draw, MRB_ARGS_NONE()); +} diff --git a/src/candy_gear/sprite_3d.hpp b/src/candy_gear/sprite_3d.hpp new file mode 100644 index 0000000..526c23a --- /dev/null +++ b/src/candy_gear/sprite_3d.hpp @@ -0,0 +1,25 @@ +/* + * Copyright 2022-2023 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_SPRITE_3D_H +#define CANDY_GEAR_SPRITE_3D_H 1 + +#include "core.hpp" + +void +cg_sprite_3d_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_SPRITE_3D_H */ diff --git a/src/candy_gear/static_mesh.cpp b/src/candy_gear/static_mesh.cpp new file mode 100644 index 0000000..9cb79ef --- /dev/null +++ b/src/candy_gear/static_mesh.cpp @@ -0,0 +1,67 @@ +/* + * Copyright 2022-2024 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 "static_mesh.hpp" + +#include "orientation_3d.hpp" +#include "vector_3d.hpp" +#include "../blu_cat/gra/static_mesh.hpp" + +void +cg_free_static_mesh(mrb_state *mrb, void* obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_static_mesh_type = { + "CG_StaticMesh", cg_free_static_mesh }; + +static mrb_value +cg_cStaticMesh_initialize(mrb_state *mrb, mrb_value self) +{ + const char *file_path; + + std::shared_ptr *ptr; + + mrb_get_args(mrb, "z", &file_path); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + new(ptr)std::shared_ptr( + std::make_shared(file_path)); + + mrb_data_init(self, ptr, &cg_static_mesh_type); + return self; +} + +void +cg_static_mesh_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cStaticMesh; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cStaticMesh = mrb_define_class_under( + mrb, cg_m, "StaticMesh", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cStaticMesh, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cStaticMesh, "initialize", cg_cStaticMesh_initialize, + MRB_ARGS_REQ(1)); +} diff --git a/src/candy_gear/static_mesh.hpp b/src/candy_gear/static_mesh.hpp new file mode 100644 index 0000000..8f3b2d6 --- /dev/null +++ b/src/candy_gear/static_mesh.hpp @@ -0,0 +1,27 @@ +/* + * Copyright 2022-2023 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_STATIC_MESH_H +#define CANDY_GEAR_STATIC_MESH_H 1 + +#include "core.hpp" + +extern const struct mrb_data_type cg_static_mesh_type; + +void +cg_static_mesh_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_STATIC_MESH_H */ diff --git a/src/candy_gear/static_model.cpp b/src/candy_gear/static_model.cpp new file mode 100644 index 0000000..1a6eabe --- /dev/null +++ b/src/candy_gear/static_model.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2022-2024 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 "static_model.hpp" + +#include "orientation_3d.hpp" +#include "static_mesh.hpp" +#include "texture.hpp" +#include "vector_3d.hpp" +#include "../blu_cat/gra/static_model.hpp" + +void +cg_free_static_model(mrb_state *mrb, void *obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_static_model_type = { + "CG_StaticModel", cg_free_static_model }; + +static mrb_value +cg_cStaticModel_initialize(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *static_mesh; + std::shared_ptr *texture; + std::shared_ptr *position; + std::shared_ptr *orientation; + std::shared_ptr *ptr; + + mrb_get_args( + mrb, "dddd", &static_mesh, &cg_static_mesh_type, &texture, + &cg_texture_type, &position, &cg_vector_3d_type, &orientation, + &cg_orientation_3d_type); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + new(ptr)std::shared_ptr( + std::make_shared( + *static_mesh, *texture, *position, *orientation)); + + mrb_data_init(self, ptr, &cg_static_model_type); + return self; +} + +static mrb_value +cg_cStaticModel_set_orientation(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + std::shared_ptr *orientation; + + mrb_get_args(mrb, "d", &orientation, &cg_orientation_3d_type); + (*ptr)->orientation = *orientation; + + return self; +} + +static mrb_value +cg_cStaticModel_set_position(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + std::shared_ptr *position; + + mrb_get_args(mrb, "d", &position, &cg_vector_3d_type); + (*ptr)->position = *position; + + return self; +} + +static mrb_value +cg_cStaticModel_set_texture(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + std::shared_ptr *texture; + + mrb_get_args(mrb, "d", &texture, &cg_texture_type); + (*ptr)->texture = *texture; + + return self; +} + +static mrb_value +cg_cStaticModel_draw(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + auto &instances = BluCat::INT::core.vk_renderer->static_models_to_draw[ + BluCat::INT::core.vk_swapchain->current_frame][(*ptr)->static_mesh]; + instances.push_back(*ptr); + + return self; +} + +void +cg_static_model_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cStaticModel; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cStaticModel = mrb_define_class_under( + mrb, cg_m, "StaticModel", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cStaticModel, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cStaticModel, "initialize", cg_cStaticModel_initialize, + MRB_ARGS_REQ(4)); + mrb_define_method( + mrb, cg_cStaticModel, "position=", cg_cStaticModel_set_position, + MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cStaticModel, "orientation=", cg_cStaticModel_set_orientation, + MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cStaticModel, "texture=", cg_cStaticModel_set_texture, + MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cStaticModel, "draw", cg_cStaticModel_draw, MRB_ARGS_NONE()); +} diff --git a/src/candy_gear/static_model.hpp b/src/candy_gear/static_model.hpp new file mode 100644 index 0000000..dfb7054 --- /dev/null +++ b/src/candy_gear/static_model.hpp @@ -0,0 +1,25 @@ +/* + * Copyright 2022-2023 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_STATIC_MODEL_H +#define CANDY_GEAR_STATIC_MODEL_H 1 + +#include "core.hpp" + +void +cg_static_model_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_STATIC_MODEL_H */ diff --git a/src/candy_gear/texture.cpp b/src/candy_gear/texture.cpp new file mode 100644 index 0000000..355a622 --- /dev/null +++ b/src/candy_gear/texture.cpp @@ -0,0 +1,121 @@ +/* + * Copyright 2022-2024 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 "texture.hpp" + +#include "core.hpp" +#include "font.hpp" +#include "../blu_cat/gra/texture.hpp" + +void +cg_free_texture(mrb_state *mrb, void* obj) +{ + auto *ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_texture_type = { "CG_Texture", cg_free_texture }; + +static mrb_value +texture_alloc(mrb_state *mrb, mrb_value klass) +{ + struct RClass *cg_cTexture = mrb_class_ptr(klass); + enum mrb_vtype ttype = MRB_INSTANCE_TT(cg_cTexture); + + // I do not know if I need this. If things break, try uncomment this line. + // if (ttype == 0) ttype = MRB_TT_OBJECT; + return mrb_obj_value( + (struct RObject*)mrb_obj_alloc(mrb, ttype, cg_cTexture)); +} + +static mrb_value +cg_cTexture_from_image(mrb_state *mrb, mrb_value self) +{ + struct mrb_value texture = texture_alloc(mrb, self); + const char *file_path; + std::shared_ptr *ptr; + + mrb_get_args(mrb, "z", &file_path); + ptr = (std::shared_ptr*)DATA_PTR(texture); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + new(ptr)std::shared_ptr( + std::make_shared(file_path)); + + mrb_data_init(texture, ptr, &cg_texture_type); + return texture; +} + +mrb_value +cg_cTexture_from_text(mrb_state *mrb, mrb_value self) +{ + const char *text; + unsigned int width, height; + struct mrb_value texture = texture_alloc(mrb, self); + BluCat::GRA::Font *font_ptr; + std::shared_ptr *ptr; + + mrb_get_args(mrb, "dz", &font_ptr, &cg_font_type, &text); + + ptr = (std::shared_ptr*)DATA_PTR(texture); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + new(ptr)std::shared_ptr( + std::make_shared(font_ptr, text)); + + mrb_data_init(texture, ptr, &cg_texture_type); + return texture; +} + +static mrb_value +cg_cTexture_width(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + return mrb_int_value(mrb, (*ptr)->width); +} + +static mrb_value +cg_cTexture_height(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + return mrb_int_value(mrb, (*ptr)->height); +} + +void +cg_texture_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cTexture; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cTexture = mrb_define_class_under( + mrb, cg_m, "Texture", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cTexture, MRB_TT_DATA); + + mrb_undef_class_method(mrb, cg_cTexture, "new"); + mrb_define_class_method( + mrb, cg_cTexture, "from_image", cg_cTexture_from_image, + MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); + mrb_define_class_method( + mrb, cg_cTexture, "from_text", cg_cTexture_from_text, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cTexture, "width", cg_cTexture_width, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cTexture, "height", cg_cTexture_height, MRB_ARGS_NONE()); +} diff --git a/src/candy_gear/texture.hpp b/src/candy_gear/texture.hpp new file mode 100644 index 0000000..cd96026 --- /dev/null +++ b/src/candy_gear/texture.hpp @@ -0,0 +1,28 @@ +/* + * 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_TEXTURE_H +#define CANDY_GEAR_TEXTURE_H 1 + +#include "core.hpp" +#include "../blu_cat/com/command.hpp" + +extern const struct mrb_data_type cg_texture_type; + +void +cg_texture_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_TEXTURE_H */ diff --git a/src/candy_gear/vector_3d.cpp b/src/candy_gear/vector_3d.cpp new file mode 100644 index 0000000..fc5d186 --- /dev/null +++ b/src/candy_gear/vector_3d.cpp @@ -0,0 +1,302 @@ +/* + * Copyright 2022-2024 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 "vector_3d.hpp" + +#include + +#include + +#include + +#include "orientation_3d.hpp" + +void +cg_free_vector_3d(mrb_state *mrb, void* obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_vector_3d_type = { + "CG_Vector3D", cg_free_vector_3d}; + +static mrb_value +cg_cVector3D_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_float x = 0.0f; + mrb_float y = 0.0f; + mrb_float z = 0.0f; + std::shared_ptr *ptr; + + mrb_get_args(mrb, "|fff", &x, &y, &z); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + new(ptr)std::shared_ptr(std::make_shared(x, y, z)); + + mrb_data_init(self, ptr, &cg_vector_3d_type); + return self; +} + +mrb_value +cg_cVector3D_get_x(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->x); +} + +mrb_value +cg_cVector3D_get_y(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->y); +} + +mrb_value +cg_cVector3D_get_z(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->z); +} + +mrb_value +cg_cVector3D_get_xy(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 2); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); + + return array; +} + +mrb_value +cg_cVector3D_get_xz(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 2); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); + + return array; +} + +mrb_value +cg_cVector3D_get_yz(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 2); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); + + return array; +} + +mrb_value +cg_cVector3D_get_xyz(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 3); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); + + return array; +} + +static mrb_value +cg_cVector3D_set_x(mrb_state *mrb, mrb_value self) +{ + mrb_float x; + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "f", &x); + (*ptr)->x = x; + + return self; +} + +static mrb_value +cg_cVector3D_set_y(mrb_state *mrb, mrb_value self) +{ + mrb_float y; + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "f", &y); + (*ptr)->y = y; + + return self; +} + +static mrb_value +cg_cVector3D_set_z(mrb_state *mrb, mrb_value self) +{ + mrb_float z; + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "f", &z); + (*ptr)->z = z; + + return self; +} + +static mrb_value +cg_cVector3D_set_xy(mrb_state *mrb, mrb_value self) +{ + mrb_float x, y; + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "ff", &x, &y); + (*ptr)->x = x; + (*ptr)->y = y; + + return self; +} + +static mrb_value +cg_cVector3D_set_xz(mrb_state *mrb, mrb_value self) +{ + mrb_float x, z; + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "ff", &x, &z); + (*ptr)->x = x; + (*ptr)->z = z; + + return self; +} + +static mrb_value +cg_cVector3D_set_yz(mrb_state *mrb, mrb_value self) +{ + mrb_float y, z; + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "ff", &y, &z); + (*ptr)->y = y; + (*ptr)->z = z; + + return self; +} + +static mrb_value +cg_cVector3D_set_xyz(mrb_state *mrb, mrb_value self) +{ + mrb_float x, y, z; + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "fff", &x, &y, &z); + (*ptr)->x = x; + (*ptr)->y = y; + (*ptr)->z = z; + + return self; +} + +static mrb_value +cg_cVector3D_translate(mrb_state *mrb, mrb_value self) +{ + auto *ptr = (std::shared_ptr*)DATA_PTR(self); + std::shared_ptr *direction; + std::shared_ptr *orientation; + + mrb_get_args( + mrb, "dd", &direction, &cg_vector_3d_type, + &orientation, &cg_orientation_3d_type); + + auto rotated_direction = **orientation * **direction; + + **ptr += rotated_direction; + + return self; +} + +void +cg_vector_3d_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cVector3D; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cVector3D = mrb_define_class_under( + mrb, cg_m, "Vector3D", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cVector3D, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cVector3D, "initialize", cg_cVector3D_initialize, + MRB_ARGS_NONE()|MRB_ARGS_OPT(3)); + + mrb_define_method( + mrb, cg_cVector3D, "x", cg_cVector3D_get_x, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector3D, "y", cg_cVector3D_get_y, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector3D, "z", cg_cVector3D_get_z, MRB_ARGS_NONE()); + + mrb_define_method( + mrb, cg_cVector3D, "xy", cg_cVector3D_get_xy, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector3D, "xz", cg_cVector3D_get_xz, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector3D, "yz", cg_cVector3D_get_yz, MRB_ARGS_NONE()); + + mrb_define_method( + mrb, cg_cVector3D, "xyz", cg_cVector3D_get_xyz, MRB_ARGS_NONE()); + + mrb_define_method( + mrb, cg_cVector3D, "x=", cg_cVector3D_set_x, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector3D, "y=", cg_cVector3D_set_y, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector3D, "z=", cg_cVector3D_set_z, MRB_ARGS_REQ(1)); + + mrb_define_method( + mrb, cg_cVector3D, "set_xy", cg_cVector3D_set_xy, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector3D, "set_xz", cg_cVector3D_set_xz, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector3D, "set_yz", cg_cVector3D_set_yz, MRB_ARGS_REQ(2)); + + mrb_define_method( + mrb, cg_cVector3D, "set_xyz", cg_cVector3D_set_xyz, MRB_ARGS_REQ(3)); + + mrb_define_method( + mrb, cg_cVector3D, "translate", cg_cVector3D_translate, MRB_ARGS_REQ(2)); +} diff --git a/src/candy_gear/vector_3d.hpp b/src/candy_gear/vector_3d.hpp new file mode 100644 index 0000000..2827813 --- /dev/null +++ b/src/candy_gear/vector_3d.hpp @@ -0,0 +1,34 @@ +/* + * 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_VECTOR_3D_H +#define CANDY_GEAR_VECTOR_3D_H 1 + +#include "core.hpp" + +extern const struct mrb_data_type cg_vector_3d_type; + +mrb_value +cg_cVector3D_get_x(mrb_state *mrb, mrb_value self); +mrb_value +cg_cVector3D_get_y(mrb_state *mrb, mrb_value self); +mrb_value +cg_cVector3D_get_z(mrb_state *mrb, mrb_value self); + +void +cg_vector_3d_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_VECTOR_3D_H */ diff --git a/src/candy_gear/vector_4d.cpp b/src/candy_gear/vector_4d.cpp new file mode 100644 index 0000000..b44b612 --- /dev/null +++ b/src/candy_gear/vector_4d.cpp @@ -0,0 +1,479 @@ +/* + * Copyright 2022-2024 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 "vector_4d.hpp" + +#include + +#include +#include + +#include "vector_3d.hpp" +#include "view_2d.hpp" + +namespace +{ + +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; +} + +} + +void +cg_free_vector_4d(mrb_state *mrb, void* obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_vector_4d_type = { + "CG_Vector4D", cg_free_vector_4d}; + +static mrb_value +cg_cVector4D_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_float x = 0.0f; + mrb_float y = 0.0f; + mrb_float w = 0.0f; + mrb_float h = 0.0f; + std::shared_ptr *ptr; + + mrb_get_args(mrb, "|ffff", &x, &y, &w, &h); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + new(ptr)std::shared_ptr(std::make_shared(x, y, w, h)); + + mrb_data_init(self, ptr, &cg_vector_4d_type); + return self; +} + +mrb_value +cg_cVector4D_get_x(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr = + (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->x); +} + +mrb_value +cg_cVector4D_get_y(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->y); +} + +mrb_value +cg_cVector4D_get_w(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->z); +} + +mrb_value +cg_cVector4D_get_h(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->w); +} + +mrb_value +cg_cVector4D_get_xy(mrb_state *mrb, mrb_value self) +{ + auto *ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 2); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); + + return array; +} + +mrb_value +cg_cVector4D_get_xw(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 2); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); + + return array; +} + +mrb_value +cg_cVector4D_get_xh(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 2); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->w)); + + return array; +} + +mrb_value +cg_cVector4D_get_yw(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 2); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); + + return array; +} + +mrb_value +cg_cVector4D_get_yh(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 2); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->w)); + + return array; +} + +mrb_value +cg_cVector4D_get_wh(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_value array = mrb_ary_new_capa(mrb, 2); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); + mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->w)); + + return array; +} + +static mrb_value +cg_cVector4D_set_x(mrb_state *mrb, mrb_value self) +{ + mrb_float x; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "f", &x); + (*ptr)->x = x; + + return self; +} + +static mrb_value +cg_cVector4D_set_y(mrb_state *mrb, mrb_value self) +{ + mrb_float y; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "f", &y); + (*ptr)->y = y; + + return self; +} + +static mrb_value +cg_cVector4D_set_w(mrb_state *mrb, mrb_value self) +{ + mrb_float w; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "f", &w); + (*ptr)->z = w; + + return self; +} + +static mrb_value +cg_cVector4D_set_h(mrb_state *mrb, mrb_value self) +{ + mrb_float h; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "f", &h); + (*ptr)->w = h; + + return self; +} + +static mrb_value +cg_cVector4D_set_xy(mrb_state *mrb, mrb_value self) +{ + mrb_float x, y; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "ff", &x, &y); + (*ptr)->x = x; + (*ptr)->y = y; + + return self; +} + +static mrb_value +cg_cVector4D_set_xw(mrb_state *mrb, mrb_value self) +{ + mrb_float x, w; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "ff", &x, &w); + (*ptr)->x = x; + (*ptr)->z = w; + + return self; +} + +static mrb_value +cg_cVector4D_set_xh(mrb_state *mrb, mrb_value self) +{ + mrb_float x, h; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "ff", &x, &h); + (*ptr)->x = x; + (*ptr)->w = h; + + return self; +} + +static mrb_value +cg_cVector4D_set_yw(mrb_state *mrb, mrb_value self) +{ + mrb_float y, w; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "ff", &y, &w); + (*ptr)->y = y; + (*ptr)->z = w; + + return self; +} + +static mrb_value +cg_cVector4D_set_yh(mrb_state *mrb, mrb_value self) +{ + mrb_float y, h; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "ff", &y, &h); + (*ptr)->x = y; + (*ptr)->w = h; + + return self; +} + +static mrb_value +cg_cVector4D_set_wh(mrb_state *mrb, mrb_value self) +{ + mrb_float w, h; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "ff", &w, &h); + (*ptr)->z = w; + (*ptr)->w = h; + + return self; +} + +static mrb_value +cg_cVector4D_align_vertically(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr, *that; + + mrb_get_args(mrb, "d", &that, &cg_vector_4d_type); + ptr = (std::shared_ptr*)DATA_PTR(self); + + return mrb_bool_value( + align_vertically((*ptr)->x, (*ptr)->z, (*that)->x, (*that)->z)); +} + +static mrb_value +cg_cVector4D_align_horizontally(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr, *that; + + mrb_get_args(mrb, "d", &that, &cg_vector_4d_type); + ptr = (std::shared_ptr*)DATA_PTR(self); + + return mrb_bool_value( + align_horizontally((*ptr)->y, (*ptr)->w, (*that)->y, (*that)->w)); +} + +static mrb_value +cg_cVector4D_collide(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *ptr, *that; + + mrb_get_args(mrb, "d", &that, &cg_vector_4d_type); + ptr = (std::shared_ptr*)DATA_PTR(self); + + return mrb_bool_value( + align_vertically((*ptr)->x, (*ptr)->z, (*that)->x, (*that)->z) && + align_horizontally((*ptr)->y, (*ptr)->w, (*that)->y, (*that)->w)); +} + +static mrb_value +cg_cVector4D_draw_rectangle(mrb_state *mrb, mrb_value self) +{ + mrb_value view_value; + BluCat::GRA::View2D *view_2d; + std::shared_ptr *color; + auto ptr = (std::shared_ptr*)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); + + glm::vec4 position( + (*ptr)->x, (*ptr)->y, (*ptr)->x + (*ptr)->z, (*ptr)->y + (*ptr)->w); + BluCat::GRA::Rectangle rect{position, (**color)}; + auto &rectangles = view_2d->rectangles_to_draw[ + BluCat::INT::core.vk_swapchain->current_frame]; + rectangles.push_back(rect); + + return self; +} + +void +cg_vector_4d_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cVector4D; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cVector4D = mrb_define_class_under( + mrb, cg_m, "Vector4D", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cVector4D, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cVector4D, "initialize", cg_cVector4D_initialize, + MRB_ARGS_NONE()|MRB_ARGS_OPT(4)); + + mrb_define_method( + mrb, cg_cVector4D, "x", cg_cVector4D_get_x, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "y", cg_cVector4D_get_y, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "w", cg_cVector4D_get_w, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "h", cg_cVector4D_get_h, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "r", cg_cVector4D_get_x, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "g", cg_cVector4D_get_y, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "b", cg_cVector4D_get_w, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "a", cg_cVector4D_get_h, MRB_ARGS_NONE()); + + mrb_define_method( + mrb, cg_cVector4D, "xy", cg_cVector4D_get_xy, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "xw", cg_cVector4D_get_xw, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "xh", cg_cVector4D_get_xh, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "yw", cg_cVector4D_get_yw, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "yh", cg_cVector4D_get_yh, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "wh", cg_cVector4D_get_wh, MRB_ARGS_NONE()); + + mrb_define_method( + mrb, cg_cVector4D, "rg", cg_cVector4D_get_xy, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "rb", cg_cVector4D_get_xw, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "ra", cg_cVector4D_get_xh, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "gb", cg_cVector4D_get_yw, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "ga", cg_cVector4D_get_yh, MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cVector4D, "ba", cg_cVector4D_get_wh, MRB_ARGS_NONE()); + + mrb_define_method( + mrb, cg_cVector4D, "x=", cg_cVector4D_set_x, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "y=", cg_cVector4D_set_y, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "w=", cg_cVector4D_set_w, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "h=", cg_cVector4D_set_h, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "r=", cg_cVector4D_set_x, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "g=", cg_cVector4D_set_y, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "b=", cg_cVector4D_set_w, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "a=", cg_cVector4D_set_h, MRB_ARGS_REQ(1)); + + mrb_define_method( + mrb, cg_cVector4D, "set_xy", cg_cVector4D_set_xy, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_xw", cg_cVector4D_set_xw, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_xh", cg_cVector4D_set_xh, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_yw", cg_cVector4D_set_yw, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_yh", cg_cVector4D_set_yh, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_wh", cg_cVector4D_set_wh, MRB_ARGS_REQ(2)); + + mrb_define_method( + mrb, cg_cVector4D, "set_rg", cg_cVector4D_set_xy, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_rb", cg_cVector4D_set_xw, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_ra", cg_cVector4D_set_xh, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_gb", cg_cVector4D_set_yw, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_ga", cg_cVector4D_set_yh, MRB_ARGS_REQ(2)); + mrb_define_method( + mrb, cg_cVector4D, "set_ba", cg_cVector4D_set_wh, MRB_ARGS_REQ(2)); + + mrb_define_method( + mrb, cg_cVector4D, "align_vertically?", cg_cVector4D_align_vertically, + MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "align_horizontally?", + cg_cVector4D_align_horizontally, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "collide?", cg_cVector4D_collide, MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cVector4D, "draw_rectangle", cg_cVector4D_draw_rectangle, + MRB_ARGS_REQ(2)); +} diff --git a/src/candy_gear/vector_4d.hpp b/src/candy_gear/vector_4d.hpp new file mode 100644 index 0000000..2797d53 --- /dev/null +++ b/src/candy_gear/vector_4d.hpp @@ -0,0 +1,27 @@ +/* + * 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_VECTOR_4D_H +#define CANDY_GEAR_VECTOR_4D_H 1 + +#include "core.hpp" + +extern const struct mrb_data_type cg_vector_4d_type; + +void +cg_vector_4d_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_VECTOR_4D_H */ diff --git a/src/candy_gear/view_2d.cpp b/src/candy_gear/view_2d.cpp new file mode 100644 index 0000000..e0dc8a1 --- /dev/null +++ b/src/candy_gear/view_2d.cpp @@ -0,0 +1,90 @@ +/* + * Copyright 2022-2024 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 "view_2d.hpp" + +#include "sprite.hpp" +#include "vector_4d.hpp" +#include "view_3d.hpp" +#include "../blu_cat/gra/sprite.hpp" +#include "../blu_cat/gra/view_2d.hpp" + +void +cg_free_view_2d(mrb_state *mrb, void* obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_view_2d_type = { "CG_View2D", cg_free_view_2d }; + +static mrb_value +cg_cView2D_initialize(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *region; + mrb_float projection_width, projection_height; + std::shared_ptr *ptr; + + mrb_get_args(mrb, "dff", ®ion, &cg_vector_4d_type, + &projection_width, &projection_height); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + new(ptr)std::shared_ptr( + std::make_shared( + *region->get(), projection_width, projection_height)); + + mrb_data_init(self, ptr, &cg_view_2d_type); + return self; +} + +BluCat::GRA::View2D* +cg_cView_to_view_2d(mrb_state *mrb, mrb_value view_value) +{ + BluCat::GRA::View2D* view_2d; + const mrb_data_type *type = DATA_TYPE(view_value); + + if(type == &cg_view_2d_type) + view_2d = static_cast*>( + DATA_PTR(view_value))->get(); + else if (type == &cg_view_3d_type) + view_2d = static_cast( + static_cast*>( + 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 view_2d; +} + +void +cg_view_2d_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cView2D; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cView2D = mrb_define_class_under(mrb, cg_m, "View2D", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cView2D, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cView2D, "initialize", cg_cView2D_initialize, MRB_ARGS_REQ(3)); +} diff --git a/src/candy_gear/view_2d.hpp b/src/candy_gear/view_2d.hpp new file mode 100644 index 0000000..9b742a0 --- /dev/null +++ b/src/candy_gear/view_2d.hpp @@ -0,0 +1,33 @@ +/* + * Copyright 2022-2024 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_VIEW_2D_H +#define CANDY_GEAR_VIEW_2D_H 1 + +#include "core.hpp" + +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 BluCat::GRA::View2D. +BluCat::GRA::View2D* +cg_cView_to_view_2d(mrb_state *mrb, mrb_value view_value); + +void +cg_view_2d_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_VIEW_2D_H */ diff --git a/src/candy_gear/view_3d.cpp b/src/candy_gear/view_3d.cpp new file mode 100644 index 0000000..b829cca --- /dev/null +++ b/src/candy_gear/view_3d.cpp @@ -0,0 +1,127 @@ +/* + * Copyright 2022-2024 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 "view_3d.hpp" + +#include "sprite.hpp" +#include "orientation_3d.hpp" +#include "vector_3d.hpp" +#include "vector_4d.hpp" +#include "../blu_cat/gra/sprite.hpp" +#include "../blu_cat/gra/view_3d.hpp" + +void +cg_free_view_3d(mrb_state *mrb, void* obj) +{ + auto ptr = static_cast*>(obj); + + ptr->~shared_ptr(); + mrb_free(mrb, ptr); +} + +const struct mrb_data_type cg_view_3d_type = { "CG_View3D", cg_free_view_3d }; + +static mrb_value +cg_cView3D_initialize(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *region; + mrb_float projection_width, projection_height; + std::shared_ptr *ptr; + + mrb_get_args(mrb, "dff", ®ion, &cg_vector_4d_type, + &projection_width, &projection_height); + ptr = (std::shared_ptr*)DATA_PTR(self); + if(ptr) mrb_free(mrb, ptr); + ptr = (std::shared_ptr*)mrb_malloc( + mrb, sizeof(std::shared_ptr)); + + new(ptr)std::shared_ptr( + std::make_shared( + *region->get(), projection_width, projection_height)); + + mrb_data_init(self, ptr, &cg_view_3d_type); + return self; +} + +static mrb_value +cg_cView3D_set_camera_position(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *camera_position; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "d", &camera_position, &cg_vector_3d_type); + (*ptr)->camera_position = (*camera_position); + + return self; +} + +static mrb_value +cg_cView3D_set_camera_orientation(mrb_state *mrb, mrb_value self) +{ + std::shared_ptr *camera_orientation; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "d", &camera_orientation, &cg_orientation_3d_type); + (*ptr)->camera_orientation = (*camera_orientation); + + return self; +} + +static mrb_value +cg_cView3D_get_field_of_view(mrb_state *mrb, mrb_value self) +{ + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + return mrb_float_value(mrb, (*ptr)->field_of_view); + + return self; +} + +static mrb_value +cg_cView3D_set_field_of_view(mrb_state *mrb, mrb_value self) +{ + mrb_float fov; + auto ptr = (std::shared_ptr*)DATA_PTR(self); + + mrb_get_args(mrb, "f", &fov); + (*ptr)->field_of_view = fov; + + return self; +} + +void +cg_view_3d_init(mrb_state *mrb) +{ + struct RClass *cg_m, *cg_cView3D; + + cg_m = mrb_module_get(mrb, "CandyGear"); + cg_cView3D = mrb_define_class_under(mrb, cg_m, "View3D", mrb->object_class); + MRB_SET_INSTANCE_TT(cg_cView3D, MRB_TT_DATA); + mrb_define_method( + mrb, cg_cView3D, "initialize", cg_cView3D_initialize, MRB_ARGS_REQ(3)); + mrb_define_method( + mrb, cg_cView3D, "camera_position=", cg_cView3D_set_camera_position, + MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cView3D, "camera_orientation=", cg_cView3D_set_camera_orientation, + MRB_ARGS_REQ(1)); + mrb_define_method( + mrb, cg_cView3D, "field_of_view", cg_cView3D_get_field_of_view, + MRB_ARGS_NONE()); + mrb_define_method( + mrb, cg_cView3D, "field_of_view=", cg_cView3D_set_field_of_view, + MRB_ARGS_REQ(1)); +} diff --git a/src/candy_gear/view_3d.hpp b/src/candy_gear/view_3d.hpp new file mode 100644 index 0000000..22aa084 --- /dev/null +++ b/src/candy_gear/view_3d.hpp @@ -0,0 +1,27 @@ +/* + * 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_VIEW_3D_H +#define CANDY_GEAR_VIEW_3D_H 1 + +#include "core.hpp" + +extern const struct mrb_data_type cg_view_3d_type; + +void +cg_view_3d_init(mrb_state *mrb); + +#endif /* CANDY_GEAR_VIEW_3D_H */ diff --git a/src/core.cpp b/src/core.cpp deleted file mode 100644 index dd68edb..0000000 --- a/src/core.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright 2022-2024 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 "core.hpp" - -#include "candy_gear.hpp" -#include "font.hpp" -#include "graphic.hpp" -#include "key.hpp" -#include "orientation_3d.hpp" -#include "skeletal_model.hpp" -#include "skeletal_mesh.hpp" -#include "static_model.hpp" -#include "static_mesh.hpp" -#include "sound.hpp" -#include "sprite.hpp" -#include "sprite_3d.hpp" -#include "texture.hpp" -#include "vector_3d.hpp" -#include "vector_4d.hpp" -#include "view_2d.hpp" -#include "view_3d.hpp" - -#ifdef DEBUG -#include -#endif - -namespace -{ - -void -load_mruby_symbols(void *obj) -{ - cg_core.sym_config = mrb_intern_cstr(cg_core.mrb, "config"); - cg_core.sym_debug = mrb_intern_cstr(cg_core.mrb, "debug"); - cg_core.sym_error = mrb_intern_cstr(cg_core.mrb, "error"); - cg_core.sym_fatal = mrb_intern_cstr(cg_core.mrb, "fatal"); - cg_core.sym_information = mrb_intern_cstr(cg_core.mrb, "information"); - cg_core.sym_init = mrb_intern_cstr(cg_core.mrb, "init"); - cg_core.sym_key_down = mrb_intern_cstr(cg_core.mrb, "key_down"); - cg_core.sym_key_up = mrb_intern_cstr(cg_core.mrb, "key_up"); - cg_core.sym_quit = mrb_intern_cstr(cg_core.mrb, "quit"); - cg_core.sym_tick = mrb_intern_cstr(cg_core.mrb, "tick"); - cg_core.sym_trace = mrb_intern_cstr(cg_core.mrb, "trace"); - cg_core.sym_warning = mrb_intern_cstr(cg_core.mrb, "warning"); -} - -void -load_game(void *obj) -{ - FILE *fp; - mrb_value main_obj{mrb_top_self(cg_core.mrb)}; - - BluCat::core.game_name = "CandyGear Game"; - - BluCat::core.display_width = 800; - BluCat::core.display_height = 600; - - BluCat::core.game_version_major = 0; - BluCat::core.game_version_minor = 1; - BluCat::core.game_version_patch = 0; - - BluCat::core.fps = 30; - - mrb_define_module(cg_core.mrb, "CandyGear"); - cg_candy_gear_init_config(cg_core.mrb); - cg_graphic_init_config(cg_core.mrb); - - fp = fopen(cg_core.game_file.c_str(), "rb"); - mrb_load_irep_file(cg_core.mrb, fp); - fclose(fp); - if (cg_core.mrb->exc) - { - mrb_print_error(cg_core.mrb); - throw CommandError{"Error loading game."}; - } - - mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_config, 0); - if (cg_core.mrb->exc) - { - mrb_print_error(cg_core.mrb); - throw CommandError{"Error configuring game."}; - } - - cg_candy_gear_finish_config(cg_core.mrb); - cg_graphic_finish_config(cg_core.mrb); -} - -void -load_sdl(void *obj) -{ - if(SDL_Init(SDL_INIT_EVERYTHING) < 0) - { - std::string error{"SDL could not initialize! SDL Error → "}; - error += SDL_GetError(); - throw error; - } - - if(SDL_Vulkan_LoadLibrary(nullptr) != 0) - { - SDL_Quit(); - std::string error{"SDL could not initialize Vulkan! SDL_Error → "}; - error += SDL_GetError(); - throw CommandError{error}; - } -} - -void -unload_sdl(void *obj) -{ - SDL_Vulkan_UnloadLibrary(); - SDL_Quit(); -} - -void -load_sdl_mixer(void *obj) -{ - int flags = MIX_INIT_OGG|MIX_INIT_MOD; - int initted = Mix_Init(flags); - if(initted&flags != flags) - { - std::string error{"Could not initialize SDL mixer → "}; - error += Mix_GetError(); - throw CommandError{error}; - } -} - -void -unload_sdl_mixer(void *obj) -{ - while(Mix_Init(0)) Mix_Quit(); -} - -void -load_sdl_open_audio(void *obj) -{ - if(Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 1024) == -1) - { - std::string error{"Could not open SDL mixer audio → "}; - error += Mix_GetError(); - throw CommandError{error}; - } -} - -void -unload_sdl_open_audio(void *obj) -{ - Mix_CloseAudio(); -} - -void -load_window(void *obj) -{ - cg_core.window = NULL; - cg_core.window = SDL_CreateWindow( - BluCat::core.game_name.c_str(), - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - BluCat::core.display_width, BluCat::core.display_height, - SDL_WINDOW_VULKAN); - if(cg_core.window == NULL) - { - std::string error{"Window could not be created! SDL_Error → "}; - error += SDL_GetError(); - throw CommandError{error}; - } -} - -void -unload_window(void *obj) -{ - SDL_DestroyWindow(cg_core.window); -} - -void -load_vk_instance(void *obj) -{ - std::vector vk_extensions; - std::vector vk_required_layers_names; - - // Get extensions. - { - uint32_t vk_extensions_count; - std::vector vk_required_extensions; - - // Load debuging layers. -#ifdef DEBUG - vk_required_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - vk_required_layers_names.push_back("VK_LAYER_KHRONOS_validation"); -#endif - - // Get extensions for SDL. - { - uint32_t vk_sdl_extension_count; - std::vector vk_sdl_extensions; - - if(!SDL_Vulkan_GetInstanceExtensions( - cg_core.window, &vk_sdl_extension_count, nullptr)) - { - std::string error{ - "Vulkan extensions could not be loaded by SDL! SDL_Error: "}; - error += SDL_GetError(); - throw CommandError{error}; - } - - vk_sdl_extensions.resize(vk_sdl_extension_count); - SDL_Vulkan_GetInstanceExtensions( - cg_core.window, &vk_sdl_extension_count, vk_sdl_extensions.data()); - - // Combine all extensions. - vk_extensions_count = vk_sdl_extension_count + - vk_required_extensions.size(); - vk_extensions.resize(vk_extensions_count); - for(auto i{0}; i < vk_sdl_extension_count; i++) - vk_extensions[i] = vk_sdl_extensions[i]; - for(auto i{0}; i < vk_required_extensions.size(); i++) - vk_extensions[i + vk_sdl_extension_count] = vk_required_extensions[i]; - } - -#ifdef DEBUG - BluCat::core.log.message(Log::Level::Trace, "Enabled VK extensions."); - for(auto vk_extension: vk_extensions) - { - std::string message{"Extension name: "}; - message += vk_extension; - BluCat::core.log.message(Log::Level::Trace, message); - } -#endif - } - - // Get available instance layers. - { - uint32_t vk_available_layers_count; - std::vector vk_available_layers; - std::vector vk_available_layers_names; - - vkEnumerateInstanceLayerProperties(&vk_available_layers_count, nullptr); - vk_available_layers.resize(vk_available_layers_count); - vkEnumerateInstanceLayerProperties(&vk_available_layers_count, - vk_available_layers.data()); - vk_available_layers_names.resize(vk_available_layers_count); -#ifdef DEBUG - BluCat::core.log.message( - Log::Level::Trace, "Available VK instance layers."); -#endif - for(uint32_t i = 0; i < vk_available_layers_count; i++) - { -#ifdef DEBUG - std::stringstream message{}; - message << "\nname: " << vk_available_layers[i].layerName << std::endl; - message << "Description: " << vk_available_layers[i].description << - std::endl; - message << "Spec version: " << vk_available_layers[i].specVersion << - std::endl; - message << "Implementation version: " << - vk_available_layers[i].implementationVersion << std::endl; - BluCat::core.log.message(Log::Level::Trace, message.str()); -#endif - - vk_available_layers_names[i] = vk_available_layers[i].layerName; - } - - // If required layers are not all available. - if(!std::includes( - vk_available_layers_names.begin(), vk_available_layers_names.end(), - vk_required_layers_names.begin(), vk_required_layers_names.begin())) - throw CommandError{"Some required Vulkan layers are not available."}; - } - - { - VkApplicationInfo app_info; - app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - app_info.pNext = nullptr; - app_info.pApplicationName = BluCat::core.game_name.c_str(); - app_info.applicationVersion = VK_MAKE_VERSION( - BluCat::core.game_version_major, - BluCat::core.game_version_minor, - BluCat::core.game_version_patch); - app_info.pEngineName = "BluCat"; - app_info.engineVersion = VK_MAKE_VERSION( - BLU_CAT_VERSION_MAJOR, - BLU_CAT_VERSION_MINOR, - BLU_CAT_VERSION_PATCH); - app_info.apiVersion = VK_API_VERSION_1_0; - - VkInstanceCreateInfo create_info; - create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - create_info.pNext = nullptr; - create_info.flags = 0; - create_info.pApplicationInfo = &app_info; - create_info.enabledExtensionCount = vk_extensions.size(); - create_info.ppEnabledExtensionNames = vk_extensions.data(); - create_info.enabledLayerCount = vk_required_layers_names.size(); - create_info.ppEnabledLayerNames = vk_required_layers_names.data(); - - VkResult result = - vkCreateInstance(&create_info, nullptr, &BluCat::core.vk_instance); - if(result != VK_SUCCESS) - { - std::string error{""}; - switch(result) - { - case VK_ERROR_LAYER_NOT_PRESENT: - error = " Layer not present."; - break; - case VK_ERROR_EXTENSION_NOT_PRESENT: - error = " Extension not present."; - } - error = "Failed to create Vulkan instance." + error; - throw CommandError{error}; - } - } -} - -void -unload_vk_instance(void *obj) -{ - vkDestroyInstance(BluCat::core.vk_instance, nullptr); -} - -void -load_window_surface(void *obj) -{ - if(!SDL_Vulkan_CreateSurface( - cg_core.window, BluCat::core.vk_instance, &BluCat::core.window_surface)) - { - std::string error{"Failed to create a window surface → "}; - error += SDL_GetError(); - throw CommandError{error}; - } -} - -void -unload_window_surface(void *obj) -{ - vkDestroySurfaceKHR( - BluCat::core.vk_instance, BluCat::core.window_surface, nullptr); -} - -void -load_blucat(void *obj) -{ - BluCat::core.loader.execute(nullptr); -} - -void -unload_blucat(void *obj) -{ - BluCat::core.loader.revert(nullptr); -} - -void -load_mruby_interface(void *obj) -{ - cg_candy_gear_init(cg_core.mrb); - cg_font_init(cg_core.mrb); - cg_key_init(cg_core.mrb); - cg_orientation_3d_init(cg_core.mrb); - cg_skeletal_model_init(cg_core.mrb); - cg_skeletal_mesh_init(cg_core.mrb); - cg_static_model_init(cg_core.mrb); - cg_static_mesh_init(cg_core.mrb); - cg_sound_init(cg_core.mrb); - cg_sprite_init(cg_core.mrb); - cg_sprite_3d_init(cg_core.mrb); - cg_texture_init(cg_core.mrb); - cg_vector_3d_init(cg_core.mrb); - cg_vector_4d_init(cg_core.mrb); - cg_view_2d_init(cg_core.mrb); - cg_view_3d_init(cg_core.mrb); -} - -} - -const CommandChain cg_sCore::loader{ - {&load_mruby_symbols, nullptr}, - {&load_game, nullptr}, - {&load_sdl, &unload_sdl}, - {&load_sdl_mixer, &unload_sdl_mixer}, - {&load_sdl_open_audio, &unload_sdl_open_audio}, - {&load_window, &unload_window}, - {&load_vk_instance, &unload_vk_instance}, - {&load_window_surface, &unload_window_surface}, - {&load_blucat, &unload_blucat}, - {&load_mruby_interface, nullptr} -}; diff --git a/src/core.hpp b/src/core.hpp deleted file mode 100644 index e7caf8b..0000000 --- a/src/core.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2022-2024 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_CORE_H -#define CANDY_GEAR_CORE_H 1 - -#define CANDY_GEAR_VERSION_MAJOR 0 -#define CANDY_GEAR_VERSION_MINOR 1 -#define CANDY_GEAR_VERSION_PATCH 0 - -#include -#include -#include -#include -#include -#include - -#define SDL_MAIN_HANDLED - -#ifdef _WIN64 -#include -#endif - -#include -#include -#include - -#include -#include FT_FREETYPE_H - -#include "blucat/core.hpp" - -/** - * The Core class stores all global states that the engine needs to work. - * Global variables are not evil if you use them carefully. - */ -struct cg_sCore -{ - static const CommandChain loader; - - mrb_state *mrb; - - std::string game_file; - - /// mruby symbols - mrb_sym sym_config, sym_debug, sym_error, sym_fatal, sym_information, - sym_init, sym_key_down, sym_key_up, sym_quit, sym_tick, sym_trace, - sym_warning; - - bool quit_game; - - SDL_Window *window; -}; - -extern cg_sCore cg_core; - -#endif /* CANDY_GEAR_CORE_H */ diff --git a/src/font.cpp b/src/font.cpp deleted file mode 100644 index 919d271..0000000 --- a/src/font.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2022-2024 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 "font.hpp" - -#include "blucat/font.hpp" - -void -cg_free_font(mrb_state *mrb, void *obj) -{ - auto ptr = static_cast(obj); - - ptr->~Font(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type -cg_font_type = {"CG_Font", cg_free_font}; - -static mrb_value -cg_cFont_initialize(mrb_state *mrb, mrb_value self) -{ - BluCat::Font *ptr; - const char *font_path; - mrb_int font_size; - - mrb_get_args(mrb, "zi", &font_path, &font_size); - ptr = (BluCat::Font*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (BluCat::Font*)mrb_malloc(mrb, sizeof(BluCat::Font)); - - try - { - new(ptr)BluCat::Font(font_path, font_size); - } - catch(const std::invalid_argument &e) - { - mrb_raise(mrb, E_RUNTIME_ERROR, e.what()); - } - - mrb_data_init(self, ptr, &cg_font_type); - return self; -} - -void -cg_font_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cFont; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cFont = mrb_define_class_under(mrb, cg_m, "Font", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cFont, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cFont, "initialize", cg_cFont_initialize, MRB_ARGS_REQ(2)); -} diff --git a/src/font.hpp b/src/font.hpp deleted file mode 100644 index 0128ea0..0000000 --- a/src/font.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2022-2023 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_FONT_H -#define CANDY_GEAR_FONT_H 1 - -#include "core.hpp" - -extern const struct mrb_data_type -cg_font_type; - -void -cg_font_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_FONT_H */ diff --git a/src/graphic.cpp b/src/graphic.cpp deleted file mode 100644 index a991130..0000000 --- a/src/graphic.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 "graphic.hpp" - -#include "core.hpp" - -static mrb_value -cg_mCandyGear_set_display_width(mrb_state *mrb, mrb_value self) -{ - mrb_int width; - - mrb_get_args(mrb, "i", &width); - BluCat::core.display_width = width; - - return self; -} - -static mrb_value -cg_mCandyGear_set_display_height(mrb_state *mrb, mrb_value self) -{ - mrb_int height; - - mrb_get_args(mrb, "i", &height); - BluCat::core.display_height = height; - - return self; -} - -static mrb_value -cg_mCandyGear_set_fps(mrb_state *mrb, mrb_value self) -{ - mrb_int fps; - - mrb_get_args(mrb, "i", &fps); - BluCat::core.fps = fps; - - return self; -} - -void -cg_graphic_init_config(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_mGraphic; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_mGraphic = mrb_define_module_under(mrb, cg_m, "Graphic"); - - mrb_define_class_method( - mrb, cg_mGraphic, "display_width=", cg_mCandyGear_set_display_width, - MRB_ARGS_REQ(1)); - mrb_define_class_method( - mrb, cg_mGraphic, "display_height=", cg_mCandyGear_set_display_height, - MRB_ARGS_REQ(1)); - mrb_define_class_method( - mrb, cg_mGraphic, "fps=", cg_mCandyGear_set_fps, MRB_ARGS_REQ(1)); -} - -void -cg_graphic_finish_config(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_mGraphic; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_mGraphic = mrb_module_get_under(mrb, cg_m, "Graphic"); - - mrb_undef_class_method(mrb, cg_mGraphic, "display_width="); - mrb_undef_class_method(mrb, cg_mGraphic, "display_height="); - mrb_undef_class_method(mrb, cg_mGraphic, "fps="); -} diff --git a/src/graphic.hpp b/src/graphic.hpp deleted file mode 100644 index fbd9df8..0000000 --- a/src/graphic.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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_GRAPHIC_H -#define CANDY_GEAR_GRAPHIC_H 1 - -#include "core.hpp" - -// Provides the basic interface the game needs to configure the engine's -// initialization. -void -cg_graphic_init_config(mrb_state *mrb); -void -cg_graphic_finish_config(mrb_state *mrb); - -#endif /* CANDY_GEAR_GRAPHIC_H */ diff --git a/src/key.cpp b/src/key.cpp deleted file mode 100644 index 615119c..0000000 --- a/src/key.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 "key.hpp" - -void -cg_key_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_mKey; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_mKey = mrb_define_module_under(mrb, cg_m, "Key"); - - mrb_define_const(mrb, cg_mKey, "A", mrb_int_value(mrb, SDLK_a)); - mrb_define_const(mrb, cg_mKey, "B", mrb_int_value(mrb, SDLK_b)); - mrb_define_const(mrb, cg_mKey, "C", mrb_int_value(mrb, SDLK_c)); - mrb_define_const(mrb, cg_mKey, "D", mrb_int_value(mrb, SDLK_d)); - mrb_define_const(mrb, cg_mKey, "E", mrb_int_value(mrb, SDLK_e)); - mrb_define_const(mrb, cg_mKey, "F", mrb_int_value(mrb, SDLK_f)); - mrb_define_const(mrb, cg_mKey, "G", mrb_int_value(mrb, SDLK_g)); - mrb_define_const(mrb, cg_mKey, "H", mrb_int_value(mrb, SDLK_h)); - mrb_define_const(mrb, cg_mKey, "I", mrb_int_value(mrb, SDLK_i)); - mrb_define_const(mrb, cg_mKey, "J", mrb_int_value(mrb, SDLK_j)); - mrb_define_const(mrb, cg_mKey, "K", mrb_int_value(mrb, SDLK_k)); - mrb_define_const(mrb, cg_mKey, "L", mrb_int_value(mrb, SDLK_l)); - mrb_define_const(mrb, cg_mKey, "M", mrb_int_value(mrb, SDLK_m)); - mrb_define_const(mrb, cg_mKey, "N", mrb_int_value(mrb, SDLK_n)); - mrb_define_const(mrb, cg_mKey, "O", mrb_int_value(mrb, SDLK_o)); - mrb_define_const(mrb, cg_mKey, "P", mrb_int_value(mrb, SDLK_p)); - mrb_define_const(mrb, cg_mKey, "Q", mrb_int_value(mrb, SDLK_q)); - mrb_define_const(mrb, cg_mKey, "R", mrb_int_value(mrb, SDLK_r)); - mrb_define_const(mrb, cg_mKey, "S", mrb_int_value(mrb, SDLK_s)); - mrb_define_const(mrb, cg_mKey, "T", mrb_int_value(mrb, SDLK_t)); - mrb_define_const(mrb, cg_mKey, "U", mrb_int_value(mrb, SDLK_u)); - mrb_define_const(mrb, cg_mKey, "V", mrb_int_value(mrb, SDLK_v)); - mrb_define_const(mrb, cg_mKey, "W", mrb_int_value(mrb, SDLK_w)); - mrb_define_const(mrb, cg_mKey, "X", mrb_int_value(mrb, SDLK_x)); - mrb_define_const(mrb, cg_mKey, "Y", mrb_int_value(mrb, SDLK_y)); - mrb_define_const(mrb, cg_mKey, "Z", mrb_int_value(mrb, SDLK_z)); - - mrb_define_const(mrb, cg_mKey, "UP", mrb_int_value(mrb, SDLK_UP)); - mrb_define_const(mrb, cg_mKey, "DOWN", mrb_int_value(mrb, SDLK_DOWN)); - mrb_define_const(mrb, cg_mKey, "LEFT", mrb_int_value(mrb, SDLK_LEFT)); - mrb_define_const(mrb, cg_mKey, "RIGHT", mrb_int_value(mrb, SDLK_RIGHT)); - - mrb_define_const( - mrb, cg_mKey, "BACKSPACE", mrb_int_value(mrb, SDLK_BACKSPACE)); - mrb_define_const(mrb, cg_mKey, "TAB", mrb_int_value(mrb, SDLK_TAB)); - mrb_define_const( - mrb, cg_mKey, "LEFT_SHIFT", mrb_int_value(mrb, SDLK_LSHIFT)); - mrb_define_const( - mrb, cg_mKey, "RIGHT_SHIFT", mrb_int_value(mrb, SDLK_RSHIFT)); - mrb_define_const(mrb, cg_mKey, "SPACE", mrb_int_value(mrb, SDLK_SPACE)); - mrb_define_const(mrb, cg_mKey, "LEFT_ALT", mrb_int_value(mrb, SDLK_LALT)); - mrb_define_const(mrb, cg_mKey, "RIGHT_ALT", mrb_int_value(mrb, SDLK_RALT)); - mrb_define_const(mrb, cg_mKey, "LEFT_CTRL", mrb_int_value(mrb, SDLK_LCTRL)); - mrb_define_const(mrb, cg_mKey, "RIGHT_CTRL", mrb_int_value(mrb, SDLK_RCTRL)); -} diff --git a/src/key.hpp b/src/key.hpp deleted file mode 100644 index d3f4f5f..0000000 --- a/src/key.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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_KEY_H -#define CANDY_GEAR_KEY_H 1 - -#include "core.hpp" - -void -cg_key_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_KEY_H */ diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 3627c9c..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2022-2024 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 -#include - -#include "core.hpp" - -cg_sCore cg_core; - -int main(int argc, char *argv[]) -{ - using namespace std::chrono; - using namespace std::this_thread; - - SDL_Event event; - - // Random numbers - BluCat::random_number_generator.seed(BluCat::random_seed()); - - cg_core.game_file = argv[1]; - cg_core.mrb = mrb_open(); - if (!cg_core.mrb) throw CommandError{"Failed to initialize mruby."}; - try{ cg_sCore::loader.execute(nullptr); } - catch(const CommandError &error) - { - BluCat::core.log.message(Log::Level::Fatal, error.what()); - mrb_close(cg_core.mrb); - return 1; - } - - mrb_value main_obj{mrb_top_self(cg_core.mrb)}; - - mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_init, 0); - if (cg_core.mrb->exc) - { - mrb_print_error(cg_core.mrb); - mrb_close(cg_core.mrb); - cg_sCore::loader.revert(nullptr); - return 1; - } - - auto frame_start = steady_clock::now(); - - // Game main loop. - while(!cg_core.quit_game) - { - // Get input. - while(SDL_PollEvent(&event) != 0) - { - switch(event.type) - { - case SDL_KEYDOWN: - mrb_funcall_id( - cg_core.mrb, main_obj, cg_core.sym_key_down, 1, - mrb_int_value(cg_core.mrb, event.key.keysym.sym)); - break; - case SDL_KEYUP: - mrb_funcall_id( - cg_core.mrb, main_obj, cg_core.sym_key_up, 1, - mrb_int_value(cg_core.mrb, event.key.keysym.sym)); - break; - case SDL_MOUSEMOTION: - break; - case SDL_MOUSEBUTTONDOWN: - break; - case SDL_MOUSEBUTTONUP: - break; - case SDL_QUIT: - mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_quit, 0); - break; - } - } - - mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_tick, 0); - if (cg_core.mrb->exc) - { - mrb_print_error(cg_core.mrb); - cg_core.quit_game = true; - } - else - { - BluCat::core.vk_renderer->draw(); - - { // Timer - auto frame_stop = steady_clock::now(); - auto frame_duration = frame_stop - frame_start; - - // If frame take less time than maximum allowed. - if(BluCat::core.max_frame_duration > frame_duration) - sleep_for(BluCat::core.max_frame_duration - frame_duration); - - frame_start = frame_stop; - } - } - } - - mrb_close(cg_core.mrb); - cg_sCore::loader.revert(nullptr); - - return 0; -} diff --git a/src/orientation_3d.cpp b/src/orientation_3d.cpp deleted file mode 100644 index cb42984..0000000 --- a/src/orientation_3d.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2022-2024 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. - */ - -#define _USE_MATH_DEFINES - -#include "orientation_3d.hpp" - -#include "vector_3d.hpp" - -void -cg_free_orientation_3d(mrb_state *mrb, void* obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_orientation_3d_type = { - "CG_Orientation3D", cg_free_orientation_3d}; - -static mrb_value -cg_cOrientation3D_initialize(mrb_state *mrb, mrb_value self) -{ - mrb_float x, y, z; - std::shared_ptr *ptr; - - mrb_get_args(mrb, "fff", &x, &y, &z); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - glm::vec3 angles(x, y, z); - new(ptr)std::shared_ptr( - std::make_shared(angles)); - (**ptr) = glm::normalize(**ptr); - - mrb_data_init(self, ptr, &cg_orientation_3d_type); - return self; -} - -static mrb_value -cg_cOrientation3D_get_w(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->w); -} - -static mrb_value -cg_cOrientation3D_get_x(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->x); -} - -static mrb_value -cg_cOrientation3D_get_y(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->y); -} - -static mrb_value -cg_cOrientation3D_get_z(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->z); -} - -static mrb_value -cg_cOrientation3D_rotate(mrb_state *mrb, mrb_value self) -{ - mrb_float x, y, z; - auto *ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "fff", &x, &y, &z); - - glm::vec3 angles(x, y, z); - glm::quat rot(angles); - (**ptr) *= rot; - - // TODO: calling normalize for every rotation is expensive. - (**ptr) = glm::normalize(**ptr); - - return self; -} - -void -cg_orientation_3d_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cOrientation3D; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cOrientation3D = mrb_define_class_under( - mrb, cg_m, "Orientation3D", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cOrientation3D, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cOrientation3D, "initialize", cg_cOrientation3D_initialize, - MRB_ARGS_REQ(3)); - - mrb_define_method( - mrb, cg_cOrientation3D, "w", cg_cOrientation3D_get_w, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cOrientation3D, "x", cg_cOrientation3D_get_x, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cOrientation3D, "y", cg_cOrientation3D_get_y, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cOrientation3D, "z", cg_cOrientation3D_get_z, MRB_ARGS_NONE()); - - mrb_define_method( - mrb, cg_cOrientation3D, "rotate", cg_cOrientation3D_rotate, - MRB_ARGS_REQ(3)); -} diff --git a/src/orientation_3d.hpp b/src/orientation_3d.hpp deleted file mode 100644 index 45a8ab2..0000000 --- a/src/orientation_3d.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2022-2024 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_ORIENTATION_3D_H -#define CANDY_GEAR_ORIENTATION_3D_H 1 - -#include "core.hpp" - -extern const struct mrb_data_type cg_orientation_3d_type; - -void -cg_orientation_3d_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_ORIENTATION_3D_H */ diff --git a/src/skeletal_mesh.cpp b/src/skeletal_mesh.cpp deleted file mode 100644 index 90cbeee..0000000 --- a/src/skeletal_mesh.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2022-2024 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 "skeletal_mesh.hpp" - -#include "orientation_3d.hpp" -#include "vector_3d.hpp" -#include "blucat/skeletal_mesh.hpp" - -void -cg_free_skeletal_mesh(mrb_state *mrb, void* obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_skeletal_mesh_type = { - "CG_SkeletalMesh", cg_free_skeletal_mesh }; - -static mrb_value -cg_cSkeletalMesh_initialize(mrb_state *mrb, mrb_value self) -{ - const char *file_path; - - std::shared_ptr *ptr; - - mrb_get_args(mrb, "z", &file_path); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - new(ptr)std::shared_ptr( - std::make_shared(file_path)); - - mrb_data_init(self, ptr, &cg_skeletal_mesh_type); - return self; -} - -void -cg_skeletal_mesh_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cSkeletalMesh; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cSkeletalMesh = mrb_define_class_under( - mrb, cg_m, "SkeletalMesh", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cSkeletalMesh, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cSkeletalMesh, "initialize", cg_cSkeletalMesh_initialize, - MRB_ARGS_REQ(1)); -} diff --git a/src/skeletal_mesh.hpp b/src/skeletal_mesh.hpp deleted file mode 100644 index 476aa9b..0000000 --- a/src/skeletal_mesh.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2022-2023 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_SKELETAL_MESH_H -#define CANDY_GEAR_SKELETAL_MESH_H 1 - -#include "core.hpp" - -extern const struct mrb_data_type cg_skeletal_mesh_type; - -void -cg_skeletal_mesh_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_SKELETAL_MESH_H */ diff --git a/src/skeletal_model.cpp b/src/skeletal_model.cpp deleted file mode 100644 index f42306b..0000000 --- a/src/skeletal_model.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2022-2024 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 "skeletal_model.hpp" - -#include "orientation_3d.hpp" -#include "vector_3d.hpp" -#include "skeletal_mesh.hpp" -#include "texture.hpp" -#include "blucat/skeletal_model.hpp" - -void -cg_free_skeletal_model(mrb_state *mrb, void *obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_skeletal_model_type = { - "CG_SkeletalModel", cg_free_skeletal_model }; - -static mrb_value -cg_cSkeletalModel_initialize(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *skeletal_mesh; - std::shared_ptr *texture; - std::shared_ptr *position; - std::shared_ptr *orientation; - std::shared_ptr *ptr; - - mrb_get_args( - mrb, "dddd", &skeletal_mesh, &cg_skeletal_mesh_type, &texture, - &cg_texture_type, &position, &cg_vector_3d_type, &orientation, - &cg_orientation_3d_type); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - new(ptr)std::shared_ptr( - std::make_shared( - *skeletal_mesh, *texture, *position, *orientation)); - - mrb_data_init(self, ptr, &cg_skeletal_model_type); - return self; -} - -static mrb_value -cg_cSkeletalModel_set_orientation(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - std::shared_ptr *orientation; - - mrb_get_args(mrb, "d", &orientation, &cg_orientation_3d_type); - (*ptr)->orientation = *orientation; - - return self; -} - -static mrb_value -cg_cSkeletalModel_set_position(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - std::shared_ptr *position; - - mrb_get_args(mrb, "d", &position, &cg_vector_3d_type); - (*ptr)->position = *position; - - return self; -} - -static mrb_value -cg_cSkeletalModel_set_animation(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - mrb_int animation_index; - - mrb_get_args(mrb, "i", &animation_index); - (*ptr)->animation_index = animation_index; - - return self; -} - -static mrb_value -cg_cSkeletalModel_draw(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - auto &instances = BluCat::core.vk_renderer->skeletal_models_to_draw[ - BluCat::core.vk_swapchain->current_frame][(*ptr)->skeletal_mesh]; - instances.push_back(*ptr); - - return self; -} - -void -cg_skeletal_model_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cSkeletalModel; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cSkeletalModel = mrb_define_class_under( - mrb, cg_m, "SkeletalModel", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cSkeletalModel, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cSkeletalModel, "initialize", cg_cSkeletalModel_initialize, - MRB_ARGS_REQ(4)); - mrb_define_method( - mrb, cg_cSkeletalModel, "position=", cg_cSkeletalModel_set_position, - MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cSkeletalModel, "orientation=", cg_cSkeletalModel_set_orientation, - MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cSkeletalModel, "animation=", cg_cSkeletalModel_set_animation, - MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cSkeletalModel, "draw", cg_cSkeletalModel_draw, MRB_ARGS_NONE()); -} diff --git a/src/skeletal_model.hpp b/src/skeletal_model.hpp deleted file mode 100644 index 05f9c2e..0000000 --- a/src/skeletal_model.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2022-2023 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_SKELETAL_MODEL_H -#define CANDY_GEAR_SKELETAL_MODEL_H 1 - -#include "core.hpp" - -void -cg_skeletal_model_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_SKELETAL_MODEL_H */ diff --git a/src/sound.cpp b/src/sound.cpp deleted file mode 100644 index 0b3518f..0000000 --- a/src/sound.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 "sound.hpp" - -void -cg_free_sound(mrb_state *mrb, void* obj) -{ - struct cg_sound *ptr = static_cast(obj); - - Mix_FreeChunk(ptr->chunk); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_sound_type = { - "CG_Sound", cg_free_sound }; - -static mrb_value -cg_cSound_initialize(mrb_state *mrb, mrb_value self) -{ - const char *file_path; - - struct cg_sound *ptr; - - mrb_get_args(mrb, "z", &file_path); - ptr = (struct cg_sound *)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (struct cg_sound *)mrb_malloc(mrb, sizeof(struct cg_sound)); - - ptr->chunk = Mix_LoadWAV(file_path); - if(ptr->chunk == NULL) mrb_raise(mrb, E_RUNTIME_ERROR, Mix_GetError()); - - mrb_data_init(self, ptr, &cg_sound_type); - return self; -} - -static mrb_value -cg_cSound_play(mrb_state *mrb, mrb_value self) -{ - struct cg_sound *ptr; - - ptr = (struct cg_sound *)DATA_PTR(self); - - Mix_PlayChannel(-1, ptr->chunk, 0); - - return self; -} - -void -cg_sound_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cSound; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cSound = mrb_define_class_under(mrb, cg_m, "Sound", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cSound, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cSound, "initialize", cg_cSound_initialize, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, cg_cSound, "play", cg_cSound_play, MRB_ARGS_NONE()); -} diff --git a/src/sound.hpp b/src/sound.hpp deleted file mode 100644 index 2f483e3..0000000 --- a/src/sound.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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_SOUND_H -#define CANDY_GEAR_SOUND_H 1 - -#include "core.hpp" - -struct cg_sound -{ - Mix_Chunk *chunk; -}; - -extern const struct mrb_data_type cg_sound_type; - -void -cg_sound_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_SOUND_H */ diff --git a/src/sprite.cpp b/src/sprite.cpp deleted file mode 100644 index 0041107..0000000 --- a/src/sprite.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2022-2024 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 "sprite.hpp" - -#include "texture.hpp" -#include "vector_4d.hpp" -#include "view_2d.hpp" -#include "blucat/sprite.hpp" - -void -cg_free_sprite(mrb_state *mrb, void* obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_sprite_type = { "CG_Sprite", cg_free_sprite }; - -static mrb_value -cg_cSprite_initialize(mrb_state *mrb, mrb_value self) -{ - mrb_float x, y, w, h; - glm::vec4 vector_4d; - std::shared_ptr *texture; - std::shared_ptr *ptr; - - mrb_get_args( - mrb, "dffff", &texture, &cg_texture_type, &x, &y, &w, &h); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - vector_4d.x = x; - vector_4d.y = y; - vector_4d.z = w; - vector_4d.w = h; - new(ptr)std::shared_ptr( - std::make_shared(*texture, vector_4d)); - - mrb_data_init(self, ptr, &cg_sprite_type); - return self; -} - -static mrb_value -cg_cSprite_draw(mrb_state *mrb, mrb_value self) -{ - mrb_value view_value; - BluCat::View2D *view_2d; - mrb_float x, y, w, h, z_index{0.0}; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "offff|f", &view_value, &x, &y, &w, &h, &z_index); - - view_2d = cg_cView_to_view_2d(mrb, view_value); - - glm::vec4 rect(x, y, x + w, y + h); - auto &sprites_to_draw = view_2d->sprites_to_draw[ - BluCat::core.vk_swapchain->current_frame]; - sprites_to_draw.emplace_back(*ptr, rect, z_index); - - return self; -} - -void -cg_sprite_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cSprite; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cSprite = mrb_define_class_under(mrb, cg_m, "Sprite", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cSprite, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cSprite, "initialize", cg_cSprite_initialize, MRB_ARGS_REQ(5)); - mrb_define_method(mrb, cg_cSprite, "draw", cg_cSprite_draw, MRB_ARGS_REQ(5)| - MRB_ARGS_OPT(1)); -} diff --git a/src/sprite.hpp b/src/sprite.hpp deleted file mode 100644 index 528f2f7..0000000 --- a/src/sprite.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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_SPRITE_H -#define CANDY_GEAR_SPRITE_H 1 - -#include "core.hpp" - -extern const struct mrb_data_type cg_sprite_type; - -void -cg_sprite_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_SPRITE_H */ diff --git a/src/sprite_3d.cpp b/src/sprite_3d.cpp deleted file mode 100644 index 6e6759f..0000000 --- a/src/sprite_3d.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2022-2024 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 "sprite_3d.hpp" - -#include "sprite.hpp" -#include "vector_3d.hpp" - -void -cg_free_sprite_3d(mrb_state *mrb, void *obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_sprite_3d_type = { - "CG_Sprite3D", cg_free_sprite_3d }; - -static mrb_value -cg_cSprite3D_initialize(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *sprite; - std::shared_ptr *position; - mrb_float w, h; - std::shared_ptr *ptr; - - mrb_get_args(mrb, "ddff", &sprite, &cg_sprite_type, - &position, &cg_vector_3d_type, &w, &h); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - glm::vec3 size{w, h, 0.0}; - new(ptr)std::shared_ptr( - std::make_shared(*sprite, *position, size)); - - mrb_data_init(self, ptr, &cg_sprite_3d_type); - return self; -} - -static mrb_value -cg_cSprite3D_draw(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - auto &sprites_3d_to_draw = BluCat::core.vk_renderer->sprites_3d_to_draw[ - BluCat::core.vk_swapchain->current_frame]; - sprites_3d_to_draw.emplace_back(*ptr); - - return self; -} - -void -cg_sprite_3d_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cSprite3D; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cSprite3D = mrb_define_class_under( - mrb, cg_m, "Sprite3D", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cSprite3D, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cSprite3D, "initialize", cg_cSprite3D_initialize, MRB_ARGS_REQ(3)); - mrb_define_method( - mrb, cg_cSprite3D, "draw", cg_cSprite3D_draw, MRB_ARGS_NONE()); -} diff --git a/src/sprite_3d.hpp b/src/sprite_3d.hpp deleted file mode 100644 index 526c23a..0000000 --- a/src/sprite_3d.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2022-2023 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_SPRITE_3D_H -#define CANDY_GEAR_SPRITE_3D_H 1 - -#include "core.hpp" - -void -cg_sprite_3d_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_SPRITE_3D_H */ diff --git a/src/static_mesh.cpp b/src/static_mesh.cpp deleted file mode 100644 index 3ae616e..0000000 --- a/src/static_mesh.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2022-2024 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 "static_mesh.hpp" - -#include "orientation_3d.hpp" -#include "vector_3d.hpp" -#include "blucat/static_mesh.hpp" - -void -cg_free_static_mesh(mrb_state *mrb, void* obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_static_mesh_type = { - "CG_StaticMesh", cg_free_static_mesh }; - -static mrb_value -cg_cStaticMesh_initialize(mrb_state *mrb, mrb_value self) -{ - const char *file_path; - - std::shared_ptr *ptr; - - mrb_get_args(mrb, "z", &file_path); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - new(ptr)std::shared_ptr( - std::make_shared(file_path)); - - mrb_data_init(self, ptr, &cg_static_mesh_type); - return self; -} - -void -cg_static_mesh_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cStaticMesh; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cStaticMesh = mrb_define_class_under( - mrb, cg_m, "StaticMesh", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cStaticMesh, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cStaticMesh, "initialize", cg_cStaticMesh_initialize, - MRB_ARGS_REQ(1)); -} diff --git a/src/static_mesh.hpp b/src/static_mesh.hpp deleted file mode 100644 index 8f3b2d6..0000000 --- a/src/static_mesh.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2022-2023 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_STATIC_MESH_H -#define CANDY_GEAR_STATIC_MESH_H 1 - -#include "core.hpp" - -extern const struct mrb_data_type cg_static_mesh_type; - -void -cg_static_mesh_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_STATIC_MESH_H */ diff --git a/src/static_model.cpp b/src/static_model.cpp deleted file mode 100644 index f9a1039..0000000 --- a/src/static_model.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2022-2024 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 "static_model.hpp" - -#include "orientation_3d.hpp" -#include "static_mesh.hpp" -#include "texture.hpp" -#include "vector_3d.hpp" -#include "blucat/static_model.hpp" - -void -cg_free_static_model(mrb_state *mrb, void *obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_static_model_type = { - "CG_StaticModel", cg_free_static_model }; - -static mrb_value -cg_cStaticModel_initialize(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *static_mesh; - std::shared_ptr *texture; - std::shared_ptr *position; - std::shared_ptr *orientation; - std::shared_ptr *ptr; - - mrb_get_args( - mrb, "dddd", &static_mesh, &cg_static_mesh_type, &texture, - &cg_texture_type, &position, &cg_vector_3d_type, &orientation, - &cg_orientation_3d_type); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - new(ptr)std::shared_ptr( - std::make_shared( - *static_mesh, *texture, *position, *orientation)); - - mrb_data_init(self, ptr, &cg_static_model_type); - return self; -} - -static mrb_value -cg_cStaticModel_set_orientation(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - std::shared_ptr *orientation; - - mrb_get_args(mrb, "d", &orientation, &cg_orientation_3d_type); - (*ptr)->orientation = *orientation; - - return self; -} - -static mrb_value -cg_cStaticModel_set_position(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - std::shared_ptr *position; - - mrb_get_args(mrb, "d", &position, &cg_vector_3d_type); - (*ptr)->position = *position; - - return self; -} - -static mrb_value -cg_cStaticModel_set_texture(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - std::shared_ptr *texture; - - mrb_get_args(mrb, "d", &texture, &cg_texture_type); - (*ptr)->texture = *texture; - - return self; -} - -static mrb_value -cg_cStaticModel_draw(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - auto &instances = BluCat::core.vk_renderer->static_models_to_draw[ - BluCat::core.vk_swapchain->current_frame][(*ptr)->static_mesh]; - instances.push_back(*ptr); - - return self; -} - -void -cg_static_model_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cStaticModel; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cStaticModel = mrb_define_class_under( - mrb, cg_m, "StaticModel", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cStaticModel, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cStaticModel, "initialize", cg_cStaticModel_initialize, - MRB_ARGS_REQ(4)); - mrb_define_method( - mrb, cg_cStaticModel, "position=", cg_cStaticModel_set_position, - MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cStaticModel, "orientation=", cg_cStaticModel_set_orientation, - MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cStaticModel, "texture=", cg_cStaticModel_set_texture, - MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cStaticModel, "draw", cg_cStaticModel_draw, MRB_ARGS_NONE()); -} diff --git a/src/static_model.hpp b/src/static_model.hpp deleted file mode 100644 index dfb7054..0000000 --- a/src/static_model.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2022-2023 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_STATIC_MODEL_H -#define CANDY_GEAR_STATIC_MODEL_H 1 - -#include "core.hpp" - -void -cg_static_model_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_STATIC_MODEL_H */ diff --git a/src/texture.cpp b/src/texture.cpp deleted file mode 100644 index 0bfac25..0000000 --- a/src/texture.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2022-2024 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 "texture.hpp" - -#include "core.hpp" -#include "font.hpp" -#include "blucat/texture.hpp" - -void -cg_free_texture(mrb_state *mrb, void* obj) -{ - auto *ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_texture_type = { "CG_Texture", cg_free_texture }; - -static mrb_value -texture_alloc(mrb_state *mrb, mrb_value klass) -{ - struct RClass *cg_cTexture = mrb_class_ptr(klass); - enum mrb_vtype ttype = MRB_INSTANCE_TT(cg_cTexture); - - // I do not know if I need this. If things break, try uncomment this line. - // if (ttype == 0) ttype = MRB_TT_OBJECT; - return mrb_obj_value( - (struct RObject*)mrb_obj_alloc(mrb, ttype, cg_cTexture)); -} - -static mrb_value -cg_cTexture_from_image(mrb_state *mrb, mrb_value self) -{ - struct mrb_value texture = texture_alloc(mrb, self); - const char *file_path; - std::shared_ptr *ptr; - - mrb_get_args(mrb, "z", &file_path); - ptr = (std::shared_ptr*)DATA_PTR(texture); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - new(ptr)std::shared_ptr( - std::make_shared(file_path)); - - mrb_data_init(texture, ptr, &cg_texture_type); - return texture; -} - -mrb_value -cg_cTexture_from_text(mrb_state *mrb, mrb_value self) -{ - const char *text; - unsigned int width, height; - struct mrb_value texture = texture_alloc(mrb, self); - BluCat::Font *font_ptr; - std::shared_ptr *ptr; - - mrb_get_args(mrb, "dz", &font_ptr, &cg_font_type, &text); - - ptr = (std::shared_ptr*)DATA_PTR(texture); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - new(ptr)std::shared_ptr( - std::make_shared(font_ptr, text)); - - mrb_data_init(texture, ptr, &cg_texture_type); - return texture; -} - -static mrb_value -cg_cTexture_width(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - return mrb_int_value(mrb, (*ptr)->width); -} - -static mrb_value -cg_cTexture_height(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - return mrb_int_value(mrb, (*ptr)->height); -} - -void -cg_texture_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cTexture; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cTexture = mrb_define_class_under( - mrb, cg_m, "Texture", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cTexture, MRB_TT_DATA); - - mrb_undef_class_method(mrb, cg_cTexture, "new"); - mrb_define_class_method( - mrb, cg_cTexture, "from_image", cg_cTexture_from_image, - MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); - mrb_define_class_method( - mrb, cg_cTexture, "from_text", cg_cTexture_from_text, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cTexture, "width", cg_cTexture_width, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cTexture, "height", cg_cTexture_height, MRB_ARGS_NONE()); -} diff --git a/src/texture.hpp b/src/texture.hpp deleted file mode 100644 index 36f23db..0000000 --- a/src/texture.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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_TEXTURE_H -#define CANDY_GEAR_TEXTURE_H 1 - -#include "core.hpp" -#include "blucat/command.hpp" - -extern const struct mrb_data_type cg_texture_type; - -void -cg_texture_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_TEXTURE_H */ diff --git a/src/vector_3d.cpp b/src/vector_3d.cpp deleted file mode 100644 index fc5d186..0000000 --- a/src/vector_3d.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright 2022-2024 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 "vector_3d.hpp" - -#include - -#include - -#include - -#include "orientation_3d.hpp" - -void -cg_free_vector_3d(mrb_state *mrb, void* obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_vector_3d_type = { - "CG_Vector3D", cg_free_vector_3d}; - -static mrb_value -cg_cVector3D_initialize(mrb_state *mrb, mrb_value self) -{ - mrb_float x = 0.0f; - mrb_float y = 0.0f; - mrb_float z = 0.0f; - std::shared_ptr *ptr; - - mrb_get_args(mrb, "|fff", &x, &y, &z); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - new(ptr)std::shared_ptr(std::make_shared(x, y, z)); - - mrb_data_init(self, ptr, &cg_vector_3d_type); - return self; -} - -mrb_value -cg_cVector3D_get_x(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->x); -} - -mrb_value -cg_cVector3D_get_y(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->y); -} - -mrb_value -cg_cVector3D_get_z(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->z); -} - -mrb_value -cg_cVector3D_get_xy(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 2); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); - - return array; -} - -mrb_value -cg_cVector3D_get_xz(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 2); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); - - return array; -} - -mrb_value -cg_cVector3D_get_yz(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 2); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); - - return array; -} - -mrb_value -cg_cVector3D_get_xyz(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 3); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); - - return array; -} - -static mrb_value -cg_cVector3D_set_x(mrb_state *mrb, mrb_value self) -{ - mrb_float x; - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "f", &x); - (*ptr)->x = x; - - return self; -} - -static mrb_value -cg_cVector3D_set_y(mrb_state *mrb, mrb_value self) -{ - mrb_float y; - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "f", &y); - (*ptr)->y = y; - - return self; -} - -static mrb_value -cg_cVector3D_set_z(mrb_state *mrb, mrb_value self) -{ - mrb_float z; - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "f", &z); - (*ptr)->z = z; - - return self; -} - -static mrb_value -cg_cVector3D_set_xy(mrb_state *mrb, mrb_value self) -{ - mrb_float x, y; - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "ff", &x, &y); - (*ptr)->x = x; - (*ptr)->y = y; - - return self; -} - -static mrb_value -cg_cVector3D_set_xz(mrb_state *mrb, mrb_value self) -{ - mrb_float x, z; - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "ff", &x, &z); - (*ptr)->x = x; - (*ptr)->z = z; - - return self; -} - -static mrb_value -cg_cVector3D_set_yz(mrb_state *mrb, mrb_value self) -{ - mrb_float y, z; - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "ff", &y, &z); - (*ptr)->y = y; - (*ptr)->z = z; - - return self; -} - -static mrb_value -cg_cVector3D_set_xyz(mrb_state *mrb, mrb_value self) -{ - mrb_float x, y, z; - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "fff", &x, &y, &z); - (*ptr)->x = x; - (*ptr)->y = y; - (*ptr)->z = z; - - return self; -} - -static mrb_value -cg_cVector3D_translate(mrb_state *mrb, mrb_value self) -{ - auto *ptr = (std::shared_ptr*)DATA_PTR(self); - std::shared_ptr *direction; - std::shared_ptr *orientation; - - mrb_get_args( - mrb, "dd", &direction, &cg_vector_3d_type, - &orientation, &cg_orientation_3d_type); - - auto rotated_direction = **orientation * **direction; - - **ptr += rotated_direction; - - return self; -} - -void -cg_vector_3d_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cVector3D; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cVector3D = mrb_define_class_under( - mrb, cg_m, "Vector3D", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cVector3D, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cVector3D, "initialize", cg_cVector3D_initialize, - MRB_ARGS_NONE()|MRB_ARGS_OPT(3)); - - mrb_define_method( - mrb, cg_cVector3D, "x", cg_cVector3D_get_x, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector3D, "y", cg_cVector3D_get_y, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector3D, "z", cg_cVector3D_get_z, MRB_ARGS_NONE()); - - mrb_define_method( - mrb, cg_cVector3D, "xy", cg_cVector3D_get_xy, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector3D, "xz", cg_cVector3D_get_xz, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector3D, "yz", cg_cVector3D_get_yz, MRB_ARGS_NONE()); - - mrb_define_method( - mrb, cg_cVector3D, "xyz", cg_cVector3D_get_xyz, MRB_ARGS_NONE()); - - mrb_define_method( - mrb, cg_cVector3D, "x=", cg_cVector3D_set_x, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector3D, "y=", cg_cVector3D_set_y, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector3D, "z=", cg_cVector3D_set_z, MRB_ARGS_REQ(1)); - - mrb_define_method( - mrb, cg_cVector3D, "set_xy", cg_cVector3D_set_xy, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector3D, "set_xz", cg_cVector3D_set_xz, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector3D, "set_yz", cg_cVector3D_set_yz, MRB_ARGS_REQ(2)); - - mrb_define_method( - mrb, cg_cVector3D, "set_xyz", cg_cVector3D_set_xyz, MRB_ARGS_REQ(3)); - - mrb_define_method( - mrb, cg_cVector3D, "translate", cg_cVector3D_translate, MRB_ARGS_REQ(2)); -} diff --git a/src/vector_3d.hpp b/src/vector_3d.hpp deleted file mode 100644 index 2827813..0000000 --- a/src/vector_3d.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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_VECTOR_3D_H -#define CANDY_GEAR_VECTOR_3D_H 1 - -#include "core.hpp" - -extern const struct mrb_data_type cg_vector_3d_type; - -mrb_value -cg_cVector3D_get_x(mrb_state *mrb, mrb_value self); -mrb_value -cg_cVector3D_get_y(mrb_state *mrb, mrb_value self); -mrb_value -cg_cVector3D_get_z(mrb_state *mrb, mrb_value self); - -void -cg_vector_3d_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_VECTOR_3D_H */ diff --git a/src/vector_4d.cpp b/src/vector_4d.cpp deleted file mode 100644 index dedda2f..0000000 --- a/src/vector_4d.cpp +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright 2022-2024 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 "vector_4d.hpp" - -#include - -#include -#include - -#include "vector_3d.hpp" -#include "view_2d.hpp" - -namespace -{ - -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; -} - -} - -void -cg_free_vector_4d(mrb_state *mrb, void* obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_vector_4d_type = { - "CG_Vector4D", cg_free_vector_4d}; - -static mrb_value -cg_cVector4D_initialize(mrb_state *mrb, mrb_value self) -{ - mrb_float x = 0.0f; - mrb_float y = 0.0f; - mrb_float w = 0.0f; - mrb_float h = 0.0f; - std::shared_ptr *ptr; - - mrb_get_args(mrb, "|ffff", &x, &y, &w, &h); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - new(ptr)std::shared_ptr(std::make_shared(x, y, w, h)); - - mrb_data_init(self, ptr, &cg_vector_4d_type); - return self; -} - -mrb_value -cg_cVector4D_get_x(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr = - (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->x); -} - -mrb_value -cg_cVector4D_get_y(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->y); -} - -mrb_value -cg_cVector4D_get_w(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->z); -} - -mrb_value -cg_cVector4D_get_h(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->w); -} - -mrb_value -cg_cVector4D_get_xy(mrb_state *mrb, mrb_value self) -{ - auto *ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 2); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); - - return array; -} - -mrb_value -cg_cVector4D_get_xw(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 2); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); - - return array; -} - -mrb_value -cg_cVector4D_get_xh(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 2); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->x)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->w)); - - return array; -} - -mrb_value -cg_cVector4D_get_yw(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 2); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); - - return array; -} - -mrb_value -cg_cVector4D_get_yh(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 2); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->y)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->w)); - - return array; -} - -mrb_value -cg_cVector4D_get_wh(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_value array = mrb_ary_new_capa(mrb, 2); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->z)); - mrb_ary_push(mrb, array, mrb_float_value(mrb, (*ptr)->w)); - - return array; -} - -static mrb_value -cg_cVector4D_set_x(mrb_state *mrb, mrb_value self) -{ - mrb_float x; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "f", &x); - (*ptr)->x = x; - - return self; -} - -static mrb_value -cg_cVector4D_set_y(mrb_state *mrb, mrb_value self) -{ - mrb_float y; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "f", &y); - (*ptr)->y = y; - - return self; -} - -static mrb_value -cg_cVector4D_set_w(mrb_state *mrb, mrb_value self) -{ - mrb_float w; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "f", &w); - (*ptr)->z = w; - - return self; -} - -static mrb_value -cg_cVector4D_set_h(mrb_state *mrb, mrb_value self) -{ - mrb_float h; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "f", &h); - (*ptr)->w = h; - - return self; -} - -static mrb_value -cg_cVector4D_set_xy(mrb_state *mrb, mrb_value self) -{ - mrb_float x, y; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "ff", &x, &y); - (*ptr)->x = x; - (*ptr)->y = y; - - return self; -} - -static mrb_value -cg_cVector4D_set_xw(mrb_state *mrb, mrb_value self) -{ - mrb_float x, w; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "ff", &x, &w); - (*ptr)->x = x; - (*ptr)->z = w; - - return self; -} - -static mrb_value -cg_cVector4D_set_xh(mrb_state *mrb, mrb_value self) -{ - mrb_float x, h; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "ff", &x, &h); - (*ptr)->x = x; - (*ptr)->w = h; - - return self; -} - -static mrb_value -cg_cVector4D_set_yw(mrb_state *mrb, mrb_value self) -{ - mrb_float y, w; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "ff", &y, &w); - (*ptr)->y = y; - (*ptr)->z = w; - - return self; -} - -static mrb_value -cg_cVector4D_set_yh(mrb_state *mrb, mrb_value self) -{ - mrb_float y, h; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "ff", &y, &h); - (*ptr)->x = y; - (*ptr)->w = h; - - return self; -} - -static mrb_value -cg_cVector4D_set_wh(mrb_state *mrb, mrb_value self) -{ - mrb_float w, h; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "ff", &w, &h); - (*ptr)->z = w; - (*ptr)->w = h; - - return self; -} - -static mrb_value -cg_cVector4D_align_vertically(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr, *that; - - mrb_get_args(mrb, "d", &that, &cg_vector_4d_type); - ptr = (std::shared_ptr*)DATA_PTR(self); - - return mrb_bool_value( - align_vertically((*ptr)->x, (*ptr)->z, (*that)->x, (*that)->z)); -} - -static mrb_value -cg_cVector4D_align_horizontally(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr, *that; - - mrb_get_args(mrb, "d", &that, &cg_vector_4d_type); - ptr = (std::shared_ptr*)DATA_PTR(self); - - return mrb_bool_value( - align_horizontally((*ptr)->y, (*ptr)->w, (*that)->y, (*that)->w)); -} - -static mrb_value -cg_cVector4D_collide(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *ptr, *that; - - mrb_get_args(mrb, "d", &that, &cg_vector_4d_type); - ptr = (std::shared_ptr*)DATA_PTR(self); - - return mrb_bool_value( - align_vertically((*ptr)->x, (*ptr)->z, (*that)->x, (*that)->z) && - align_horizontally((*ptr)->y, (*ptr)->w, (*that)->y, (*that)->w)); -} - -static mrb_value -cg_cVector4D_draw_rectangle(mrb_state *mrb, mrb_value self) -{ - mrb_value view_value; - BluCat::View2D *view_2d; - std::shared_ptr *color; - auto ptr = (std::shared_ptr*)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); - - glm::vec4 position( - (*ptr)->x, (*ptr)->y, (*ptr)->x + (*ptr)->z, (*ptr)->y + (*ptr)->w); - BluCat::Rectangle rect{position, (**color)}; - auto &rectangles = view_2d->rectangles_to_draw[ - BluCat::core.vk_swapchain->current_frame]; - rectangles.push_back(rect); - - return self; -} - -void -cg_vector_4d_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cVector4D; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cVector4D = mrb_define_class_under( - mrb, cg_m, "Vector4D", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cVector4D, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cVector4D, "initialize", cg_cVector4D_initialize, - MRB_ARGS_NONE()|MRB_ARGS_OPT(4)); - - mrb_define_method( - mrb, cg_cVector4D, "x", cg_cVector4D_get_x, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "y", cg_cVector4D_get_y, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "w", cg_cVector4D_get_w, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "h", cg_cVector4D_get_h, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "r", cg_cVector4D_get_x, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "g", cg_cVector4D_get_y, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "b", cg_cVector4D_get_w, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "a", cg_cVector4D_get_h, MRB_ARGS_NONE()); - - mrb_define_method( - mrb, cg_cVector4D, "xy", cg_cVector4D_get_xy, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "xw", cg_cVector4D_get_xw, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "xh", cg_cVector4D_get_xh, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "yw", cg_cVector4D_get_yw, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "yh", cg_cVector4D_get_yh, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "wh", cg_cVector4D_get_wh, MRB_ARGS_NONE()); - - mrb_define_method( - mrb, cg_cVector4D, "rg", cg_cVector4D_get_xy, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "rb", cg_cVector4D_get_xw, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "ra", cg_cVector4D_get_xh, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "gb", cg_cVector4D_get_yw, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "ga", cg_cVector4D_get_yh, MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cVector4D, "ba", cg_cVector4D_get_wh, MRB_ARGS_NONE()); - - mrb_define_method( - mrb, cg_cVector4D, "x=", cg_cVector4D_set_x, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "y=", cg_cVector4D_set_y, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "w=", cg_cVector4D_set_w, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "h=", cg_cVector4D_set_h, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "r=", cg_cVector4D_set_x, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "g=", cg_cVector4D_set_y, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "b=", cg_cVector4D_set_w, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "a=", cg_cVector4D_set_h, MRB_ARGS_REQ(1)); - - mrb_define_method( - mrb, cg_cVector4D, "set_xy", cg_cVector4D_set_xy, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_xw", cg_cVector4D_set_xw, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_xh", cg_cVector4D_set_xh, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_yw", cg_cVector4D_set_yw, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_yh", cg_cVector4D_set_yh, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_wh", cg_cVector4D_set_wh, MRB_ARGS_REQ(2)); - - mrb_define_method( - mrb, cg_cVector4D, "set_rg", cg_cVector4D_set_xy, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_rb", cg_cVector4D_set_xw, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_ra", cg_cVector4D_set_xh, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_gb", cg_cVector4D_set_yw, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_ga", cg_cVector4D_set_yh, MRB_ARGS_REQ(2)); - mrb_define_method( - mrb, cg_cVector4D, "set_ba", cg_cVector4D_set_wh, MRB_ARGS_REQ(2)); - - mrb_define_method( - mrb, cg_cVector4D, "align_vertically?", cg_cVector4D_align_vertically, - MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "align_horizontally?", - cg_cVector4D_align_horizontally, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "collide?", cg_cVector4D_collide, MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cVector4D, "draw_rectangle", cg_cVector4D_draw_rectangle, - MRB_ARGS_REQ(2)); -} diff --git a/src/vector_4d.hpp b/src/vector_4d.hpp deleted file mode 100644 index 2797d53..0000000 --- a/src/vector_4d.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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_VECTOR_4D_H -#define CANDY_GEAR_VECTOR_4D_H 1 - -#include "core.hpp" - -extern const struct mrb_data_type cg_vector_4d_type; - -void -cg_vector_4d_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_VECTOR_4D_H */ diff --git a/src/view_2d.cpp b/src/view_2d.cpp deleted file mode 100644 index 09cbac1..0000000 --- a/src/view_2d.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2022-2024 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 "view_2d.hpp" - -#include "sprite.hpp" -#include "vector_4d.hpp" -#include "view_3d.hpp" -#include "blucat/sprite.hpp" -#include "blucat/view_2d.hpp" - -void -cg_free_view_2d(mrb_state *mrb, void* obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_view_2d_type = { "CG_View2D", cg_free_view_2d }; - -static mrb_value -cg_cView2D_initialize(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *region; - mrb_float projection_width, projection_height; - std::shared_ptr *ptr; - - mrb_get_args(mrb, "dff", ®ion, &cg_vector_4d_type, - &projection_width, &projection_height); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - new(ptr)std::shared_ptr( - std::make_shared( - *region->get(), projection_width, projection_height)); - - mrb_data_init(self, ptr, &cg_view_2d_type); - return self; -} - -BluCat::View2D* -cg_cView_to_view_2d(mrb_state *mrb, mrb_value view_value) -{ - BluCat::View2D* view_2d; - const mrb_data_type *type = DATA_TYPE(view_value); - - if(type == &cg_view_2d_type) - view_2d = static_cast*>( - DATA_PTR(view_value))->get(); - else if (type == &cg_view_3d_type) - view_2d = static_cast( - static_cast*>( - 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 view_2d; -} - -void -cg_view_2d_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cView2D; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cView2D = mrb_define_class_under(mrb, cg_m, "View2D", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cView2D, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cView2D, "initialize", cg_cView2D_initialize, MRB_ARGS_REQ(3)); -} diff --git a/src/view_2d.hpp b/src/view_2d.hpp deleted file mode 100644 index a18937e..0000000 --- a/src/view_2d.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2022-2024 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_VIEW_2D_H -#define CANDY_GEAR_VIEW_2D_H 1 - -#include "core.hpp" - -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 BluCat::View2D. -BluCat::View2D* -cg_cView_to_view_2d(mrb_state *mrb, mrb_value view_value); - -void -cg_view_2d_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_VIEW_2D_H */ diff --git a/src/view_3d.cpp b/src/view_3d.cpp deleted file mode 100644 index ddaa3eb..0000000 --- a/src/view_3d.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2022-2024 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 "view_3d.hpp" - -#include "sprite.hpp" -#include "orientation_3d.hpp" -#include "vector_3d.hpp" -#include "vector_4d.hpp" -#include "blucat/sprite.hpp" -#include "blucat/view_3d.hpp" - -void -cg_free_view_3d(mrb_state *mrb, void* obj) -{ - auto ptr = static_cast*>(obj); - - ptr->~shared_ptr(); - mrb_free(mrb, ptr); -} - -const struct mrb_data_type cg_view_3d_type = { "CG_View3D", cg_free_view_3d }; - -static mrb_value -cg_cView3D_initialize(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *region; - mrb_float projection_width, projection_height; - std::shared_ptr *ptr; - - mrb_get_args(mrb, "dff", ®ion, &cg_vector_4d_type, - &projection_width, &projection_height); - ptr = (std::shared_ptr*)DATA_PTR(self); - if(ptr) mrb_free(mrb, ptr); - ptr = (std::shared_ptr*)mrb_malloc( - mrb, sizeof(std::shared_ptr)); - - new(ptr)std::shared_ptr( - std::make_shared( - *region->get(), projection_width, projection_height)); - - mrb_data_init(self, ptr, &cg_view_3d_type); - return self; -} - -static mrb_value -cg_cView3D_set_camera_position(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *camera_position; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "d", &camera_position, &cg_vector_3d_type); - (*ptr)->camera_position = (*camera_position); - - return self; -} - -static mrb_value -cg_cView3D_set_camera_orientation(mrb_state *mrb, mrb_value self) -{ - std::shared_ptr *camera_orientation; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "d", &camera_orientation, &cg_orientation_3d_type); - (*ptr)->camera_orientation = (*camera_orientation); - - return self; -} - -static mrb_value -cg_cView3D_get_field_of_view(mrb_state *mrb, mrb_value self) -{ - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - return mrb_float_value(mrb, (*ptr)->field_of_view); - - return self; -} - -static mrb_value -cg_cView3D_set_field_of_view(mrb_state *mrb, mrb_value self) -{ - mrb_float fov; - auto ptr = (std::shared_ptr*)DATA_PTR(self); - - mrb_get_args(mrb, "f", &fov); - (*ptr)->field_of_view = fov; - - return self; -} - -void -cg_view_3d_init(mrb_state *mrb) -{ - struct RClass *cg_m, *cg_cView3D; - - cg_m = mrb_module_get(mrb, "CandyGear"); - cg_cView3D = mrb_define_class_under(mrb, cg_m, "View3D", mrb->object_class); - MRB_SET_INSTANCE_TT(cg_cView3D, MRB_TT_DATA); - mrb_define_method( - mrb, cg_cView3D, "initialize", cg_cView3D_initialize, MRB_ARGS_REQ(3)); - mrb_define_method( - mrb, cg_cView3D, "camera_position=", cg_cView3D_set_camera_position, - MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cView3D, "camera_orientation=", cg_cView3D_set_camera_orientation, - MRB_ARGS_REQ(1)); - mrb_define_method( - mrb, cg_cView3D, "field_of_view", cg_cView3D_get_field_of_view, - MRB_ARGS_NONE()); - mrb_define_method( - mrb, cg_cView3D, "field_of_view=", cg_cView3D_set_field_of_view, - MRB_ARGS_REQ(1)); -} diff --git a/src/view_3d.hpp b/src/view_3d.hpp deleted file mode 100644 index 22aa084..0000000 --- a/src/view_3d.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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_VIEW_3D_H -#define CANDY_GEAR_VIEW_3D_H 1 - -#include "core.hpp" - -extern const struct mrb_data_type cg_view_3d_type; - -void -cg_view_3d_init(mrb_state *mrb); - -#endif /* CANDY_GEAR_VIEW_3D_H */ -- cgit v1.2.3