You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-16 14:00:40 +00:00
Add Persistent Buffers
This work is a heavily refactored and rewritten from TheForge's initial code. TheForge's original code had too many race conditions and was fundamentally flawed as it was too easy to incur into those data races by accident. However they identified the proper places that needed changes, and the idea was sound. I used their work as a blueprint to design this work. This PR implements: - Introduction of UMA buffers used by a few buffers (most notably the ones filled by _fill_instance_data). Ironically this change seems to positively affect PC more than it does on Mobile. Updates D3D12 Memory Allocator to get GPU_UPLOAD heap support. Metal implementation by Stuart Carnie. Co-authored-by: Stuart Carnie <stuart.carnie@gmail.com> Co-authored-by: TheForge team
This commit is contained in:
@@ -147,6 +147,14 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
|
||||
#endif
|
||||
DeviceFunctions device_functions;
|
||||
|
||||
struct PendingFlushes {
|
||||
LocalVector<VmaAllocation> allocations;
|
||||
LocalVector<VkDeviceSize> offsets;
|
||||
LocalVector<VkDeviceSize> sizes;
|
||||
};
|
||||
|
||||
PendingFlushes pending_flushes;
|
||||
|
||||
void _register_requested_device_extension(const CharString &p_extension_name, bool p_required);
|
||||
Error _initialize_device_extensions();
|
||||
Error _check_device_features();
|
||||
@@ -194,14 +202,29 @@ public:
|
||||
} allocation;
|
||||
uint64_t size = 0;
|
||||
VkBufferView vk_view = VK_NULL_HANDLE; // For texel buffers.
|
||||
// If dynamic buffer, then its range is [0; RenderingDeviceDriverVulkan::frame_count)
|
||||
// else it's UINT32_MAX.
|
||||
uint32_t frame_idx = UINT32_MAX;
|
||||
|
||||
bool is_dynamic() const { return frame_idx != UINT32_MAX; }
|
||||
};
|
||||
|
||||
virtual BufferID buffer_create(uint64_t p_size, BitField<BufferUsageBits> p_usage, MemoryAllocationType p_allocation_type) override final;
|
||||
struct BufferDynamicInfo : BufferInfo {
|
||||
uint8_t *persistent_ptr = nullptr;
|
||||
#ifdef DEBUG_ENABLED
|
||||
// For tracking that a persistent buffer isn't mapped twice in the same frame.
|
||||
uint64_t last_frame_mapped = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
virtual BufferID buffer_create(uint64_t p_size, BitField<BufferUsageBits> p_usage, MemoryAllocationType p_allocation_type, uint64_t p_frames_drawn) override final;
|
||||
virtual bool buffer_set_texel_format(BufferID p_buffer, DataFormat p_format) override final;
|
||||
virtual void buffer_free(BufferID p_buffer) override final;
|
||||
virtual uint64_t buffer_get_allocation_size(BufferID p_buffer) override final;
|
||||
virtual uint8_t *buffer_map(BufferID p_buffer) override final;
|
||||
virtual void buffer_unmap(BufferID p_buffer) override final;
|
||||
virtual uint8_t *buffer_persistent_map_advance(BufferID p_buffer, uint64_t p_frames_drawn) override final;
|
||||
virtual void buffer_flush(BufferID p_buffer) override final;
|
||||
virtual uint64_t buffer_get_device_address(BufferID p_buffer) override final;
|
||||
|
||||
/*****************/
|
||||
@@ -473,6 +496,7 @@ private:
|
||||
VkDescriptorPool vk_descriptor_pool = VK_NULL_HANDLE;
|
||||
VkDescriptorPool vk_linear_descriptor_pool = VK_NULL_HANDLE;
|
||||
DescriptorSetPools::Iterator pool_sets_it;
|
||||
TightLocalVector<BufferInfo const *, uint32_t> dynamic_buffers;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -480,6 +504,7 @@ public:
|
||||
virtual void linear_uniform_set_pools_reset(int p_linear_pool_index) override final;
|
||||
virtual void uniform_set_free(UniformSetID p_uniform_set) override final;
|
||||
virtual bool uniform_sets_have_linear_pools() const override final;
|
||||
virtual uint32_t uniform_sets_get_dynamic_offsets(VectorView<UniformSetID> p_uniform_sets, ShaderID p_shader, uint32_t p_first_set_index, uint32_t p_set_count) const override final;
|
||||
|
||||
// ----- COMMANDS -----
|
||||
|
||||
@@ -567,8 +592,7 @@ public:
|
||||
|
||||
// Binding.
|
||||
virtual void command_bind_render_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) override final;
|
||||
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;
|
||||
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;
|
||||
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, uint32_t p_dynamic_offsets) override final;
|
||||
|
||||
// Drawing.
|
||||
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;
|
||||
@@ -610,8 +634,7 @@ public:
|
||||
|
||||
// Binding.
|
||||
virtual void command_bind_compute_pipeline(CommandBufferID p_cmd_buffer, PipelineID p_pipeline) override final;
|
||||
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;
|
||||
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;
|
||||
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, uint32_t p_dynamic_offsets) override final;
|
||||
|
||||
// Dispatching.
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user