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.
This commit is contained in:
Józef Kucia 2016-10-25 13:23:18 +02:00
parent b011f0b972
commit b9da47ebe2
3 changed files with 90 additions and 9 deletions

View File

@ -1111,6 +1111,71 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state,
return true; 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, static HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(ID3D12GraphicsCommandList *iface,
REFIID riid, void **object) REFIID riid, void **object)
{ {
@ -1542,6 +1607,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_CopyBufferRegion(ID3D12Graphics
src_resource = unsafe_impl_from_ID3D12Resource(src); src_resource = unsafe_impl_from_ID3D12Resource(src);
assert(d3d12_resource_is_buffer(src_resource)); 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.srcOffset = src_offset;
buffer_copy.dstOffset = dst_offset; buffer_copy.dstOffset = dst_offset;
buffer_copy.size = byte_count; 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); dst_resource = unsafe_impl_from_ID3D12Resource(dst->pResource);
src_resource = unsafe_impl_from_ID3D12Resource(src->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 if (src->Type == D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX
&& dst->Type == D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT) && dst->Type == D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT)
{ {
@ -1825,6 +1896,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC
continue; continue;
} }
if (resource)
d3d12_command_list_track_resource_usage(list, resource);
if (!resource) if (!resource)
{ {
VkMemoryBarrier vk_barrier; 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; 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; list->views[i] = rtv_desc->vk_view;
if (rtv_desc->width > list->fb_width) if (rtv_desc->width > list->fb_width)
list->fb_width = rtv_desc->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", TRACE("iface %p, rtv %#lx, color %p, rect_count %u, rects %p.\n",
iface, rtv.ptr, color, rect_count, rects); iface, rtv.ptr, color, rect_count, rects);
d3d12_command_list_track_resource_usage(list, rtv_desc->resource);
vk_procs = &list->device->vk_procs; vk_procs = &list->device->vk_procs;
if (!rect_count) if (!rect_count)

View File

@ -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, 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_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_vk_device_procs *vk_procs = &device->vk_procs;
VkBufferCreateInfo buffer_info; 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, 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_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_vk_device_procs *vk_procs = &device->vk_procs;
const struct vkd3d_format *format; 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) ? image_info.initialLayout = is_cpu_accessible_heap(heap_properties) ?
VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED; 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) 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); 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) switch (desc->Dimension)
{ {
case D3D12_RESOURCE_DIMENSION_BUFFER: case D3D12_RESOURCE_DIMENSION_BUFFER:
if (FAILED(hr = vkd3d_create_buffer(resource, device, heap_properties, heap_flags, if (FAILED(hr = vkd3d_create_buffer(resource, device, heap_properties, heap_flags, desc)))
desc, initial_state)))
return hr; return hr;
if (FAILED(hr = vkd3d_allocate_buffer_memory(resource, device, heap_properties, heap_flags))) 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_TEXTURE1D:
case D3D12_RESOURCE_DIMENSION_TEXTURE2D: case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
case D3D12_RESOURCE_DIMENSION_TEXTURE3D: case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
if (FAILED(hr = vkd3d_create_image(resource, device, heap_properties, heap_flags, resource->flags |= VKD3D_RESOURCE_INITIAL_STATE_TRANSITION;
desc, initial_state))) if (FAILED(hr = vkd3d_create_image(resource, device, heap_properties, heap_flags, desc)))
return hr; return hr;
if (FAILED(hr = vkd3d_allocate_image_memory(resource, device, heap_properties, heap_flags))) 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->map_data = NULL;
resource->heap_properties = *heap_properties; resource->heap_properties = *heap_properties;
resource->initial_state = initial_state;
resource->device = device; resource->device = device;
ID3D12Device_AddRef(&device->ID3D12Device_iface); ID3D12Device_AddRef(&device->ID3D12Device_iface);
@ -758,6 +756,7 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_D
object->map_data = NULL; object->map_data = NULL;
memset(&object->heap_properties, 0, sizeof(object->heap_properties)); memset(&object->heap_properties, 0, sizeof(object->heap_properties));
object->heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; object->heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
object->initial_state = D3D12_RESOURCE_STATE_COMMON;
object->device = d3d12_device; object->device = d3d12_device;
ID3D12Device_AddRef(&d3d12_device->ID3D12Device_iface); 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->width = resource->desc.Width;
rtv_desc->height = resource->desc.Height; rtv_desc->height = resource->desc.Height;
rtv_desc->magic = VKD3D_DESCRIPTOR_MAGIC_RTV; rtv_desc->magic = VKD3D_DESCRIPTOR_MAGIC_RTV;
rtv_desc->resource = resource;
} }
/* ID3D12DescriptorHeap */ /* ID3D12DescriptorHeap */

View File

@ -114,7 +114,8 @@ struct d3d12_fence
HRESULT d3d12_fence_create(struct d3d12_device *device, HRESULT d3d12_fence_create(struct d3d12_device *device,
UINT64 initial_value, D3D12_FENCE_FLAGS flags, struct d3d12_fence **fence) DECLSPEC_HIDDEN; 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 */ /* ID3D12Resource */
struct d3d12_resource struct d3d12_resource
@ -137,6 +138,7 @@ struct d3d12_resource
void *map_data; void *map_data;
D3D12_HEAP_PROPERTIES heap_properties; D3D12_HEAP_PROPERTIES heap_properties;
D3D12_RESOURCE_STATES initial_state;
struct d3d12_device *device; struct d3d12_device *device;
}; };
@ -169,6 +171,7 @@ struct d3d12_rtv_desc
uint64_t width; uint64_t width;
unsigned int height; unsigned int height;
VkImageView vk_view; VkImageView vk_view;
struct d3d12_resource *resource;
}; };
void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_device *device, void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_device *device,