Skip to content

Commit c77cbf0

Browse files
committed
Improvements from TheForge (see description)
The work was performed by collaboration of TheForge and Google. I am merely splitting it up into smaller PRs and cleaning it up. This is the most "risky" PR so far because the previous ones have been miscellaneous stuff aimed at either [improve debugging](godotengine#90993) (e.g. device lost), [improve Android experience](godotengine#96439) (add Swappy for better Frame Pacing + Pre-Transformed Swapchains for slightly better performance), or harmless [ASTC improvements](godotengine#96045) (better performance by simply toggling a feature when available). However this PR contains larger modifications aimed at improving performance or reducing memory fragmentation. With greater modifications, come greater risks of bugs or breakage. Changes introduced by this PR: TBDR GPUs (e.g. most of Android + iOS + M1 Apple) support rendering to Render Targets that are not backed by actual GPU memory (everything stays in cache). This works as long as load action isn't `LOAD`, and store action must be `DONT_CARE`. This saves VRAM (it also makes painfully obvious when a mistake introduces a performance regression). Of particular usefulness is when doing MSAA and keeping the raw MSAA content is not necessary. Some GPUs get faster when the sampler settings are hard-coded into the GLSL shaders (instead of being dynamically bound at runtime). This required changes to the GLSL shaders, PSO creation routines, Descriptor creation routines, and Descriptor binding routines. - `bool immutable_samplers_enabled = true` Setting it to false enforces the old behavior. Useful for debugging bugs and regressions. Immutable samplers requires that the samplers stay... immutable, hence this boolean is useful if the promise gets broken. We might want to turn this into a `GLOBAL_DEF` setting. Instead of creating dozen/hundreds/thousands of `VkDescriptorSet` every frame that need to be freed individually when they are no longer needed, they all get freed at once by resetting the whole pool. Once the whole pool is no longer in use by the GPU, it gets reset and its memory recycled. Descriptor sets that are created to be kept around for longer or forever (i.e. not created and freed within the same frame) **must not** use linear pools. There may be more than one pool per frame. How many pools per frame Godot ends up with depends on its capacity, and that is controlled by `rendering/rendering_device/vulkan/max_descriptors_per_pool`. - **Possible improvement for later:** It should be possible for Godot to adapt to how many descriptors per pool are needed on a per-key basis (i.e. grow their capacity like `std::vector` does) after rendering a few frames; which would be better than the current solution of having a single global value for all pools (`max_descriptors_per_pool`) that the user needs to tweak. - `bool linear_descriptor_pools_enabled = true` Setting it to false enforces the old behavior. Useful for debugging bugs and regressions. Setting it to false is required when workarounding driver bugs (e.g. Adreno 730). A ridiculous optimization. Ridiculous because the original code should've done this in the first place. Previously Godot was doing the following: 1. Create a command buffer **pool**. One per frame. 2. Create multiple command buffers from the pool in point 1. 3. Call `vkBeginCommandBuffer` on the cmd buffer in point 2. This resets the cmd buffer because Godot requests the `VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT` flag. 4. Add commands to the cmd buffers from point 2. 5. Submit those commands. 6. On frame N + 2, recycle the buffer pool and cmd buffers from pt 1 & 2, and repeat from step 3. The problem here is that step 3 resets each command buffer individually. Initially Godot used to have 1 cmd buffer per pool, thus the impact is very low. But not anymore (specially with Adreno workarounds to force splitting compute dispatches into a new cmd buffer, more on this later). However Godot keeps around a very low amount of command buffers per frame. The recommended method is to reset the whole pool, to reset all cmd buffers at once. Hence the new steps would be: 1. Create a command buffer **pool**. One per frame. 2. Create multiple command buffers from the pool in point 1. 3. Call `vkBeginCommandBuffer` on the cmd buffer in point 2, which is already reset/empty (see step 6). 4. Add commands to the cmd buffers from point 2. 5. Submit those commands. 6. On frame N + 2, recycle the buffer pool and cmd buffers from pt 1 & 2, call `vkResetCommandPool` and repeat from step 3. **Possible issues:** @DarioSamo added `transfer_worker` which creates a command buffer pool: ```cpp transfer_worker->command_pool = driver->command_pool_create(transfer_queue_family, RDD::COMMAND_BUFFER_TYPE_PRIMARY); ``` As expected, validation was complaining that command buffers were being reused without being reset (that's good, we now know Validation Layers will warn us of wrong use). I fixed it by adding: ```cpp void RenderingDevice::_wait_for_transfer_worker(TransferWorker *p_transfer_worker) { driver->fence_wait(p_transfer_worker->command_fence); driver->command_pool_reset(p_transfer_worker->command_pool); // ! New line ! ``` **Secondary cmd buffers are subject to the same issue but I didn't alter them. I talked this with Dario and he is aware of this.** Secondary cmd buffers are currently disabled due to other issues (it's disabled on master). - `bool RenderingDeviceCommons::command_pool_reset_enabled` Setting it to false enforces the old behavior. Useful for debugging bugs and regressions. There's no other reason for this boolean. Possibly once it becomes well tested, the boolean could be removed entirely. Adds `command_bind_render_uniform_sets` and `add_draw_list_bind_uniform_sets` (+ compute variants). It performs the same as `add_draw_list_bind_uniform_set` (notice singular vs plural), but on multiple consecutive uniform sets, thus reducing graph and draw call overhead. - `bool descriptor_set_batching = true;` Setting it to false enforces the old behavior. Useful for debugging bugs and regressions. There's no other reason for this boolean. Possibly once it becomes well tested, the boolean could be removed entirely. Godot currently does the following: 1. Fill the entire cmd buffer with commands. 2. `submit()` - Wait with a semaphore for the swapchain. - Trigger a semaphore to indicate when we're done (so the swapchain can submit). 3. `present()` The optimization opportunity here is that 95% of Godot's rendering is done offscreen. Then a fullscreen pass copies everything to the swapchain. Godot doesn't practically render directly to the swapchain. The problem with this is that the GPU has to wait for the swapchain to be released **to start anything**, when we could start *much earlier*. Only the final blit pass must wait for the swapchain. TheForge changed it to the following (more complicated, I'm simplifying the idea): 1. Fill the entire cmd buffer with commands. 2. In `screen_prepare_for_drawing` do `submit()` - There are no semaphore waits for the swapchain. - Trigger a semaphore to indicate when we're done. 3. Fill a new cmd buffer that only does the final blit to the swapchain. 4. `submit()` - Wait with a semaphore for the submit() from step 2. - Wait with a semaphore for the swapchain (so the swapchain can submit). - Trigger a semaphore to indicate when we're done (so the swapchain can submit). 5. `present()` Dario discovered this problem independently while working on a different platform. **However TheForge's solution had to be rewritten from scratch:** The complexity to achieve the solution was high and quite difficult to maintain with the way Godot works now (after Übershaders PR). But on the other hand, re-implementing the solution became much simpler because Dario already had to do something similar: To fix an Adreno 730 driver bug, he had to implement splitting command buffers. **This is exactly what we need!**. Thus it was re-written using this existing functionality for a new purpose. To achieve this, I added a new argument, `bool p_split_cmd_buffer`, to `RenderingDeviceGraph::add_draw_list_begin`, which is only set to true by `RenderingDevice::draw_list_begin_for_screen`. The graph will split the draw list into its own command buffer. - `bool split_swapchain_into_its_own_cmd_buffer = true;` Setting it to false enforces the old behavior. This might be necessary for consoles which follow an alternate solution to the same problem. If not, then we should consider removing it. PR godotengine#90993 added `shader_destroy_modules()` but it was not actually in use. This PR adds several places where `shader_destroy_modules()` is called after initialization to free up memory of SPIR-V structures that are no longer needed.
1 parent aa8d9b8 commit c77cbf0

24 files changed

+984
-201
lines changed

doc/classes/ProjectSettings.xml

+3
Original file line numberDiff line numberDiff line change
@@ -2861,6 +2861,9 @@
28612861
[b]Note:[/b] Some platforms may restrict the actual value.
28622862
</member>
28632863
<member name="rendering/rendering_device/vulkan/max_descriptors_per_pool" type="int" setter="" getter="" default="64">
2864+
The number of descriptors per pool. Godot's Vulkan backend uses linear pools for descriptors that will be created and destroyed within a single frame. Instead of destroying every single descriptor every frame, they all can be destroyed at once by resetting the pool they belong to.
2865+
A larger number is more efficient up to a limit, after that it will only waste RAM (maximum efficiency is achieved when there is no more than 1 pool per frame). A small number could end up with one pool per descriptor, which negatively impacts performance.
2866+
[b]Note:[/b] Changing this property requires a restart to take effect.
28642867
</member>
28652868
<member name="rendering/scaling_3d/fsr_sharpness" type="float" setter="" getter="" default="0.2">
28662869
Determines how sharp the upscaled image will be when using the FSR upscaling mode. Sharpness halves with every whole number. Values go from 0.0 (sharpest) to 2.0. Values above 2.0 won't make a visible difference.

drivers/d3d12/rendering_device_driver_d3d12.cpp

+26-2
Original file line numberDiff line numberDiff line change
@@ -2286,6 +2286,10 @@ RDD::CommandPoolID RenderingDeviceDriverD3D12::command_pool_create(CommandQueueF
22862286
return CommandPoolID(command_pool);
22872287
}
22882288

2289+
bool RenderingDeviceDriverD3D12::command_pool_reset(CommandPoolID p_cmd_pool) {
2290+
return true;
2291+
}
2292+
22892293
void RenderingDeviceDriverD3D12::command_pool_free(CommandPoolID p_cmd_pool) {
22902294
CommandPoolInfo *command_pool = (CommandPoolInfo *)(p_cmd_pool.id);
22912295
memdelete(command_pool);
@@ -3616,7 +3620,7 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
36163620
return ret;
36173621
}
36183622

3619-
RDD::ShaderID RenderingDeviceDriverD3D12::shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary, ShaderDescription &r_shader_desc, String &r_name) {
3623+
RDD::ShaderID RenderingDeviceDriverD3D12::shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary, ShaderDescription &r_shader_desc, String &r_name, const Vector<ImmutableSampler> &p_immutable_samplers) {
36203624
r_shader_desc = {}; // Driver-agnostic.
36213625
ShaderInfo shader_info_in; // Driver-specific.
36223626

@@ -3825,7 +3829,9 @@ static void _add_descriptor_count_for_uniform(RenderingDevice::UniformType p_typ
38253829
}
38263830
}
38273831

3828-
RDD::UniformSetID RenderingDeviceDriverD3D12::uniform_set_create(VectorView<BoundUniform> p_uniforms, ShaderID p_shader, uint32_t p_set_index) {
3832+
RDD::UniformSetID RenderingDeviceDriverD3D12::uniform_set_create(VectorView<BoundUniform> p_uniforms, ShaderID p_shader, uint32_t p_set_index, int p_linear_pool_index) {
3833+
// p_linear_pool_index = -1; // TODO:? Linear pools not implemented or not supported by API backend.
3834+
38293835
// Pre-bookkeep.
38303836
UniformSetInfo *uniform_set_info = VersatileResource::allocate<UniformSetInfo>(resources_allocator);
38313837

@@ -5352,6 +5358,13 @@ void RenderingDeviceDriverD3D12::command_bind_render_uniform_set(CommandBufferID
53525358
_command_bind_uniform_set(p_cmd_buffer, p_uniform_set, p_shader, p_set_index, false);
53535359
}
53545360

5361+
void RenderingDeviceDriverD3D12::command_bind_render_uniform_sets(CommandBufferID p_cmd_buffer, VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) {
5362+
for (uint32_t i = 0u; i < p_set_count; ++i) {
5363+
// TODO: _command_bind_uniform_set() does WAAAAY too much stuff. A lot of it should be already cached in UniformSetID when uniform_set_create() was called. Binding is supposed to be a cheap operation, ideally a memcpy.
5364+
_command_bind_uniform_set(p_cmd_buffer, p_uniform_sets[i], p_shader, p_first_set_index + i, false);
5365+
}
5366+
}
5367+
53555368
void RenderingDeviceDriverD3D12::command_render_draw(CommandBufferID p_cmd_buffer, uint32_t p_vertex_count, uint32_t p_instance_count, uint32_t p_base_vertex, uint32_t p_first_instance) {
53565369
CommandBufferInfo *cmd_buf_info = (CommandBufferInfo *)p_cmd_buffer.id;
53575370
_bind_vertex_buffers(cmd_buf_info);
@@ -5856,6 +5869,13 @@ void RenderingDeviceDriverD3D12::command_bind_compute_uniform_set(CommandBufferI
58565869
_command_bind_uniform_set(p_cmd_buffer, p_uniform_set, p_shader, p_set_index, true);
58575870
}
58585871

5872+
void RenderingDeviceDriverD3D12::command_bind_compute_uniform_sets(CommandBufferID p_cmd_buffer, VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) {
5873+
for (uint32_t i = 0u; i < p_set_count; ++i) {
5874+
// TODO: _command_bind_uniform_set() does WAAAAY too much stuff. A lot of it should be already cached in UniformSetID when uniform_set_create() was called. Binding is supposed to be a cheap operation, ideally a memcpy.
5875+
_command_bind_uniform_set(p_cmd_buffer, p_uniform_sets[i], p_shader, p_first_set_index + i, true);
5876+
}
5877+
}
5878+
58595879
void RenderingDeviceDriverD3D12::command_compute_dispatch(CommandBufferID p_cmd_buffer, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) {
58605880
CommandBufferInfo *cmd_buf_info = (CommandBufferInfo *)p_cmd_buffer.id;
58615881
if (!barrier_capabilities.enhanced_barriers_supported) {
@@ -6139,6 +6159,10 @@ uint64_t RenderingDeviceDriverD3D12::get_total_memory_used() {
61396159
return stats.Total.Stats.BlockBytes;
61406160
}
61416161

6162+
uint64_t RenderingDeviceDriverD3D12::get_lazily_memory_used() {
6163+
return 0;
6164+
}
6165+
61426166
uint64_t RenderingDeviceDriverD3D12::limit_get(Limit p_limit) {
61436167
uint64_t safe_unbounded = ((uint64_t)1 << 30);
61446168
switch (p_limit) {

drivers/d3d12/rendering_device_driver_d3d12.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
434434

435435
public:
436436
virtual CommandPoolID command_pool_create(CommandQueueFamilyID p_cmd_queue_family, CommandBufferType p_cmd_buffer_type) override final;
437+
virtual bool command_pool_reset(CommandPoolID p_cmd_pool) override final;
437438
virtual void command_pool_free(CommandPoolID p_cmd_pool) override final;
438439

439440
// ----- BUFFER -----
@@ -697,7 +698,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
697698
public:
698699
virtual String shader_get_binary_cache_key() override final;
699700
virtual Vector<uint8_t> shader_compile_binary_from_spirv(VectorView<ShaderStageSPIRVData> p_spirv, const String &p_shader_name) override final;
700-
virtual ShaderID shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary, ShaderDescription &r_shader_desc, String &r_name) override final;
701+
virtual ShaderID shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary, ShaderDescription &r_shader_desc, String &r_name, const Vector<ImmutableSampler> &p_immutable_samplers) override final;
701702
virtual uint32_t shader_get_layout_hash(ShaderID p_shader) override final;
702703
virtual void shader_free(ShaderID p_shader) override final;
703704
virtual void shader_destroy_modules(ShaderID p_shader) override final;
@@ -747,7 +748,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
747748
};
748749

749750
public:
750-
virtual UniformSetID uniform_set_create(VectorView<BoundUniform> p_uniforms, ShaderID p_shader, uint32_t p_set_index) override final;
751+
virtual UniformSetID uniform_set_create(VectorView<BoundUniform> p_uniforms, ShaderID p_shader, uint32_t p_set_index, int p_linear_pool_index) override final;
751752
virtual void uniform_set_free(UniformSetID p_uniform_set) override final;
752753

753754
// ----- COMMANDS -----
@@ -757,6 +758,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
757758
private:
758759
void _command_check_descriptor_sets(CommandBufferID p_cmd_buffer);
759760
void _command_bind_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index, bool p_for_compute);
761+
void _command_bind_uniform_sets(CommandBufferID p_cmd_buffer, VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count, bool p_for_compute);
760762

761763
public:
762764
/******************/
@@ -846,6 +848,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
846848
// Binding.
847849
virtual void command_bind_render_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) override final;
848850
virtual void command_bind_render_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) override final;
851+
virtual void command_bind_render_uniform_sets(CommandBufferID p_cmd_buffer, VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) override final;
849852

850853
// Drawing.
851854
virtual void command_render_draw(CommandBufferID p_cmd_buffer, uint32_t p_vertex_count, uint32_t p_instance_count, uint32_t p_base_vertex, uint32_t p_first_instance) override final;
@@ -893,6 +896,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
893896
// Binding.
894897
virtual void command_bind_compute_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) override final;
895898
virtual void command_bind_compute_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) override final;
899+
virtual void command_bind_compute_uniform_sets(CommandBufferID p_cmd_buffer, VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) override final;
896900

897901
// Dispatching.
898902
virtual void command_compute_dispatch(CommandBufferID p_cmd_buffer, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) override final;
@@ -986,6 +990,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
986990
virtual void set_object_name(ObjectType p_type, ID p_driver_id, const String &p_name) override final;
987991
virtual uint64_t get_resource_native_handle(DriverResource p_type, ID p_driver_id) override final;
988992
virtual uint64_t get_total_memory_used() override final;
993+
virtual uint64_t get_lazily_memory_used() override final;
989994
virtual uint64_t limit_get(Limit p_limit) override final;
990995
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
991996
virtual bool has_feature(Features p_feature) override final;

drivers/metal/metal_objects.h

+2
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) MDCommandBuffer {
502502
#pragma mark - Render Commands
503503

504504
void render_bind_uniform_set(RDD::UniformSetID p_uniform_set, RDD::ShaderID p_shader, uint32_t p_set_index);
505+
void render_bind_uniform_sets(VectorView<RDD::UniformSetID> p_uniform_sets, RDD::ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count);
505506
void render_clear_attachments(VectorView<RDD::AttachmentClear> p_attachment_clears, VectorView<Rect2i> p_rects);
506507
void render_set_viewport(VectorView<Rect2i> p_viewports);
507508
void render_set_scissor(VectorView<Rect2i> p_scissors);
@@ -535,6 +536,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) MDCommandBuffer {
535536
#pragma mark - Compute Commands
536537

537538
void compute_bind_uniform_set(RDD::UniformSetID p_uniform_set, RDD::ShaderID p_shader, uint32_t p_set_index);
539+
void compute_bind_uniform_sets(VectorView<RDD::UniformSetID> p_uniform_sets, RDD::ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count);
538540
void compute_dispatch(uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups);
539541
void compute_dispatch_indirect(RDD::BufferID p_indirect_buffer, uint64_t p_offset);
540542

drivers/metal/metal_objects.mm

+54
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,26 @@
223223
}
224224
}
225225

226+
void MDCommandBuffer::render_bind_uniform_sets(VectorView<RDD::UniformSetID> p_uniform_sets, RDD::ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) {
227+
DEV_ASSERT(type == MDCommandBufferStateType::Render);
228+
229+
for (size_t i = 0u; i < p_set_count; ++i) {
230+
MDUniformSet *set = (MDUniformSet *)(p_uniform_sets[i].id);
231+
if (render.uniform_sets.size() <= set->index) {
232+
uint32_t s = render.uniform_sets.size();
233+
render.uniform_sets.resize(set->index + 1);
234+
// Set intermediate values to null.
235+
std::fill(&render.uniform_sets[s], &render.uniform_sets[set->index] + 1, nullptr);
236+
}
237+
238+
if (render.uniform_sets[set->index] != set) {
239+
render.dirty.set_flag(RenderState::DIRTY_UNIFORMS);
240+
render.uniform_set_mask |= 1ULL << set->index;
241+
render.uniform_sets[set->index] = set;
242+
}
243+
}
244+
}
245+
226246
void MDCommandBuffer::render_clear_attachments(VectorView<RDD::AttachmentClear> p_attachment_clears, VectorView<Rect2i> p_rects) {
227247
DEV_ASSERT(type == MDCommandBufferStateType::Render);
228248

@@ -964,6 +984,40 @@
964984
}
965985
}
966986

987+
void MDCommandBuffer::compute_bind_uniform_sets(VectorView<RDD::UniformSetID> p_uniform_sets, RDD::ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) {
988+
DEV_ASSERT(type == MDCommandBufferStateType::Compute);
989+
990+
id<MTLComputeCommandEncoder> enc = compute.encoder;
991+
id<MTLDevice> device = enc.device;
992+
993+
MDShader *shader = (MDShader *)(p_shader.id);
994+
995+
thread_local LocalVector<__unsafe_unretained id<MTLBuffer>> buffers;
996+
thread_local LocalVector<NSUInteger> offsets;
997+
998+
buffers.resize(p_set_count);
999+
offsets.resize(p_set_count);
1000+
1001+
for (size_t i = 0u; i < p_set_count; ++i) {
1002+
UniformSet const &set_info = shader->sets[p_first_set_index + i];
1003+
1004+
MDUniformSet *set = (MDUniformSet *)(p_uniform_sets[i].id);
1005+
BoundUniformSet &bus = set->boundUniformSetForShader(shader, device);
1006+
bus.merge_into(compute.resource_usage);
1007+
1008+
uint32_t const *offset = set_info.offsets.getptr(RDD::SHADER_STAGE_COMPUTE);
1009+
if (offset) {
1010+
buffers[i] = bus.buffer;
1011+
offsets[i] = *offset;
1012+
} else {
1013+
buffers[i] = nullptr;
1014+
offsets[i] = 0u;
1015+
}
1016+
}
1017+
1018+
[enc setBuffers:buffers.ptr() offsets:offsets.ptr() withRange:NSMakeRange(p_first_set_index, p_set_count)];
1019+
}
1020+
9671021
void MDCommandBuffer::compute_dispatch(uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) {
9681022
DEV_ASSERT(type == MDCommandBufferStateType::Compute);
9691023

drivers/metal/rendering_device_driver_metal.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
185185
// ----- POOL -----
186186

187187
virtual CommandPoolID command_pool_create(CommandQueueFamilyID p_cmd_queue_family, CommandBufferType p_cmd_buffer_type) override final;
188+
virtual bool command_pool_reset(CommandPoolID p_cmd_pool) override final;
188189
virtual void command_pool_free(CommandPoolID p_cmd_pool) override final;
189190

190191
// ----- BUFFER -----
@@ -251,14 +252,14 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
251252
public:
252253
virtual String shader_get_binary_cache_key() override final;
253254
virtual Vector<uint8_t> shader_compile_binary_from_spirv(VectorView<ShaderStageSPIRVData> p_spirv, const String &p_shader_name) override final;
254-
virtual ShaderID shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary, ShaderDescription &r_shader_desc, String &r_name) override final;
255+
virtual ShaderID shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary, ShaderDescription &r_shader_desc, String &r_name, const Vector<ImmutableSampler> &p_immutable_samplers) override final;
255256
virtual void shader_free(ShaderID p_shader) override final;
256257
virtual void shader_destroy_modules(ShaderID p_shader) override final;
257258

258259
#pragma mark - Uniform Set
259260

260261
public:
261-
virtual UniformSetID uniform_set_create(VectorView<BoundUniform> p_uniforms, ShaderID p_shader, uint32_t p_set_index) override final;
262+
virtual UniformSetID uniform_set_create(VectorView<BoundUniform> p_uniforms, ShaderID p_shader, uint32_t p_set_index, int p_linear_pool_index) override final;
262263
virtual void uniform_set_free(UniformSetID p_uniform_set) override final;
263264

264265
#pragma mark - Commands
@@ -331,6 +332,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
331332
// Binding.
332333
virtual void command_bind_render_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) override final;
333334
virtual void command_bind_render_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) override final;
335+
virtual void command_bind_render_uniform_sets(CommandBufferID p_cmd_buffer, VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) override final;
334336

335337
// Drawing.
336338
virtual void command_render_draw(CommandBufferID p_cmd_buffer, uint32_t p_vertex_count, uint32_t p_instance_count, uint32_t p_base_vertex, uint32_t p_first_instance) override final;
@@ -371,6 +373,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
371373
// Binding.
372374
virtual void command_bind_compute_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) override final;
373375
virtual void command_bind_compute_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) override final;
376+
virtual void command_bind_compute_uniform_sets(CommandBufferID p_cmd_buffer, VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) override final;
374377

375378
// Dispatching.
376379
virtual void command_compute_dispatch(CommandBufferID p_cmd_buffer, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) override final;
@@ -413,6 +416,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
413416
virtual void set_object_name(ObjectType p_type, ID p_driver_id, const String &p_name) override final;
414417
virtual uint64_t get_resource_native_handle(DriverResource p_type, ID p_driver_id) override final;
415418
virtual uint64_t get_total_memory_used() override final;
419+
virtual uint64_t get_lazily_memory_used() override final;
416420
virtual uint64_t limit_get(Limit p_limit) override final;
417421
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
418422
virtual bool has_feature(Features p_feature) override final;

0 commit comments

Comments
 (0)