mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-27 23:27:29 +01:00
168 lines
7.4 KiB
C++
168 lines
7.4 KiB
C++
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
// the ray traced reflections of the vulkan renderer (gfx.raytracing, on a gpu with ray queries): what the screen space reflections
|
|
// don't find is traced through the scenery around the camera (shaders/vk14/rt_reflections.glsl).
|
|
//
|
|
// the renderer walks the scene for it once a frame (the walk in its reflection mode, gathering the draws instead of making them) and
|
|
// hands the draws over: each chunk of geometry gets a bottom level acceleration structure of its own the first time it's met (a few
|
|
// of them a frame, the rest wait for the next ones; made anew when its data changes, let go when it isn't met for a while), each draw
|
|
// an instance of the top level structure of the frame with a record the shading reads (where its vertices are, the texture and the
|
|
// colour of its material). each frame in flight has its own top level structure, buffers and set of the pipelines of the scene (set
|
|
// RT_SET), written while the frame is made: the gpu is done with the frame which used them before
|
|
|
|
#pragma once
|
|
|
|
#include "rendering/vulkan14/vulkan14memory.h"
|
|
#include "rendering/vulkan14/vulkan14geometry.h"
|
|
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace vk14
|
|
{
|
|
|
|
class device;
|
|
class command_stream;
|
|
class image_table;
|
|
|
|
// a draw of the walk for the ray tracing: what an instance of the top level structure is made of
|
|
struct ray_draw
|
|
{
|
|
glm::mat4 transform{1.f}; // the vertices of the chunk to the world around the camera (the axes of the world, the camera at the origin)
|
|
std::uint64_t key{0}; // the chunk, gfx::geometry_handle
|
|
chunk_source source; // where its data is
|
|
std::uint64_t texture{0}; // the id of the diffuse texture in the image table, 0: none
|
|
glm::vec3 colour{1.f}; // the diffuse colour of the material, linear
|
|
float cutoff{0.f}; // the alpha test of the texture, 0: none
|
|
float glow{0.f}; // the light of its own
|
|
// a chunk of the heightmap terrain: its weights (two maps of four layers), its table of the layers (the ids of the images) and
|
|
// the texture array of the diffuse maps of the layers, shared by the chunks; placement: param[2] of its material
|
|
std::uint64_t terrain_weights[2]{0, 0};
|
|
std::uint64_t terrain_table{0};
|
|
std::uint64_t terrain_layers{0};
|
|
glm::vec4 placement{0.f};
|
|
};
|
|
|
|
class ray_tracing
|
|
{
|
|
public:
|
|
ray_tracing() = default;
|
|
ray_tracing(ray_tracing const &) = delete;
|
|
ray_tracing &operator=(ray_tracing const &) = delete;
|
|
~ray_tracing();
|
|
|
|
// Frames: the frames in flight
|
|
bool init(device const &Device, allocator &Memory, deletion_queue &Deletions, std::uint32_t Frames, std::string &Reason);
|
|
// the texture of the records without one (index 0 of the array), before the first frame
|
|
void set_white(VkImageView View, VkSampler Sampler)
|
|
{
|
|
m_white = View;
|
|
m_whitesampler = Sampler;
|
|
}
|
|
void destroy();
|
|
bool ready() const
|
|
{
|
|
return m_layout != VK_NULL_HANDLE;
|
|
}
|
|
// the layout of the set of the pipelines of the scene
|
|
VkDescriptorSetLayout layout() const
|
|
{
|
|
return m_layout;
|
|
}
|
|
// the frame Slot begins (its frame before is done on the gpu): the set of the slot gets an empty structure the first time, so the
|
|
// shaders always have one to read. Value: of the timeline, when the gpu is done with the frame
|
|
void begin_frame(command_stream *Commands, std::uint32_t Slot, std::uint64_t Value);
|
|
// the scenery of the frame: the bottom level structures of the draws which aren't there yet (as many as a frame lets), the top
|
|
// level structure with the instances of the draws, their records and textures written to the set of the frame. outside of a
|
|
// rendering, before the passes which trace the rays
|
|
void build(command_stream *Commands, std::uint32_t Slot, std::uint64_t Value, std::uint64_t Frame, std::vector<ray_draw> const &Draws, image_table const &Images);
|
|
// the set of the frame
|
|
VkDescriptorSet set(std::uint32_t Slot) const
|
|
{
|
|
return (Slot < m_frames.size() ? m_frames[Slot].set : VK_NULL_HANDLE);
|
|
}
|
|
// a scenery is being loaded, or the geometry is gone: the bottom level structures go
|
|
void clear(std::uint64_t Value);
|
|
// for the debug panel: the structures, their memory, the instances of the last frame
|
|
std::string info() const;
|
|
|
|
private:
|
|
struct bottom
|
|
{
|
|
std::shared_ptr<buffer> storage;
|
|
VkAccelerationStructureKHR handle{VK_NULL_HANDLE};
|
|
VkDeviceAddress address{0};
|
|
std::uint64_t generation{0}; // of the data of the chunk it was built from
|
|
std::uint64_t used{0}; // the frame it was last met in
|
|
VkDeviceSize bytes{0};
|
|
// the triangles of a strip or a fan, which the structure is built from and the shading reads
|
|
std::shared_ptr<buffer> indices;
|
|
VkDeviceAddress index_address{0};
|
|
};
|
|
struct frame_data
|
|
{
|
|
VkDescriptorSet set{VK_NULL_HANDLE};
|
|
// the top level structure, its memory and the instances it's built from, the records of the shading, the scratch of the builds
|
|
std::shared_ptr<buffer> storage;
|
|
VkAccelerationStructureKHR top{VK_NULL_HANDLE};
|
|
std::uint32_t top_capacity{0}; // instances
|
|
VkDeviceSize top_scratch{0}; // what a build of the structure needs of the scratch, with the alignment
|
|
std::shared_ptr<buffer> instances;
|
|
std::shared_ptr<buffer> records;
|
|
std::shared_ptr<buffer> scratch;
|
|
// what the set holds: the structure, the records, and the textures by their index
|
|
VkAccelerationStructureKHR written_top{VK_NULL_HANDLE};
|
|
VkBuffer written_records{VK_NULL_HANDLE};
|
|
struct written_texture
|
|
{
|
|
VkImageView view{VK_NULL_HANDLE};
|
|
VkSampler sampler{VK_NULL_HANDLE};
|
|
std::weak_ptr<image> source; // a view made after this one is gone can get its handle
|
|
};
|
|
std::vector<written_texture> written_textures;
|
|
written_texture written_terrain;
|
|
};
|
|
|
|
// a buffer of the frame at least Size bytes, grown when it isn't (the old one stays when the new one can't be made)
|
|
bool ensure(std::shared_ptr<buffer> &Buffer, VkDeviceSize Size, VkBufferUsageFlags Usage, memory_kind Kind, char const *Name, std::uint64_t Value);
|
|
// the top level structure of the frame for Count instances, recorded to Commands; false: no memory
|
|
bool build_top(command_stream *Commands, frame_data &Frame, std::uint32_t Count, std::uint64_t Value);
|
|
// the index of a texture in the array of the set, 0: none (white, or no room)
|
|
std::uint32_t texture_index(std::uint64_t Id, std::uint64_t Frame);
|
|
VkDeviceAddress aligned_scratch(frame_data const &Frame) const;
|
|
|
|
device const *m_device{nullptr};
|
|
allocator *m_memory{nullptr};
|
|
deletion_queue *m_deletions{nullptr};
|
|
VkDescriptorSetLayout m_layout{VK_NULL_HANDLE};
|
|
VkDescriptorPool m_pool{VK_NULL_HANDLE};
|
|
VkImageView m_white{VK_NULL_HANDLE};
|
|
VkSampler m_whitesampler{VK_NULL_HANDLE};
|
|
std::uint32_t m_texturecount{0};
|
|
std::uint32_t m_scratchalignment{256};
|
|
std::vector<frame_data> m_frames;
|
|
std::unordered_map<std::uint64_t, bottom> m_bottoms; // by the chunk
|
|
VkDeviceSize m_bottombytes{0};
|
|
// the indices of the textures in the array: by the id of the image, the image of each index and the frame it was last used in
|
|
std::unordered_map<std::uint64_t, std::uint32_t> m_textureindices;
|
|
std::vector<std::uint64_t> m_textureowners;
|
|
std::vector<std::uint64_t> m_textureused;
|
|
std::vector<std::uint32_t> m_freetextures;
|
|
// what the last frame had, for the panel
|
|
std::uint32_t m_lastinstances{0};
|
|
std::uint32_t m_lastrecords{0};
|
|
std::uint32_t m_lastbuilt{0};
|
|
std::uint32_t m_lastwaiting{0};
|
|
std::uint32_t m_lasttextures{0};
|
|
};
|
|
|
|
} // namespace vk14
|