89 lines
4 KiB
C++
89 lines
4 KiB
C++
/*
|
|
Crafter®.Graphics
|
|
Copyright (C) 2026 Catcrafts®
|
|
catcrafts.net
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License version 3.0 as published by the Free Software Foundation;
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
module;
|
|
#ifndef CRAFTER_GRAPHICS_WINDOW_DOM
|
|
#include "vulkan/vulkan.h"
|
|
#endif // !CRAFTER_GRAPHICS_WINDOW_DOM
|
|
export module Crafter.Graphics:RenderingElement3D;
|
|
#ifndef CRAFTER_GRAPHICS_WINDOW_DOM
|
|
import std;
|
|
import :Mesh;
|
|
import :VulkanBuffer;
|
|
import Crafter.Math;
|
|
import :Window;
|
|
|
|
export namespace Crafter {
|
|
struct TlasWithBuffer {
|
|
VkDeviceAddress address = 0;
|
|
VulkanBuffer<char, false> buffer;
|
|
VkAccelerationStructureKHR accelerationStructure = VK_NULL_HANDLE;
|
|
VulkanBuffer<VkAccelerationStructureInstanceKHR, true> instanceBuffer;
|
|
VulkanBuffer<char, false> scratchBuffer;
|
|
// Parallel to instanceBuffer, indexed by TLAS instance ID. Filled
|
|
// from each element's userMetadata during BuildTLAS. Consumers
|
|
// (e.g. ray-query collision) bind this in the descriptor heap and
|
|
// look up via rayQueryGetIntersectionInstanceIdEXT to recover
|
|
// application-side per-instance data without touching the
|
|
// Vulkan-mandated instanceCustomIndex (which renderers may already
|
|
// use for their own encoding).
|
|
VulkanBuffer<std::uint32_t, true> metadataBuffer;
|
|
// Last instance count this TLAS was built (not refit) for. When
|
|
// elements.size() matches this, BuildTLAS does an in-place refit
|
|
// (UPDATE mode) which is dramatically cheaper than a full rebuild
|
|
// — refit walks the existing BVH and updates AABBs, while rebuild
|
|
// reconstructs the topology from scratch. A change in count forces
|
|
// a fresh rebuild because the AS is sized for that primitive count.
|
|
std::uint32_t builtInstanceCount = 0;
|
|
};
|
|
|
|
class RenderingElement3D {
|
|
public:
|
|
VkAccelerationStructureInstanceKHR instance;
|
|
// Position in `elements`, maintained by Add/Remove for O(1) swap-and-pop.
|
|
// Sentinel value = not currently registered.
|
|
std::uint32_t indexInElements = std::numeric_limits<std::uint32_t>::max();
|
|
// Application-defined per-instance tag, copied verbatim into
|
|
// tlases[*].metadataBuffer at this element's TLAS instance ID
|
|
// every BuildTLAS. Crafter doesn't interpret it.
|
|
std::uint32_t userMetadata = 0;
|
|
// When true, BuildTLAS skips copying instance.transform into the
|
|
// TLAS instance buffer — the application's compute shader writes
|
|
// the transform field directly into instanceBuffer at this
|
|
// element's TLAS instance ID. Other instance fields (mask,
|
|
// customIndex, SBT offset, BLAS reference) are still copied from
|
|
// the CPU instance struct.
|
|
//
|
|
// Used to take per-frame transform updates off the CPU for bodies
|
|
// whose transforms derive from GPU-side state (physics nodes that
|
|
// already live on the GPU).
|
|
bool transformOwnedByGpu = false;
|
|
|
|
static std::vector<RenderingElement3D*> elements;
|
|
inline static TlasWithBuffer tlases[Window::numFrames];
|
|
static void BuildTLAS(VkCommandBuffer cmd, std::uint32_t index);
|
|
|
|
// Register / unregister with `elements`. Use these instead of touching
|
|
// the vector directly: linear find+erase is O(n) and pathological at
|
|
// the body counts physics targets (millions of braces).
|
|
static void Add(RenderingElement3D* e);
|
|
static void Remove(RenderingElement3D* e);
|
|
};
|
|
}
|
|
#endif // !CRAFTER_GRAPHICS_WINDOW_DOM
|