Skip to content

Commit

Permalink
Implement Buffer Device Address for Rendering Device Vulkan and Direc…
Browse files Browse the repository at this point in the history
…tX12
  • Loading branch information
thimenesup committed Dec 20, 2024
1 parent fafc073 commit 93fdcc3
Show file tree
Hide file tree
Showing 13 changed files with 169 additions and 14 deletions.
28 changes: 28 additions & 0 deletions doc/classes/RenderingDevice.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@
[/codeblock]
</description>
</method>
<method name="buffer_get_device_address">
<return type="int" />
<param index="0" name="buffer" type="RID" />
<description>
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.
You must check that the GPU supports this functionality by calling [method has_feature] with [constant SUPPORTS_BUFFER_ADDRESS] as a parameter.
</description>
</method>
<method name="buffer_update">
<return type="int" enum="Error" />
<param index="0" name="buffer" type="RID" />
Expand Down Expand Up @@ -672,6 +681,13 @@
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].
</description>
</method>
<method name="has_feature" qualifiers="const">
<return type="bool" />
<param index="0" name="feature" type="int" enum="RenderingDevice.Features" />
<description>
Returns [code]true[/code] if the [param feature] is supported by the GPU.
</description>
</method>
<method name="index_array_create">
<return type="RID" />
<param index="0" name="index_buffer" type="RID" />
Expand All @@ -688,9 +704,11 @@
<param index="1" name="format" type="int" enum="RenderingDevice.IndexBufferFormat" />
<param index="2" name="data" type="PackedByteArray" default="PackedByteArray()" />
<param index="3" name="use_restart_indices" type="bool" default="false" />
<param index="4" name="enable_shader_address" type="bool" default="false" />
<description>
Creates a new index buffer. It can be accessed with the RID that is returned.
Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method.
Optionally, set [param enable_shader_address] if you wish to use [method buffer_get_device_address] functionality and the GPU supports it.
</description>
</method>
<method name="limit_get" qualifiers="const">
Expand Down Expand Up @@ -1056,9 +1074,11 @@
<return type="RID" />
<param index="0" name="size_bytes" type="int" />
<param index="1" name="data" type="PackedByteArray" default="PackedByteArray()" />
<param index="2" name="enable_shader_address" type="bool" default="false" />
<description>
Creates a new uniform buffer. It can be accessed with the RID that is returned.
Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method.
Optionally, set [param enable_shader_address] if you wish to use [method buffer_get_device_address] functionality and the GPU supports it.
</description>
</method>
<method name="uniform_set_create">
Expand Down Expand Up @@ -1093,9 +1113,11 @@
<param index="0" name="size_bytes" type="int" />
<param index="1" name="data" type="PackedByteArray" default="PackedByteArray()" />
<param index="2" name="use_as_storage" type="bool" default="false" />
<param index="3" name="enable_shader_address" type="bool" default="false" />
<description>
It can be accessed with the RID that is returned.
Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method.
Optionally, set [param enable_shader_address] if you wish to use [method buffer_get_device_address] functionality and the GPU supports it.
</description>
</method>
<method name="vertex_format_create">
Expand Down Expand Up @@ -2047,6 +2069,9 @@
</constant>
<constant name="STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT" value="1" enum="StorageBufferUsage" is_bitfield="true">
</constant>
<constant name="STORAGE_BUFFER_USAGE_SHADER_DEVICE_ADDRESS" value="2" enum="StorageBufferUsage" is_bitfield="true">
Allows usage of [method buffer_get_device_address] on supported GPUs.
</constant>
<constant name="UNIFORM_TYPE_SAMPLER" value="0" enum="UniformType">
Sampler uniform.
</constant>
Expand Down Expand Up @@ -2418,6 +2443,9 @@
<constant name="PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT" value="2" enum="PipelineSpecializationConstantType">
Floating-point specialization constant.
</constant>
<constant name="SUPPORTS_BUFFER_ADDRESS" value="4" enum="Features">
Features support for buffer device address extension.
</constant>
<constant name="LIMIT_MAX_BOUND_UNIFORM_SETS" value="0" enum="Limit">
Maximum number of uniform sets that can be bound at a given time.
</constant>
Expand Down
7 changes: 7 additions & 0 deletions drivers/d3d12/rendering_device_driver_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,11 @@ void RenderingDeviceDriverD3D12::buffer_unmap(BufferID p_buffer) {
buf_info->resource->Unmap(0, &VOID_RANGE);
}

uint64_t RenderingDeviceDriverD3D12::buffer_get_device_address(BufferID p_buffer) {
const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;
return buf_info->resource->GetGPUVirtualAddress();
}

/*****************/
/**** TEXTURE ****/
/*****************/
Expand Down Expand Up @@ -6271,6 +6276,8 @@ bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) {
return vrs_capabilities.ss_image_supported;
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
return true;
case SUPPORTS_BUFFER_ADDRESS:
return true;
default:
return false;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/d3d12/rendering_device_driver_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
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 uint64_t buffer_get_device_address(BufferID p_buffer) override final;

/*****************/
/**** TEXTURE ****/
Expand Down
1 change: 1 addition & 0 deletions drivers/metal/rendering_device_driver_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
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 uint64_t buffer_get_device_address(BufferID p_buffer) override final;

#pragma mark - Texture

Expand Down
11 changes: 11 additions & 0 deletions drivers/metal/rendering_device_driver_metal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,15 @@ _FORCE_INLINE_ MTLSize mipmapLevelSizeFromSize(MTLSize p_size, NSUInteger p_leve
// Nothing to do.
}

uint64_t RenderingDeviceDriverMetal::buffer_get_device_address(BufferID p_buffer) {
if (@available(iOS 16.0, macOS 13.0, *)) {
id<MTLBuffer> obj = rid::get(p_buffer);
return obj.gpuAddress;
} else {
return 0;
}
}

#pragma mark - Texture

#pragma mark - Format Conversions
Expand Down Expand Up @@ -3947,6 +3956,8 @@ bool isArrayTexture(MTLTextureType p_type) {
return false;
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
return true;
case SUPPORTS_BUFFER_ADDRESS:
return false;
default:
return false;
}
Expand Down
46 changes: 42 additions & 4 deletions drivers/vulkan/rendering_device_driver_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() {
_register_requested_device_extension(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME, false);
_register_requested_device_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);
_register_requested_device_extension(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, false);
_register_requested_device_extension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, false);

if (Engine::get_singleton()->is_generate_spirv_debug_info_enabled()) {
_register_requested_device_extension(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME, true);
Expand Down Expand Up @@ -730,6 +731,7 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
void *next_features = nullptr;
VkPhysicalDeviceVulkan12Features device_features_vk_1_2 = {};
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {};
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_address_features = {};
VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features = {};
VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {};
VkPhysicalDeviceMultiviewFeatures multiview_features = {};
Expand All @@ -740,10 +742,17 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
device_features_vk_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
device_features_vk_1_2.pNext = next_features;
next_features = &device_features_vk_1_2;
} else if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {
shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;
shader_features.pNext = next_features;
next_features = &shader_features;
} else {
if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {
shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;
shader_features.pNext = next_features;
next_features = &shader_features;
}
if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
buffer_address_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;
buffer_address_features.pNext = next_features;
next_features = &buffer_address_features;
}
}

if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {
Expand Down Expand Up @@ -783,11 +792,17 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
shader_capabilities.shader_float16_is_supported = device_features_vk_1_2.shaderFloat16;
shader_capabilities.shader_int8_is_supported = device_features_vk_1_2.shaderInt8;
}
if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
buffer_device_address_support = device_features_vk_1_2.bufferDeviceAddress;
}
} else {
if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {
shader_capabilities.shader_float16_is_supported = shader_features.shaderFloat16;
shader_capabilities.shader_int8_is_supported = shader_features.shaderInt8;
}
if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
buffer_device_address_support = buffer_address_features.bufferDeviceAddress;
}
}

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

VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_address_features = {};
if (buffer_device_address_support) {
buffer_address_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;
buffer_address_features.pNext = create_info_next;
buffer_address_features.bufferDeviceAddress = buffer_device_address_support;
create_info_next = &buffer_address_features;
}

VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features = {};
if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) {
vrs_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;
Expand Down Expand Up @@ -1112,6 +1135,9 @@ Error RenderingDeviceDriverVulkan::_initialize_allocator() {
if (use_1_3_features) {
allocator_info.flags |= VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT;
}
if (buffer_device_address_support) {
allocator_info.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
}
VkResult err = vmaCreateAllocator(&allocator_info, &allocator);
ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "vmaCreateAllocator failed with error " + itos(err) + ".");

Expand Down Expand Up @@ -1487,6 +1513,7 @@ static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_STORAGE_BIT, VK_BUFFER_USAGE_
static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_INDEX_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT));
static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_VERTEX_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_INDIRECT_BIT, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT));
static_assert(ENUM_MEMBERS_EQUAL(RDD::BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT));

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

uint64_t RenderingDeviceDriverVulkan::buffer_get_device_address(BufferID p_buffer) {
const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;
VkBufferDeviceAddressInfo address_info = {};
address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
address_info.pNext = nullptr;
address_info.buffer = buf_info->vk_buffer;
return vkGetBufferDeviceAddress(vk_device, &address_info);
}

/*****************/
/**** TEXTURE ****/
/*****************/
Expand Down Expand Up @@ -5874,6 +5910,8 @@ bool RenderingDeviceDriverVulkan::has_feature(Features p_feature) {
return vrs_capabilities.attachment_vrs_supported && physical_device_features.shaderStorageImageExtendedFormats;
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
return true;
case SUPPORTS_BUFFER_ADDRESS:
return buffer_device_address_support;
default:
return false;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/vulkan/rendering_device_driver_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
VRSCapabilities vrs_capabilities;
ShaderCapabilities shader_capabilities;
StorageBufferCapabilities storage_buffer_capabilities;
bool buffer_device_address_support = false;
bool pipeline_cache_control_support = false;
bool device_fault_support = false;
#if defined(VK_TRACK_DEVICE_MEMORY)
Expand Down Expand Up @@ -204,6 +205,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
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 uint64_t buffer_get_device_address(BufferID p_buffer) override final;

/*****************/
/**** TEXTURE ****/
Expand Down
9 changes: 9 additions & 0 deletions misc/extension_api_validation/4.3-stable.expected
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,12 @@ Validate extension JSON: Error: Field 'classes/PointLight2D/properties/texture':

Property hints modified to disallow resource types that don't work. The types allowed are now more restricted, but this change only impacts the editor and not the actual exposed API. No adjustments should be necessary.
Decal properties were previously changed from Texture to Texture2D in 4.2, so we need to silence those warnings too.


GH-100062
--------
Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/index_buffer_create/arguments': size changed value in new API, from 4 to 5.
Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/uniform_buffer_create/arguments': size changed value in new API, from 2 to 3.
Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/vertex_buffer_create/arguments': size changed value in new API, from 3 to 4.

Optional argument added. Compatibility method registered.
16 changes: 16 additions & 0 deletions servers/rendering/rendering_device.compat.inc
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ RenderingDevice::FramebufferFormatID RenderingDevice::_screen_get_framebuffer_fo
return screen_get_framebuffer_format(DisplayServer::MAIN_WINDOW_ID);
}

RID RenderingDevice::_uniform_buffer_create_compat_100062(uint32_t p_size_bytes, const Vector<uint8_t> &p_data) {
return uniform_buffer_create(p_size_bytes, p_data, false);
}

RID RenderingDevice::_vertex_buffer_create_compat_100062(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, bool p_use_as_storage) {
return vertex_buffer_create(p_size_bytes, p_data, p_use_as_storage, false);
}

RID RenderingDevice::_index_buffer_create_compat_100062(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector<uint8_t> &p_data, bool p_use_restart_indices) {
return index_buffer_create(p_size_indices, p_format, p_data, p_use_restart_indices, false);
}

void RenderingDevice::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("shader_create_from_bytecode", "binary_data"), &RenderingDevice::_shader_create_from_bytecode_bind_compat_79606);

Expand All @@ -166,6 +178,10 @@ void RenderingDevice::_bind_compatibility_methods() {
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()));

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));

ClassDB::bind_compatibility_method(D_METHOD("uniform_buffer_create"), &RenderingDevice::_uniform_buffer_create_compat_100062, DEFVAL(Vector<uint8_t>()));
ClassDB::bind_compatibility_method(D_METHOD("vertex_buffer_create"), &RenderingDevice::_vertex_buffer_create_compat_100062, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
ClassDB::bind_compatibility_method(D_METHOD("index_buffer_create"), &RenderingDevice::_index_buffer_create_compat_100062, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
}

#endif
Loading

0 comments on commit 93fdcc3

Please sign in to comment.