From b9da47ebe27ad92b818a46b91580d5c0aac3ad0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Tue, 25 Oct 2016 13:23:18 +0200 Subject: [PATCH] libs/vkd3d: Implement naive initial state transition. This is not a complete solution yet. In order to allow recording multiple command list and executing them in any order we have to fix up the current image layout when submitting a command list instead of when a command list is being recorded. --- libs/vkd3d/command.c | 78 ++++++++++++++++++++++++++++++++++++++ libs/vkd3d/resource.c | 16 ++++---- libs/vkd3d/vkd3d_private.h | 5 ++- 3 files changed, 90 insertions(+), 9 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index cb09fdcc..61fe1471 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -1111,6 +1111,71 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state, return true; } +static void d3d12_command_list_transition_resource_to_initial_state(struct d3d12_command_list *list, + struct d3d12_resource *resource) +{ + const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; + VkPipelineStageFlags src_stage_mask, dst_stage_mask; + const struct vkd3d_format *format; + VkImageMemoryBarrier barrier; + + assert(!d3d12_resource_is_buffer(resource)); + + if (!(format = vkd3d_get_format(resource->desc.Format))) + { + ERR("Resource %p has invalid format %#x.\n", resource, resource->desc.Format); + return; + } + + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = NULL; + + if (is_cpu_accessible_heap(&resource->heap_properties)) + { + barrier.srcAccessMask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT; + barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + src_stage_mask = VK_PIPELINE_STAGE_HOST_BIT; + } + else + { + barrier.srcAccessMask = 0; + barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + src_stage_mask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + } + + if (!vk_barrier_parameters_from_d3d12_resource_state(resource->initial_state, + &barrier.dstAccessMask, &dst_stage_mask, &barrier.newLayout)) + { + FIXME("Unhandled state %#x.\n", resource->initial_state); + return; + } + + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = resource->u.vk_image; + barrier.subresourceRange.aspectMask = format->vk_aspect_mask; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + + TRACE("Initial state %#x transition for resource %p (old layout %#x, new layout %#x).\n", + resource->initial_state, resource, barrier.oldLayout, barrier.newLayout); + + VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, src_stage_mask, dst_stage_mask, 0, + 0, NULL, 0, NULL, 1, &barrier)); +} + +static void d3d12_command_list_track_resource_usage(struct d3d12_command_list *list, + struct d3d12_resource *resource) +{ + if (resource->flags & VKD3D_RESOURCE_INITIAL_STATE_TRANSITION) + { + d3d12_command_list_transition_resource_to_initial_state(list, resource); + resource->flags &= ~VKD3D_RESOURCE_INITIAL_STATE_TRANSITION; + } +} + static HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(ID3D12GraphicsCommandList *iface, REFIID riid, void **object) { @@ -1542,6 +1607,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_CopyBufferRegion(ID3D12Graphics src_resource = unsafe_impl_from_ID3D12Resource(src); assert(d3d12_resource_is_buffer(src_resource)); + d3d12_command_list_track_resource_usage(list, dst_resource); + d3d12_command_list_track_resource_usage(list, src_resource); + buffer_copy.srcOffset = src_offset; buffer_copy.dstOffset = dst_offset; buffer_copy.size = byte_count; @@ -1568,6 +1636,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_CopyTextureRegion(ID3D12Graphic dst_resource = unsafe_impl_from_ID3D12Resource(dst->pResource); src_resource = unsafe_impl_from_ID3D12Resource(src->pResource); + d3d12_command_list_track_resource_usage(list, dst_resource); + d3d12_command_list_track_resource_usage(list, src_resource);; + if (src->Type == D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX && dst->Type == D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT) { @@ -1825,6 +1896,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC continue; } + if (resource) + d3d12_command_list_track_resource_usage(list, resource); + if (!resource) { VkMemoryBarrier vk_barrier; @@ -2083,6 +2157,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi { const struct d3d12_rtv_desc *rtv_desc = (const struct d3d12_rtv_desc *)render_target_descriptors[i].ptr; + d3d12_command_list_track_resource_usage(list, rtv_desc->resource); + list->views[i] = rtv_desc->vk_view; if (rtv_desc->width > list->fb_width) list->fb_width = rtv_desc->width; @@ -2123,6 +2199,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearRenderTargetView(ID3D12Gra TRACE("iface %p, rtv %#lx, color %p, rect_count %u, rects %p.\n", iface, rtv.ptr, color, rect_count, rects); + d3d12_command_list_track_resource_usage(list, rtv_desc->resource); + vk_procs = &list->device->vk_procs; if (!rect_count) diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 7116b848..97773d31 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -64,7 +64,7 @@ static VkSampleCountFlagBits vk_samples_from_dxgi_sample_desc(const DXGI_SAMPLE_ static HRESULT vkd3d_create_buffer(struct d3d12_resource *resource, struct d3d12_device *device, const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, - const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state) + const D3D12_RESOURCE_DESC *desc) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; VkBufferCreateInfo buffer_info; @@ -108,7 +108,7 @@ static HRESULT vkd3d_create_buffer(struct d3d12_resource *resource, struct d3d12 static HRESULT vkd3d_create_image(struct d3d12_resource *resource, struct d3d12_device *device, const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, - const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state) + const D3D12_RESOURCE_DESC *desc) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; const struct vkd3d_format *format; @@ -186,8 +186,6 @@ static HRESULT vkd3d_create_image(struct d3d12_resource *resource, struct d3d12_ image_info.initialLayout = is_cpu_accessible_heap(heap_properties) ? VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED; - FIXME("Ignoring initial state %#x.\n", initial_state); - if ((vr = VK_CALL(vkCreateImage(device->vk_device, &image_info, NULL, &resource->u.vk_image))) < 0) { WARN("Failed to create Vulkan image, vr %d.\n", vr); @@ -675,8 +673,7 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st switch (desc->Dimension) { case D3D12_RESOURCE_DIMENSION_BUFFER: - if (FAILED(hr = vkd3d_create_buffer(resource, device, heap_properties, heap_flags, - desc, initial_state))) + if (FAILED(hr = vkd3d_create_buffer(resource, device, heap_properties, heap_flags, desc))) return hr; if (FAILED(hr = vkd3d_allocate_buffer_memory(resource, device, heap_properties, heap_flags))) { @@ -688,8 +685,8 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st case D3D12_RESOURCE_DIMENSION_TEXTURE1D: case D3D12_RESOURCE_DIMENSION_TEXTURE2D: case D3D12_RESOURCE_DIMENSION_TEXTURE3D: - if (FAILED(hr = vkd3d_create_image(resource, device, heap_properties, heap_flags, - desc, initial_state))) + resource->flags |= VKD3D_RESOURCE_INITIAL_STATE_TRANSITION; + if (FAILED(hr = vkd3d_create_image(resource, device, heap_properties, heap_flags, desc))) return hr; if (FAILED(hr = vkd3d_allocate_image_memory(resource, device, heap_properties, heap_flags))) { @@ -707,6 +704,7 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st resource->map_data = NULL; resource->heap_properties = *heap_properties; + resource->initial_state = initial_state; resource->device = device; ID3D12Device_AddRef(&device->ID3D12Device_iface); @@ -758,6 +756,7 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_D object->map_data = NULL; memset(&object->heap_properties, 0, sizeof(object->heap_properties)); object->heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; + object->initial_state = D3D12_RESOURCE_STATE_COMMON; object->device = d3d12_device; ID3D12Device_AddRef(&d3d12_device->ID3D12Device_iface); @@ -841,6 +840,7 @@ void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_dev rtv_desc->width = resource->desc.Width; rtv_desc->height = resource->desc.Height; rtv_desc->magic = VKD3D_DESCRIPTOR_MAGIC_RTV; + rtv_desc->resource = resource; } /* ID3D12DescriptorHeap */ diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 060abb21..c4c67fba 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -114,7 +114,8 @@ struct d3d12_fence HRESULT d3d12_fence_create(struct d3d12_device *device, UINT64 initial_value, D3D12_FENCE_FLAGS flags, struct d3d12_fence **fence) DECLSPEC_HIDDEN; -#define VKD3D_RESOURCE_EXTERNAL 0x00000001 +#define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001 +#define VKD3D_RESOURCE_EXTERNAL 0x00000002 /* ID3D12Resource */ struct d3d12_resource @@ -137,6 +138,7 @@ struct d3d12_resource void *map_data; D3D12_HEAP_PROPERTIES heap_properties; + D3D12_RESOURCE_STATES initial_state; struct d3d12_device *device; }; @@ -169,6 +171,7 @@ struct d3d12_rtv_desc uint64_t width; unsigned int height; VkImageView vk_view; + struct d3d12_resource *resource; }; void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_device *device,