Skip to content

Commit

Permalink
Implement buffer_get_data_async and texture_get_data_async.
Browse files Browse the repository at this point in the history
  • Loading branch information
DarioSamo committed Dec 10, 2024
1 parent a372214 commit b798097
Show file tree
Hide file tree
Showing 5 changed files with 490 additions and 85 deletions.
1 change: 1 addition & 0 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1563,6 +1563,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/block_size_kb", PROPERTY_HINT_RANGE, "4,2048,1,or_greater"), 256);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/max_size_mb", PROPERTY_HINT_RANGE, "1,1024,1,or_greater"), 128);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/texture_upload_region_size_px", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 64);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/staging_buffer/texture_download_region_size_px", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 64);
GLOBAL_DEF_RST(PropertyInfo(Variant::BOOL, "rendering/rendering_device/pipeline_cache/enable"), true);
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/rendering_device/pipeline_cache/save_chunk_size_mb", PROPERTY_HINT_RANGE, "0.000001,64.0,0.001,or_greater"), 3.0);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/vulkan/max_descriptors_per_pool", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 64);
Expand Down
12 changes: 12 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2841,10 +2841,22 @@
Determines at which interval pipeline cache is saved to disk. The lower the value, the more often it is saved.
</member>
<member name="rendering/rendering_device/staging_buffer/block_size_kb" type="int" setter="" getter="" default="256">
The size of a block allocated in the staging buffers. Staging buffers are the intermediate resources the engine uses to upload or download data to the GPU. This setting determines the max amount of data that can be transferred in a copy operation. Increasing this will result in faster data transfers at the cost of extra memory.
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this value at run-time.
</member>
<member name="rendering/rendering_device/staging_buffer/max_size_mb" type="int" setter="" getter="" default="128">
The maximum amount of memory allowed to be used by staging buffers. If the amount of data being uploaded or downloaded exceeds this amount, the GPU will stall and wait for previous frames to finish.
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this value at run-time.
</member>
<member name="rendering/rendering_device/staging_buffer/texture_download_region_size_px" type="int" setter="" getter="" default="64">
The region size in pixels used to download texture data from the GPU when using methods like [method RenderingDevice.texture_get_data_async].
[b]Note:[/b] This property's upper limit is controlled by [member rendering/rendering_device/staging_buffer/block_size_kb] and whether it's possible to allocate a single block of texture data with this region size in the format that is requested.
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this value at run-time.
</member>
<member name="rendering/rendering_device/staging_buffer/texture_upload_region_size_px" type="int" setter="" getter="" default="64">
The region size in pixels used to upload texture data from the GPU when using methods like [method RenderingDevice.texture_update].
[b]Note:[/b] This property's upper limit is controlled by [member rendering/rendering_device/staging_buffer/block_size_kb] and whether it's possible to allocate a single block of texture data with this region size in the format that is requested.
[b]Note:[/b] This property is only read when the project starts. There is currently no way to change this value at run-time.
</member>
<member name="rendering/rendering_device/vsync/frame_queue_size" type="int" setter="" getter="" default="2">
The number of frames to track on the CPU side before stalling to wait for the GPU.
Expand Down
41 changes: 41 additions & 0 deletions doc/classes/RenderingDevice.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,27 @@
<param index="2" name="size_bytes" type="int" default="0" />
<description>
Returns a copy of the data of the specified [param buffer], optionally [param offset_bytes] and [param size_bytes] can be set to copy only a portion of the buffer.
[b]Note:[/b] This method will block the GPU from working until the data is retrieved. Refer to [method buffer_get_data_async] for an alternative that returns the data in more performant way.
</description>
</method>
<method name="buffer_get_data_async">
<return type="int" enum="Error" />
<param index="0" name="buffer" type="RID" />
<param index="1" name="callback" type="Callable" />
<param index="2" name="offset_bytes" type="int" default="0" />
<param index="3" name="size_bytes" type="int" default="0" />
<description>
Asynchronous version of [method buffer_get_data]. RenderingDevice will call [param callback] in a certain amount of frames with the data the buffer had at the time of the request.
[b]Note:[/b] At the moment, the delay corresponds to the amount of frames specified by [member ProjectSettings.rendering/rendering_device/vsync/frame_queue_size].
[b]Note:[/b] Downloading large buffers can have a prohibitive cost for real-time even when using the asynchronous method due to hardware bandwidth limitations. When dealing with large resources, you can adjust settings such as [member ProjectSettings.rendering/rendering_device/staging_buffer/block_size_kb] to improve the transfer speed at the cost of extra memory.
[codeblock]
func _buffer_get_data_callback(array):
value = array.decode_u32(0)

...

rd.buffer_get_data_async(buffer, _buffer_get_data_callback)
[/codeblock]
</description>
</method>
<method name="buffer_update">
Expand Down Expand Up @@ -928,6 +949,26 @@
Returns the [param texture] data for the specified [param layer] as raw binary data. For 2D textures (which only have one layer), [param layer] must be [code]0[/code].
[b]Note:[/b] [param texture] can't be retrieved while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to [constant FINAL_ACTION_CONTINUE]) to retrieve this texture. Otherwise, an error is printed and a empty [PackedByteArray] is returned.
[b]Note:[/b] [param texture] requires the [constant TEXTURE_USAGE_CAN_COPY_FROM_BIT] to be retrieved. Otherwise, an error is printed and a empty [PackedByteArray] is returned.
[b]Note:[/b] This method will block the GPU from working until the data is retrieved. Refer to [method texture_get_data_async] for an alternative that returns the data in more performant way.
</description>
</method>
<method name="texture_get_data_async">
<return type="int" enum="Error" />
<param index="0" name="texture" type="RID" />
<param index="1" name="layer" type="int" />
<param index="2" name="callback" type="Callable" />
<description>
Asynchronous version of [method texture_get_data]. RenderingDevice will call [param callback] in a certain amount of frames with the data the texture had at the time of the request.
[b]Note:[/b] At the moment, the delay corresponds to the amount of frames specified by [member ProjectSettings.rendering/rendering_device/vsync/frame_queue_size].
[b]Note:[/b] Downloading large textures can have a prohibitive cost for real-time even when using the asynchronous method due to hardware bandwidth limitations. When dealing with large resources, you can adjust settings such as [member ProjectSettings.rendering/rendering_device/staging_buffer/texture_download_region_size_px] and [member ProjectSettings.rendering/rendering_device/staging_buffer/block_size_kb] to improve the transfer speed at the cost of extra memory.
[codeblock]
func _texture_get_data_callback(array):
value = array.decode_u32(0)

...

rd.texture_get_data_async(texture, 0, _texture_get_data_callback)
[/codeblock]
</description>
</method>
<method name="texture_get_format">
Expand Down
Loading

0 comments on commit b798097

Please sign in to comment.