diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index aa614335..7854672b 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -2428,7 +2428,9 @@ static void d3d12_command_list_invalidate_root_parameters(struct d3d12_command_l if (bindings->root_signature->descriptor_table_count) bindings->dirty_flags |= VKD3D_PIPELINE_DIRTY_DESCRIPTOR_TABLE_OFFSETS; - bindings->root_descriptor_dirty_mask = bindings->root_signature->root_descriptor_mask; + bindings->root_descriptor_dirty_mask = + bindings->root_signature->root_descriptor_raw_va_mask | + bindings->root_signature->root_descriptor_push_mask; bindings->root_constant_dirty_mask = bindings->root_signature->root_constant_mask; if (invalidate_descriptor_heaps) @@ -2541,7 +2543,7 @@ static void vk_access_and_stage_flags_from_d3d12_resource_state(const struct d3d *stages |= queue_shader_stages; *access |= VK_ACCESS_UNIFORM_READ_BIT; - if (device->bindless_state.flags & (VKD3D_BINDLESS_CBV_AS_SSBO | VKD3D_RAW_VA_ROOT_DESCRIPTOR)) + if (device->bindless_state.flags & (VKD3D_BINDLESS_CBV_AS_SSBO | VKD3D_RAW_VA_ROOT_DESCRIPTOR_CBV)) *access |= VK_ACCESS_SHADER_READ_BIT; if (vk_queue_flags & VK_QUEUE_GRAPHICS_BIT) @@ -3337,7 +3339,7 @@ static unsigned int d3d12_command_list_fetch_root_descriptor_vas(struct d3d12_co { struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point]; const struct d3d12_root_signature *root_signature = bindings->root_signature; - uint64_t root_descriptor_mask = root_signature->root_descriptor_mask; + uint64_t root_descriptor_mask = root_signature->root_descriptor_raw_va_mask; unsigned int va_idx = 0; /* Ignore dirty mask. We'll always update all VAs either via push constants @@ -3349,7 +3351,6 @@ static unsigned int d3d12_command_list_fetch_root_descriptor_vas(struct d3d12_co dst_data->root_descriptor_vas[va_idx++] = bindings->root_descriptors[root_parameter_index].info.va; } - bindings->root_descriptor_dirty_mask = 0; return va_idx; } @@ -3367,8 +3368,7 @@ static void d3d12_command_list_fetch_inline_uniform_block_data(struct d3d12_comm uint64_t descriptor_table_mask; uint32_t first_table_offset; - if (list->device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR) - d3d12_command_list_fetch_root_descriptor_vas(list, bind_point, dst_data); + /* Root descriptors are already filled in dst_data. */ while (root_constant_mask) { @@ -3409,26 +3409,37 @@ static void d3d12_command_list_update_root_descriptors(struct d3d12_command_list const struct d3d12_root_parameter *root_parameter; VkDescriptorSet descriptor_set = VK_NULL_HANDLE; union root_parameter_data root_parameter_data; - unsigned int root_parameter_index, va_count; unsigned int descriptor_write_count = 0; + unsigned int root_parameter_index; + unsigned int va_count = 0; + uint64_t dirty_push_mask; if (root_signature->flags & VKD3D_ROOT_SIGNATURE_USE_ROOT_DESCRIPTOR_SET) { /* Ensure that we populate all descriptors if push descriptors cannot be used */ - bindings->root_descriptor_dirty_mask |= bindings->root_descriptor_active_mask & root_signature->root_descriptor_mask; + bindings->root_descriptor_dirty_mask |= + bindings->root_descriptor_active_mask & + (root_signature->root_descriptor_raw_va_mask | root_signature->root_descriptor_push_mask); descriptor_set = d3d12_command_allocator_allocate_descriptor_set( list->allocator, root_signature->vk_root_descriptor_layout, VKD3D_DESCRIPTOR_POOL_TYPE_STATIC); } - if (!(list->device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR)) + if (bindings->root_descriptor_dirty_mask) { - /* TODO bind null descriptors for inactive root descriptors */ - bindings->root_descriptor_dirty_mask &= bindings->root_descriptor_active_mask; + /* If any raw VA descriptor is dirty, we need to update all of them. */ + if (root_signature->root_descriptor_raw_va_mask & bindings->root_descriptor_dirty_mask) + va_count = d3d12_command_list_fetch_root_descriptor_vas(list, bind_point, &root_parameter_data); - while (bindings->root_descriptor_dirty_mask) + /* TODO bind null descriptors for inactive root descriptors. */ + dirty_push_mask = + bindings->root_descriptor_dirty_mask & + root_signature->root_descriptor_push_mask & + bindings->root_descriptor_active_mask; + + while (dirty_push_mask) { - root_parameter_index = vkd3d_bitmask_iter64(&bindings->root_descriptor_dirty_mask); + root_parameter_index = vkd3d_bitmask_iter64(&dirty_push_mask); root_parameter = root_signature_get_root_descriptor(root_signature, root_parameter_index); if (!vk_write_descriptor_set_from_root_descriptor(list, @@ -3438,6 +3449,8 @@ static void d3d12_command_list_update_root_descriptors(struct d3d12_command_list descriptor_write_count += 1; } + + bindings->root_descriptor_dirty_mask = 0; } if (root_signature->flags & VKD3D_ROOT_SIGNATURE_USE_INLINE_UNIFORM_BLOCK) @@ -3449,10 +3462,8 @@ static void d3d12_command_list_update_root_descriptors(struct d3d12_command_list descriptor_write_count += 1; } - else if (bindings->root_descriptor_dirty_mask) + else if (va_count) { - va_count = d3d12_command_list_fetch_root_descriptor_vas(list, bind_point, &root_parameter_data); - VK_CALL(vkCmdPushConstants(list->vk_command_buffer, root_signature->vk_pipeline_layout, VK_SHADER_STAGE_ALL, 0, va_count * sizeof(*root_parameter_data.root_descriptor_vas), @@ -5367,7 +5378,7 @@ static void d3d12_command_list_set_root_descriptor(struct d3d12_command_list *li struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point]; struct vkd3d_root_descriptor_info *descriptor = &bindings->root_descriptors[index]; - if (list->device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR) + if (bindings->root_signature->root_descriptor_raw_va_mask & (1ull << index)) d3d12_command_list_set_root_descriptor_va(list, descriptor, gpu_address); else d3d12_command_list_set_push_descriptor_info(list, bind_point, index, gpu_address); diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 3e810e33..0d47da6b 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -403,9 +403,16 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i break; case D3D12_ROOT_PARAMETER_TYPE_CBV: + if (!(device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR_CBV)) + info->push_descriptor_count += 1; + + info->binding_count += 1; + info->cost += 2; + break; + case D3D12_ROOT_PARAMETER_TYPE_SRV: case D3D12_ROOT_PARAMETER_TYPE_UAV: - if (!(device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR)) + if (!(device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR_SRV_UAV)) info->push_descriptor_count += 1; info->binding_count += 1; @@ -427,6 +434,17 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i return S_OK; } +static bool d3d12_root_signature_parameter_is_raw_va(struct d3d12_root_signature *root_signature, + D3D12_ROOT_PARAMETER_TYPE type) +{ + if (type == D3D12_ROOT_PARAMETER_TYPE_CBV) + return !!(root_signature->device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR_CBV); + else if (type == D3D12_ROOT_PARAMETER_TYPE_SRV || type == D3D12_ROOT_PARAMETER_TYPE_UAV) + return !!(root_signature->device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR_SRV_UAV); + else + return false; +} + static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signature *root_signature, const D3D12_ROOT_SIGNATURE_DESC *desc, const struct d3d12_root_signature_info *info, struct VkPushConstantRange *push_constant_range) @@ -438,17 +456,11 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat push_constant_range->size = 0; /* Put root descriptor VAs at the start to avoid alignment issues */ - if (root_signature->device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR) + for (i = 0; i < desc->NumParameters; ++i) { - for (i = 0; i < desc->NumParameters; ++i) - { - const D3D12_ROOT_PARAMETER *p = &desc->pParameters[i]; - - if (p->ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || - p->ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || - p->ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV) - push_constant_range->size += sizeof(VkDeviceSize); - } + const D3D12_ROOT_PARAMETER *p = &desc->pParameters[i]; + if (d3d12_root_signature_parameter_is_raw_va(root_signature, p->ParameterType)) + push_constant_range->size += sizeof(VkDeviceSize); } /* Append actual root constants */ @@ -639,27 +651,29 @@ static HRESULT d3d12_root_signature_init_root_descriptors(struct d3d12_root_sign struct d3d12_root_parameter *param; unsigned int i, j; HRESULT hr = S_OK; - bool raw_va; - - raw_va = !!(root_signature->device->bindless_state.flags & VKD3D_RAW_VA_ROOT_DESCRIPTOR); if (info->push_descriptor_count || (root_signature->flags & VKD3D_ROOT_SIGNATURE_USE_INLINE_UNIFORM_BLOCK)) { if (!(vk_binding_info = vkd3d_malloc(sizeof(*vk_binding_info) * (info->push_descriptor_count + 1)))) return E_OUTOFMEMORY; } - else if (!raw_va) + else if (!(root_signature->device->bindless_state.flags & + (VKD3D_RAW_VA_ROOT_DESCRIPTOR_CBV | VKD3D_RAW_VA_ROOT_DESCRIPTOR_SRV_UAV))) + { return S_OK; + } for (i = 0, j = 0; i < desc->NumParameters; ++i) { const D3D12_ROOT_PARAMETER *p = &desc->pParameters[i]; + bool raw_va; + if (p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_CBV && p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_SRV && p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_UAV) continue; - root_signature->root_descriptor_mask |= 1ull << i; + raw_va = d3d12_root_signature_parameter_is_raw_va(root_signature, p->ParameterType); if (!raw_va) { @@ -669,7 +683,10 @@ static HRESULT d3d12_root_signature_init_root_descriptors(struct d3d12_root_sign vk_binding->descriptorCount = 1; vk_binding->stageFlags = stage_flags_from_visibility(p->ShaderVisibility); vk_binding->pImmutableSamplers = NULL; + root_signature->root_descriptor_push_mask |= 1ull << i; } + else + root_signature->root_descriptor_raw_va_mask |= 1ull << i; binding = &root_signature->bindings[context->binding_index]; binding->type = vkd3d_descriptor_type_from_d3d12_root_parameter_type(p->ParameterType); @@ -3546,7 +3563,7 @@ static uint32_t vkd3d_bindless_state_get_bindless_flags(struct d3d12_device *dev flags |= VKD3D_RAW_VA_UAV_COUNTER; if (device_info->buffer_device_address_features.bufferDeviceAddress) - flags |= VKD3D_RAW_VA_ROOT_DESCRIPTOR; + flags |= VKD3D_RAW_VA_ROOT_DESCRIPTOR_CBV | VKD3D_RAW_VA_ROOT_DESCRIPTOR_SRV_UAV; return flags; } diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index f18eac0f..2cb619e8 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -835,7 +835,8 @@ struct d3d12_root_signature uint64_t descriptor_table_mask; uint64_t root_constant_mask; - uint64_t root_descriptor_mask; + uint64_t root_descriptor_raw_va_mask; + uint64_t root_descriptor_push_mask; D3D12_ROOT_SIGNATURE_FLAGS d3d12_flags; unsigned int flags; /* vkd3d_root_signature_flag */ @@ -1563,16 +1564,17 @@ void vkd3d_destroy_null_resources(struct vkd3d_null_resources *null_resources, /* Bindless */ enum vkd3d_bindless_flags { - VKD3D_BINDLESS_SAMPLER = (1u << 0), - VKD3D_BINDLESS_CBV = (1u << 1), - VKD3D_BINDLESS_SRV = (1u << 2), - VKD3D_BINDLESS_UAV = (1u << 3), - VKD3D_RAW_VA_UAV_COUNTER = (1u << 4), - VKD3D_BINDLESS_CBV_AS_SSBO = (1u << 5), - VKD3D_BINDLESS_RAW_SSBO = (1u << 6), - VKD3D_SSBO_OFFSET_BUFFER = (1u << 7), - VKD3D_TYPED_OFFSET_BUFFER = (1u << 8), - VKD3D_RAW_VA_ROOT_DESCRIPTOR = (1u << 9), + VKD3D_BINDLESS_SAMPLER = (1u << 0), + VKD3D_BINDLESS_CBV = (1u << 1), + VKD3D_BINDLESS_SRV = (1u << 2), + VKD3D_BINDLESS_UAV = (1u << 3), + VKD3D_RAW_VA_UAV_COUNTER = (1u << 4), + VKD3D_BINDLESS_CBV_AS_SSBO = (1u << 5), + VKD3D_BINDLESS_RAW_SSBO = (1u << 6), + VKD3D_SSBO_OFFSET_BUFFER = (1u << 7), + VKD3D_TYPED_OFFSET_BUFFER = (1u << 8), + VKD3D_RAW_VA_ROOT_DESCRIPTOR_CBV = (1u << 9), + VKD3D_RAW_VA_ROOT_DESCRIPTOR_SRV_UAV = (1u << 10), }; #define VKD3D_BINDLESS_SET_MAX_EXTRA_BINDINGS 8