Files
tanks-reborn/source/render/renderer.cpp

138 lines
4.7 KiB
C++

#include "renderer.hpp"
#include "ui/display.hpp"
#include "vuk/ImageAttachment.hpp"
#include "vuk/RenderGraph.hpp"
#include "vuk/Types.hpp"
#include "vuk/Value.hpp"
#include "vuk/runtime/CommandBuffer.hpp"
#include "vuk/runtime/vk/Allocator.hpp"
#include "vuk/runtime/vk/AllocatorHelpers.hpp"
#include "vuk/runtime/vk/DeviceFrameResource.hpp"
#include "vuk/runtime/vk/Image.hpp"
#include "vuk/runtime/vk/VkRuntime.hpp"
#include "vuk/vsl/Core.hpp"
#include <cstdint>
#include <vuk/runtime/vk/Pipeline.hpp>
#include <vuk/runtime/vk/PipelineTypes.hpp>
#include <vuk/vsl/BindlessArray.hpp>
#include <glm/glm.hpp>
#include <span>
#include <string_view>
namespace trb::render {
std::uint32_t renderer::next_mesh_id() {
// Is there someway to do this with a do while?
auto generated_id = id_dist(rng);
while (registered_meshes.contains(generated_id)) [[unlikely]] {
generated_id = id_dist(rng);
}
return generated_id;
}
vuk::PipelineBaseCreateInfo
renderer::create_compute_pipeline(std::string_view comp_module,
std::string_view comp_entry) {
const auto comp_bytes = compiler.compile(comp_module, comp_entry);
auto pipeline_info = vuk::PipelineBaseCreateInfo();
pipeline_info.add_spirv(comp_bytes, comp_module.data(), comp_entry.data());
return pipeline_info;
}
vuk::PipelineBaseCreateInfo renderer::create_graphics_pipeline(
std::string_view vs_module, std::string_view vs_entry,
std::string_view fs_module, std::string_view fs_entry) {
const auto vs_bytes = compiler.compile(vs_module, vs_entry);
const auto fs_bytes = compiler.compile(fs_module, fs_entry);
auto pipeline_info = vuk::PipelineBaseCreateInfo();
pipeline_info.add_spirv(vs_bytes, vs_module.data(), vs_entry.data());
pipeline_info.add_spirv(fs_bytes, fs_module.data(), fs_entry.data());
return pipeline_info;
}
vuk::PipelineBaseCreateInfo
renderer::create_graphics_pipeline(std::string_view module_name) {
return create_graphics_pipeline(module_name, "vert_main", module_name,
"frag_main");
}
void renderer::create_pipelines() {}
vuk::Value<vuk::ImageAttachment> renderer::get_swap_target() {
auto imported_swapchain = vuk::acquire_swapchain(context.swapchain);
auto swapchain_image =
vuk::acquire_next_image("swp_img", std::move(imported_swapchain));
return vuk::clear_image(std::move(swapchain_image),
vuk::ClearColor{0.0f, 0.0f, 1.0f, 1.0f});
}
renderer::vuk_frame_resources renderer::get_next_frame_resources() {
auto &frame_resource = context.superframe_resource.get_next_frame();
context.runtime.next_frame();
return {
.allocator = vuk::Allocator(frame_resource),
.swap_target = get_swap_target(),
};
}
renderer::renderer(ui::display *display)
: context(display), rng(std::random_device()()) {}
void renderer::render() {
auto [frame_allocator, frame_target] = get_next_frame_resources();
auto entire_thing = vuk::enqueue_presentation(frame_target);
entire_thing.submit(frame_allocator, context.compiler);
}
std::uint32_t renderer::register_mesh(const game::mesh_node &mesh) {
const auto id = next_mesh_id();
auto [vertex_buffer, vertex_future] = vuk::create_buffer(
context.superframe_allocator, vuk::MemoryUsage::eCPUtoGPU,
vuk::DomainFlagBits::eTransferOperation, std::span(mesh.positions));
auto [index_buffer, index_future] = vuk::create_buffer(
context.superframe_allocator, vuk::MemoryUsage::eCPUtoGPU,
vuk::DomainFlagBits::eTransferOperation, std::span(mesh.indices));
const auto indirect_draw = std::array<std::uint32_t, 5>({
static_cast<std::uint32_t>(mesh.indices.size()), // index count
1, // instance count
0, // first index
0, // vertex offset (int32 technically)
0, // first instance
});
auto [indirect_buffer, indirect_future] = vuk::create_buffer(
context.superframe_allocator, vuk::MemoryUsage::eCPUtoGPU,
vuk::DomainFlagBits::eTransferOperation,
std::span<const std::uint32_t>(indirect_draw));
auto futures = std::vector<vuk::UntypedValue>();
futures.push_back(std::move(vertex_future));
futures.push_back(std::move(index_future));
futures.push_back(std::move(indirect_future));
// TODO: Make async?
vuk::wait_for_values_explicit(context.superframe_allocator, context.compiler,
std::span(futures));
registered_meshes.insert(
{id, loaded_mesh{
.vertices = std::move(vertex_buffer),
.indices = std::move(index_buffer),
.indirect_command = std::move(indirect_buffer),
}});
return id;
}
} // namespace trb::render