Skip to content

Commit b48506b

Browse files
committed
wip
1 parent aeef7f8 commit b48506b

7 files changed

Lines changed: 1096 additions & 1139 deletions

File tree

sources/RenderSystem/FrameGraph/FrameGraph.Base.ixx

Lines changed: 137 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,64 @@ import HAL;
1010
using namespace HAL;
1111

1212

13+
// Precompiled-graph structs, defined early so PipelineBase can expose them.
14+
// They only depend on ResourceID / PassID from the includes above.
15+
export namespace FrameGraph
16+
{
17+
// A pass's static declaration of one resource it touches, from the SIG
18+
// PassNode block: the resource id plus whether the pass declares [Write] on
19+
// it. Emitted per-pass as Context::resource_accesses[].
20+
struct ResourceAccess
21+
{
22+
ResourceID id;
23+
bool write;
24+
};
25+
26+
// A reference to a pass in precompiled state data: the pass type plus, for
27+
// [Multiple] passes, which instance (0 otherwise).
28+
struct PassRef
29+
{
30+
PassID id;
31+
uint32_t index;
32+
};
33+
34+
// One precomputed RW-state in a pipeline's per-resource timeline (mirrors a
35+
// runtime ResourceRWState): whether it's a write, and the passes in it.
36+
struct PrecompiledState
37+
{
38+
bool write;
39+
std::span<const PassRef> passes;
40+
};
41+
42+
// A pipeline's precomputed timeline for one resource version: the ordered
43+
// states it passes through. Emitted per-pipeline as resource_infos[]. A
44+
// recreate() produces a new chain version of the same id — chain_index
45+
// selects which ResourceAllocInfo in the resource's chain this timeline maps
46+
// to (0 = the original create). This is a template — at runtime disabled
47+
// passes are pruned and cross-pipeline timelines concatenated in add order.
48+
struct PrecompiledResourceInfo
49+
{
50+
ResourceID id;
51+
uint32_t chain_index;
52+
std::span<const PrecompiledState> states;
53+
};
54+
55+
// A precomputed pass instance in a pipeline: its type, [Multiple] instance,
56+
// queue (compute vs direct/graphics), and its prev-pass dependency edges —
57+
// derived at codegen time from the per-resource state timelines (the static
58+
// equivalent of resolve_dependencies). Emitted per-pipeline as
59+
// precompiled_passes[]. Also a template: disabled passes are pruned at
60+
// runtime and cross-pipeline edges resolved at add time.
61+
struct PrecompiledPass
62+
{
63+
PassID id;
64+
uint32_t index; // [Multiple] instance (0 otherwise)
65+
bool compute; // queue: compute if true, else direct/graphics
66+
std::span<const PassRef> prev_passes;
67+
};
68+
}
69+
70+
1371
namespace Pipelines
1472
{
1573

@@ -19,6 +77,10 @@ public:
1977
virtual ~PipelineBase() = default;
2078
virtual std::span<const wchar_t* const> GetUsedPassNamesList() const = 0;
2179
virtual std::span<const wchar_t* const> GetUsedResourcesList() const = 0;
80+
81+
// Precomputed per-resource RW-state timelines and per-pass dependency data.
82+
virtual std::span<const FrameGraph::PrecompiledResourceInfo> GetResourceInfos() const = 0;
83+
virtual std::span<const FrameGraph::PrecompiledPass> GetPrecompiledPasses() const = 0;
2284
};
2385

2486
}
@@ -62,55 +124,6 @@ public:
62124

63125
constexpr ResourceFlags WRITEABLE_FLAGS =ResourceFlags::CopyDest | ResourceFlags::UnorderedAccess | ResourceFlags::RenderTarget | ResourceFlags::DepthStencil;// | ResourceFlags::GenCPU;
64126

65-
// A pass's static declaration of one resource it touches, from the SIG
66-
// PassNode block: the resource id plus whether the pass declares [Write] on
67-
// it. Emitted per-pass as Context::resource_accesses[].
68-
struct ResourceAccess
69-
{
70-
ResourceID id;
71-
bool write;
72-
};
73-
74-
// A reference to a pass in precompiled state data: the pass type plus, for
75-
// [Multiple] passes, which instance (0 otherwise).
76-
struct PassRef
77-
{
78-
PassID id;
79-
uint32_t index;
80-
};
81-
82-
// One precomputed RW-state in a pipeline's per-resource timeline (mirrors a
83-
// runtime ResourceRWState): whether it's a write, and the passes in it.
84-
struct PrecompiledState
85-
{
86-
bool write;
87-
std::span<const PassRef> passes;
88-
};
89-
90-
// A pipeline's precomputed timeline for one resource: the ordered states it
91-
// passes through. Emitted per-pipeline as resource_infos[]. This is a
92-
// template — at runtime disabled passes are pruned and cross-pipeline
93-
// timelines concatenated in pipeline-add order.
94-
struct PrecompiledResourceInfo
95-
{
96-
ResourceID id;
97-
std::span<const PrecompiledState> states;
98-
};
99-
100-
// A precomputed pass instance in a pipeline: its type, [Multiple] instance,
101-
// queue (compute vs direct/graphics), and its prev-pass dependency edges —
102-
// derived at codegen time from the per-resource state timelines (the static
103-
// equivalent of resolve_dependencies). Emitted per-pipeline as
104-
// precompiled_passes[]. Also a template: disabled passes are pruned at
105-
// runtime and cross-pipeline edges resolved at add time.
106-
struct PrecompiledPass
107-
{
108-
PassID id;
109-
uint32_t index; // [Multiple] instance (0 otherwise)
110-
bool compute; // queue: compute if true, else direct/graphics
111-
std::span<const PassRef> prev_passes;
112-
};
113-
114127
//struct BufferDesc
115128
//{
116129
// size_t size;
@@ -205,16 +218,70 @@ public:
205218
// happen single-threaded after the setup/append phase joins.
206219
concurrent_vector<Pass*> passes;
207220

208-
concurrent_vector<Pass*> compute;
209-
concurrent_vector<Pass*> graphics;
210-
211-
212221
HAL::SubResourcesGPU merged_read_state;
213222

214223
SyncState from;
215224
SyncState to;
216225
};
217226

227+
// A resource version's RW-state timeline. Cursor-based like ResourceChain:
228+
// the state slots — and each slot's passes / merged_read_state buffers —
229+
// persist across frames. reset_frame() only rewinds the cursor and push()
230+
// reuses a slot (clearing passes keeps its storage, so reserve() is a no-op
231+
// once it's large enough), so we don't reallocate the per-state vectors
232+
// every frame. Exposes a vector-like read interface for the many consumers.
233+
struct StateTimeline
234+
{
235+
std::vector<ResourceRWState> items;
236+
size_t count = 0;
237+
238+
void reset_frame() { count = 0; }
239+
240+
bool empty() const { return count == 0; }
241+
size_t size() const { return count; }
242+
243+
ResourceRWState& operator[](size_t i) { return items[i]; }
244+
const ResourceRWState& operator[](size_t i) const { return items[i]; }
245+
ResourceRWState& front() { return items[0]; }
246+
const ResourceRWState& front() const { return items[0]; }
247+
ResourceRWState& back() { return items[count - 1]; }
248+
const ResourceRWState& back() const { return items[count - 1]; }
249+
250+
ResourceRWState* begin() { return items.data(); }
251+
ResourceRWState* end() { return items.data() + count; }
252+
const ResourceRWState* begin() const { return items.data(); }
253+
const ResourceRWState* end() const { return items.data() + count; }
254+
255+
// Append a new state, reusing a persisted slot's storage when available.
256+
ResourceRWState& push(bool write, size_t reserve_n)
257+
{
258+
if (count >= items.size())
259+
items.emplace_back();
260+
ResourceRWState& s = items[count++];
261+
s.write = write;
262+
s.passes.clear(); // keeps the concurrent_vector's storage
263+
s.passes.reserve(reserve_n); // no-op once large enough
264+
s.from.reset();
265+
s.to.reset();
266+
s.merged_read_state.subres.clear();
267+
return s;
268+
}
269+
270+
// Stable removal that keeps removed slots' storage in items for reuse.
271+
template<class Pred>
272+
void remove_if(Pred pred)
273+
{
274+
size_t w = 0;
275+
for (size_t r = 0; r < count; ++r)
276+
if (!pred(items[r]))
277+
{
278+
if (w != r) std::swap(items[w], items[r]);
279+
++w;
280+
}
281+
count = w;
282+
}
283+
};
284+
218285
struct ResourceAllocInfo
219286
{
220287
ResourceID id = ResourceID::Count;
@@ -242,8 +309,7 @@ public:
242309

243310
bool is_new = false;
244311
bool resource_just_created = true;
245-
std::vector<ResourceRWState> states;
246-
int last_writer;
312+
StateTimeline states;
247313
size_t max_passes = 0; // upper bound on passes per state, known from Pass::id assignment
248314
//compile
249315

@@ -279,7 +345,6 @@ public:
279345

280346

281347
void add_pass(Pass* pass, ResourceFlags flags);
282-
void resolve_dependencies(std::vector<std::pair<Pass*, Pass*>>& edges);
283348
void reset(size_t max_passes);
284349

285350
void remove_inactive();
@@ -518,6 +583,12 @@ public:
518583
ResourceAllocInfo& active() { return items[pos]; }
519584
const ResourceAllocInfo& active() const { return items[pos]; }
520585

586+
// Number of chain versions active this frame (0 if not created), and
587+
// direct access to a specific version. Used to map a precomputed
588+
// resource timeline's chain_index to its ResourceAllocInfo.
589+
size_t active_count() const { return created_this_frame ? pos + 1 : 0; }
590+
ResourceAllocInfo& at(size_t i) { return items[i]; }
591+
521592
auto active_span()
522593
{
523594
size_t n = std::min(pos + 1, items.size());
@@ -568,6 +639,12 @@ public:
568639
// iterate only what matters instead of rescanning all of alloc_resources.
569640
std::vector<ResourceAllocInfo*> enabled_resources;
570641

642+
// Builds each resource's RW-state timeline after all setups have run —
643+
// from the added pipelines' precomputed resource_infos (recreate chains
644+
// fall back to add_pass). Setup itself only records resource desc/flags
645+
// and what each pass touched (used.resources / used.resource_flags).
646+
void build_resource_states();
647+
571648
// Persistent pass cache, indexed by PassID (+ index for [Multiple] passes),
572649
// so library passes are reused frame to frame instead of reallocated. Only
573650
// covers add_library_pass — the raw add_pass<T>(name, ...) path has no PassID
@@ -745,9 +822,6 @@ public:
745822
SyncState sync_state_with_self;
746823

747824

748-
std::unordered_set<Pass*> prev_passes;
749-
750-
std::unordered_set<Pass*> next_passes;
751825
std::future<void> render_task;
752826
std::future<void> compile_task;
753827

@@ -972,6 +1046,10 @@ public:
9721046
void set_pipeline(Pipelines::PipelineBase* p);
9731047
Pipelines::PipelineBase* get_pipeline() const;
9741048

1049+
// All pipelines added this frame, in add order (for concatenating their
1050+
// precomputed per-resource timelines). Cleared in reset().
1051+
std::vector<Pipelines::PipelineBase*> added_pipelines;
1052+
9751053
private:
9761054
Pipelines::PipelineBase* current_pipeline = nullptr;
9771055
public:

0 commit comments

Comments
 (0)