nvk: Advertise minStorageBufferOffsetAlignment=4 for VKD3D

VKD3D won't enable the VK_EXT_descriptor_buffer path unless we advertise
a minStorageBufferOffsetAlignment of 4.  On the NVIDIA proprietary
driver, they get around the limit by just detecting the driver and
smashing it to 4 internally.  It's better if we set the limit for them
so that we can also adjust NIR's optimizations to not assume higher
alignments.

v2 (mhenning): Rebase and always initialize value of
               instance->ssbo_align_4b

Reviewed-by: Mel Henning <mhenning@darkrefraction.com>
This commit is contained in:
Faith Ekstrand 2025-02-18 17:40:51 -06:00 committed by Mel Henning
parent f3ce8fe90b
commit 3f0fe1538b
8 changed files with 35 additions and 10 deletions

View file

@ -7,6 +7,7 @@
#include "nvk_entrypoints.h"
#include "nvk_device.h"
#include "nvk_device_memory.h"
#include "nvk_instance.h"
#include "nvk_physical_device.h"
#include "nvk_queue.h"
#include "nvkmd/nvkmd.h"
@ -20,13 +21,14 @@ nvk_get_buffer_alignment(const struct nvk_physical_device *pdev,
VkBufferUsageFlags2KHR usage_flags,
VkBufferCreateFlags create_flags)
{
const struct nvk_instance *instance = nvk_physical_device_instance(pdev);
uint32_t alignment = 16;
if (usage_flags & VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR)
alignment = MAX2(alignment, nvk_min_cbuf_alignment(&pdev->info));
if (usage_flags & VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR)
alignment = MAX2(alignment, NVK_MIN_SSBO_ALIGNMENT);
alignment = MAX2(alignment, nvk_min_ssbo_alignment(instance));
if (usage_flags & (VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR |
VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR))

View file

@ -11,6 +11,7 @@
#include "nvk_entrypoints.h"
#include "nvk_format.h"
#include "nvk_image_view.h"
#include "nvk_instance.h"
#include "nvk_physical_device.h"
#include "nvk_sampler.h"
#include "nvkmd/nvkmd.h"
@ -314,12 +315,14 @@ write_dynamic_ubo_desc(struct nvk_descriptor_writer *w,
}
static union nvk_buffer_descriptor
ssbo_desc(struct nvk_addr_range addr_range)
ssbo_desc(const struct nvk_physical_device *pdev,
struct nvk_addr_range addr_range)
{
assert(addr_range.addr % NVK_MIN_SSBO_ALIGNMENT == 0);
const struct nvk_instance *instance = nvk_physical_device_instance(pdev);
const uint32_t min_ssbo_alignment = nvk_min_ssbo_alignment(instance);
assert(addr_range.range <= UINT32_MAX);
addr_range.addr = ROUND_DOWN_TO(addr_range.addr, NVK_MIN_SSBO_ALIGNMENT);
addr_range.addr = ROUND_DOWN_TO(addr_range.addr, min_ssbo_alignment);
addr_range.range = align(addr_range.range, NVK_SSBO_BOUNDS_CHECK_ALIGNMENT);
return (union nvk_buffer_descriptor) { .addr = {
@ -337,7 +340,7 @@ write_ssbo_desc(struct nvk_descriptor_writer *w,
struct nvk_addr_range addr_range =
nvk_buffer_addr_range(buffer, info->offset, info->range);
const union nvk_buffer_descriptor desc = ssbo_desc(addr_range);
const union nvk_buffer_descriptor desc = ssbo_desc(w->pdev, addr_range);
write_desc(w, binding, elem, &desc, sizeof(desc));
}
@ -353,7 +356,7 @@ write_dynamic_ssbo_desc(struct nvk_descriptor_writer *w,
const struct nvk_descriptor_set_binding_layout *binding_layout =
&w->layout->binding[binding];
w->set->dynamic_buffers[binding_layout->dynamic_buffer_index + elem] =
ssbo_desc(addr_range);
ssbo_desc(w->pdev, addr_range);
}
static struct nvk_edb_buffer_view_descriptor
@ -1207,7 +1210,7 @@ nvk_GetDescriptorEXT(VkDevice _device,
.range = pDescriptorInfo->data.pStorageBuffer->range,
};
}
union nvk_buffer_descriptor desc = ssbo_desc(addr_range);
union nvk_buffer_descriptor desc = ssbo_desc(pdev, addr_range);
assert(sizeof(desc) <= dataSize);
memcpy(pDescriptor, &desc, sizeof(desc));
break;

View file

@ -130,6 +130,15 @@ nvk_init_dri_options(struct nvk_instance *instance)
instance->debug_flags |= NVK_DEBUG_ZERO_MEMORY;
instance->app_layer = driQueryOptionstr(&instance->dri_options, "nvk_app_layer");
/* VKD3D really wants a min SSBO alignment of 4B instead of 16B because
* it's required for structure buffers. If we don't do this, it'll hack
* it behind our back and we don't really want that. We just have to trust
* it to not misalign 64-bit atomics.
*/
instance->ssbo_align_4b =
(instance->vk.app_info.engine_name != NULL &&
strcmp(instance->vk.app_info.engine_name, "vkd3d") == 0);
}
VKAPI_ATTR VkResult VKAPI_CALL

View file

@ -22,8 +22,15 @@ struct nvk_instance {
uint8_t driver_build_sha[BLAKE3_KEY_LEN];
uint32_t force_vk_vendor;
bool ssbo_align_4b;
};
VK_DEFINE_HANDLE_CASTS(nvk_instance, vk.base, VkInstance, VK_OBJECT_TYPE_INSTANCE)
static inline uint32_t
nvk_min_ssbo_alignment(const struct nvk_instance *instance)
{
return instance->ssbo_align_4b ? 4 : 16;
}
#endif

View file

@ -877,7 +877,7 @@ nvk_get_device_properties(const struct nvk_instance *instance,
.minMemoryMapAlignment = os_page_size,
.minTexelBufferOffsetAlignment = NVK_MIN_TEXEL_BUFFER_ALIGNMENT,
.minUniformBufferOffsetAlignment = nvk_min_cbuf_alignment(info),
.minStorageBufferOffsetAlignment = NVK_MIN_SSBO_ALIGNMENT,
.minStorageBufferOffsetAlignment = nvk_min_ssbo_alignment(instance),
.minTexelOffset = -8,
.maxTexelOffset = 7,
.minTexelGatherOffset = -32,

View file

@ -39,6 +39,7 @@ struct nvk_physical_device {
struct vk_physical_device vk;
struct nv_device_info info;
enum nvk_debug debug_flags;
bool ssbo_align_4b;
struct nvkmd_pdev *nvkmd;

View file

@ -15,7 +15,6 @@
#define NVK_MAX_DYNAMIC_BUFFERS 64
#define NVK_MAX_RTS 8
#define NVK_MAX_SAMPLES 8
#define NVK_MIN_SSBO_ALIGNMENT 16
#define NVK_MIN_TEXEL_BUFFER_ALIGNMENT 16
#define NVK_MIN_UBO_ALIGNMENT 64
#define NVK_MAX_VIEWPORTS 16

View file

@ -7,6 +7,7 @@
#include "nvk_cmd_buffer.h"
#include "nvk_descriptor_set_layout.h"
#include "nvk_device.h"
#include "nvk_instance.h"
#include "nvk_mme.h"
#include "nvk_physical_device.h"
#include "nvk_sampler.h"
@ -68,6 +69,7 @@ shared_var_info(const struct glsl_type *type, unsigned *size, unsigned *align)
uint64_t
nvk_physical_device_compiler_flags(const struct nvk_physical_device *pdev)
{
const struct nvk_instance *instance = nvk_physical_device_instance(pdev);
bool no_cbufs = pdev->debug_flags & NVK_DEBUG_NO_CBUF;
bool use_edb_buffer_views = nvk_use_edb_buffer_views(pdev);
uint64_t nak_flags = nak_debug_flags(pdev->nak);
@ -76,6 +78,7 @@ nvk_physical_device_compiler_flags(const struct nvk_physical_device *pdev)
return ((uint64_t)no_cbufs << 12)
| ((uint64_t)use_edb_buffer_views << 13)
| ((uint64_t)instance->ssbo_align_4b << 14)
| (nak_flags << 48);
}
@ -138,13 +141,14 @@ nvk_get_spirv_options(struct vk_physical_device *vk_pdev,
{
const struct nvk_physical_device *pdev =
container_of(vk_pdev, struct nvk_physical_device, vk);
const struct nvk_instance *instance = nvk_physical_device_instance(pdev);
return (struct spirv_to_nir_options) {
.ssbo_addr_format = nvk_ssbo_addr_format(pdev, rs),
.phys_ssbo_addr_format = nir_address_format_64bit_global,
.ubo_addr_format = nvk_ubo_addr_format(pdev, rs),
.shared_addr_format = nir_address_format_32bit_offset,
.min_ssbo_alignment = NVK_MIN_SSBO_ALIGNMENT,
.min_ssbo_alignment = nvk_min_ssbo_alignment(instance),
.min_ubo_alignment = nvk_min_cbuf_alignment(&pdev->info),
};
}