-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathThoughts.blog
More file actions
139 lines (106 loc) · 9.33 KB
/
Thoughts.blog
File metadata and controls
139 lines (106 loc) · 9.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# 11/6
## ownership
I'm not sure about the current structure. I want Command Buffer (for example) to have a reference to the CommandPool that created it,
and I want that commandPool to have a reference to it's device, and so on, but I also want CommandPool to own that CommandBuffer.
So that when the CommandPool is destructed, so is the CommandBuffer.
My current thoughts are to make it so tha CommandBuffer has a reference to CommandPool, and so on, and then I'll come back
and make a RAII wrapper that would assign ownership. I'm not really sure if it's necessary though,
that might be more in the engine space, rather than framework space. Nothing should ever use a CommandBuffer after it's owning
CommandPool is destructed however, so I'm unsure.
## structure
I'm tempted to design the framework around a main thread, and auxilary threads. For example, a special command pool could be
designed to facilitate the render graph on the main thread, while a different specialized command pool could be designed to
support short lived work, like transfers. I'll have to see how it evolves
## thoughts
i feel like I'm creating a wrapper around a wrapper (vulkan.hpp). vulkanhpp feels completely redundant
# 11/15
## Device Specialization
One of the big things I wanted to address was logical device specialization. I don't know how I would've worded that before, but that's
where I'm at with it. Device Specialization is defined by API version, then extensions, then features. Properties are also tied to
specialization, but they're more of a result than an input. Anyways, that led me to EightWinds/DeviceSpecialization/ (the entire folder as of now).
Using EightWinds/DeviceSpecialization/DeviceSpecialization.h, the user can use template arguments of featuremanager and property manager (found in FeatureProperty.h)
and the ExtensionManager (found in ExtensionHandler.h) to specialize the device AT COMPILE TIME. At run time, extensions will be filtered,
and extension support can be polled at runtime. The main purpose of this, overall, is that an engine/application
can specialize the device without a large amount of handwritten code, and without cracking open the framework. This amount of templates is
going to harm compile time, but with a bit of effort, an engine should be able to mask DeviceSpecialization.
## Device Scoring
This isn't finalized yet. But the idea is that each vulkan struct (im planning on separately scoring extensions) can be scored
in a method similar to std::hash. https://github.com/GDBobby/VulkanFramework/blob/086ad9375f5c60279580fad8696a5b4c5a50a119/include/EightWinds/Helpers/DeviceScoring.h#L76C1-L82C7
Using this function, a default scoring method can be provided, and the plan is, the default can be easily overridden by an end-user
that might want to prefer different options. But ideally, this would be publicly sourced and people more knowledgeable than me could
help with default values.
## fully optional
I want the provided device specialization and device scoring to be fully customizable and optional. It would be a shame
if someone was like "yeah I like everythign in here, except this one part" and that one part makes the entire thing unusable.
I've been there with a few libs.
## thoughts
it's coming to a close, basically all I need now is pipelines. i'm having a big issue, in that I want the user to fully specialize the device, but
i need to be able to access at least a few properties from within the framework. that would be uniform buffer minimum alignment and so on.
## 11/15
i'm curious if hooking (runtime assembly manipulation) would be the most optimal optimization route for extension branching. Only 1 direction will be taken in the branch
for the entire runtime. So, my hypothesis is not branching at all, just inject the correct path.
## 11/21
it's pretty much all there. i'm not sure if i have the patience to complete the render graph before i get the first triangle render or not.
it wouldn't take long to just get the triangle on screen, but it won't be very productive, give nthat i'll have to just go back and erase all
of the temp code, and replace it with healthy longer term systems. i've never done a render graph before, BUT, i recently watched a Vulkanized
video talking about optimizing rendergraphs down to the spirv level. seems exciting, i probably won't be that ambitious, BUT, i'd like to keep
that in mind.
the goal I have right now, i'd like to be able to compile a level based engine's rendergraph. basically, i'll have a small area (probably less than 100m, up to 1km-ish)
and a number of resources (descriptors, buffers, images) to make that happen. The idea, is these resources are tied to the lifetime of this level, nothing more nothing less.
POTENTIALLY, a certain type of entity could have a more precise scope than the entire level, and have resources tied to it, but the level comes first. levels MAY be transferable
to chunks in an open world game, idk.
ANYWAYS, the plan is to register commands to a framework-level command buffer, as opposed to directly recording to VkCommandBuffer. It'll be a bit
similar to global state tracking, if a draw is commanded, it'll check the command binded descriptors, which will give information on their required
buffers and images, along with the status, read or write. Given that, I can then set a priority, probably just setting what the task needs to be done
before which other task (with the final task being a submit).
I'm not too sure how to give the buffers/images meaningful IDs that don't also require hashmaps for some kind of lookup, but I'll have to crack that
egg when I get to it.
## 11/22
im not confident in any particular direction, so i'm planning a bit more than usual, and moving significantly slower lol. i think building an intricate
series of commands is the way to go. I suspect it'll be transferable to GPU work graphs (not that either of my cards support that, or probably ever will)
but anyways, real talk, the plan is to have three functions now as opposed to two.
PREVIOUSLY, i had Logic() and Render(), now I want to add RecordRender() and I want to change the old Render() to ExecuteRender()
the concept will be in today's push,
RecordRender -
DetailedCommandBuffer will store commands, and it will attach a boolean to some amount of commands. this boolean is a pointer, and
in ExecuteRender, the value of the boolean for that frame is determined, deciding if that group of commands will be executed or not.
ExecuteRender -
This is going to be similar to the old Render(), but instead of dealing with direct vulkan commands, it'll just deal with booleans that
were defined in the recording. Other data will be updated here, like buffer content, and whatever.
## 11/25
ive kinda just been staring at the command containers just trying to figure out how I want to do them for
the last few days. i think having a global push constant structure, and making it required to be uniform across
all pipelines will make the compilation of the command record much simpler. i think that will make it possible for
compile time optimization
## 12/2
instead of doing each command explicitly, i need the object to "just draw". some background process should
handle the explicit expansion of each draw command. the pass has it's config, and each object has it's own config
that will combine to create the pipelines and such. i think that will be a render graph builder. idk. the more i think
about it the more vague it becomes.
## 12/4
im tmepted to completely remove blits. it forces a bit of separate handling compared to the push constants,
which leads to a bit more complexity in GPUTask. and i don't think it has any benefits beyond an explicit
compute shader copy.
also, i don't really know how I want to handle barrier generation. im tempted to make explicit vectors of read and write
resources, but i don't know
if i can put a semaphore in between each task, maybe an 'event' in between same command buffer renders, i can narrow the cross reference to writes on the left side only.
i could separate task into
* read only graphics task
* read/write graphics tasks (most likely mesh shaders and blits)
* read/write compute task
* write only transfer task
the question is, how would specifying that a task is read/write as opposed to read only simplify the logic? or would it complicate it? that would probably be a flag for the rendergraph,
to prevent a bridge being created between that task and whatever follows.
i could have typign on the resources as well, that specifies wether it's expecting to be written to or not.
i decided to go with adding the layout to resource. now any usage of a image needs to declare the layout it wants,
which will then be interpreted by TaskBridge when the barriers are generated
## 12/15
I think GPUTask should be changed. From the current TaskBridge system, to a Prefix, Body, and Suffix system.
Prefix will replace TaskBridge, basically a rename. Suffix will be used to facilitate queue ownership transfers.
I don't think Submission Task will be need Prefix and Suffix, but they might use a Header and Footer GPUTask for inserting barriers for queue transfers.
## 2/5/2026
i can use imgui and the param pool to edit the command buffer params without any other context
## 2/10/2026
i think i can change the parampool a bit. it's a bit like an array at the moment,
where if i wasnt to resize it i basically need to recreate it.
i think i can make it more like my hive implementation, in which i just chain static parts