Assassin's Creed: Valhalla sets a null index buffer, but Windows allows null for root descriptors too.
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/command.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 6eddcfa2..492f0bec 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4481,11 +4481,20 @@ static void d3d12_command_list_set_root_cbv(struct d3d12_command_list *list, root_parameter = root_signature_get_root_descriptor(root_signature, index); assert(root_parameter->parameter_type == D3D12_ROOT_PARAMETER_TYPE_CBV);
- resource = vkd3d_gpu_va_allocator_dereference(&list->device->gpu_va_allocator, gpu_address); - buffer_info.buffer = resource->u.vk_buffer; - buffer_info.offset = gpu_address - resource->gpu_address; - buffer_info.range = resource->desc.Width - buffer_info.offset; - buffer_info.range = min(buffer_info.range, vk_info->device_limits.maxUniformBufferRange); + if (gpu_address) + { + resource = vkd3d_gpu_va_allocator_dereference(&list->device->gpu_va_allocator, gpu_address); + buffer_info.buffer = resource->u.vk_buffer; + buffer_info.offset = gpu_address - resource->gpu_address; + buffer_info.range = resource->desc.Width - buffer_info.offset; + buffer_info.range = min(buffer_info.range, vk_info->device_limits.maxUniformBufferRange); + } + else + { + buffer_info.buffer = list->device->null_resources.vk_buffer; + buffer_info.offset = 0; + buffer_info.range = VK_WHOLE_SIZE; + }
if (vk_info->KHR_push_descriptor) {
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/command.c | 5 +++-- libs/vkd3d/resource.c | 15 ++++++++++++++- libs/vkd3d/vkd3d_private.h | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 492f0bec..c20b2d88 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4556,13 +4556,14 @@ static void d3d12_command_list_set_root_descriptor(struct d3d12_command_list *li assert(root_parameter->parameter_type != D3D12_ROOT_PARAMETER_TYPE_CBV);
/* FIXME: Re-use buffer views. */ - if (!vkd3d_create_raw_buffer_view(list->device, gpu_address, &vk_buffer_view)) + if (!vkd3d_create_raw_buffer_view(list->device, gpu_address, + root_parameter->parameter_type == D3D12_ROOT_PARAMETER_TYPE_UAV, &vk_buffer_view)) { ERR("Failed to create buffer view.\n"); return; }
- if (!(d3d12_command_allocator_add_buffer_view(list->allocator, vk_buffer_view))) + if (vk_buffer_view && !(d3d12_command_allocator_add_buffer_view(list->allocator, vk_buffer_view))) { ERR("Failed to add buffer view.\n"); VK_CALL(vkDestroyBufferView(vk_device, vk_buffer_view, NULL)); diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index c282f116..b5607fb2 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -3274,12 +3274,25 @@ void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *d }
bool vkd3d_create_raw_buffer_view(struct d3d12_device *device, - D3D12_GPU_VIRTUAL_ADDRESS gpu_address, VkBufferView *vk_buffer_view) + D3D12_GPU_VIRTUAL_ADDRESS gpu_address, bool is_uav, VkBufferView *vk_buffer_view) { const struct vkd3d_format *format; struct d3d12_resource *resource;
format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false); + + if (!gpu_address) + { + if (device->vk_info.EXT_robustness2) + { + *vk_buffer_view = VK_NULL_HANDLE; + return true; + } + WARN("Creating null buffer view.\n"); + return vkd3d_create_vk_buffer_view(device, is_uav ? device->null_resources.vk_storage_buffer + : device->null_resources.vk_buffer, format, 0, VK_WHOLE_SIZE, vk_buffer_view); + } + resource = vkd3d_gpu_va_allocator_dereference(&device->gpu_va_allocator, gpu_address); assert(d3d12_resource_is_buffer(resource)); return vkd3d_create_vk_buffer_view(device, resource->u.vk_buffer, format, diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 1a277a47..4300d6d3 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -762,7 +762,7 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler, struct d3d12_device * void d3d12_desc_write_atomic(struct d3d12_desc *dst, const struct d3d12_desc *src, struct d3d12_device *device);
bool vkd3d_create_raw_buffer_view(struct d3d12_device *device, - D3D12_GPU_VIRTUAL_ADDRESS gpu_address, VkBufferView *vk_buffer_view); + D3D12_GPU_VIRTUAL_ADDRESS gpu_address, bool is_uav, VkBufferView *vk_buffer_view); HRESULT vkd3d_create_static_sampler(struct d3d12_device *device, const D3D12_STATIC_SAMPLER_DESC *desc, VkSampler *vk_sampler);
From: Conor McCarthy cmccarthy@codeweavers.com
--- tests/d3d12.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 8a7e6b30..6a8698ba 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -16423,7 +16423,7 @@ static void test_update_root_descriptors(void) { D3D12_ROOT_SIGNATURE_DESC root_signature_desc; D3D12_GPU_VIRTUAL_ADDRESS cb_va, uav_va; - D3D12_ROOT_PARAMETER root_parameters[2]; + D3D12_ROOT_PARAMETER root_parameters[3]; ID3D12GraphicsCommandList *command_list; ID3D12RootSignature *root_signature; ID3D12PipelineState *pipeline_state; @@ -16496,8 +16496,12 @@ static void test_update_root_descriptors(void) root_parameters[1].Descriptor.ShaderRegister = 0; root_parameters[1].Descriptor.RegisterSpace = 0; root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + root_parameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + root_parameters[2].Descriptor.ShaderRegister = 0; + root_parameters[2].Descriptor.RegisterSpace = 0; + root_parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; memset(&root_signature_desc, 0, sizeof(root_signature_desc)); - root_signature_desc.NumParameters = 2; + root_signature_desc.NumParameters = 3; root_signature_desc.pParameters = root_parameters; hr = create_root_signature(device, &root_signature_desc, &root_signature); ok(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); @@ -16507,6 +16511,9 @@ static void test_update_root_descriptors(void)
ID3D12GraphicsCommandList_SetPipelineState(command_list, pipeline_state); ID3D12GraphicsCommandList_SetComputeRootSignature(command_list, root_signature); + ID3D12GraphicsCommandList_SetComputeRootConstantBufferView(command_list, 0, 0); + ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(command_list, 1, 0); + ID3D12GraphicsCommandList_SetComputeRootShaderResourceView(command_list, 2, 0); for (i = 0; i < ARRAY_SIZE(input); ++i) { ID3D12GraphicsCommandList_SetComputeRootConstantBufferView(command_list,
From: Conor McCarthy cmccarthy@codeweavers.com
VK_EXT_robustness2 does not support null index buffers so we only warn and return immediately. --- libs/vkd3d/command.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index c20b2d88..3dcc817d 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4654,6 +4654,11 @@ static void STDMETHODCALLTYPE d3d12_command_list_IASetIndexBuffer(ID3D12Graphics WARN("Ignoring NULL index buffer view.\n"); return; } + if (!view->BufferLocation) + { + WARN("Ignoring index buffer location 0.\n"); + return; + }
vk_procs = &list->device->vk_procs;
From: Conor McCarthy cmccarthy@codeweavers.com
Only verify it doesn't crash. --- tests/d3d12.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 6a8698ba..bfc10f79 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -5365,7 +5365,6 @@ static void test_draw_indexed_instanced(void)
ib = create_upload_buffer(context.device, sizeof(indices), indices);
- ibv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(ib); ibv.SizeInBytes = sizeof(indices); ibv.Format = DXGI_FORMAT_R16_UINT;
@@ -5382,6 +5381,9 @@ static void test_draw_indexed_instanced(void) ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_IASetIndexBuffer(command_list, NULL); + ibv.BufferLocation = 0; + ID3D12GraphicsCommandList_IASetIndexBuffer(command_list, &ibv); + ibv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(ib); ID3D12GraphicsCommandList_IASetIndexBuffer(command_list, &ibv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect);
bool vkd3d_create_raw_buffer_view(struct d3d12_device *device, - D3D12_GPU_VIRTUAL_ADDRESS gpu_address, VkBufferView *vk_buffer_view) + D3D12_GPU_VIRTUAL_ADDRESS gpu_address, bool is_uav, VkBufferView *vk_buffer_view)
More often than not, boolean flags are best avoided. Could we pass the parameter type here instead?