mirror of
https://github.com/slendidev/lunar.git
synced 2025-12-16 20:19:52 +02:00
Compare commits
1 Commits
608dc583be
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 59999f211d |
@@ -23,6 +23,8 @@
|
|||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
#include <linux/input-event-codes.h>
|
#include <linux/input-event-codes.h>
|
||||||
|
|
||||||
|
#include <smath.hpp>
|
||||||
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "VulkanRenderer.h"
|
#include "VulkanRenderer.h"
|
||||||
|
|
||||||
@@ -308,7 +310,60 @@ auto Application::run() -> void
|
|||||||
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
|
||||||
m_renderer->render();
|
m_renderer->render([&](VulkanRenderer::GL &gl) {
|
||||||
|
auto view { smath::matrix_look_at(smath::Vec3 { 0.0f, 0.0f, 3.0f },
|
||||||
|
smath::Vec3 { 0.0f, 0.0f, 0.0f },
|
||||||
|
smath::Vec3 { 0.0f, 1.0f, 0.0f }, false) };
|
||||||
|
auto const draw_extent = m_renderer->draw_extent();
|
||||||
|
auto const aspect = draw_extent.height == 0
|
||||||
|
? 1.0f
|
||||||
|
: static_cast<float>(draw_extent.width)
|
||||||
|
/ static_cast<float>(draw_extent.height);
|
||||||
|
auto projection { smath::matrix_perspective(
|
||||||
|
smath::deg(70.0f), aspect, 0.1f, 10000.0f) };
|
||||||
|
projection[1][1] *= -1;
|
||||||
|
auto view_projection { projection * view };
|
||||||
|
|
||||||
|
auto rect_model { smath::scale(
|
||||||
|
smath::translate(smath::Vec3 { 0.0f, 0.0f, -5.0f }),
|
||||||
|
smath::Vec3 { 5.0f, 5.0f, 1.0f }) };
|
||||||
|
|
||||||
|
gl.set_transform(view_projection * rect_model);
|
||||||
|
|
||||||
|
gl.set_texture();
|
||||||
|
auto const &meshes { m_renderer->test_meshes() };
|
||||||
|
if (meshes.size() > 2 && !meshes[2]->surfaces.empty()) {
|
||||||
|
auto const &surface = meshes[2]->surfaces[0];
|
||||||
|
gl.draw_mesh(meshes[2]->mesh_buffers, view_projection,
|
||||||
|
surface.count, surface.start_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.set_texture(&m_renderer->white_texture());
|
||||||
|
|
||||||
|
gl.begin(VulkanRenderer::GL::GeometryKind::Quads);
|
||||||
|
|
||||||
|
gl.color(smath::Vec3 { 0.0f, 0.0f, 0.0f });
|
||||||
|
gl.uv(smath::Vec2 { 1.0f, 1.0f });
|
||||||
|
gl.vert(smath::Vec3 { 0.5f, -0.5f, 0.0f });
|
||||||
|
|
||||||
|
gl.color(smath::Vec3 { 0.5f, 0.5f, 0.5f });
|
||||||
|
gl.uv(smath::Vec2 { 1.0f, 0.0f });
|
||||||
|
gl.vert(smath::Vec3 { 0.5f, 0.5f, 0.0f });
|
||||||
|
|
||||||
|
gl.color(smath::Vec3 { 1.0f, 0.0f, 0.0f });
|
||||||
|
gl.uv(smath::Vec2 { 0.0f, 1.0f });
|
||||||
|
gl.vert(smath::Vec3 { -0.5f, -0.5f, 0.0f });
|
||||||
|
|
||||||
|
gl.color(smath::Vec3 { 0.0f, 1.0f, 0.0f });
|
||||||
|
gl.uv(smath::Vec2 { 0.0f, 0.0f });
|
||||||
|
gl.vert(smath::Vec3 { -0.5f, 0.5f, 0.0f });
|
||||||
|
|
||||||
|
gl.end();
|
||||||
|
|
||||||
|
gl.draw_rectangle({ -0.5f, 0.5f }, { 0.5f, 0.5f });
|
||||||
|
gl.draw_rectangle(
|
||||||
|
{ 0, 0.5f }, { 0.5f, 0.5f }, { Colors::TEAL, 1.0f });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
177
src/Colors.h
Normal file
177
src/Colors.h
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <smath.hpp>
|
||||||
|
|
||||||
|
namespace Lunar::Colors {
|
||||||
|
|
||||||
|
constexpr auto hex_to_vec3(uint32_t hex) -> smath::Vec3
|
||||||
|
{
|
||||||
|
return smath::Vec3 { static_cast<float>((hex >> 16) & 0xFF) / 255.0f,
|
||||||
|
static_cast<float>((hex >> 8) & 0xFF) / 255.0f,
|
||||||
|
static_cast<float>(hex & 0xFF) / 255.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr smath::Vec3 WHITE { hex_to_vec3(0xFFFFFF) };
|
||||||
|
inline constexpr smath::Vec3 SILVER { hex_to_vec3(0xC0C0C0) };
|
||||||
|
inline constexpr smath::Vec3 GRAY { hex_to_vec3(0x808080) };
|
||||||
|
inline constexpr smath::Vec3 BLACK { hex_to_vec3(0x000000) };
|
||||||
|
inline constexpr smath::Vec3 RED { hex_to_vec3(0xFF0000) };
|
||||||
|
inline constexpr smath::Vec3 MAROON { hex_to_vec3(0x800000) };
|
||||||
|
inline constexpr smath::Vec3 YELLOW { hex_to_vec3(0xFFFF00) };
|
||||||
|
inline constexpr smath::Vec3 OLIVE { hex_to_vec3(0x808000) };
|
||||||
|
inline constexpr smath::Vec3 LIME { hex_to_vec3(0x00FF00) };
|
||||||
|
inline constexpr smath::Vec3 GREEN { hex_to_vec3(0x008000) };
|
||||||
|
inline constexpr smath::Vec3 AQUA { hex_to_vec3(0x00FFFF) };
|
||||||
|
inline constexpr smath::Vec3 TEAL { hex_to_vec3(0x008080) };
|
||||||
|
inline constexpr smath::Vec3 BLUE { hex_to_vec3(0x0000FF) };
|
||||||
|
inline constexpr smath::Vec3 NAVY { hex_to_vec3(0x000080) };
|
||||||
|
inline constexpr smath::Vec3 FUCHSIA { hex_to_vec3(0xFF00FF) };
|
||||||
|
inline constexpr smath::Vec3 PURPLE { hex_to_vec3(0x800080) };
|
||||||
|
|
||||||
|
// Pink colors
|
||||||
|
inline constexpr smath::Vec3 MEDIUM_VIOLET_RED { hex_to_vec3(0xC71585) };
|
||||||
|
inline constexpr smath::Vec3 DEEP_PINK { hex_to_vec3(0xFF1493) };
|
||||||
|
inline constexpr smath::Vec3 PALE_VIOLET_RED { hex_to_vec3(0xDB7093) };
|
||||||
|
inline constexpr smath::Vec3 HOT_PINK { hex_to_vec3(0xFF69B4) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_PINK { hex_to_vec3(0xFFB6C1) };
|
||||||
|
inline constexpr smath::Vec3 PINK { hex_to_vec3(0xFFC0CB) };
|
||||||
|
|
||||||
|
// Red colors
|
||||||
|
inline constexpr smath::Vec3 DARK_RED { hex_to_vec3(0x8B0000) };
|
||||||
|
inline constexpr smath::Vec3 FIREBRICK { hex_to_vec3(0xB22222) };
|
||||||
|
inline constexpr smath::Vec3 CRIMSON { hex_to_vec3(0xDC143C) };
|
||||||
|
inline constexpr smath::Vec3 INDIAN_RED { hex_to_vec3(0xCD5C5C) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_CORAL { hex_to_vec3(0xF08080) };
|
||||||
|
inline constexpr smath::Vec3 SALMON { hex_to_vec3(0xFA8072) };
|
||||||
|
inline constexpr smath::Vec3 DARK_SALMON { hex_to_vec3(0xE9967A) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_SALMON { hex_to_vec3(0xFFA07A) };
|
||||||
|
|
||||||
|
// Orange colors
|
||||||
|
inline constexpr smath::Vec3 ORANGE_RED { hex_to_vec3(0xFF4500) };
|
||||||
|
inline constexpr smath::Vec3 TOMATO { hex_to_vec3(0xFF6347) };
|
||||||
|
inline constexpr smath::Vec3 DARK_ORANGE { hex_to_vec3(0xFF8C00) };
|
||||||
|
inline constexpr smath::Vec3 CORAL { hex_to_vec3(0xFF7F50) };
|
||||||
|
inline constexpr smath::Vec3 ORANGE { hex_to_vec3(0xFFA500) };
|
||||||
|
|
||||||
|
// Yellow colors
|
||||||
|
inline constexpr smath::Vec3 DARK_KHAKI { hex_to_vec3(0xBDB76B) };
|
||||||
|
inline constexpr smath::Vec3 GOLD { hex_to_vec3(0xFFD700) };
|
||||||
|
inline constexpr smath::Vec3 KHAKI { hex_to_vec3(0xF0E68C) };
|
||||||
|
inline constexpr smath::Vec3 PEACH_PUFF { hex_to_vec3(0xFFDAB9) };
|
||||||
|
inline constexpr smath::Vec3 PALE_GOLDENROD { hex_to_vec3(0xEEE8AA) };
|
||||||
|
inline constexpr smath::Vec3 MOCCASIN { hex_to_vec3(0xFFE4B5) };
|
||||||
|
inline constexpr smath::Vec3 PAPAYA_WHIP { hex_to_vec3(0xFFEFD5) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_GOLDENROD_YELLOW { hex_to_vec3(0xFAFAD2) };
|
||||||
|
inline constexpr smath::Vec3 LEMON_CHIFFON { hex_to_vec3(0xFFFACD) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_YELLOW { hex_to_vec3(0xFFFFE0) };
|
||||||
|
|
||||||
|
// Brown colors
|
||||||
|
inline constexpr smath::Vec3 BROWN { hex_to_vec3(0xA52A2A) };
|
||||||
|
inline constexpr smath::Vec3 SADDLE_BROWN { hex_to_vec3(0x8B4513) };
|
||||||
|
inline constexpr smath::Vec3 SIENNA { hex_to_vec3(0xA0522D) };
|
||||||
|
inline constexpr smath::Vec3 CHOCOLATE { hex_to_vec3(0xD2691E) };
|
||||||
|
inline constexpr smath::Vec3 DARK_GOLDENROD { hex_to_vec3(0xB8860B) };
|
||||||
|
inline constexpr smath::Vec3 PERU { hex_to_vec3(0xCD853F) };
|
||||||
|
inline constexpr smath::Vec3 ROSY_BROWN { hex_to_vec3(0xBC8F8F) };
|
||||||
|
inline constexpr smath::Vec3 GOLDENROD { hex_to_vec3(0xDAA520) };
|
||||||
|
inline constexpr smath::Vec3 SANDY_BROWN { hex_to_vec3(0xF4A460) };
|
||||||
|
inline constexpr smath::Vec3 TAN { hex_to_vec3(0xD2B48C) };
|
||||||
|
inline constexpr smath::Vec3 BURLYWOOD { hex_to_vec3(0xDEB887) };
|
||||||
|
inline constexpr smath::Vec3 WHEAT { hex_to_vec3(0xF5DEB3) };
|
||||||
|
inline constexpr smath::Vec3 NAVAJO_WHITE { hex_to_vec3(0xFFDEAD) };
|
||||||
|
inline constexpr smath::Vec3 BISQUE { hex_to_vec3(0xFFE4C4) };
|
||||||
|
inline constexpr smath::Vec3 BLANCHED_ALMOND { hex_to_vec3(0xFFEBCD) };
|
||||||
|
inline constexpr smath::Vec3 CORNSILK { hex_to_vec3(0xFFF8DC) };
|
||||||
|
|
||||||
|
// Purple, violet, magenta colors
|
||||||
|
inline constexpr smath::Vec3 INDIGO { hex_to_vec3(0x4B0082) };
|
||||||
|
inline constexpr smath::Vec3 DARK_MAGENTA { hex_to_vec3(0x8B008B) };
|
||||||
|
inline constexpr smath::Vec3 DARK_VIOLET { hex_to_vec3(0x9400D3) };
|
||||||
|
inline constexpr smath::Vec3 DARK_SLATE_BLUE { hex_to_vec3(0x483D8B) };
|
||||||
|
inline constexpr smath::Vec3 BLUE_VIOLET { hex_to_vec3(0x8A2BE2) };
|
||||||
|
inline constexpr smath::Vec3 DARK_ORCHID { hex_to_vec3(0x9932CC) };
|
||||||
|
inline constexpr smath::Vec3 MAGENTA { hex_to_vec3(0xFF00FF) };
|
||||||
|
inline constexpr smath::Vec3 SLATE_BLUE { hex_to_vec3(0x6A5ACD) };
|
||||||
|
inline constexpr smath::Vec3 MEDIUM_SLATE_BLUE { hex_to_vec3(0x7B68EE) };
|
||||||
|
inline constexpr smath::Vec3 MEDIUM_ORCHID { hex_to_vec3(0xBA55D3) };
|
||||||
|
inline constexpr smath::Vec3 MEDIUM_PURPLE { hex_to_vec3(0x9370DB) };
|
||||||
|
inline constexpr smath::Vec3 ORCHID { hex_to_vec3(0xDA70D6) };
|
||||||
|
inline constexpr smath::Vec3 VIOLET { hex_to_vec3(0xEE82EE) };
|
||||||
|
inline constexpr smath::Vec3 PLUM { hex_to_vec3(0xDDA0DD) };
|
||||||
|
inline constexpr smath::Vec3 THISTLE { hex_to_vec3(0xD8BFD8) };
|
||||||
|
inline constexpr smath::Vec3 LAVENDER { hex_to_vec3(0xE6E6FA) };
|
||||||
|
|
||||||
|
// Blue colors
|
||||||
|
inline constexpr smath::Vec3 MIDNIGHT_BLUE { hex_to_vec3(0x191970) };
|
||||||
|
inline constexpr smath::Vec3 DARK_BLUE { hex_to_vec3(0x00008B) };
|
||||||
|
inline constexpr smath::Vec3 MEDIUM_BLUE { hex_to_vec3(0x0000CD) };
|
||||||
|
inline constexpr smath::Vec3 ROYAL_BLUE { hex_to_vec3(0x4169E1) };
|
||||||
|
inline constexpr smath::Vec3 STEEL_BLUE { hex_to_vec3(0x4682B4) };
|
||||||
|
inline constexpr smath::Vec3 DODGER_BLUE { hex_to_vec3(0x1E90FF) };
|
||||||
|
inline constexpr smath::Vec3 DEEP_SKY_BLUE { hex_to_vec3(0x00BFFF) };
|
||||||
|
inline constexpr smath::Vec3 CORNFLOWER_BLUE { hex_to_vec3(0x6495ED) };
|
||||||
|
inline constexpr smath::Vec3 SKY_BLUE { hex_to_vec3(0x87CEEB) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_SKY_BLUE { hex_to_vec3(0x87CEFA) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_STEEL_BLUE { hex_to_vec3(0xB0C4DE) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_BLUE { hex_to_vec3(0xADD8E6) };
|
||||||
|
inline constexpr smath::Vec3 POWDER_BLUE { hex_to_vec3(0xB0E0E6) };
|
||||||
|
|
||||||
|
// Cyan colors
|
||||||
|
inline constexpr smath::Vec3 DARK_CYAN { hex_to_vec3(0x008B8B) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_SEA_GREEN { hex_to_vec3(0x20B2AA) };
|
||||||
|
inline constexpr smath::Vec3 CADET_BLUE { hex_to_vec3(0x5F9EA0) };
|
||||||
|
inline constexpr smath::Vec3 DARK_TURQUOISE { hex_to_vec3(0x00CED1) };
|
||||||
|
inline constexpr smath::Vec3 MEDIUM_TURQUOISE { hex_to_vec3(0x48D1CC) };
|
||||||
|
inline constexpr smath::Vec3 TURQUOISE { hex_to_vec3(0x40E0D0) };
|
||||||
|
inline constexpr smath::Vec3 CYAN { hex_to_vec3(0x00FFFF) };
|
||||||
|
inline constexpr smath::Vec3 AQUAMARINE { hex_to_vec3(0x7FFFD4) };
|
||||||
|
inline constexpr smath::Vec3 PALE_TURQUOISE { hex_to_vec3(0xAFEEEE) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_CYAN { hex_to_vec3(0xE0FFFF) };
|
||||||
|
|
||||||
|
// Green colors
|
||||||
|
inline constexpr smath::Vec3 DARK_GREEN { hex_to_vec3(0x006400) };
|
||||||
|
inline constexpr smath::Vec3 DARK_OLIVE_GREEN { hex_to_vec3(0x556B2F) };
|
||||||
|
inline constexpr smath::Vec3 FOREST_GREEN { hex_to_vec3(0x228B22) };
|
||||||
|
inline constexpr smath::Vec3 SEA_GREEN { hex_to_vec3(0x2E8B57) };
|
||||||
|
inline constexpr smath::Vec3 OLIVE_DRAB { hex_to_vec3(0x6B8E23) };
|
||||||
|
inline constexpr smath::Vec3 MEDIUM_SEA_GREEN { hex_to_vec3(0x3CB371) };
|
||||||
|
inline constexpr smath::Vec3 LIME_GREEN { hex_to_vec3(0x32CD32) };
|
||||||
|
inline constexpr smath::Vec3 SPRING_GREEN { hex_to_vec3(0x00FF7F) };
|
||||||
|
inline constexpr smath::Vec3 MEDIUM_SPRING_GREEN { hex_to_vec3(0x00FA9A) };
|
||||||
|
inline constexpr smath::Vec3 DARK_SEA_GREEN { hex_to_vec3(0x8FBC8F) };
|
||||||
|
inline constexpr smath::Vec3 MEDIUM_AQUAMARINE { hex_to_vec3(0x66CDAA) };
|
||||||
|
inline constexpr smath::Vec3 YELLOW_GREEN { hex_to_vec3(0x9ACD32) };
|
||||||
|
inline constexpr smath::Vec3 LAWN_GREEN { hex_to_vec3(0x7CFC00) };
|
||||||
|
inline constexpr smath::Vec3 CHARTREUSE { hex_to_vec3(0x7FFF00) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_GREEN { hex_to_vec3(0x90EE90) };
|
||||||
|
inline constexpr smath::Vec3 GREEN_YELLOW { hex_to_vec3(0xADFF2F) };
|
||||||
|
inline constexpr smath::Vec3 PALE_GREEN { hex_to_vec3(0x98FB98) };
|
||||||
|
|
||||||
|
// White colors
|
||||||
|
inline constexpr smath::Vec3 MISTY_ROSE { hex_to_vec3(0xFFE4E1) };
|
||||||
|
inline constexpr smath::Vec3 ANTIQUE_WHITE { hex_to_vec3(0xFAEBD7) };
|
||||||
|
inline constexpr smath::Vec3 LINEN { hex_to_vec3(0xFAF0E6) };
|
||||||
|
inline constexpr smath::Vec3 BEIGE { hex_to_vec3(0xF5F5DC) };
|
||||||
|
inline constexpr smath::Vec3 WHITE_SMOKE { hex_to_vec3(0xF5F5F5) };
|
||||||
|
inline constexpr smath::Vec3 LAVENDER_BLUSH { hex_to_vec3(0xFFF0F5) };
|
||||||
|
inline constexpr smath::Vec3 OLD_LACE { hex_to_vec3(0xFDF5E6) };
|
||||||
|
inline constexpr smath::Vec3 ALICE_BLUE { hex_to_vec3(0xF0F8FF) };
|
||||||
|
inline constexpr smath::Vec3 SEASHELL { hex_to_vec3(0xFFF5EE) };
|
||||||
|
inline constexpr smath::Vec3 GHOST_WHITE { hex_to_vec3(0xF8F8FF) };
|
||||||
|
inline constexpr smath::Vec3 HONEYDEW { hex_to_vec3(0xF0FFF0) };
|
||||||
|
inline constexpr smath::Vec3 FLORAL_WHITE { hex_to_vec3(0xFFFAF0) };
|
||||||
|
inline constexpr smath::Vec3 AZURE { hex_to_vec3(0xF0FFFF) };
|
||||||
|
inline constexpr smath::Vec3 MINT_CREAM { hex_to_vec3(0xF5FFFA) };
|
||||||
|
inline constexpr smath::Vec3 SNOW { hex_to_vec3(0xFFFAFA) };
|
||||||
|
inline constexpr smath::Vec3 IVORY { hex_to_vec3(0xFFFFF0) };
|
||||||
|
|
||||||
|
// Gray and black colors
|
||||||
|
inline constexpr smath::Vec3 DARK_SLATE_GRAY { hex_to_vec3(0x2F4F4F) };
|
||||||
|
inline constexpr smath::Vec3 DIM_GRAY { hex_to_vec3(0x696969) };
|
||||||
|
inline constexpr smath::Vec3 SLATE_GRAY { hex_to_vec3(0x708090) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_SLATE_GRAY { hex_to_vec3(0x778899) };
|
||||||
|
inline constexpr smath::Vec3 DARK_GRAY { hex_to_vec3(0xA9A9A9) };
|
||||||
|
inline constexpr smath::Vec3 LIGHT_GRAY { hex_to_vec3(0xD3D3D3) };
|
||||||
|
inline constexpr smath::Vec3 GAINSBORO { hex_to_vec3(0xDCDCDC) };
|
||||||
|
|
||||||
|
} // namespace Lunar::Colors
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <optional>
|
||||||
#include <print>
|
#include <print>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
@@ -24,8 +25,422 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
|||||||
|
|
||||||
namespace Lunar {
|
namespace Lunar {
|
||||||
|
|
||||||
|
VulkanRenderer::GL::GL(VulkanRenderer &renderer)
|
||||||
|
: m_renderer(renderer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::begin_drawing(vk::CommandBuffer cmd,
|
||||||
|
AllocatedImage &color_target, AllocatedImage *depth_target) -> void
|
||||||
|
{
|
||||||
|
if (m_drawing) {
|
||||||
|
end_drawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cmd = cmd;
|
||||||
|
m_color_target = &color_target;
|
||||||
|
m_depth_target = depth_target;
|
||||||
|
m_vertices.clear();
|
||||||
|
m_indices.clear();
|
||||||
|
m_inside_primitive = false;
|
||||||
|
m_drawing = true;
|
||||||
|
m_active_pipeline = &m_renderer.m_vk.mesh_pipeline;
|
||||||
|
m_transform = smath::Mat4::identity();
|
||||||
|
m_current_color = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
m_current_normal = { 0.0f, 0.0f, 1.0f };
|
||||||
|
m_current_uv = { 0.0f, 0.0f };
|
||||||
|
m_bound_texture = &m_renderer.m_vk.error_image;
|
||||||
|
|
||||||
|
auto const extent = vk::Extent2D {
|
||||||
|
m_color_target->extent.width,
|
||||||
|
m_color_target->extent.height,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto color_att { vkinit::attachment_info(m_color_target->image_view,
|
||||||
|
nullptr, vk::ImageLayout::eColorAttachmentOptimal) };
|
||||||
|
std::optional<vk::RenderingAttachmentInfo> depth_att;
|
||||||
|
if (m_depth_target) {
|
||||||
|
depth_att = vkinit::depth_attachment_info(m_depth_target->image_view,
|
||||||
|
vk::ImageLayout::eDepthAttachmentOptimal);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto render_info { vkinit::render_info(
|
||||||
|
extent, &color_att, depth_att ? &*depth_att : nullptr) };
|
||||||
|
m_cmd.beginRendering(render_info);
|
||||||
|
|
||||||
|
vk::Viewport viewport {};
|
||||||
|
viewport.x = 0.0f;
|
||||||
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = static_cast<float>(extent.width);
|
||||||
|
viewport.height = static_cast<float>(extent.height);
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
m_cmd.setViewport(0, viewport);
|
||||||
|
|
||||||
|
vk::Rect2D scissor {};
|
||||||
|
scissor.offset.x = 0;
|
||||||
|
scissor.offset.y = 0;
|
||||||
|
scissor.extent = extent;
|
||||||
|
m_cmd.setScissor(0, scissor);
|
||||||
|
|
||||||
|
bind_pipeline_if_needed();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::end_drawing() -> void
|
||||||
|
{
|
||||||
|
if (!m_drawing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_inside_primitive) {
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
|
flush();
|
||||||
|
m_cmd.endRendering();
|
||||||
|
|
||||||
|
m_cmd = nullptr;
|
||||||
|
m_color_target = nullptr;
|
||||||
|
m_depth_target = nullptr;
|
||||||
|
m_drawing = false;
|
||||||
|
m_active_pipeline = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::begin(GeometryKind kind) -> void
|
||||||
|
{
|
||||||
|
assert(m_drawing && "begin_drawing must be called first");
|
||||||
|
if (m_inside_primitive) {
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_current_kind = kind;
|
||||||
|
m_primitive_start = m_vertices.size();
|
||||||
|
m_inside_primitive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::color(smath::Vec3 const &rgb) -> void
|
||||||
|
{
|
||||||
|
m_current_color = smath::Vec4 { rgb, 1.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::color(smath::Vec4 const &rgba) -> void
|
||||||
|
{
|
||||||
|
m_current_color = rgba;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::uv(smath::Vec2 const &uv) -> void
|
||||||
|
{
|
||||||
|
m_current_uv = uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::normal(smath::Vec3 const &normal) -> void
|
||||||
|
{
|
||||||
|
m_current_normal = normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::set_texture(
|
||||||
|
std::optional<AllocatedImage const *> texture) -> void
|
||||||
|
{
|
||||||
|
assert(m_drawing && "begin_drawing must be called first");
|
||||||
|
flush();
|
||||||
|
m_bound_texture = texture.value_or(&m_renderer.m_vk.error_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::end() -> void
|
||||||
|
{
|
||||||
|
if (!m_inside_primitive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto const count = m_vertices.size() - m_primitive_start;
|
||||||
|
emit_indices(m_primitive_start, count);
|
||||||
|
m_inside_primitive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::flush() -> void
|
||||||
|
{
|
||||||
|
if (!m_drawing || m_vertices.empty() || m_indices.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto const vertex_data_size { m_vertices.size() * sizeof(Vertex) };
|
||||||
|
auto const index_data_size { m_indices.size() * sizeof(uint32_t) };
|
||||||
|
auto const staging_size { vertex_data_size + index_data_size };
|
||||||
|
|
||||||
|
auto staging = m_renderer.create_buffer(staging_size,
|
||||||
|
vk::BufferUsageFlagBits::eTransferSrc, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||||
|
|
||||||
|
void *staging_dst = staging.info.pMappedData;
|
||||||
|
bool staging_mapped_here { false };
|
||||||
|
if (!staging_dst) {
|
||||||
|
VkResult res = vmaMapMemory(
|
||||||
|
m_renderer.m_vk.allocator, staging.allocation, &staging_dst);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
staging_mapped_here = true;
|
||||||
|
}
|
||||||
|
memcpy(staging_dst, m_vertices.data(), vertex_data_size);
|
||||||
|
memcpy(reinterpret_cast<uint8_t *>(staging_dst) + vertex_data_size,
|
||||||
|
m_indices.data(), index_data_size);
|
||||||
|
if (staging_mapped_here) {
|
||||||
|
vmaUnmapMemory(m_renderer.m_vk.allocator, staging.allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto vertex_buffer { m_renderer.create_buffer(vertex_data_size,
|
||||||
|
vk::BufferUsageFlagBits::eVertexBuffer
|
||||||
|
| vk::BufferUsageFlagBits::eTransferDst
|
||||||
|
| vk::BufferUsageFlagBits::eShaderDeviceAddress,
|
||||||
|
VMA_MEMORY_USAGE_GPU_ONLY) };
|
||||||
|
auto index_buffer { m_renderer.create_buffer(index_data_size,
|
||||||
|
vk::BufferUsageFlagBits::eIndexBuffer
|
||||||
|
| vk::BufferUsageFlagBits::eTransferDst,
|
||||||
|
VMA_MEMORY_USAGE_GPU_ONLY) };
|
||||||
|
|
||||||
|
m_renderer.immediate_submit([&](vk::CommandBuffer cmd) {
|
||||||
|
vk::BufferCopy vertex_copy {};
|
||||||
|
vertex_copy.srcOffset = 0;
|
||||||
|
vertex_copy.dstOffset = 0;
|
||||||
|
vertex_copy.size = vertex_data_size;
|
||||||
|
cmd.copyBuffer(
|
||||||
|
staging.buffer, vertex_buffer.buffer, 1, &vertex_copy);
|
||||||
|
|
||||||
|
vk::BufferCopy index_copy {};
|
||||||
|
index_copy.srcOffset = vertex_data_size;
|
||||||
|
index_copy.dstOffset = 0;
|
||||||
|
index_copy.size = index_data_size;
|
||||||
|
cmd.copyBuffer(
|
||||||
|
staging.buffer, index_buffer.buffer, 1, &index_copy);
|
||||||
|
},
|
||||||
|
/*flush_frame_deletion_queue=*/false,
|
||||||
|
/*clear_frame_descriptors=*/false);
|
||||||
|
|
||||||
|
m_renderer.destroy_buffer(staging);
|
||||||
|
|
||||||
|
auto cmd { m_cmd };
|
||||||
|
|
||||||
|
bind_pipeline_if_needed();
|
||||||
|
|
||||||
|
if (m_active_pipeline == &m_renderer.m_vk.mesh_pipeline) {
|
||||||
|
auto const image_set {
|
||||||
|
m_renderer.m_vk.get_current_frame().frame_descriptors.allocate(
|
||||||
|
m_renderer.m_logger, m_renderer.m_vkb.dev.device,
|
||||||
|
m_renderer.m_vk.single_image_descriptor_layout)
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const *image
|
||||||
|
= m_bound_texture ? m_bound_texture : &m_renderer.m_vk.error_image;
|
||||||
|
DescriptorWriter()
|
||||||
|
.write_image(0, image->image_view,
|
||||||
|
m_renderer.m_vk.default_sampler_nearest.get(),
|
||||||
|
static_cast<VkImageLayout>(
|
||||||
|
vk::ImageLayout::eShaderReadOnlyOptimal),
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
|
||||||
|
.update_set(m_renderer.m_vkb.dev.device, image_set);
|
||||||
|
|
||||||
|
auto vk_image_set = vk::DescriptorSet { image_set };
|
||||||
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||||
|
m_renderer.m_vk.mesh_pipeline.get_layout(), 0, vk_image_set, {});
|
||||||
|
|
||||||
|
GPUDrawPushConstants push_constants {};
|
||||||
|
push_constants.world_matrix = m_transform;
|
||||||
|
|
||||||
|
vk::BufferDeviceAddressInfo device_address_info {};
|
||||||
|
device_address_info.buffer = vertex_buffer.buffer;
|
||||||
|
push_constants.vertex_buffer
|
||||||
|
= m_renderer.m_device.getBufferAddress(device_address_info);
|
||||||
|
|
||||||
|
cmd.pushConstants(m_renderer.m_vk.mesh_pipeline.get_layout(),
|
||||||
|
vk::ShaderStageFlagBits::eVertex, 0, sizeof(push_constants),
|
||||||
|
&push_constants);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.bindIndexBuffer(index_buffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
|
cmd.drawIndexed(static_cast<uint32_t>(m_indices.size()), 1, 0, 0, 0);
|
||||||
|
|
||||||
|
m_renderer.m_vk.get_current_frame().deletion_queue.emplace([=, this]() {
|
||||||
|
m_renderer.destroy_buffer(index_buffer);
|
||||||
|
m_renderer.destroy_buffer(vertex_buffer);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_vertices.clear();
|
||||||
|
m_indices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::use_pipeline(Pipeline &pipeline) -> void
|
||||||
|
{
|
||||||
|
if (&pipeline == m_active_pipeline) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flush();
|
||||||
|
|
||||||
|
m_active_pipeline = &pipeline;
|
||||||
|
bind_pipeline_if_needed();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::set_transform(smath::Mat4 const &transform) -> void
|
||||||
|
{
|
||||||
|
flush();
|
||||||
|
m_transform = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::draw_rectangle(
|
||||||
|
smath::Vec2 pos, smath::Vec2 size, smath::Vec4 rect_color, float rotation)
|
||||||
|
-> void
|
||||||
|
{
|
||||||
|
auto const half_size = size * 0.5f;
|
||||||
|
auto const center = pos + half_size;
|
||||||
|
|
||||||
|
auto rotate = [&](smath::Vec2 const &p) {
|
||||||
|
float const c = std::cos(rotation);
|
||||||
|
float const s = std::sin(rotation);
|
||||||
|
return smath::Vec2 { c * p.x() - s * p.y(), s * p.x() + c * p.y() };
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const br = center + rotate(smath::Vec2 { half_size.x(), -half_size.y() });
|
||||||
|
auto const tr = center + rotate(smath::Vec2 { half_size.x(), half_size.y() });
|
||||||
|
auto const bl = center + rotate(smath::Vec2 { -half_size.x(), -half_size.y() });
|
||||||
|
auto const tl = center + rotate(smath::Vec2 { -half_size.x(), half_size.y() });
|
||||||
|
|
||||||
|
begin(GeometryKind::Quads);
|
||||||
|
|
||||||
|
color(rect_color);
|
||||||
|
uv(smath::Vec2 { 1.0f, 1.0f });
|
||||||
|
vert(smath::Vec3 { br.x(), br.y(), 0.0f });
|
||||||
|
|
||||||
|
color(rect_color);
|
||||||
|
uv(smath::Vec2 { 1.0f, 0.0f });
|
||||||
|
vert(smath::Vec3 { tr.x(), tr.y(), 0.0f });
|
||||||
|
|
||||||
|
color(rect_color);
|
||||||
|
uv(smath::Vec2 { 0.0f, 1.0f });
|
||||||
|
vert(smath::Vec3 { bl.x(), bl.y(), 0.0f });
|
||||||
|
|
||||||
|
color(rect_color);
|
||||||
|
uv(smath::Vec2 { 0.0f, 0.0f });
|
||||||
|
vert(smath::Vec3 { tl.x(), tl.y(), 0.0f });
|
||||||
|
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::draw_mesh(GPUMeshBuffers const &mesh,
|
||||||
|
smath::Mat4 const &transform, uint32_t index_count, uint32_t first_index,
|
||||||
|
int32_t vertex_offset) -> void
|
||||||
|
{
|
||||||
|
assert(m_drawing && "begin_drawing must be called first");
|
||||||
|
|
||||||
|
flush();
|
||||||
|
use_pipeline(m_renderer.m_vk.mesh_pipeline);
|
||||||
|
|
||||||
|
auto const image_set {
|
||||||
|
m_renderer.m_vk.get_current_frame().frame_descriptors.allocate(
|
||||||
|
m_renderer.m_logger, m_renderer.m_vkb.dev.device,
|
||||||
|
m_renderer.m_vk.single_image_descriptor_layout)
|
||||||
|
};
|
||||||
|
auto const *image
|
||||||
|
= m_bound_texture ? m_bound_texture : &m_renderer.m_vk.error_image;
|
||||||
|
DescriptorWriter()
|
||||||
|
.write_image(0, image->image_view,
|
||||||
|
m_renderer.m_vk.default_sampler_nearest.get(),
|
||||||
|
static_cast<VkImageLayout>(vk::ImageLayout::eShaderReadOnlyOptimal),
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
|
||||||
|
.update_set(m_renderer.m_vkb.dev.device, image_set);
|
||||||
|
|
||||||
|
auto vk_image_set = vk::DescriptorSet { image_set };
|
||||||
|
m_cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||||
|
m_renderer.m_vk.mesh_pipeline.get_layout(), 0, vk_image_set, {});
|
||||||
|
|
||||||
|
GPUDrawPushConstants push_constants {};
|
||||||
|
push_constants.world_matrix = transform;
|
||||||
|
push_constants.vertex_buffer = mesh.vertex_buffer_address;
|
||||||
|
|
||||||
|
m_cmd.pushConstants(m_renderer.m_vk.mesh_pipeline.get_layout(),
|
||||||
|
vk::ShaderStageFlagBits::eVertex, 0, sizeof(push_constants),
|
||||||
|
&push_constants);
|
||||||
|
|
||||||
|
m_cmd.bindIndexBuffer(mesh.index_buffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
|
m_cmd.drawIndexed(index_count, 1, first_index, vertex_offset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::push_vertex(smath::Vec3 const &pos) -> void
|
||||||
|
{
|
||||||
|
assert(m_drawing && "begin_drawing must be called first");
|
||||||
|
|
||||||
|
Vertex v {};
|
||||||
|
v.position = pos;
|
||||||
|
v.u = m_current_uv.x();
|
||||||
|
v.v = m_current_uv.y();
|
||||||
|
v.normal = m_current_normal;
|
||||||
|
v.color = m_current_color;
|
||||||
|
|
||||||
|
m_vertices.emplace_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::emit_indices(size_t start, size_t count) -> void
|
||||||
|
{
|
||||||
|
switch (m_current_kind) {
|
||||||
|
case GeometryKind::Triangles: {
|
||||||
|
for (size_t i = 0; (i + 2) < count; i += 3) {
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 0));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 1));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 2));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeometryKind::TriangleStrip: {
|
||||||
|
if (count < 3)
|
||||||
|
break;
|
||||||
|
for (size_t i = 0; (i + 2) < count; i++) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 0));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 1));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 2));
|
||||||
|
} else {
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 1));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 0));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeometryKind::TriangleFan: {
|
||||||
|
if (count < 3)
|
||||||
|
break;
|
||||||
|
for (size_t i = 1; (i + 1) < count; i++) {
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(start + i + 1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GeometryKind::Quads: {
|
||||||
|
if (count < 4)
|
||||||
|
break;
|
||||||
|
|
||||||
|
size_t const quad_count { count / 4 };
|
||||||
|
for (size_t q = 0; q < quad_count; q++) {
|
||||||
|
size_t const base = start + q * 4;
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(base + 0));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(base + 1));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(base + 2));
|
||||||
|
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(base + 2));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(base + 1));
|
||||||
|
m_indices.emplace_back(static_cast<uint32_t>(base + 3));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::GL::bind_pipeline_if_needed() -> void
|
||||||
|
{
|
||||||
|
if (!m_drawing || !m_active_pipeline)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_cmd.bindPipeline(
|
||||||
|
vk::PipelineBindPoint::eGraphics, m_active_pipeline->get());
|
||||||
|
}
|
||||||
|
|
||||||
VulkanRenderer::VulkanRenderer(SDL_Window *window, Logger &logger)
|
VulkanRenderer::VulkanRenderer(SDL_Window *window, Logger &logger)
|
||||||
: m_window(window)
|
: gl(*this)
|
||||||
|
, m_window(window)
|
||||||
, m_logger(logger)
|
, m_logger(logger)
|
||||||
{
|
{
|
||||||
if (m_window == nullptr) {
|
if (m_window == nullptr) {
|
||||||
@@ -91,7 +506,8 @@ auto VulkanRenderer::resize(uint32_t width, uint32_t height) -> void
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::immediate_submit(
|
auto VulkanRenderer::immediate_submit(
|
||||||
std::function<void(vk::CommandBuffer cmd)> &&function) -> void
|
std::function<void(vk::CommandBuffer cmd)> &&function,
|
||||||
|
bool flush_frame_deletion_queue, bool clear_frame_descriptors) -> void
|
||||||
{
|
{
|
||||||
m_device.resetFences(m_vk.imm_fence.get());
|
m_device.resetFences(m_vk.imm_fence.get());
|
||||||
m_vk.imm_command_buffer.get().reset();
|
m_vk.imm_command_buffer.get().reset();
|
||||||
@@ -112,8 +528,13 @@ auto VulkanRenderer::immediate_submit(
|
|||||||
VK_CHECK(m_logger,
|
VK_CHECK(m_logger,
|
||||||
m_device.waitForFences(m_vk.imm_fence.get(), true, 9'999'999'999));
|
m_device.waitForFences(m_vk.imm_fence.get(), true, 9'999'999'999));
|
||||||
|
|
||||||
m_vk.get_current_frame().deletion_queue.flush();
|
if (flush_frame_deletion_queue) {
|
||||||
m_vk.get_current_frame().frame_descriptors.clear_pools(m_vkb.dev.device);
|
m_vk.get_current_frame().deletion_queue.flush();
|
||||||
|
}
|
||||||
|
if (clear_frame_descriptors) {
|
||||||
|
m_vk.get_current_frame().frame_descriptors.clear_pools(
|
||||||
|
m_vkb.dev.device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::vk_init() -> void
|
auto VulkanRenderer::vk_init() -> void
|
||||||
@@ -647,7 +1068,7 @@ auto VulkanRenderer::default_data_init() -> void
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::render() -> void
|
auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
||||||
{
|
{
|
||||||
defer(m_vk.frame_number++);
|
defer(m_vk.frame_number++);
|
||||||
|
|
||||||
@@ -698,7 +1119,11 @@ auto VulkanRenderer::render() -> void
|
|||||||
vkutil::transition_image(cmd, m_vk.depth_image.image,
|
vkutil::transition_image(cmd, m_vk.depth_image.image,
|
||||||
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthAttachmentOptimal);
|
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthAttachmentOptimal);
|
||||||
|
|
||||||
draw_geometry(cmd);
|
gl.begin_drawing(cmd, m_vk.draw_image, &m_vk.depth_image);
|
||||||
|
if (record) {
|
||||||
|
record(gl);
|
||||||
|
}
|
||||||
|
gl.end_drawing();
|
||||||
|
|
||||||
vkutil::transition_image(cmd, m_vk.draw_image.image,
|
vkutil::transition_image(cmd, m_vk.draw_image.image,
|
||||||
vk::ImageLayout::eColorAttachmentOptimal,
|
vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
@@ -767,130 +1192,6 @@ auto VulkanRenderer::draw_background(vk::CommandBuffer cmd) -> void
|
|||||||
static_cast<uint32_t>(std::ceil(m_vk.draw_extent.height / 16.0)), 1);
|
static_cast<uint32_t>(std::ceil(m_vk.draw_extent.height / 16.0)), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::draw_geometry(vk::CommandBuffer cmd) -> void
|
|
||||||
{
|
|
||||||
auto gpu_scene_data_buffer { create_buffer(sizeof(GPUSceneData),
|
|
||||||
vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_CPU_TO_GPU) };
|
|
||||||
m_vk.get_current_frame().deletion_queue.emplace(
|
|
||||||
[=, this]() { destroy_buffer(gpu_scene_data_buffer); });
|
|
||||||
|
|
||||||
VmaAllocationInfo info {};
|
|
||||||
vmaGetAllocationInfo(
|
|
||||||
m_vk.allocator, gpu_scene_data_buffer.allocation, &info);
|
|
||||||
|
|
||||||
GPUSceneData *scene_uniform_data
|
|
||||||
= reinterpret_cast<GPUSceneData *>(info.pMappedData);
|
|
||||||
if (!scene_uniform_data) {
|
|
||||||
VkResult res = vmaMapMemory(m_vk.allocator,
|
|
||||||
gpu_scene_data_buffer.allocation, (void **)&scene_uniform_data);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
}
|
|
||||||
defer({
|
|
||||||
if (info.pMappedData == nullptr) {
|
|
||||||
vmaUnmapMemory(m_vk.allocator, gpu_scene_data_buffer.allocation);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
*scene_uniform_data = m_vk.scene_data;
|
|
||||||
|
|
||||||
auto const global_desc {
|
|
||||||
m_vk.get_current_frame().frame_descriptors.allocate(
|
|
||||||
m_logger, m_vkb.dev.device, m_vk.gpu_scene_data_descriptor_layout)
|
|
||||||
};
|
|
||||||
|
|
||||||
DescriptorWriter writer;
|
|
||||||
writer.write_buffer(0, gpu_scene_data_buffer.buffer, sizeof(GPUSceneData),
|
|
||||||
0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
|
||||||
writer.update_set(m_vkb.dev.device, global_desc);
|
|
||||||
|
|
||||||
auto color_att { vkinit::attachment_info(m_vk.draw_image.image_view,
|
|
||||||
nullptr, vk::ImageLayout::eColorAttachmentOptimal) };
|
|
||||||
auto depth_att { vkinit::depth_attachment_info(m_vk.depth_image.image_view,
|
|
||||||
vk::ImageLayout::eDepthAttachmentOptimal) };
|
|
||||||
auto const render_info { vkinit::render_info(
|
|
||||||
m_vk.draw_extent, &color_att, &depth_att) };
|
|
||||||
|
|
||||||
cmd.beginRendering(render_info);
|
|
||||||
|
|
||||||
cmd.bindPipeline(
|
|
||||||
vk::PipelineBindPoint::eGraphics, m_vk.triangle_pipeline.get());
|
|
||||||
|
|
||||||
vk::Viewport viewport {};
|
|
||||||
viewport.x = 0;
|
|
||||||
viewport.y = 0;
|
|
||||||
viewport.width = static_cast<float>(m_vk.draw_extent.width);
|
|
||||||
viewport.height = static_cast<float>(m_vk.draw_extent.height);
|
|
||||||
viewport.minDepth = 0.0f;
|
|
||||||
viewport.maxDepth = 1.0f;
|
|
||||||
cmd.setViewport(0, viewport);
|
|
||||||
|
|
||||||
vk::Rect2D scissor {};
|
|
||||||
scissor.offset.x = 0;
|
|
||||||
scissor.offset.y = 0;
|
|
||||||
scissor.extent = m_vk.draw_extent;
|
|
||||||
cmd.setScissor(0, scissor);
|
|
||||||
|
|
||||||
cmd.bindPipeline(
|
|
||||||
vk::PipelineBindPoint::eGraphics, m_vk.mesh_pipeline.get());
|
|
||||||
|
|
||||||
auto const image_set { m_vk.get_current_frame().frame_descriptors.allocate(
|
|
||||||
m_logger, m_vkb.dev.device, m_vk.single_image_descriptor_layout) };
|
|
||||||
DescriptorWriter()
|
|
||||||
.write_image(0, m_vk.error_image.image_view,
|
|
||||||
m_vk.default_sampler_nearest.get(),
|
|
||||||
static_cast<VkImageLayout>(vk::ImageLayout::eShaderReadOnlyOptimal),
|
|
||||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
|
|
||||||
.update_set(m_vkb.dev.device, image_set);
|
|
||||||
|
|
||||||
auto vk_image_set = vk::DescriptorSet { image_set };
|
|
||||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
|
||||||
m_vk.mesh_pipeline.get_layout(), 0, vk_image_set, {});
|
|
||||||
|
|
||||||
auto view { smath::matrix_look_at(smath::Vec3 { 0.0f, 0.0f, 3.0f },
|
|
||||||
smath::Vec3 { 0.0f, 0.0f, 0.0f }, smath::Vec3 { 0.0f, 1.0f, 0.0f },
|
|
||||||
false) };
|
|
||||||
auto projection {
|
|
||||||
smath::matrix_perspective(smath::deg(70.0f),
|
|
||||||
static_cast<float>(m_vk.draw_extent.width)
|
|
||||||
/ static_cast<float>(m_vk.draw_extent.height),
|
|
||||||
0.1f, 10000.0f),
|
|
||||||
};
|
|
||||||
projection[1][1] *= -1;
|
|
||||||
auto view_projection { projection * view };
|
|
||||||
|
|
||||||
GPUDrawPushConstants push_constants;
|
|
||||||
auto rect_model { smath::scale(
|
|
||||||
smath::translate(smath::Vec3 { 0.0f, 0.0f, -5.0f }),
|
|
||||||
smath::Vec3 { 5.0f, 5.0f, 1.0f }) };
|
|
||||||
push_constants.world_matrix = view_projection * rect_model;
|
|
||||||
push_constants.vertex_buffer = m_vk.rectangle.vertex_buffer_address;
|
|
||||||
|
|
||||||
cmd.pushConstants(m_vk.mesh_pipeline.get_layout(),
|
|
||||||
vk::ShaderStageFlagBits::eVertex, 0, sizeof(push_constants),
|
|
||||||
&push_constants);
|
|
||||||
cmd.bindIndexBuffer(
|
|
||||||
m_vk.rectangle.index_buffer.buffer, 0, vk::IndexType::eUint32);
|
|
||||||
|
|
||||||
cmd.drawIndexed(6, 1, 0, 0, 0);
|
|
||||||
|
|
||||||
push_constants.vertex_buffer
|
|
||||||
= m_vk.test_meshes[2]->mesh_buffers.vertex_buffer_address;
|
|
||||||
|
|
||||||
auto model { smath::Mat4::identity() };
|
|
||||||
push_constants.world_matrix = view_projection * model;
|
|
||||||
|
|
||||||
cmd.pushConstants(m_vk.mesh_pipeline.get_layout(),
|
|
||||||
vk::ShaderStageFlagBits::eVertex, 0, sizeof(push_constants),
|
|
||||||
&push_constants);
|
|
||||||
cmd.bindIndexBuffer(m_vk.test_meshes[2]->mesh_buffers.index_buffer.buffer,
|
|
||||||
0, vk::IndexType::eUint32);
|
|
||||||
|
|
||||||
cmd.drawIndexed(m_vk.test_meshes[2]->surfaces[0].count, 1,
|
|
||||||
m_vk.test_meshes[2]->surfaces[0].start_index, 0, 0);
|
|
||||||
|
|
||||||
cmd.endRendering();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto VulkanRenderer::draw_imgui(
|
auto VulkanRenderer::draw_imgui(
|
||||||
vk::CommandBuffer cmd, vk::ImageView target_image_view) -> void
|
vk::CommandBuffer cmd, vk::ImageView target_image_view) -> void
|
||||||
{
|
{
|
||||||
@@ -1168,7 +1469,8 @@ auto VulkanRenderer::create_buffer(size_t alloc_size,
|
|||||||
VmaAllocationCreateInfo alloc_ci {};
|
VmaAllocationCreateInfo alloc_ci {};
|
||||||
alloc_ci.usage = memory_usage;
|
alloc_ci.usage = memory_usage;
|
||||||
alloc_ci.flags = 0;
|
alloc_ci.flags = 0;
|
||||||
if (memory_usage == VMA_MEMORY_USAGE_CPU_ONLY) {
|
if (memory_usage == VMA_MEMORY_USAGE_CPU_ONLY
|
||||||
|
|| memory_usage == VMA_MEMORY_USAGE_CPU_TO_GPU) {
|
||||||
alloc_ci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT
|
alloc_ci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT
|
||||||
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <SDL3/SDL_video.h>
|
#include <SDL3/SDL_video.h>
|
||||||
@@ -9,6 +11,7 @@
|
|||||||
#include <vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
#include "Colors.h"
|
||||||
#include "DeletionQueue.h"
|
#include "DeletionQueue.h"
|
||||||
#include "DescriptorAllocator.h"
|
#include "DescriptorAllocator.h"
|
||||||
#include "Loader.h"
|
#include "Loader.h"
|
||||||
@@ -26,19 +29,121 @@ struct GPUDrawPushConstants {
|
|||||||
constexpr unsigned FRAME_OVERLAP = 2;
|
constexpr unsigned FRAME_OVERLAP = 2;
|
||||||
|
|
||||||
struct VulkanRenderer {
|
struct VulkanRenderer {
|
||||||
|
struct GL {
|
||||||
|
enum class GeometryKind {
|
||||||
|
Triangles,
|
||||||
|
TriangleStrip,
|
||||||
|
TriangleFan,
|
||||||
|
Quads
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit GL(VulkanRenderer &renderer);
|
||||||
|
|
||||||
|
auto begin_drawing(vk::CommandBuffer cmd, AllocatedImage &color_target,
|
||||||
|
AllocatedImage *depth_target = nullptr) -> void;
|
||||||
|
auto end_drawing() -> void;
|
||||||
|
|
||||||
|
auto begin(GeometryKind kind) -> void;
|
||||||
|
template<size_t N>
|
||||||
|
auto vert(smath::Vec<N, float> const &position) -> void
|
||||||
|
{
|
||||||
|
static_assert(N == 2 || N == 3 || N == 4,
|
||||||
|
"Position must be a 2D, 3D, or 4D vec");
|
||||||
|
|
||||||
|
smath::Vec3 pos { 0.0f, 0.0f, 0.0f };
|
||||||
|
pos[0] = position[0];
|
||||||
|
pos[1] = position[1];
|
||||||
|
if constexpr (N >= 3) {
|
||||||
|
pos[2] = position[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
push_vertex(pos);
|
||||||
|
}
|
||||||
|
auto color(smath::Vec3 const &rgb) -> void;
|
||||||
|
auto color(smath::Vec4 const &rgba) -> void;
|
||||||
|
auto uv(smath::Vec2 const &uv) -> void;
|
||||||
|
auto normal(smath::Vec3 const &normal) -> void;
|
||||||
|
auto set_texture(std::optional<AllocatedImage const *> texture
|
||||||
|
= std::nullopt) -> void;
|
||||||
|
auto draw_rectangle(smath::Vec2 pos, smath::Vec2 size,
|
||||||
|
smath::Vec4 color = smath::Vec4 { Colors::WHITE, 1.0f },
|
||||||
|
float rotation = 0.0f) -> void;
|
||||||
|
auto end() -> void;
|
||||||
|
auto flush() -> void;
|
||||||
|
|
||||||
|
auto use_pipeline(Pipeline &pipeline) -> void;
|
||||||
|
auto set_transform(smath::Mat4 const &transform) -> void;
|
||||||
|
auto draw_mesh(GPUMeshBuffers const &mesh, smath::Mat4 const &transform,
|
||||||
|
uint32_t index_count, uint32_t first_index = 0,
|
||||||
|
int32_t vertex_offset = 0) -> void;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto push_vertex(smath::Vec3 const &pos) -> void;
|
||||||
|
auto emit_indices(size_t start, size_t count) -> void;
|
||||||
|
auto bind_pipeline_if_needed() -> void;
|
||||||
|
|
||||||
|
VulkanRenderer &m_renderer;
|
||||||
|
vk::CommandBuffer m_cmd {};
|
||||||
|
AllocatedImage *m_color_target { nullptr };
|
||||||
|
AllocatedImage *m_depth_target { nullptr };
|
||||||
|
GeometryKind m_current_kind { GeometryKind::Triangles };
|
||||||
|
bool m_inside_primitive { false };
|
||||||
|
bool m_drawing { false };
|
||||||
|
Pipeline *m_active_pipeline { nullptr };
|
||||||
|
smath::Mat4 m_transform { smath::Mat4::identity() };
|
||||||
|
smath::Vec4 m_current_color { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
smath::Vec3 m_current_normal { 0.0f, 0.0f, 1.0f };
|
||||||
|
smath::Vec2 m_current_uv { 0.0f, 0.0f };
|
||||||
|
AllocatedImage const *m_bound_texture { nullptr };
|
||||||
|
size_t m_primitive_start { 0 };
|
||||||
|
std::vector<Vertex> m_vertices;
|
||||||
|
std::vector<uint32_t> m_indices;
|
||||||
|
};
|
||||||
|
|
||||||
VulkanRenderer(SDL_Window *window, Logger &logger);
|
VulkanRenderer(SDL_Window *window, Logger &logger);
|
||||||
~VulkanRenderer();
|
~VulkanRenderer();
|
||||||
|
|
||||||
auto render() -> void;
|
auto render(std::function<void(GL &)> const &record = {}) -> void;
|
||||||
auto resize(uint32_t width, uint32_t height) -> void;
|
auto resize(uint32_t width, uint32_t height) -> void;
|
||||||
|
|
||||||
auto immediate_submit(std::function<void(vk::CommandBuffer cmd)> &&function)
|
auto immediate_submit(std::function<void(vk::CommandBuffer cmd)> &&function,
|
||||||
-> void;
|
bool flush_frame_deletion_queue = true,
|
||||||
|
bool clear_frame_descriptors = true) -> void;
|
||||||
auto upload_mesh(std::span<uint32_t> indices, std::span<Vertex> vertices)
|
auto upload_mesh(std::span<uint32_t> indices, std::span<Vertex> vertices)
|
||||||
-> GPUMeshBuffers;
|
-> GPUMeshBuffers;
|
||||||
|
auto rectangle_mesh() const -> GPUMeshBuffers const &
|
||||||
|
{
|
||||||
|
return m_vk.rectangle;
|
||||||
|
}
|
||||||
|
auto test_meshes() const -> std::vector<std::shared_ptr<Mesh>> const &
|
||||||
|
{
|
||||||
|
return m_vk.test_meshes;
|
||||||
|
}
|
||||||
|
auto white_texture() const -> AllocatedImage const &
|
||||||
|
{
|
||||||
|
return m_vk.white_image;
|
||||||
|
}
|
||||||
|
auto gray_texture() const -> AllocatedImage const &
|
||||||
|
{
|
||||||
|
return m_vk.gray_image;
|
||||||
|
}
|
||||||
|
auto black_texture() const -> AllocatedImage const &
|
||||||
|
{
|
||||||
|
return m_vk.black_image;
|
||||||
|
}
|
||||||
|
auto error_texture() const -> AllocatedImage const &
|
||||||
|
{
|
||||||
|
return m_vk.error_image;
|
||||||
|
}
|
||||||
|
auto draw_extent() const -> vk::Extent2D { return m_vk.draw_extent; }
|
||||||
|
auto mesh_pipeline() -> Pipeline & { return m_vk.mesh_pipeline; }
|
||||||
|
auto triangle_pipeline() -> Pipeline & { return m_vk.triangle_pipeline; }
|
||||||
|
auto gl_api() -> GL & { return gl; }
|
||||||
|
|
||||||
auto logger() const -> Logger & { return m_logger; }
|
auto logger() const -> Logger & { return m_logger; }
|
||||||
|
|
||||||
|
GL gl;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto vk_init() -> void;
|
auto vk_init() -> void;
|
||||||
auto swapchain_init() -> void;
|
auto swapchain_init() -> void;
|
||||||
@@ -53,7 +158,6 @@ private:
|
|||||||
auto default_data_init() -> void;
|
auto default_data_init() -> void;
|
||||||
|
|
||||||
auto draw_background(vk::CommandBuffer cmd) -> void;
|
auto draw_background(vk::CommandBuffer cmd) -> void;
|
||||||
auto draw_geometry(vk::CommandBuffer cmd) -> void;
|
|
||||||
auto draw_imgui(vk::CommandBuffer cmd, vk::ImageView target_image_view)
|
auto draw_imgui(vk::CommandBuffer cmd, vk::ImageView target_image_view)
|
||||||
-> void;
|
-> void;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user