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 9, 2024
1 parent 0eadbdb commit 0326684
Show file tree
Hide file tree
Showing 11 changed files with 132 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 @@ -60,6 +60,15 @@
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.
</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 @@ -651,6 +660,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 @@ -667,9 +683,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 @@ -1015,9 +1033,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 @@ -1052,9 +1072,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 @@ -2006,6 +2028,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 @@ -2377,6 +2402,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 @@ -6221,6 +6226,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 @@ -3905,6 +3914,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
38 changes: 34 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 @@ -1112,6 +1127,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 @@ -1478,6 +1496,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 @@ -1579,6 +1598,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 @@ -5676,6 +5704,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
Loading

0 comments on commit 0326684

Please sign in to comment.