Skip to content

Commit 3d92f40

Browse files
thimenesupclayjohn
authored andcommitted
Implement Buffer Device Address for Rendering Device Vulkan and DirectX12
1 parent b3a44e8 commit 3d92f40

13 files changed

+168
-14
lines changed

doc/classes/RenderingDevice.xml

+27
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@
8181
[/codeblock]
8282
</description>
8383
</method>
84+
<method name="buffer_get_device_address">
85+
<return type="int" />
86+
<param index="0" name="buffer" type="RID" />
87+
<description>
88+
Returns the address of the given [param buffer] which can be passed to shaders in any way to access underlying data. Buffer must have been created with this feature enabled.
89+
[b]Note:[/b] You must check that the GPU supports this functionality by calling [method has_feature] with [constant SUPPORTS_BUFFER_DEVICE_ADDRESS] as a parameter.
90+
</description>
91+
</method>
8492
<method name="buffer_update">
8593
<return type="int" enum="Error" />
8694
<param index="0" name="buffer" type="RID" />
@@ -672,6 +680,13 @@
672680
This is only used by Vulkan in debug builds. Godot must also be started with the [code]--extra-gpu-memory-tracking[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url].
673681
</description>
674682
</method>
683+
<method name="has_feature" qualifiers="const">
684+
<return type="bool" />
685+
<param index="0" name="feature" type="int" enum="RenderingDevice.Features" />
686+
<description>
687+
Returns [code]true[/code] if the [param feature] is supported by the GPU.
688+
</description>
689+
</method>
675690
<method name="index_array_create">
676691
<return type="RID" />
677692
<param index="0" name="index_buffer" type="RID" />
@@ -688,9 +703,11 @@
688703
<param index="1" name="format" type="int" enum="RenderingDevice.IndexBufferFormat" />
689704
<param index="2" name="data" type="PackedByteArray" default="PackedByteArray()" />
690705
<param index="3" name="use_restart_indices" type="bool" default="false" />
706+
<param index="4" name="enable_device_address" type="bool" default="false" />
691707
<description>
692708
Creates a new index buffer. It can be accessed with the RID that is returned.
693709
Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method.
710+
Optionally, set [param enable_device_address] if you wish to use [method buffer_get_device_address] functionality and the GPU supports it.
694711
</description>
695712
</method>
696713
<method name="limit_get" qualifiers="const">
@@ -1056,9 +1073,11 @@
10561073
<return type="RID" />
10571074
<param index="0" name="size_bytes" type="int" />
10581075
<param index="1" name="data" type="PackedByteArray" default="PackedByteArray()" />
1076+
<param index="2" name="enable_device_address" type="bool" default="false" />
10591077
<description>
10601078
Creates a new uniform buffer. It can be accessed with the RID that is returned.
10611079
Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method.
1080+
Optionally, set [param enable_device_address] if you wish to use [method buffer_get_device_address] functionality and the GPU supports it.
10621081
</description>
10631082
</method>
10641083
<method name="uniform_set_create">
@@ -1093,9 +1112,11 @@
10931112
<param index="0" name="size_bytes" type="int" />
10941113
<param index="1" name="data" type="PackedByteArray" default="PackedByteArray()" />
10951114
<param index="2" name="use_as_storage" type="bool" default="false" />
1115+
<param index="3" name="enable_device_address" type="bool" default="false" />
10961116
<description>
10971117
It can be accessed with the RID that is returned.
10981118
Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method.
1119+
Optionally, set [param enable_device_address] if you wish to use [method buffer_get_device_address] functionality and the GPU supports it.
10991120
</description>
11001121
</method>
11011122
<method name="vertex_format_create">
@@ -2047,6 +2068,9 @@
20472068
</constant>
20482069
<constant name="STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT" value="1" enum="StorageBufferUsage" is_bitfield="true">
20492070
</constant>
2071+
<constant name="STORAGE_BUFFER_USAGE_DEVICE_ADDRESS" value="2" enum="StorageBufferUsage" is_bitfield="true">
2072+
Allows usage of [method buffer_get_device_address] on supported GPUs.
2073+
</constant>
20502074
<constant name="UNIFORM_TYPE_SAMPLER" value="0" enum="UniformType">
20512075
Sampler uniform.
20522076
</constant>
@@ -2418,6 +2442,9 @@
24182442
<constant name="PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT" value="2" enum="PipelineSpecializationConstantType">
24192443
Floating-point specialization constant.
24202444
</constant>
2445+
<constant name="SUPPORTS_BUFFER_DEVICE_ADDRESS" value="6" enum="Features">
2446+
Features support for buffer device address extension.
2447+
</constant>
24212448
<constant name="LIMIT_MAX_BOUND_UNIFORM_SETS" value="0" enum="Limit">
24222449
Maximum number of uniform sets that can be bound at a given time.
24232450
</constant>

drivers/d3d12/rendering_device_driver_d3d12.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,11 @@ void RenderingDeviceDriverD3D12::buffer_unmap(BufferID p_buffer) {
905905
buf_info->resource->Unmap(0, &VOID_RANGE);
906906
}
907907

908+
uint64_t RenderingDeviceDriverD3D12::buffer_get_device_address(BufferID p_buffer) {
909+
const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;
910+
return buf_info->resource->GetGPUVirtualAddress();
911+
}
912+
908913
/*****************/
909914
/**** TEXTURE ****/
910915
/*****************/
@@ -6271,6 +6276,8 @@ bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) {
62716276
return vrs_capabilities.ss_image_supported;
62726277
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
62736278
return true;
6279+
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
6280+
return true;
62746281
default:
62756282
return false;
62766283
}

drivers/d3d12/rendering_device_driver_d3d12.h

+1
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
284284
virtual uint64_t buffer_get_allocation_size(BufferID p_buffer) override final;
285285
virtual uint8_t *buffer_map(BufferID p_buffer) override final;
286286
virtual void buffer_unmap(BufferID p_buffer) override final;
287+
virtual uint64_t buffer_get_device_address(BufferID p_buffer) override final;
287288

288289
/*****************/
289290
/**** TEXTURE ****/

drivers/metal/rendering_device_driver_metal.h

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet
105105
virtual uint64_t buffer_get_allocation_size(BufferID p_buffer) override final;
106106
virtual uint8_t *buffer_map(BufferID p_buffer) override final;
107107
virtual void buffer_unmap(BufferID p_buffer) override final;
108+
virtual uint64_t buffer_get_device_address(BufferID p_buffer) override final;
108109

109110
#pragma mark - Texture
110111

drivers/metal/rendering_device_driver_metal.mm

+11
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@ _FORCE_INLINE_ MTLSize mipmapLevelSizeFromSize(MTLSize p_size, NSUInteger p_leve
159159
// Nothing to do.
160160
}
161161

162+
uint64_t RenderingDeviceDriverMetal::buffer_get_device_address(BufferID p_buffer) {
163+
if (@available(iOS 16.0, macOS 13.0, *)) {
164+
id<MTLBuffer> obj = rid::get(p_buffer);
165+
return obj.gpuAddress;
166+
} else {
167+
return 0;
168+
}
169+
}
170+
162171
#pragma mark - Texture
163172

164173
#pragma mark - Format Conversions
@@ -4026,6 +4035,8 @@ bool isArrayTexture(MTLTextureType p_type) {
40264035
return false;
40274036
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
40284037
return true;
4038+
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
4039+
return false;
40294040
case SUPPORTS_METALFX_SPATIAL:
40304041
return device_properties->features.metal_fx_spatial;
40314042
case SUPPORTS_METALFX_TEMPORAL:

drivers/vulkan/rendering_device_driver_vulkan.cpp

+42-4
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() {
513513
_register_requested_device_extension(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME, false);
514514
_register_requested_device_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);
515515
_register_requested_device_extension(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, false);
516+
_register_requested_device_extension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, false);
516517

517518
if (Engine::get_singleton()->is_generate_spirv_debug_info_enabled()) {
518519
_register_requested_device_extension(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME, true);
@@ -730,6 +731,7 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
730731
void *next_features = nullptr;
731732
VkPhysicalDeviceVulkan12Features device_features_vk_1_2 = {};
732733
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {};
734+
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_device_address_features = {};
733735
VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features = {};
734736
VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {};
735737
VkPhysicalDeviceMultiviewFeatures multiview_features = {};
@@ -740,10 +742,17 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
740742
device_features_vk_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
741743
device_features_vk_1_2.pNext = next_features;
742744
next_features = &device_features_vk_1_2;
743-
} else if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {
744-
shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;
745-
shader_features.pNext = next_features;
746-
next_features = &shader_features;
745+
} else {
746+
if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {
747+
shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;
748+
shader_features.pNext = next_features;
749+
next_features = &shader_features;
750+
}
751+
if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
752+
buffer_device_address_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;
753+
buffer_device_address_features.pNext = next_features;
754+
next_features = &buffer_device_address_features;
755+
}
747756
}
748757

749758
if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {
@@ -783,11 +792,17 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
783792
shader_capabilities.shader_float16_is_supported = device_features_vk_1_2.shaderFloat16;
784793
shader_capabilities.shader_int8_is_supported = device_features_vk_1_2.shaderInt8;
785794
}
795+
if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
796+
buffer_device_address_support = device_features_vk_1_2.bufferDeviceAddress;
797+
}
786798
} else {
787799
if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {
788800
shader_capabilities.shader_float16_is_supported = shader_features.shaderFloat16;
789801
shader_capabilities.shader_int8_is_supported = shader_features.shaderInt8;
790802
}
803+
if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
804+
buffer_device_address_support = buffer_device_address_features.bufferDeviceAddress;
805+
}
791806
}
792807

793808
if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {
@@ -971,6 +986,14 @@ Error RenderingDeviceDriverVulkan::_initialize_device(const LocalVector<VkDevice
971986
shader_features.shaderInt8 = shader_capabilities.shader_int8_is_supported;
972987
create_info_next = &shader_features;
973988

989+
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_device_address_features = {};
990+
if (buffer_device_address_support) {
991+
buffer_device_address_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;
992+
buffer_device_address_features.pNext = create_info_next;
993+
buffer_device_address_features.bufferDeviceAddress = buffer_device_address_support;
994+
create_info_next = &buffer_device_address_features;
995+
}
996+
974997
VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features = {};
975998
if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) {
976999
vrs_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;
@@ -1112,6 +1135,9 @@ Error RenderingDeviceDriverVulkan::_initialize_allocator() {
11121135
if (use_1_3_features) {
11131136
allocator_info.flags |= VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT;
11141137
}
1138+
if (buffer_device_address_support) {
1139+
allocator_info.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
1140+
}
11151141
VkResult err = vmaCreateAllocator(&allocator_info, &allocator);
11161142
ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "vmaCreateAllocator failed with error " + itos(err) + ".");
11171143

@@ -1487,6 +1513,7 @@ static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_STORAGE_BIT, VK_BUFFER_USAGE_
14871513
static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_INDEX_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT));
14881514
static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_VERTEX_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
14891515
static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_INDIRECT_BIT, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT));
1516+
static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT));
14901517

14911518
RDD::BufferID RenderingDeviceDriverVulkan::buffer_create(uint64_t p_size, BitField<BufferUsageBits> p_usage, MemoryAllocationType p_allocation_type) {
14921519
VkBufferCreateInfo create_info = {};
@@ -1588,6 +1615,15 @@ void RenderingDeviceDriverVulkan::buffer_unmap(BufferID p_buffer) {
15881615
vmaUnmapMemory(allocator, buf_info->allocation.handle);
15891616
}
15901617

1618+
uint64_t RenderingDeviceDriverVulkan::buffer_get_device_address(BufferID p_buffer) {
1619+
const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;
1620+
VkBufferDeviceAddressInfo address_info = {};
1621+
address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
1622+
address_info.pNext = nullptr;
1623+
address_info.buffer = buf_info->vk_buffer;
1624+
return vkGetBufferDeviceAddress(vk_device, &address_info);
1625+
}
1626+
15911627
/*****************/
15921628
/**** TEXTURE ****/
15931629
/*****************/
@@ -5874,6 +5910,8 @@ bool RenderingDeviceDriverVulkan::has_feature(Features p_feature) {
58745910
return vrs_capabilities.attachment_vrs_supported && physical_device_features.shaderStorageImageExtendedFormats;
58755911
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
58765912
return true;
5913+
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
5914+
return buffer_device_address_support;
58775915
default:
58785916
return false;
58795917
}

drivers/vulkan/rendering_device_driver_vulkan.h

+2
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
138138
VRSCapabilities vrs_capabilities;
139139
ShaderCapabilities shader_capabilities;
140140
StorageBufferCapabilities storage_buffer_capabilities;
141+
bool buffer_device_address_support = false;
141142
bool pipeline_cache_control_support = false;
142143
bool device_fault_support = false;
143144
#if defined(VK_TRACK_DEVICE_MEMORY)
@@ -204,6 +205,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
204205
virtual uint64_t buffer_get_allocation_size(BufferID p_buffer) override final;
205206
virtual uint8_t *buffer_map(BufferID p_buffer) override final;
206207
virtual void buffer_unmap(BufferID p_buffer) override final;
208+
virtual uint64_t buffer_get_device_address(BufferID p_buffer) override final;
207209

208210
/*****************/
209211
/**** TEXTURE ****/

misc/extension_api_validation/4.3-stable.expected

+9
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,12 @@ GH-101482
285285
Validate extension JSON: Error: Field 'classes/RichTextLabel/methods/set_table_column_expand/arguments': size changed value in new API, from 3 to 4.
286286

287287
Added optional "shrink" argument. Compatibility method registered.
288+
289+
290+
GH-100062
291+
--------
292+
Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/index_buffer_create/arguments': size changed value in new API, from 4 to 5.
293+
Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/uniform_buffer_create/arguments': size changed value in new API, from 2 to 3.
294+
Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/vertex_buffer_create/arguments': size changed value in new API, from 3 to 4.
295+
296+
Optional argument added. Compatibility methods registered.

servers/rendering/rendering_device.compat.inc

+16
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,18 @@ RenderingDevice::FramebufferFormatID RenderingDevice::_screen_get_framebuffer_fo
143143
return screen_get_framebuffer_format(DisplayServer::MAIN_WINDOW_ID);
144144
}
145145

146+
RID RenderingDevice::_uniform_buffer_create_bind_compat_100062(uint32_t p_size_bytes, const Vector<uint8_t> &p_data) {
147+
return uniform_buffer_create(p_size_bytes, p_data, false);
148+
}
149+
150+
RID RenderingDevice::_vertex_buffer_create_bind_compat_100062(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, bool p_use_as_storage) {
151+
return vertex_buffer_create(p_size_bytes, p_data, p_use_as_storage, false);
152+
}
153+
154+
RID RenderingDevice::_index_buffer_create_bind_compat_100062(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector<uint8_t> &p_data, bool p_use_restart_indices) {
155+
return index_buffer_create(p_size_indices, p_format, p_data, p_use_restart_indices, false);
156+
}
157+
146158
void RenderingDevice::_bind_compatibility_methods() {
147159
ClassDB::bind_compatibility_method(D_METHOD("shader_create_from_bytecode", "binary_data"), &RenderingDevice::_shader_create_from_bytecode_bind_compat_79606);
148160

@@ -166,6 +178,10 @@ void RenderingDevice::_bind_compatibility_methods() {
166178
ClassDB::bind_compatibility_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region"), &RenderingDevice::_draw_list_begin_bind_compat_90993, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()));
167179

168180
ClassDB::bind_compatibility_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "breadcrumb"), &RenderingDevice::_draw_list_begin_bind_compat_98670, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(0));
181+
182+
ClassDB::bind_compatibility_method(D_METHOD("uniform_buffer_create"), &RenderingDevice::_uniform_buffer_create_bind_compat_100062, DEFVAL(Vector<uint8_t>()));
183+
ClassDB::bind_compatibility_method(D_METHOD("vertex_buffer_create"), &RenderingDevice::_vertex_buffer_create_bind_compat_100062, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
184+
ClassDB::bind_compatibility_method(D_METHOD("index_buffer_create"), &RenderingDevice::_index_buffer_create_bind_compat_100062, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
169185
}
170186

171187
#endif

0 commit comments

Comments
 (0)