diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index e04d3b85..4e7e338c 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -61,6 +61,7 @@ struct vkd3d_shader_resource_binding { enum vkd3d_descriptor_type type; unsigned int register_index; + bool is_buffer; uint32_t descriptor_set; uint32_t binding; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 5c5dee10..31dec118 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1682,11 +1682,13 @@ struct vkd3d_descriptor_binding }; static struct vkd3d_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding( - struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg) + struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, + enum vkd3d_shader_resource_type resource_type) { enum vkd3d_descriptor_type descriptor_type; struct vkd3d_descriptor_binding vk_binding; unsigned int reg_idx = reg->idx[0].offset; + bool is_buffer_resource; unsigned int i; descriptor_type = VKD3D_DESCRIPTOR_TYPE_UNKNOWN; @@ -1701,13 +1703,15 @@ static struct vkd3d_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_bindin else FIXME("Unhandled register type %#x.\n", reg->type); + is_buffer_resource = resource_type == VKD3D_SHADER_RESOURCE_BUFFER; if (descriptor_type != VKD3D_DESCRIPTOR_TYPE_UNKNOWN) { for (i = 0; i < compiler->binding_count; ++i) { const struct vkd3d_shader_resource_binding *current = &compiler->bindings[i]; - if (current->type == descriptor_type && current->register_index == reg_idx) + if (current->type == descriptor_type && current->register_index == reg_idx + && current->is_buffer == is_buffer_resource) { vk_binding.set = current->descriptor_set; vk_binding.binding = current->binding; @@ -1724,12 +1728,13 @@ static struct vkd3d_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_bindin } static void vkd3d_dxbc_compiler_emit_descriptor_binding(struct vkd3d_dxbc_compiler *compiler, - uint32_t variable_id, const struct vkd3d_shader_register *reg) + uint32_t variable_id, const struct vkd3d_shader_register *reg, + enum vkd3d_shader_resource_type resource_type) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; struct vkd3d_descriptor_binding vk_binding; - vk_binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg); + vk_binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, resource_type); vkd3d_spirv_build_op_decorate1(builder, variable_id, SpvDecorationDescriptorSet, vk_binding.set); vkd3d_spirv_build_op_decorate1(builder, variable_id, SpvDecorationBinding, vk_binding.binding); } @@ -2701,7 +2706,7 @@ static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compi var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, pointer_type_id, storage_class, 0); - vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg); + vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg, VKD3D_SHADER_RESOURCE_BUFFER); vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); @@ -2759,7 +2764,7 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ptr_type_id, storage_class, 0); - vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg); + vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg, VKD3D_SHADER_RESOURCE_NONE); vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); @@ -2863,7 +2868,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ptr_type_id, storage_class, 0); - vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg); + vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg, semantic->resource_type); vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index f6d6059e..3f627add 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -2274,12 +2274,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_SetGraphicsRootSignature(ID3D12 static bool vk_write_descriptor_set_from_d3d12_desc(VkWriteDescriptorSet *vk_descriptor_write, VkDescriptorImageInfo *vk_image_info, struct d3d12_desc *descriptor, - VkDescriptorSet vk_descriptor_set, uint32_t vk_binding) + VkDescriptorSet vk_descriptor_set, uint32_t vk_binding, unsigned int index) { vk_descriptor_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; vk_descriptor_write->pNext = NULL; vk_descriptor_write->dstSet = vk_descriptor_set; - vk_descriptor_write->dstBinding = vk_binding; + vk_descriptor_write->dstBinding = vk_binding + index; vk_descriptor_write->dstArrayElement = 0; vk_descriptor_write->descriptorCount = 1; vk_descriptor_write->descriptorType = descriptor->vk_descriptor_type; @@ -2287,6 +2287,17 @@ static bool vk_write_descriptor_set_from_d3d12_desc(VkWriteDescriptorSet *vk_des vk_descriptor_write->pBufferInfo = NULL; vk_descriptor_write->pTexelBufferView = NULL; + if (descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SRV + || descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_UAV) + { + /* We use separate bindings for buffer and texture SRVs/UAVs. + * See d3d12_root_signature_init(). */ + vk_descriptor_write->dstBinding = vk_binding + 2 * index; + if (descriptor->vk_descriptor_type != VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + && descriptor->vk_descriptor_type != VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) + ++vk_descriptor_write->dstBinding; + } + if (descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_CBV) { vk_descriptor_write->pBufferInfo = &descriptor->u.vk_cbv_info; @@ -2369,7 +2380,7 @@ static void d3d12_command_list_set_descriptor_table(struct d3d12_command_list *l for (j = 0; j < range->descriptor_count; ++j, ++descriptor) { if (!vk_write_descriptor_set_from_d3d12_desc(current_descriptor_write, - current_image_info, descriptor, descriptor_set, range->binding + j)) + current_image_info, descriptor, descriptor_set, range->binding, j)) continue; ++descriptor_count; diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 76dc1cc2..9f7e219e 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -221,14 +221,15 @@ static enum vkd3d_shader_visibility vkd3d_shader_visibility_from_d3d12(D3D12_SHA } } -static VkDescriptorType vk_descriptor_type_from_d3d12_range_type(D3D12_DESCRIPTOR_RANGE_TYPE type) +static VkDescriptorType vk_descriptor_type_from_d3d12_range_type(D3D12_DESCRIPTOR_RANGE_TYPE type, + bool is_buffer) { switch (type) { case D3D12_DESCRIPTOR_RANGE_TYPE_SRV: - return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + return is_buffer ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; case D3D12_DESCRIPTOR_RANGE_TYPE_UAV: - return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; /* FIXME: Add support for images. */ + return is_buffer ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; case D3D12_DESCRIPTOR_RANGE_TYPE_CBV: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER: @@ -292,10 +293,12 @@ static enum vkd3d_descriptor_type vkd3d_descriptor_type_from_d3d12_root_paramete } static bool vk_binding_from_d3d12_descriptor_range(struct VkDescriptorSetLayoutBinding *binding_desc, - const D3D12_DESCRIPTOR_RANGE *descriptor_range, uint32_t vk_binding) + const D3D12_DESCRIPTOR_RANGE *descriptor_range, D3D12_SHADER_VISIBILITY shader_visibility, + bool is_buffer, uint32_t vk_binding) { binding_desc->binding = vk_binding; - binding_desc->descriptorType = vk_descriptor_type_from_d3d12_range_type(descriptor_range->RangeType); + binding_desc->descriptorType + = vk_descriptor_type_from_d3d12_range_type(descriptor_range->RangeType, is_buffer); binding_desc->descriptorCount = 1; if (descriptor_range->RegisterSpace) @@ -306,6 +309,9 @@ static bool vk_binding_from_d3d12_descriptor_range(struct VkDescriptorSetLayoutB if (descriptor_range->OffsetInDescriptorsFromTableStart != D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) FIXME("Unhandled offset %#x.\n", descriptor_range->OffsetInDescriptorsFromTableStart); + binding_desc->stageFlags = stage_flags_from_visibility(shader_visibility); + binding_desc->pImmutableSamplers = NULL; + return true; } @@ -500,26 +506,44 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat return S_OK; } +static void d3d12_root_signature_append_vk_binding(struct d3d12_root_signature *root_signature, + enum vkd3d_descriptor_type descriptor_type, unsigned int register_idx, + bool buffer_descriptor, uint32_t *descriptor_idx) +{ + uint32_t binding = *descriptor_idx; + + root_signature->descriptor_mapping[binding].type = descriptor_type; + root_signature->descriptor_mapping[binding].register_index = register_idx; + root_signature->descriptor_mapping[binding].is_buffer = buffer_descriptor; + root_signature->descriptor_mapping[binding].descriptor_set = 0; + root_signature->descriptor_mapping[binding].binding = binding; + + *descriptor_idx += 1; +} + static uint32_t d3d12_root_signature_assign_vk_bindings(struct d3d12_root_signature *root_signature, enum vkd3d_descriptor_type descriptor_type, unsigned int base_register_idx, - unsigned int binding_count, uint32_t *descriptor_idx) + unsigned int binding_count, bool duplicate_descriptors, uint32_t *descriptor_idx) { - uint32_t first_binding, binding; + bool is_buffer_descriptor; + uint32_t first_binding; unsigned int i; + is_buffer_descriptor = descriptor_type == VKD3D_DESCRIPTOR_TYPE_CBV; + duplicate_descriptors = (descriptor_type == VKD3D_DESCRIPTOR_TYPE_SRV + || descriptor_type == VKD3D_DESCRIPTOR_TYPE_UAV) + && duplicate_descriptors; + first_binding = *descriptor_idx; for (i = 0; i < binding_count; ++i) { - binding = *descriptor_idx; + if (duplicate_descriptors) + d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, + base_register_idx + i, true, descriptor_idx); - root_signature->descriptor_mapping[binding].type = descriptor_type; - root_signature->descriptor_mapping[binding].register_index = base_register_idx + i; - root_signature->descriptor_mapping[binding].descriptor_set = 0; - root_signature->descriptor_mapping[binding].binding = binding; - - *descriptor_idx += 1; + d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, + base_register_idx + i, is_buffer_descriptor, descriptor_idx); } - return first_binding; } @@ -564,6 +588,12 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa goto fail; } + /* XXX: Vulkan buffer and image descriptors have different types. In order + * to preserve compatibility between Vulkan resource bindings for the same + * root signature, we create descriptor set layouts with two bindings for + * each SRV and UAV. */ + info.descriptor_count += info.srv_count + info.uav_count; + if (!(binding_desc = vkd3d_calloc(info.descriptor_count, sizeof(*binding_desc)))) { hr = E_OUTOFMEMORY; @@ -619,20 +649,36 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa vk_binding = d3d12_root_signature_assign_vk_bindings(root_signature, vkd3d_descriptor_type_from_d3d12_range_type(descriptor_range->RangeType), descriptor_range->BaseShaderRegister, descriptor_range->NumDescriptors, - &descriptor_idx); + true, &descriptor_idx); /* Unroll descriptor range. */ for (k = 0; k < descriptor_range->NumDescriptors; ++k) { - if (!vk_binding_from_d3d12_descriptor_range(cur_binding, descriptor_range, vk_binding + k)) + uint32_t vk_current_binding = vk_binding + k; + + if (descriptor_range->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV + || descriptor_range->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV) + { + vk_current_binding = vk_binding + 2 * k; + + /* Assign binding for image view. */ + if (!vk_binding_from_d3d12_descriptor_range(cur_binding, + descriptor_range, p->ShaderVisibility, false, vk_current_binding + 1)) + { + hr = E_NOTIMPL; + goto fail; + } + + ++cur_binding; + } + + if (!vk_binding_from_d3d12_descriptor_range(cur_binding, + descriptor_range, p->ShaderVisibility, true, vk_current_binding)) { hr = E_NOTIMPL; goto fail; } - cur_binding->stageFlags = stage_flags_from_visibility(p->ShaderVisibility); - cur_binding->pImmutableSamplers = NULL; - ++cur_binding; } @@ -654,7 +700,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa } cur_binding->binding = d3d12_root_signature_assign_vk_bindings(root_signature, vkd3d_descriptor_type_from_d3d12_root_parameter_type(p->ParameterType), - p->u.Descriptor.ShaderRegister, 1, &descriptor_idx); + p->u.Descriptor.ShaderRegister, 1, false, &descriptor_idx); cur_binding->descriptorType = vk_descriptor_type_from_d3d12_root_parameter(p->ParameterType); cur_binding->descriptorCount = 1; cur_binding->stageFlags = stage_flags_from_visibility(p->ShaderVisibility); @@ -692,7 +738,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa goto fail; cur_binding->binding = d3d12_root_signature_assign_vk_bindings(root_signature, - VKD3D_DESCRIPTOR_TYPE_SAMPLER, s->ShaderRegister, 1, &descriptor_idx); + VKD3D_DESCRIPTOR_TYPE_SAMPLER, s->ShaderRegister, 1, false, &descriptor_idx); cur_binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; cur_binding->descriptorCount = 1; cur_binding->stageFlags = stage_flags_from_visibility(s->ShaderVisibility);