Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
MeshGPUResources.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "MeshRuntime.hpp"
4
5#include <SDL3/SDL_gpu.h>
6
7#include <cstddef>
8#include <cstdint>
9#include <expected>
10#include <memory>
11#include <span>
12#include <string>
13#include <unordered_map>
14#include <vector>
15
16namespace monopoly::engine
17{
19 {
20 float position[3]{};
21 float normal[3]{};
22 float uv[2]{};
23 float tangent[4]{};
24 };
25
27 {
28 std::vector<MeshGPUVertex> vertices;
29 std::vector<std::uint32_t> indices;
30 std::uint32_t vertexBytes{};
31 std::uint32_t indexBytes{};
32 std::uint32_t transferBytes{};
33 };
34
58
60 {
62 std::string detail;
63 };
64
65 [[nodiscard]] std::expected<MeshGPUUploadPlan, MeshGPUError>
67
69 {
70 std::uint64_t key{};
72 std::uint32_t width{};
73 std::uint32_t height{};
74 std::shared_ptr<const data::HmdTextureImage> source;
75 };
76
78 {
79 std::uint64_t key{};
82 std::uint32_t vertexCount{};
83 std::shared_ptr<const data::MeshRuntimeAsset> sourceAsset;
84 std::shared_ptr<const data::MeshRenderData> sourceRenderData;
85 };
86
94
96 {
100 std::uint32_t vertexCount{};
101 std::uint32_t indexCount{};
102 std::unordered_map<std::uint64_t, MeshGPUTextureResource> textures;
103 std::shared_ptr<const data::MeshRuntimeAsset> source;
104 std::vector<MeshGPUModernTextureResource> modernTextures;
105 std::uint64_t lastResolvedOrder{};
107 const data::ModernTextureBinding& binding) const noexcept
108 {
109 for (const auto& resource : modernTextures)
110 if (resource.source.image == binding.image &&
111 resource.source.colorSpace == binding.colorSpace &&
112 resource.source.sampler == binding.sampler)
113 return &resource;
114 return nullptr;
115 }
116
117 [[nodiscard]] SDL_GPUTexture* texture(std::uint64_t key) const noexcept
118 {
119 const auto found = textures.find(key);
120 return found == textures.end() ? nullptr : found->second.texture;
121 }
122 };
123
124 // SDL_GPU upload cache. It owns geometry, HMD textures and modern
125 // color-space/sampler-specific textures exclusively. Clear it before device destruction.
126 // Replacing the same DataId with a different immutable CPU asset uploads
127 // the whole replacement first, then swaps ownership transactionally.
129 {
130 public:
131 explicit MeshGPUCache(SDL_GPUDevice* device) noexcept;
133 MeshGPUCache(const MeshGPUCache&) = delete;
137
138 [[nodiscard]] std::expected<const MeshGPUResource*, MeshGPUError>
139 resolve(std::shared_ptr<const data::MeshRuntimeAsset> asset);
140 // Scene batches retain raw SDL handles until commands are recorded.
141 // Distinct immutable assets sharing a DATA id must coexist meanwhile.
142 [[nodiscard]] std::expected<const MeshGPUResource*, MeshGPUError>
143 resolveForScene(std::shared_ptr<const data::MeshRuntimeAsset> asset);
144 [[nodiscard]] const MeshGPUResource* find(data::DataId id) const noexcept;
145 [[nodiscard]] std::size_t size() const noexcept;
148 std::shared_ptr<const data::MeshRuntimeAsset> asset,
149 std::shared_ptr<const data::MeshRenderData> renderData);
152 [[nodiscard]] std::size_t dynamicSize() const noexcept;
154 // Keep every live scene asset, including offscreen/shared instances.
155 // SDL defers GPU destruction until submitted commands no longer use it.
156 void prune(std::span<const data::DataId> activeIds) noexcept;
157 void pruneAssets(std::span<const data::MeshRuntimeAsset* const> activeAssets) noexcept;
158 // Explicit current-board/static-decoration identities only. Temporary
159 // empty scenes may retain these uploads; dynamic vertices still retire.
160 // Invalid/oversized input clears retention and returns false. Dropped
161 // pins are released on the next ordinary prune (or erase/clear).
164 std::vector<std::shared_ptr<const data::MeshRuntimeAsset>> assets) noexcept;
165 void erase(data::DataId id) noexcept;
166 void clear() noexcept;
167 [[nodiscard]] SDL_GPUDevice* device() const noexcept { return device_; }
168
169 private:
170 void release(MeshGPUResource& resource) noexcept;
171 void release(MeshGPUDynamicVertexResource& resource) noexcept;
172 void eraseDynamicForDataId(data::DataId id) noexcept;
173 void eraseDynamicForAsset(const data::MeshRuntimeAsset* asset) noexcept;
174 void eraseOtherAssets(data::DataId id, const data::MeshRuntimeAsset* retained) noexcept;
175 [[nodiscard]] bool retainsStaticAsset(const data::MeshRuntimeAsset* asset) const noexcept;
176 [[nodiscard]] std::expected<const MeshGPUResource*, MeshGPUError>
177 resolveImpl(std::shared_ptr<const data::MeshRuntimeAsset> asset, bool coexist);
178 SDL_GPUDevice* device_{};
179 std::unordered_map<const data::MeshRuntimeAsset*, MeshGPUResource> resources_;
180 std::uint64_t resolvedOrder_{};
181 std::unordered_map<std::uint64_t, MeshGPUDynamicVertexResource> dynamicVertices_;
182 std::vector<std::shared_ptr<const data::MeshRuntimeAsset>> retainedStaticAssets_;
183 };
184}
std::uint64_t key
unsigned index
bool retainStaticAssets(std::vector< std::shared_ptr< const data::MeshRuntimeAsset > > assets) noexcept
MeshGPUCache(const MeshGPUCache &)=delete
MeshGPUCache & operator=(MeshGPUCache &&)=delete
SDL_GPUDevice * device() const noexcept
std::size_t size() const noexcept
const MeshGPUDynamicVertexResource * findDynamic(std::uint64_t key) const noexcept
void erase(data::DataId id) noexcept
const MeshGPUResource * find(data::DataId id) const noexcept
std::expected< const MeshGPUDynamicVertexResource *, MeshGPUError > resolveDynamicVertices(std::uint64_t key, std::shared_ptr< const data::MeshRuntimeAsset > asset, std::shared_ptr< const data::MeshRenderData > renderData)
void prune(std::span< const data::DataId > activeIds) noexcept
MeshGPUCache(MeshGPUCache &&)=delete
void pruneAssets(std::span< const data::MeshRuntimeAsset *const > activeAssets) noexcept
void pruneDynamicVertices(std::span< const std::uint64_t > activeKeys) noexcept
std::expected< const MeshGPUResource *, MeshGPUError > resolveForScene(std::shared_ptr< const data::MeshRuntimeAsset > asset)
static constexpr std::size_t MaximumRetainedStaticAssets
std::expected< const MeshGPUResource *, MeshGPUError > resolve(std::shared_ptr< const data::MeshRuntimeAsset > asset)
std::size_t dynamicSize() const noexcept
MeshGPUCache & operator=(const MeshGPUCache &)=delete
std::uint32_t DataId
Definition DataBanks.hpp:10
std::expected< MeshGPUUploadPlan, MeshGPUError > makeMeshGPUUploadPlan(const data::MeshRenderData &renderData)
std::shared_ptr< const data::MeshRenderData > sourceRenderData
std::shared_ptr< const data::MeshRuntimeAsset > sourceAsset
std::vector< MeshGPUModernTextureResource > modernTextures
std::shared_ptr< const data::MeshRuntimeAsset > source
std::unordered_map< std::uint64_t, MeshGPUTextureResource > textures
const MeshGPUModernTextureResource * modernTexture(const data::ModernTextureBinding &binding) const noexcept
SDL_GPUTexture * texture(std::uint64_t key) const noexcept
std::shared_ptr< const data::HmdTextureImage > source
std::vector< MeshGPUVertex > vertices
std::vector< std::uint32_t > indices