2016-09-26 02:13:30 -07:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Józef Kucia for CodeWeavers
|
|
|
|
*
|
2017-06-16 12:05:54 -07:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
2016-09-26 02:13:30 -07:00
|
|
|
*
|
2017-06-16 12:05:54 -07:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2016-09-26 02:13:30 -07:00
|
|
|
*
|
2017-06-16 12:05:54 -07:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2016-09-26 02:13:30 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "vkd3d_private.h"
|
|
|
|
|
2019-05-15 04:17:58 -07:00
|
|
|
#define VKD3D_NULL_BUFFER_SIZE 16
|
2019-03-28 09:07:27 -07:00
|
|
|
#define VKD3D_NULL_VIEW_FORMAT DXGI_FORMAT_R8G8B8A8_UNORM
|
2019-03-04 04:15:14 -08:00
|
|
|
|
2019-06-20 12:08:06 -07:00
|
|
|
static inline bool is_cpu_accessible_heap(const D3D12_HEAP_PROPERTIES *properties)
|
|
|
|
{
|
|
|
|
if (properties->Type == D3D12_HEAP_TYPE_DEFAULT)
|
|
|
|
return false;
|
|
|
|
if (properties->Type == D3D12_HEAP_TYPE_CUSTOM)
|
|
|
|
{
|
|
|
|
return properties->CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE
|
|
|
|
|| properties->CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-09-25 05:13:03 -07:00
|
|
|
static unsigned int vkd3d_select_memory_type(struct d3d12_device *device, uint32_t memory_type_mask,
|
|
|
|
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags)
|
|
|
|
{
|
2019-03-04 04:15:14 -08:00
|
|
|
const VkPhysicalDeviceMemoryProperties *memory_info = &device->memory_properties;
|
2019-03-07 02:01:12 -08:00
|
|
|
VkMemoryPropertyFlags flags[3];
|
2019-03-04 04:15:16 -08:00
|
|
|
unsigned int i, j, count = 0;
|
2018-09-25 05:13:03 -07:00
|
|
|
|
|
|
|
switch (heap_properties->Type)
|
|
|
|
{
|
|
|
|
case D3D12_HEAP_TYPE_DEFAULT:
|
2019-03-04 04:15:16 -08:00
|
|
|
flags[count++] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D12_HEAP_TYPE_UPLOAD:
|
|
|
|
flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
2018-09-25 05:13:03 -07:00
|
|
|
break;
|
|
|
|
|
2019-03-07 02:01:12 -08:00
|
|
|
case D3D12_HEAP_TYPE_READBACK:
|
|
|
|
flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
|
|
|
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
|
|
flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
|
|
break;
|
|
|
|
|
2018-09-25 05:13:03 -07:00
|
|
|
case D3D12_HEAP_TYPE_CUSTOM:
|
|
|
|
FIXME("Custom heaps not supported yet.\n");
|
2019-03-04 04:15:16 -08:00
|
|
|
flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
|
|
|
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
|
|
flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
2019-03-07 02:01:12 -08:00
|
|
|
flags[count++] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
2018-09-25 05:13:03 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
WARN("Invalid heap type %#x.\n", heap_properties->Type);
|
|
|
|
return ~0u;
|
|
|
|
}
|
|
|
|
|
2019-03-04 04:15:16 -08:00
|
|
|
for (j = 0; j < count; ++j)
|
2018-09-25 05:13:03 -07:00
|
|
|
{
|
2019-03-04 04:15:16 -08:00
|
|
|
VkMemoryPropertyFlags preferred_flags = flags[j];
|
|
|
|
|
|
|
|
for (i = 0; i < memory_info->memoryTypeCount; ++i)
|
|
|
|
{
|
|
|
|
if (!(memory_type_mask & (1u << i)))
|
|
|
|
continue;
|
|
|
|
if ((memory_info->memoryTypes[i].propertyFlags & preferred_flags) == preferred_flags)
|
|
|
|
return i;
|
|
|
|
}
|
2018-09-25 05:13:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return ~0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT vkd3d_allocate_device_memory(struct d3d12_device *device,
|
|
|
|
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
|
2019-03-28 09:07:25 -07:00
|
|
|
const VkMemoryRequirements *memory_requirements,
|
|
|
|
const VkMemoryDedicatedAllocateInfo *dedicated_allocate_info,
|
|
|
|
VkDeviceMemory *vk_memory, uint32_t *vk_memory_type)
|
2018-09-25 05:13:03 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
VkMemoryAllocateInfo allocate_info;
|
|
|
|
VkResult vr;
|
|
|
|
|
|
|
|
TRACE("Memory requirements: size %#"PRIx64", alignment %#"PRIx64".\n",
|
|
|
|
memory_requirements->size, memory_requirements->alignment);
|
|
|
|
|
|
|
|
allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
2019-03-28 09:07:25 -07:00
|
|
|
allocate_info.pNext = dedicated_allocate_info;
|
2018-09-25 05:13:03 -07:00
|
|
|
allocate_info.allocationSize = memory_requirements->size;
|
|
|
|
allocate_info.memoryTypeIndex = vkd3d_select_memory_type(device,
|
|
|
|
memory_requirements->memoryTypeBits, heap_properties, heap_flags);
|
|
|
|
|
|
|
|
if (allocate_info.memoryTypeIndex == ~0u)
|
|
|
|
{
|
|
|
|
FIXME("Failed to find suitable memory type (allowed types %#x).\n", memory_requirements->memoryTypeBits);
|
|
|
|
*vk_memory = VK_NULL_HANDLE;
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE("Allocating memory type %u.\n", allocate_info.memoryTypeIndex);
|
|
|
|
|
|
|
|
if ((vr = VK_CALL(vkAllocateMemory(device->vk_device, &allocate_info, NULL, vk_memory))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to allocate device memory, vr %d.\n", vr);
|
|
|
|
*vk_memory = VK_NULL_HANDLE;
|
|
|
|
return hresult_from_vk_result(vr);
|
|
|
|
}
|
|
|
|
|
2018-09-26 00:10:31 -07:00
|
|
|
if (vk_memory_type)
|
|
|
|
*vk_memory_type = allocate_info.memoryTypeIndex;
|
|
|
|
|
2018-09-25 05:13:03 -07:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:05 -07:00
|
|
|
HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_buffer,
|
|
|
|
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
|
2019-06-20 12:08:07 -07:00
|
|
|
VkDeviceMemory *vk_memory, uint32_t *vk_memory_type, VkDeviceSize *vk_memory_size)
|
2019-06-20 12:08:05 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
VkMemoryDedicatedAllocateInfo *dedicated_allocation = NULL;
|
|
|
|
VkMemoryDedicatedRequirements dedicated_requirements;
|
|
|
|
VkMemoryDedicatedAllocateInfo dedicated_info;
|
|
|
|
VkMemoryRequirements2 memory_requirements2;
|
|
|
|
VkMemoryRequirements *memory_requirements;
|
|
|
|
VkBufferMemoryRequirementsInfo2 info;
|
|
|
|
VkResult vr;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
memory_requirements = &memory_requirements2.memoryRequirements;
|
|
|
|
|
|
|
|
if (device->vk_info.KHR_dedicated_allocation)
|
|
|
|
{
|
|
|
|
info.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
|
|
|
|
info.pNext = NULL;
|
|
|
|
info.buffer = vk_buffer;
|
|
|
|
|
|
|
|
dedicated_requirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
|
|
|
|
dedicated_requirements.pNext = NULL;
|
|
|
|
|
|
|
|
memory_requirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
|
|
|
memory_requirements2.pNext = &dedicated_requirements;
|
|
|
|
|
|
|
|
VK_CALL(vkGetBufferMemoryRequirements2KHR(device->vk_device, &info, &memory_requirements2));
|
|
|
|
|
|
|
|
if (dedicated_requirements.prefersDedicatedAllocation)
|
|
|
|
{
|
|
|
|
dedicated_allocation = &dedicated_info;
|
|
|
|
|
|
|
|
dedicated_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
|
|
|
|
dedicated_info.pNext = NULL;
|
|
|
|
dedicated_info.image = VK_NULL_HANDLE;
|
|
|
|
dedicated_info.buffer = vk_buffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VK_CALL(vkGetBufferMemoryRequirements(device->vk_device, vk_buffer, memory_requirements));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
|
2019-06-20 12:08:07 -07:00
|
|
|
memory_requirements, dedicated_allocation, vk_memory, vk_memory_type)))
|
2019-06-20 12:08:05 -07:00
|
|
|
return hr;
|
|
|
|
|
|
|
|
if ((vr = VK_CALL(vkBindBufferMemory(device->vk_device, vk_buffer, *vk_memory, 0))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to bind memory, vr %d.\n", vr);
|
|
|
|
VK_CALL(vkFreeMemory(device->vk_device, *vk_memory, NULL));
|
|
|
|
*vk_memory = VK_NULL_HANDLE;
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:07 -07:00
|
|
|
if (vk_memory_size)
|
|
|
|
*vk_memory_size = memory_requirements->size;
|
|
|
|
|
2019-06-20 12:08:05 -07:00
|
|
|
return hresult_from_vk_result(vr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT vkd3d_allocate_image_memory(struct d3d12_device *device, VkImage vk_image,
|
|
|
|
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
|
2019-06-20 12:08:07 -07:00
|
|
|
VkDeviceMemory *vk_memory, uint32_t *vk_memory_type, VkDeviceSize *vk_memory_size)
|
2019-06-20 12:08:05 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
VkMemoryDedicatedAllocateInfo *dedicated_allocation = NULL;
|
|
|
|
VkMemoryDedicatedRequirements dedicated_requirements;
|
|
|
|
VkMemoryDedicatedAllocateInfo dedicated_info;
|
|
|
|
VkMemoryRequirements2 memory_requirements2;
|
|
|
|
VkMemoryRequirements *memory_requirements;
|
|
|
|
VkImageMemoryRequirementsInfo2 info;
|
|
|
|
VkResult vr;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
memory_requirements = &memory_requirements2.memoryRequirements;
|
|
|
|
|
|
|
|
if (device->vk_info.KHR_dedicated_allocation)
|
|
|
|
{
|
|
|
|
info.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
|
|
|
|
info.pNext = NULL;
|
|
|
|
info.image = vk_image;
|
|
|
|
|
|
|
|
dedicated_requirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
|
|
|
|
dedicated_requirements.pNext = NULL;
|
|
|
|
|
|
|
|
memory_requirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
|
|
|
memory_requirements2.pNext = &dedicated_requirements;
|
|
|
|
|
|
|
|
VK_CALL(vkGetImageMemoryRequirements2KHR(device->vk_device, &info, &memory_requirements2));
|
|
|
|
|
|
|
|
if (dedicated_requirements.prefersDedicatedAllocation)
|
|
|
|
{
|
|
|
|
dedicated_allocation = &dedicated_info;
|
|
|
|
|
|
|
|
dedicated_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
|
|
|
|
dedicated_info.pNext = NULL;
|
|
|
|
dedicated_info.image = vk_image;
|
|
|
|
dedicated_info.buffer = VK_NULL_HANDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, memory_requirements));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
|
2019-06-20 12:08:07 -07:00
|
|
|
memory_requirements, dedicated_allocation, vk_memory, vk_memory_type)))
|
2019-06-20 12:08:05 -07:00
|
|
|
return hr;
|
|
|
|
|
|
|
|
if ((vr = VK_CALL(vkBindImageMemory(device->vk_device, vk_image, *vk_memory, 0))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to bind memory, vr %d.\n", vr);
|
|
|
|
VK_CALL(vkFreeMemory(device->vk_device, *vk_memory, NULL));
|
|
|
|
*vk_memory = VK_NULL_HANDLE;
|
|
|
|
return hresult_from_vk_result(vr);
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:07 -07:00
|
|
|
if (vk_memory_size)
|
|
|
|
*vk_memory_size = memory_requirements->size;
|
|
|
|
|
2019-06-20 12:08:05 -07:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2018-07-20 05:30:18 -07:00
|
|
|
/* ID3D12Heap */
|
|
|
|
static inline struct d3d12_heap *impl_from_ID3D12Heap(ID3D12Heap *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, struct d3d12_heap, ID3D12Heap_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_heap_QueryInterface(ID3D12Heap *iface,
|
|
|
|
REFIID iid, void **object)
|
|
|
|
{
|
|
|
|
TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
|
|
|
|
|
|
|
|
if (IsEqualGUID(iid, &IID_ID3D12Heap)
|
|
|
|
|| IsEqualGUID(iid, &IID_ID3D12Pageable)
|
|
|
|
|| IsEqualGUID(iid, &IID_ID3D12DeviceChild)
|
|
|
|
|| IsEqualGUID(iid, &IID_ID3D12Object)
|
|
|
|
|| IsEqualGUID(iid, &IID_IUnknown))
|
|
|
|
{
|
|
|
|
ID3D12Heap_AddRef(iface);
|
|
|
|
*object = iface;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
|
|
|
|
|
|
|
|
*object = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(ID3D12Heap *iface)
|
|
|
|
{
|
|
|
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
|
|
|
ULONG refcount = InterlockedIncrement(&heap->refcount);
|
|
|
|
|
|
|
|
TRACE("%p increasing refcount to %u.\n", heap, refcount);
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
assert(!heap->is_private);
|
|
|
|
|
2018-07-20 05:30:18 -07:00
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
static void d3d12_heap_destroy(struct d3d12_heap *heap)
|
2018-07-20 05:30:18 -07:00
|
|
|
{
|
2019-06-20 12:08:08 -07:00
|
|
|
struct d3d12_device *device = heap->device;
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
2018-07-20 05:30:18 -07:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
TRACE("Destroying heap %p.\n", heap);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
vkd3d_private_store_destroy(&heap->private_store);
|
2018-09-25 05:13:03 -07:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
VK_CALL(vkFreeMemory(device->vk_device, heap->vk_memory, NULL));
|
2019-01-04 05:34:15 -08:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
pthread_mutex_destroy(&heap->mutex);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (heap->is_private)
|
|
|
|
device = NULL;
|
2018-11-09 09:06:20 -08:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
vkd3d_free(heap);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (device)
|
2019-06-07 05:38:03 -07:00
|
|
|
d3d12_device_release(device);
|
2019-06-20 12:08:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface)
|
|
|
|
{
|
|
|
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
|
|
|
ULONG refcount = InterlockedDecrement(&heap->refcount);
|
|
|
|
|
|
|
|
TRACE("%p decreasing refcount to %u.\n", heap, refcount);
|
|
|
|
|
|
|
|
if (!refcount)
|
|
|
|
d3d12_heap_destroy(heap);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_heap_GetPrivateData(ID3D12Heap *iface,
|
|
|
|
REFGUID guid, UINT *data_size, void *data)
|
|
|
|
{
|
2019-01-04 05:34:15 -08:00
|
|
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
2019-01-04 05:34:15 -08:00
|
|
|
TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
|
|
|
|
|
|
|
|
return vkd3d_get_private_data(&heap->private_store, guid, data_size, data);
|
2018-07-20 05:30:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_heap_SetPrivateData(ID3D12Heap *iface,
|
|
|
|
REFGUID guid, UINT data_size, const void *data)
|
|
|
|
{
|
2019-01-04 05:34:15 -08:00
|
|
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
2019-01-04 05:34:15 -08:00
|
|
|
TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
|
|
|
|
|
|
|
|
return vkd3d_set_private_data(&heap->private_store, guid, data_size, data);
|
2018-07-20 05:30:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_heap_SetPrivateDataInterface(ID3D12Heap *iface,
|
|
|
|
REFGUID guid, const IUnknown *data)
|
|
|
|
{
|
2019-01-04 05:34:15 -08:00
|
|
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
2019-01-04 05:34:15 -08:00
|
|
|
TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
|
|
|
|
|
|
|
|
return vkd3d_set_private_data_interface(&heap->private_store, guid, data);
|
2018-07-20 05:30:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_heap_SetName(ID3D12Heap *iface, const WCHAR *name)
|
|
|
|
{
|
|
|
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
|
|
|
|
2019-01-29 13:14:33 -08:00
|
|
|
TRACE("iface %p, name %s.\n", iface, debugstr_w(name, heap->device->wchar_size));
|
2018-07-20 05:30:18 -07:00
|
|
|
|
2019-01-29 13:14:33 -08:00
|
|
|
return vkd3d_set_vk_object_name(heap->device, (uint64_t)heap->vk_memory,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, name);
|
2018-07-20 05:30:18 -07:00
|
|
|
}
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_heap_GetDevice(ID3D12Heap *iface, REFIID iid, void **device)
|
2018-07-20 05:30:18 -07:00
|
|
|
{
|
|
|
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
return d3d12_device_query_interface(heap->device, iid, device);
|
2018-07-20 05:30:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static D3D12_HEAP_DESC * STDMETHODCALLTYPE d3d12_heap_GetDesc(ID3D12Heap *iface,
|
|
|
|
D3D12_HEAP_DESC *desc)
|
|
|
|
{
|
|
|
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
|
|
|
|
|
|
|
TRACE("iface %p, desc %p.\n", iface, desc);
|
|
|
|
|
|
|
|
*desc = heap->desc;
|
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct ID3D12HeapVtbl d3d12_heap_vtbl =
|
|
|
|
{
|
|
|
|
/* IUnknown methods */
|
|
|
|
d3d12_heap_QueryInterface,
|
|
|
|
d3d12_heap_AddRef,
|
|
|
|
d3d12_heap_Release,
|
|
|
|
/* ID3D12Object methods */
|
|
|
|
d3d12_heap_GetPrivateData,
|
|
|
|
d3d12_heap_SetPrivateData,
|
|
|
|
d3d12_heap_SetPrivateDataInterface,
|
|
|
|
d3d12_heap_SetName,
|
|
|
|
/* ID3D12DeviceChild methods */
|
|
|
|
d3d12_heap_GetDevice,
|
|
|
|
/* ID3D12Heap methods */
|
|
|
|
d3d12_heap_GetDesc,
|
|
|
|
};
|
|
|
|
|
2018-09-25 05:12:59 -07:00
|
|
|
struct d3d12_heap *unsafe_impl_from_ID3D12Heap(ID3D12Heap *iface)
|
|
|
|
{
|
|
|
|
if (!iface)
|
|
|
|
return NULL;
|
|
|
|
assert(iface->lpVtbl == &d3d12_heap_vtbl);
|
|
|
|
return impl_from_ID3D12Heap(iface);
|
|
|
|
}
|
|
|
|
|
2019-06-11 01:13:35 -07:00
|
|
|
static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset, void **data)
|
2018-11-09 09:06:20 -08:00
|
|
|
{
|
|
|
|
struct d3d12_device *device = heap->device;
|
2018-11-12 15:23:30 -08:00
|
|
|
HRESULT hr = S_OK;
|
2018-11-09 09:06:20 -08:00
|
|
|
VkResult vr;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if ((rc = pthread_mutex_lock(&heap->mutex)))
|
|
|
|
{
|
|
|
|
ERR("Failed to lock mutex, error %d.\n", rc);
|
|
|
|
*data = NULL;
|
2018-11-09 09:06:23 -08:00
|
|
|
return hresult_from_errno(rc);
|
2018-11-09 09:06:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!heap->map_ptr)
|
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
|
|
|
|
TRACE("Mapping heap %p.\n", heap);
|
|
|
|
|
|
|
|
if ((vr = VK_CALL(vkMapMemory(device->vk_device, heap->vk_memory,
|
|
|
|
0, VK_WHOLE_SIZE, 0, &heap->map_ptr))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to map device memory, vr %d.\n", vr);
|
|
|
|
heap->map_ptr = NULL;
|
|
|
|
}
|
2018-11-12 15:23:30 -08:00
|
|
|
|
|
|
|
hr = hresult_from_vk_result(vr);
|
2018-11-09 09:06:20 -08:00
|
|
|
}
|
|
|
|
|
2018-11-12 15:23:30 -08:00
|
|
|
if (heap->map_ptr)
|
|
|
|
{
|
|
|
|
*data = (BYTE *)heap->map_ptr + offset;
|
|
|
|
++heap->map_count;
|
|
|
|
}
|
2019-06-20 12:08:08 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
*data = NULL;
|
|
|
|
}
|
2018-11-09 09:06:20 -08:00
|
|
|
|
|
|
|
pthread_mutex_unlock(&heap->mutex);
|
|
|
|
|
2018-11-12 15:23:30 -08:00
|
|
|
return hr;
|
2018-11-09 09:06:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void d3d12_heap_unmap(struct d3d12_heap *heap)
|
|
|
|
{
|
|
|
|
struct d3d12_device *device = heap->device;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if ((rc = pthread_mutex_lock(&heap->mutex)))
|
|
|
|
{
|
|
|
|
ERR("Failed to lock mutex, error %d.\n", rc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (heap->map_count)
|
|
|
|
{
|
|
|
|
--heap->map_count;
|
|
|
|
if (!heap->map_count)
|
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
|
|
|
|
TRACE("Unmapping heap %p.\n", heap);
|
|
|
|
|
|
|
|
VK_CALL(vkUnmapMemory(device->vk_device, heap->vk_memory));
|
|
|
|
heap->map_ptr = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WARN("Heap %p is not mapped.\n", heap);
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&heap->mutex);
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
static HRESULT validate_heap_desc(const D3D12_HEAP_DESC *desc, const struct d3d12_resource *resource)
|
2018-07-20 05:30:18 -07:00
|
|
|
{
|
2019-06-20 12:08:08 -07:00
|
|
|
if (!resource && !desc->SizeInBytes)
|
2018-07-20 05:30:18 -07:00
|
|
|
{
|
|
|
|
WARN("Invalid size %"PRIu64".\n", desc->SizeInBytes);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (desc->Alignment != D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT
|
|
|
|
&& desc->Alignment != D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT)
|
|
|
|
{
|
|
|
|
WARN("Invalid alignment %"PRIu64".\n", desc->Alignment);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (!resource && desc->Flags & D3D12_HEAP_FLAG_ALLOW_DISPLAY)
|
2018-07-20 05:30:18 -07:00
|
|
|
{
|
|
|
|
WARN("D3D12_HEAP_FLAG_ALLOW_DISPLAY is only for committed resources.\n");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
|
2019-06-20 12:08:08 -07:00
|
|
|
struct d3d12_device *device, const D3D12_HEAP_DESC *desc, const struct d3d12_resource *resource)
|
2018-07-20 05:30:18 -07:00
|
|
|
{
|
2018-09-25 05:13:03 -07:00
|
|
|
VkMemoryRequirements memory_requirements;
|
2019-06-20 12:08:08 -07:00
|
|
|
VkDeviceSize vk_memory_size;
|
2018-07-20 05:30:18 -07:00
|
|
|
HRESULT hr;
|
2018-11-09 09:06:20 -08:00
|
|
|
int rc;
|
2018-07-20 05:30:18 -07:00
|
|
|
|
|
|
|
heap->ID3D12Heap_iface.lpVtbl = &d3d12_heap_vtbl;
|
|
|
|
heap->refcount = 1;
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
heap->is_private = !!resource;
|
|
|
|
|
2018-07-20 05:30:18 -07:00
|
|
|
heap->desc = *desc;
|
|
|
|
|
2018-11-09 09:06:20 -08:00
|
|
|
heap->map_ptr = NULL;
|
|
|
|
heap->map_count = 0;
|
|
|
|
|
2018-07-20 05:30:18 -07:00
|
|
|
if (!heap->desc.Properties.CreationNodeMask)
|
|
|
|
heap->desc.Properties.CreationNodeMask = 1;
|
|
|
|
if (!heap->desc.Properties.VisibleNodeMask)
|
|
|
|
heap->desc.Properties.VisibleNodeMask = 1;
|
|
|
|
|
|
|
|
debug_ignored_node_mask(heap->desc.Properties.CreationNodeMask);
|
|
|
|
debug_ignored_node_mask(heap->desc.Properties.VisibleNodeMask);
|
|
|
|
|
|
|
|
if (!heap->desc.Alignment)
|
|
|
|
heap->desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (FAILED(hr = validate_heap_desc(&heap->desc, resource)))
|
2018-07-20 05:30:18 -07:00
|
|
|
return hr;
|
|
|
|
|
2018-11-09 09:06:20 -08:00
|
|
|
if ((rc = pthread_mutex_init(&heap->mutex, NULL)))
|
|
|
|
{
|
|
|
|
ERR("Failed to initialize mutex, error %d.\n", rc);
|
2018-11-09 09:06:23 -08:00
|
|
|
return hresult_from_errno(rc);
|
2018-11-09 09:06:20 -08:00
|
|
|
}
|
|
|
|
|
2019-01-10 02:16:48 -08:00
|
|
|
if (FAILED(hr = vkd3d_private_store_init(&heap->private_store)))
|
|
|
|
{
|
|
|
|
pthread_mutex_destroy(&heap->mutex);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (resource)
|
|
|
|
{
|
|
|
|
if (d3d12_resource_is_buffer(resource))
|
|
|
|
{
|
|
|
|
hr = vkd3d_allocate_buffer_memory(device, resource->u.vk_buffer,
|
|
|
|
&heap->desc.Properties, heap->desc.Flags,
|
|
|
|
&heap->vk_memory, &heap->vk_memory_type, &vk_memory_size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hr = vkd3d_allocate_image_memory(device, resource->u.vk_image,
|
|
|
|
&heap->desc.Properties, heap->desc.Flags,
|
|
|
|
&heap->vk_memory, &heap->vk_memory_type, &vk_memory_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
heap->desc.SizeInBytes = vk_memory_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memory_requirements.size = heap->desc.SizeInBytes;
|
|
|
|
memory_requirements.alignment = heap->desc.Alignment;
|
|
|
|
memory_requirements.memoryTypeBits = ~(uint32_t)0;
|
|
|
|
|
|
|
|
hr = vkd3d_allocate_device_memory(device, &heap->desc.Properties,
|
|
|
|
heap->desc.Flags, &memory_requirements, NULL,
|
|
|
|
&heap->vk_memory, &heap->vk_memory_type);
|
|
|
|
}
|
|
|
|
if (FAILED(hr))
|
2018-11-09 09:06:20 -08:00
|
|
|
{
|
2019-01-10 02:16:48 -08:00
|
|
|
vkd3d_private_store_destroy(&heap->private_store);
|
2018-11-09 09:06:20 -08:00
|
|
|
pthread_mutex_destroy(&heap->mutex);
|
2018-09-25 05:13:03 -07:00
|
|
|
return hr;
|
2018-11-09 09:06:20 -08:00
|
|
|
}
|
2018-09-25 05:13:03 -07:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
heap->device = device;
|
|
|
|
if (!heap->is_private)
|
|
|
|
d3d12_device_add_ref(heap->device);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
HRESULT d3d12_heap_create(struct d3d12_device *device, const D3D12_HEAP_DESC *desc,
|
|
|
|
const struct d3d12_resource *resource, struct d3d12_heap **heap)
|
2018-07-20 05:30:18 -07:00
|
|
|
{
|
|
|
|
struct d3d12_heap *object;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
if (!(object = vkd3d_malloc(sizeof(*object))))
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (FAILED(hr = d3d12_heap_init(object, device, desc, resource)))
|
2018-07-20 05:30:18 -07:00
|
|
|
{
|
|
|
|
vkd3d_free(object);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
TRACE("Created %s %p.\n", object->is_private ? "private heap" : "heap", object);
|
2018-07-20 05:30:18 -07:00
|
|
|
|
|
|
|
*heap = object;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2016-09-27 03:13:37 -07:00
|
|
|
static VkImageType vk_image_type_from_d3d12_resource_dimension(D3D12_RESOURCE_DIMENSION dimension)
|
|
|
|
{
|
|
|
|
switch (dimension)
|
|
|
|
{
|
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
|
|
|
return VK_IMAGE_TYPE_1D;
|
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
|
|
|
return VK_IMAGE_TYPE_2D;
|
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
|
|
|
return VK_IMAGE_TYPE_3D;
|
|
|
|
default:
|
|
|
|
ERR("Invalid resource dimension %#x.\n", dimension);
|
|
|
|
return VK_IMAGE_TYPE_2D;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-25 04:23:32 -08:00
|
|
|
VkSampleCountFlagBits vk_samples_from_sample_count(unsigned int sample_count)
|
2016-09-27 03:13:37 -07:00
|
|
|
{
|
2019-01-25 04:23:32 -08:00
|
|
|
switch (sample_count)
|
2016-09-27 03:13:37 -07:00
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
return VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
case 2:
|
|
|
|
return VK_SAMPLE_COUNT_2_BIT;
|
|
|
|
case 4:
|
|
|
|
return VK_SAMPLE_COUNT_4_BIT;
|
|
|
|
case 8:
|
|
|
|
return VK_SAMPLE_COUNT_8_BIT;
|
|
|
|
case 16:
|
|
|
|
return VK_SAMPLE_COUNT_16_BIT;
|
|
|
|
case 32:
|
|
|
|
return VK_SAMPLE_COUNT_32_BIT;
|
|
|
|
case 64:
|
|
|
|
return VK_SAMPLE_COUNT_64_BIT;
|
|
|
|
default:
|
2019-01-25 04:23:32 -08:00
|
|
|
return 0;
|
2016-09-27 03:13:37 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-25 04:23:32 -08:00
|
|
|
VkSampleCountFlagBits vk_samples_from_dxgi_sample_desc(const DXGI_SAMPLE_DESC *desc)
|
|
|
|
{
|
|
|
|
VkSampleCountFlagBits vk_samples;
|
|
|
|
|
|
|
|
if ((vk_samples = vk_samples_from_sample_count(desc->Count)))
|
|
|
|
return vk_samples;
|
|
|
|
|
|
|
|
FIXME("Unhandled sample count %u.\n", desc->Count);
|
|
|
|
return VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
}
|
|
|
|
|
2017-10-20 09:27:17 -07:00
|
|
|
HRESULT vkd3d_create_buffer(struct d3d12_device *device,
|
2016-09-27 03:13:37 -07:00
|
|
|
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
|
2017-10-20 09:27:17 -07:00
|
|
|
const D3D12_RESOURCE_DESC *desc, VkBuffer *vk_buffer)
|
2016-09-27 03:13:37 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
2019-06-05 04:02:21 -07:00
|
|
|
const bool sparse_resource = !heap_properties;
|
2016-09-27 03:13:37 -07:00
|
|
|
VkBufferCreateInfo buffer_info;
|
2019-06-05 04:02:21 -07:00
|
|
|
D3D12_HEAP_TYPE heap_type;
|
2016-09-27 03:13:37 -07:00
|
|
|
VkResult vr;
|
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
heap_type = heap_properties ? heap_properties->Type : D3D12_HEAP_TYPE_DEFAULT;
|
|
|
|
|
2016-09-27 03:13:37 -07:00
|
|
|
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
|
|
buffer_info.pNext = NULL;
|
|
|
|
buffer_info.flags = 0;
|
|
|
|
buffer_info.size = desc->Width;
|
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
if (sparse_resource)
|
|
|
|
{
|
|
|
|
buffer_info.flags |= VK_BUFFER_CREATE_SPARSE_BINDING_BIT;
|
|
|
|
if (device->vk_info.sparse_properties.residencyNonResidentStrict)
|
|
|
|
buffer_info.flags |= VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT;
|
|
|
|
}
|
|
|
|
|
2016-09-27 03:13:37 -07:00
|
|
|
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
|
|
|
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
|
|
|
| VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
|
|
|
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT
|
|
|
|
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
|
|
|
|
| VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
|
2017-10-20 09:27:17 -07:00
|
|
|
|
2019-06-18 01:07:51 -07:00
|
|
|
if (heap_type == D3D12_HEAP_TYPE_DEFAULT)
|
2019-01-14 08:05:39 -08:00
|
|
|
{
|
2019-06-18 01:07:51 -07:00
|
|
|
if (device->vk_info.EXT_conditional_rendering)
|
|
|
|
buffer_info.usage |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT;
|
|
|
|
|
|
|
|
if (device->vk_info.EXT_transform_feedback)
|
|
|
|
{
|
|
|
|
buffer_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT
|
|
|
|
| VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT;
|
|
|
|
}
|
2019-01-14 08:05:39 -08:00
|
|
|
}
|
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
if (heap_type == D3D12_HEAP_TYPE_UPLOAD)
|
2017-10-20 09:27:17 -07:00
|
|
|
buffer_info.usage &= ~VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
2019-06-05 04:02:21 -07:00
|
|
|
else if (heap_type == D3D12_HEAP_TYPE_READBACK)
|
2017-10-20 09:27:17 -07:00
|
|
|
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
|
|
|
|
2016-09-27 03:13:37 -07:00
|
|
|
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
|
|
|
|
buffer_info.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
|
|
|
|
if (!(desc->Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE))
|
|
|
|
buffer_info.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
|
|
|
|
|
2019-05-02 07:02:36 -07:00
|
|
|
/* Buffers always have properties of D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS. */
|
2019-05-02 07:02:38 -07:00
|
|
|
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS)
|
|
|
|
{
|
|
|
|
WARN("D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS cannot be set for buffers.\n");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2019-05-06 05:47:37 -07:00
|
|
|
if (device->queue_family_count > 1)
|
|
|
|
{
|
|
|
|
buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
|
|
|
|
buffer_info.queueFamilyIndexCount = device->queue_family_count;
|
|
|
|
buffer_info.pQueueFamilyIndices = device->queue_family_indices;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
|
buffer_info.queueFamilyIndexCount = 0;
|
|
|
|
buffer_info.pQueueFamilyIndices = NULL;
|
|
|
|
}
|
2016-09-27 03:13:37 -07:00
|
|
|
|
2019-05-06 05:47:38 -07:00
|
|
|
if (desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
|
|
|
|
FIXME("Unsupported resource flags %#x.\n", desc->Flags);
|
|
|
|
|
2017-10-20 09:27:17 -07:00
|
|
|
if ((vr = VK_CALL(vkCreateBuffer(device->vk_device, &buffer_info, NULL, vk_buffer))) < 0)
|
2016-09-27 03:13:37 -07:00
|
|
|
{
|
|
|
|
WARN("Failed to create Vulkan buffer, vr %d.\n", vr);
|
2019-03-04 04:15:14 -08:00
|
|
|
*vk_buffer = VK_NULL_HANDLE;
|
2016-09-27 03:13:37 -07:00
|
|
|
}
|
|
|
|
|
2019-03-04 04:15:14 -08:00
|
|
|
return hresult_from_vk_result(vr);
|
2016-09-27 03:13:37 -07:00
|
|
|
}
|
|
|
|
|
2018-03-28 06:03:18 -07:00
|
|
|
static unsigned int max_miplevel_count(const D3D12_RESOURCE_DESC *desc)
|
|
|
|
{
|
|
|
|
unsigned int size = max(desc->Width, desc->Height);
|
2018-08-28 03:19:50 -07:00
|
|
|
size = max(size, d3d12_resource_desc_get_depth(desc, 0));
|
2018-03-28 06:03:18 -07:00
|
|
|
return vkd3d_log2i(size) + 1;
|
|
|
|
}
|
|
|
|
|
2018-09-25 05:13:01 -07:00
|
|
|
static HRESULT vkd3d_create_image(struct d3d12_device *device,
|
|
|
|
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
|
|
|
|
const D3D12_RESOURCE_DESC *desc, VkImage *vk_image)
|
2016-09-27 03:13:37 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
2019-06-05 04:02:21 -07:00
|
|
|
const bool sparse_resource = !heap_properties;
|
2016-10-08 05:31:57 -07:00
|
|
|
const struct vkd3d_format *format;
|
2016-09-27 03:13:37 -07:00
|
|
|
VkImageCreateInfo image_info;
|
|
|
|
VkResult vr;
|
|
|
|
|
2019-05-07 06:37:01 -07:00
|
|
|
if (!(format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0)))
|
2016-10-08 05:31:57 -07:00
|
|
|
{
|
|
|
|
WARN("Invalid DXGI format %#x.\n", desc->Format);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2016-09-27 03:13:37 -07:00
|
|
|
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
|
|
image_info.pNext = NULL;
|
2017-08-15 04:10:05 -07:00
|
|
|
image_info.flags = 0;
|
2017-08-16 08:38:33 -07:00
|
|
|
if (!(desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) && dxgi_format_is_typeless(desc->Format))
|
2017-08-15 04:10:05 -07:00
|
|
|
image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
2018-06-07 06:52:48 -07:00
|
|
|
if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D
|
2018-11-26 05:22:23 -08:00
|
|
|
&& desc->Width == desc->Height && desc->DepthOrArraySize >= 6
|
|
|
|
&& desc->SampleDesc.Count == 1)
|
2016-09-27 03:13:37 -07:00
|
|
|
image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
2018-08-28 03:19:50 -07:00
|
|
|
if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
|
|
|
|
image_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
|
2016-09-27 03:13:37 -07:00
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
if (sparse_resource)
|
|
|
|
{
|
|
|
|
image_info.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
|
|
|
|
if (device->vk_info.sparse_properties.residencyNonResidentStrict)
|
|
|
|
image_info.flags |= VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
|
|
|
|
}
|
|
|
|
|
2016-09-27 03:13:37 -07:00
|
|
|
image_info.imageType = vk_image_type_from_d3d12_resource_dimension(desc->Dimension);
|
2016-10-08 05:31:57 -07:00
|
|
|
image_info.format = format->vk_format;
|
2016-09-27 03:13:37 -07:00
|
|
|
image_info.extent.width = desc->Width;
|
|
|
|
image_info.extent.height = desc->Height;
|
|
|
|
|
|
|
|
if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
|
|
|
|
{
|
|
|
|
image_info.extent.depth = desc->DepthOrArraySize;
|
|
|
|
image_info.arrayLayers = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
image_info.extent.depth = 1;
|
|
|
|
image_info.arrayLayers = desc->DepthOrArraySize;
|
|
|
|
}
|
|
|
|
|
2018-03-28 06:03:18 -07:00
|
|
|
image_info.mipLevels = min(desc->MipLevels, max_miplevel_count(desc));
|
2016-09-27 03:13:37 -07:00
|
|
|
image_info.samples = vk_samples_from_dxgi_sample_desc(&desc->SampleDesc);
|
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
if (sparse_resource)
|
|
|
|
{
|
|
|
|
if (desc->Layout != D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE)
|
|
|
|
{
|
|
|
|
WARN("D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE must be used for reserved texture.\n");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
|
|
}
|
|
|
|
else if (desc->Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN)
|
2016-09-27 03:13:37 -07:00
|
|
|
{
|
|
|
|
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
|
|
}
|
|
|
|
else if (desc->Layout == D3D12_TEXTURE_LAYOUT_ROW_MAJOR)
|
|
|
|
{
|
|
|
|
image_info.tiling = VK_IMAGE_TILING_LINEAR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FIXME("Unsupported layout %#x.\n", desc->Layout);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
|
|
|
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
|
|
|
|
image_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
|
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
|
|
|
|
image_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
|
|
|
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
|
|
|
|
image_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
|
|
|
if (!(desc->Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE))
|
|
|
|
image_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
|
|
|
|
2019-05-06 05:47:37 -07:00
|
|
|
if ((desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS) && device->queue_family_count > 1)
|
2019-05-02 07:02:37 -07:00
|
|
|
{
|
|
|
|
TRACE("Creating image with VK_SHARING_MODE_CONCURRENT.\n");
|
|
|
|
image_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
|
|
|
|
image_info.queueFamilyIndexCount = device->queue_family_count;
|
|
|
|
image_info.pQueueFamilyIndices = device->queue_family_indices;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
|
image_info.queueFamilyIndexCount = 0;
|
|
|
|
image_info.pQueueFamilyIndices = NULL;
|
|
|
|
}
|
2016-10-24 04:20:09 -07:00
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
image_info.initialLayout = heap_properties && is_cpu_accessible_heap(heap_properties) ?
|
2016-10-24 04:20:09 -07:00
|
|
|
VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED;
|
2016-09-27 03:13:37 -07:00
|
|
|
|
2018-09-25 05:13:01 -07:00
|
|
|
if ((vr = VK_CALL(vkCreateImage(device->vk_device, &image_info, NULL, vk_image))) < 0)
|
2016-09-27 03:13:37 -07:00
|
|
|
{
|
|
|
|
WARN("Failed to create Vulkan image, vr %d.\n", vr);
|
|
|
|
return hresult_from_vk_result(vr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2018-09-25 05:13:02 -07:00
|
|
|
HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device,
|
|
|
|
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_ALLOCATION_INFO *allocation_info)
|
|
|
|
{
|
|
|
|
static const D3D12_HEAP_PROPERTIES heap_properties = {D3D12_HEAP_TYPE_DEFAULT};
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
2019-01-25 05:52:52 -08:00
|
|
|
D3D12_RESOURCE_DESC validated_desc;
|
2018-09-25 05:13:02 -07:00
|
|
|
VkMemoryRequirements requirements;
|
|
|
|
VkImage vk_image;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
assert(desc->Dimension != D3D12_RESOURCE_DIMENSION_BUFFER);
|
2019-05-06 05:47:38 -07:00
|
|
|
assert(d3d12_resource_validate_desc(desc) == S_OK);
|
2018-09-25 05:13:02 -07:00
|
|
|
|
2019-01-25 05:52:52 -08:00
|
|
|
if (!desc->MipLevels)
|
|
|
|
{
|
|
|
|
validated_desc = *desc;
|
|
|
|
validated_desc.MipLevels = max_miplevel_count(desc);
|
|
|
|
desc = &validated_desc;
|
|
|
|
}
|
|
|
|
|
2018-09-25 05:13:02 -07:00
|
|
|
/* XXX: We have to create an image to get its memory requirements. */
|
|
|
|
if (SUCCEEDED(hr = vkd3d_create_image(device, &heap_properties, 0, desc, &vk_image)))
|
|
|
|
{
|
|
|
|
VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, &requirements));
|
|
|
|
VK_CALL(vkDestroyImage(device->vk_device, vk_image, NULL));
|
|
|
|
|
|
|
|
allocation_info->SizeInBytes = requirements.size;
|
|
|
|
allocation_info->Alignment = requirements.alignment;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2016-10-20 07:38:04 -07:00
|
|
|
static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12_device *device)
|
2016-09-27 03:13:37 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
|
2016-10-25 04:23:18 -07:00
|
|
|
if (resource->flags & VKD3D_RESOURCE_EXTERNAL)
|
2016-10-17 09:38:39 -07:00
|
|
|
return;
|
|
|
|
|
2017-07-24 16:56:16 -07:00
|
|
|
if (resource->gpu_address)
|
|
|
|
vkd3d_gpu_va_allocator_free(&device->gpu_va_allocator, resource->gpu_address);
|
|
|
|
|
2017-07-14 04:44:35 -07:00
|
|
|
if (d3d12_resource_is_buffer(resource))
|
|
|
|
VK_CALL(vkDestroyBuffer(device->vk_device, resource->u.vk_buffer, NULL));
|
|
|
|
else
|
|
|
|
VK_CALL(vkDestroyImage(device->vk_device, resource->u.vk_image, NULL));
|
2016-09-27 03:13:37 -07:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (resource->flags & VKD3D_RESOURCE_DEDICATED_HEAP)
|
|
|
|
d3d12_heap_destroy(resource->heap);
|
2016-09-27 03:13:37 -07:00
|
|
|
}
|
|
|
|
|
2018-01-24 05:33:37 -08:00
|
|
|
static ULONG d3d12_resource_incref(struct d3d12_resource *resource)
|
|
|
|
{
|
|
|
|
ULONG refcount = InterlockedIncrement(&resource->internal_refcount);
|
|
|
|
|
|
|
|
TRACE("%p increasing refcount to %u.\n", resource, refcount);
|
|
|
|
|
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG d3d12_resource_decref(struct d3d12_resource *resource)
|
|
|
|
{
|
|
|
|
ULONG refcount = InterlockedDecrement(&resource->internal_refcount);
|
|
|
|
|
|
|
|
TRACE("%p decreasing refcount to %u.\n", resource, refcount);
|
|
|
|
|
|
|
|
if (!refcount)
|
|
|
|
{
|
2019-01-04 05:34:16 -08:00
|
|
|
vkd3d_private_store_destroy(&resource->private_store);
|
2018-01-24 05:33:37 -08:00
|
|
|
d3d12_resource_destroy(resource, resource->device);
|
|
|
|
vkd3d_free(resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:06 -07:00
|
|
|
bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource)
|
|
|
|
{
|
2019-06-20 12:08:08 -07:00
|
|
|
return resource->heap && is_cpu_accessible_heap(&resource->heap->desc.Properties);
|
2019-06-20 12:08:06 -07:00
|
|
|
}
|
|
|
|
|
2016-09-26 02:13:30 -07:00
|
|
|
/* ID3D12Resource */
|
|
|
|
static inline struct d3d12_resource *impl_from_ID3D12Resource(ID3D12Resource *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource *iface,
|
|
|
|
REFIID riid, void **object)
|
|
|
|
{
|
|
|
|
TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
|
|
|
|
|
|
|
|
if (IsEqualGUID(riid, &IID_ID3D12Resource)
|
|
|
|
|| IsEqualGUID(riid, &IID_ID3D12Pageable)
|
|
|
|
|| IsEqualGUID(riid, &IID_ID3D12DeviceChild)
|
|
|
|
|| IsEqualGUID(riid, &IID_ID3D12Object)
|
|
|
|
|| IsEqualGUID(riid, &IID_IUnknown))
|
|
|
|
{
|
|
|
|
ID3D12Resource_AddRef(iface);
|
|
|
|
*object = iface;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
|
|
|
|
|
|
|
|
*object = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource *iface)
|
|
|
|
{
|
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
|
|
|
ULONG refcount = InterlockedIncrement(&resource->refcount);
|
|
|
|
|
|
|
|
TRACE("%p increasing refcount to %u.\n", resource, refcount);
|
|
|
|
|
2018-01-24 05:33:37 -08:00
|
|
|
if (refcount == 1)
|
|
|
|
{
|
|
|
|
struct d3d12_device *device = resource->device;
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
d3d12_device_add_ref(device);
|
2018-01-24 05:33:37 -08:00
|
|
|
d3d12_resource_incref(resource);
|
|
|
|
}
|
|
|
|
|
2016-09-26 02:13:30 -07:00
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource *iface)
|
|
|
|
{
|
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
|
|
|
ULONG refcount = InterlockedDecrement(&resource->refcount);
|
|
|
|
|
|
|
|
TRACE("%p decreasing refcount to %u.\n", resource, refcount);
|
|
|
|
|
|
|
|
if (!refcount)
|
|
|
|
{
|
|
|
|
struct d3d12_device *device = resource->device;
|
|
|
|
|
2018-01-24 05:33:37 -08:00
|
|
|
d3d12_resource_decref(resource);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
d3d12_device_release(device);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_GetPrivateData(ID3D12Resource *iface,
|
|
|
|
REFGUID guid, UINT *data_size, void *data)
|
|
|
|
{
|
2019-01-04 05:34:16 -08:00
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-01-04 05:34:16 -08:00
|
|
|
TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
|
|
|
|
|
|
|
|
return vkd3d_get_private_data(&resource->private_store, guid, data_size, data);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateData(ID3D12Resource *iface,
|
|
|
|
REFGUID guid, UINT data_size, const void *data)
|
|
|
|
{
|
2019-01-04 05:34:16 -08:00
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-01-04 05:34:16 -08:00
|
|
|
TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
|
|
|
|
|
|
|
|
return vkd3d_set_private_data(&resource->private_store, guid, data_size, data);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateDataInterface(ID3D12Resource *iface,
|
|
|
|
REFGUID guid, const IUnknown *data)
|
|
|
|
{
|
2019-01-04 05:34:16 -08:00
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-01-04 05:34:16 -08:00
|
|
|
TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
|
|
|
|
|
|
|
|
return vkd3d_set_private_data_interface(&resource->private_store, guid, data);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_SetName(ID3D12Resource *iface, const WCHAR *name)
|
|
|
|
{
|
2017-08-02 01:45:06 -07:00
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
2019-01-29 13:14:32 -08:00
|
|
|
HRESULT hr;
|
2017-08-02 01:45:06 -07:00
|
|
|
|
2019-01-29 13:14:32 -08:00
|
|
|
TRACE("iface %p, name %s.\n", iface, debugstr_w(name, resource->device->wchar_size));
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (resource->flags & VKD3D_RESOURCE_DEDICATED_HEAP)
|
2019-01-29 13:14:32 -08:00
|
|
|
{
|
2019-06-20 12:08:08 -07:00
|
|
|
if (FAILED(hr = d3d12_heap_SetName(&resource->heap->ID3D12Heap_iface, name)))
|
2019-01-29 13:14:32 -08:00
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d3d12_resource_is_buffer(resource))
|
|
|
|
return vkd3d_set_vk_object_name(resource->device, (uint64_t)resource->u.vk_buffer,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, name);
|
|
|
|
else
|
|
|
|
return vkd3d_set_vk_object_name(resource->device, (uint64_t)resource->u.vk_image,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, name);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_GetDevice(ID3D12Resource *iface, REFIID iid, void **device)
|
2016-09-26 02:13:30 -07:00
|
|
|
{
|
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
return d3d12_device_query_interface(resource->device, iid, device);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource *iface, UINT sub_resource,
|
|
|
|
const D3D12_RANGE *read_range, void **data)
|
|
|
|
{
|
2016-09-28 00:42:49 -07:00
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
2018-11-12 15:23:27 -08:00
|
|
|
unsigned int sub_resource_count;
|
2018-11-12 15:23:30 -08:00
|
|
|
HRESULT hr = S_OK;
|
2016-09-28 00:42:49 -07:00
|
|
|
|
|
|
|
TRACE("iface %p, sub_resource %u, read_range %p, data %p.\n",
|
2016-09-26 02:13:30 -07:00
|
|
|
iface, sub_resource, read_range, data);
|
|
|
|
|
2019-06-20 12:08:06 -07:00
|
|
|
if (!d3d12_resource_is_cpu_accessible(resource))
|
2016-10-24 04:20:09 -07:00
|
|
|
{
|
|
|
|
WARN("Resource is not CPU accessible.\n");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2018-11-12 15:23:27 -08:00
|
|
|
sub_resource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc);
|
|
|
|
if (sub_resource >= sub_resource_count)
|
|
|
|
{
|
|
|
|
WARN("Sub-resource index %u is out of range (%u sub-resources).\n", sub_resource, sub_resource_count);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2017-08-30 09:31:52 -07:00
|
|
|
if (d3d12_resource_is_texture(resource))
|
2016-09-28 00:42:49 -07:00
|
|
|
{
|
2016-10-17 05:24:22 -07:00
|
|
|
/* Textures seem to be mappable only on UMA adapters. */
|
2016-09-28 00:42:49 -07:00
|
|
|
FIXME("Not implemented for textures.\n");
|
2016-10-17 05:24:22 -07:00
|
|
|
return E_INVALIDARG;
|
2016-09-28 00:42:49 -07:00
|
|
|
}
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (!resource->heap)
|
2016-09-28 00:42:49 -07:00
|
|
|
{
|
|
|
|
FIXME("Not implemented for this resource type.\n");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2017-08-04 08:06:33 -07:00
|
|
|
WARN("Ignoring read range %p.\n", read_range);
|
2016-10-24 04:20:09 -07:00
|
|
|
|
2016-09-28 00:42:49 -07:00
|
|
|
if (!resource->map_count)
|
|
|
|
{
|
2019-06-20 12:08:08 -07:00
|
|
|
if FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, &resource->map_ptr))
|
2018-11-09 09:06:20 -08:00
|
|
|
{
|
|
|
|
WARN("Failed to map resource, hr %#x.\n", hr);
|
2018-11-12 15:23:30 -08:00
|
|
|
resource->map_ptr = NULL;
|
2016-09-28 00:42:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-12 15:23:30 -08:00
|
|
|
if (resource->map_ptr)
|
|
|
|
{
|
|
|
|
*data = resource->map_ptr;
|
|
|
|
++resource->map_count;
|
|
|
|
}
|
2016-09-28 00:42:49 -07:00
|
|
|
|
2018-11-12 15:23:30 -08:00
|
|
|
return hr;
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource *iface, UINT sub_resource,
|
|
|
|
const D3D12_RANGE *written_range)
|
|
|
|
{
|
2016-09-28 00:42:49 -07:00
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
2018-11-12 15:23:28 -08:00
|
|
|
unsigned int sub_resource_count;
|
2016-09-28 00:42:49 -07:00
|
|
|
|
|
|
|
TRACE("iface %p, sub_resource %u, written_range %p.\n",
|
2016-09-26 02:13:30 -07:00
|
|
|
iface, sub_resource, written_range);
|
2016-09-28 00:42:49 -07:00
|
|
|
|
2018-11-12 15:23:28 -08:00
|
|
|
sub_resource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc);
|
|
|
|
if (sub_resource >= sub_resource_count)
|
|
|
|
{
|
|
|
|
WARN("Sub-resource index %u is out of range (%u sub-resources).\n", sub_resource, sub_resource_count);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-09-28 00:42:49 -07:00
|
|
|
if (!resource->map_count)
|
|
|
|
{
|
|
|
|
WARN("Resource %p is not mapped.\n", resource);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-09 09:06:20 -08:00
|
|
|
WARN("Ignoring written range %p.\n", written_range);
|
|
|
|
|
2016-09-28 00:42:49 -07:00
|
|
|
--resource->map_count;
|
|
|
|
if (!resource->map_count)
|
|
|
|
{
|
2018-11-12 15:23:30 -08:00
|
|
|
resource->map_ptr = NULL;
|
2018-11-09 09:06:20 -08:00
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
assert(resource->heap);
|
|
|
|
d3d12_heap_unmap(resource->heap);
|
2016-09-28 00:42:49 -07:00
|
|
|
}
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static D3D12_RESOURCE_DESC * STDMETHODCALLTYPE d3d12_resource_GetDesc(ID3D12Resource *iface,
|
|
|
|
D3D12_RESOURCE_DESC *resource_desc)
|
|
|
|
{
|
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
|
|
|
|
|
|
|
TRACE("iface %p, resource_desc %p.\n", iface, resource_desc);
|
|
|
|
|
|
|
|
*resource_desc = resource->desc;
|
|
|
|
return resource_desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE d3d12_resource_GetGPUVirtualAddress(ID3D12Resource *iface)
|
|
|
|
{
|
2016-09-28 03:56:02 -07:00
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
|
|
|
|
|
|
|
TRACE("iface %p.\n", iface);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2017-07-24 16:56:16 -07:00
|
|
|
return resource->gpu_address;
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resource *iface,
|
|
|
|
UINT dst_sub_resource, const D3D12_BOX *dst_box, const void *src_data,
|
|
|
|
UINT src_row_pitch, UINT src_slice_pitch)
|
|
|
|
{
|
|
|
|
FIXME("iface %p, dst_sub_resource %u, dst_box %p, src_data %p, "
|
|
|
|
"src_row_pitch %u, src_slice_pitch %u stub!\n",
|
|
|
|
iface, dst_sub_resource, dst_box,
|
|
|
|
src_data, src_row_pitch, src_slice_pitch);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resource *iface,
|
|
|
|
void *dst_data, UINT dst_row_pitch, UINT dst_slice_pitch,
|
|
|
|
UINT src_sub_resource, const D3D12_BOX *src_box)
|
|
|
|
{
|
|
|
|
FIXME("iface %p, dst_data %p, dst_row_pitch %u, dst_slice_pitch %u, "
|
|
|
|
"src_sub_resource %u, src_box %p stub!\n",
|
|
|
|
iface, dst_data, dst_row_pitch, dst_slice_pitch,
|
|
|
|
src_sub_resource, src_box);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource *iface,
|
|
|
|
D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS *flags)
|
|
|
|
{
|
2017-08-30 08:57:23 -07:00
|
|
|
struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
|
2019-06-20 12:08:08 -07:00
|
|
|
struct d3d12_heap *heap;
|
2017-08-30 08:57:23 -07:00
|
|
|
|
|
|
|
TRACE("iface %p, heap_properties %p, flags %p.\n",
|
2016-09-26 02:13:30 -07:00
|
|
|
iface, heap_properties, flags);
|
|
|
|
|
2019-06-20 12:08:08 -07:00
|
|
|
if (resource->flags & VKD3D_RESOURCE_EXTERNAL)
|
|
|
|
{
|
|
|
|
if (heap_properties)
|
|
|
|
{
|
|
|
|
memset(heap_properties, 0, sizeof(*heap_properties));
|
|
|
|
heap_properties->Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
|
|
}
|
|
|
|
if (flags)
|
|
|
|
*flags = D3D12_HEAP_FLAG_NONE;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(heap = resource->heap))
|
2019-06-05 04:02:21 -07:00
|
|
|
{
|
|
|
|
WARN("Cannot get heap properties for reserved resources.\n");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2017-08-30 08:57:23 -07:00
|
|
|
if (heap_properties)
|
2019-06-20 12:08:08 -07:00
|
|
|
*heap_properties = heap->desc.Properties;
|
2017-08-30 08:57:23 -07:00
|
|
|
if (flags)
|
2019-06-20 12:08:08 -07:00
|
|
|
*flags = heap->desc.Flags;
|
2017-08-30 08:57:23 -07:00
|
|
|
|
|
|
|
return S_OK;
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct ID3D12ResourceVtbl d3d12_resource_vtbl =
|
|
|
|
{
|
|
|
|
/* IUnknown methods */
|
|
|
|
d3d12_resource_QueryInterface,
|
|
|
|
d3d12_resource_AddRef,
|
|
|
|
d3d12_resource_Release,
|
|
|
|
/* ID3D12Object methods */
|
|
|
|
d3d12_resource_GetPrivateData,
|
|
|
|
d3d12_resource_SetPrivateData,
|
|
|
|
d3d12_resource_SetPrivateDataInterface,
|
|
|
|
d3d12_resource_SetName,
|
|
|
|
/* ID3D12DeviceChild methods */
|
|
|
|
d3d12_resource_GetDevice,
|
|
|
|
/* ID3D12Resource methods */
|
|
|
|
d3d12_resource_Map,
|
|
|
|
d3d12_resource_Unmap,
|
|
|
|
d3d12_resource_GetDesc,
|
|
|
|
d3d12_resource_GetGPUVirtualAddress,
|
|
|
|
d3d12_resource_WriteToSubresource,
|
|
|
|
d3d12_resource_ReadFromSubresource,
|
|
|
|
d3d12_resource_GetHeapProperties,
|
|
|
|
};
|
|
|
|
|
2016-09-28 04:00:39 -07:00
|
|
|
struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface)
|
|
|
|
{
|
|
|
|
if (!iface)
|
|
|
|
return NULL;
|
|
|
|
assert(iface->lpVtbl == &d3d12_resource_vtbl);
|
|
|
|
return impl_from_ID3D12Resource(iface);
|
|
|
|
}
|
|
|
|
|
2019-05-06 05:47:38 -07:00
|
|
|
static void d3d12_validate_resource_flags(D3D12_RESOURCE_FLAGS flags)
|
|
|
|
{
|
|
|
|
unsigned int unknown_flags = flags & ~(D3D12_RESOURCE_FLAG_NONE
|
|
|
|
| D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET
|
|
|
|
| D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL
|
|
|
|
| D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
|
|
|
|
| D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE
|
|
|
|
| D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER
|
|
|
|
| D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
|
|
|
|
|
|
|
|
if (unknown_flags)
|
|
|
|
FIXME("Unknown resource flags %#x.\n", unknown_flags);
|
|
|
|
if (flags & D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER)
|
|
|
|
FIXME("Ignoring D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER.\n");
|
|
|
|
}
|
|
|
|
|
2018-07-20 05:30:14 -07:00
|
|
|
HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc)
|
2018-01-11 08:03:44 -08:00
|
|
|
{
|
2018-07-20 05:30:14 -07:00
|
|
|
switch (desc->Dimension)
|
2018-01-11 08:03:44 -08:00
|
|
|
{
|
2018-07-20 05:30:14 -07:00
|
|
|
case D3D12_RESOURCE_DIMENSION_BUFFER:
|
|
|
|
if (desc->MipLevels != 1)
|
|
|
|
{
|
|
|
|
WARN("Invalid miplevel count %u for buffer.\n", desc->MipLevels);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
2018-01-11 08:03:44 -08:00
|
|
|
|
2018-07-20 05:30:14 -07:00
|
|
|
if (desc->Format != DXGI_FORMAT_UNKNOWN || desc->Layout != D3D12_TEXTURE_LAYOUT_ROW_MAJOR
|
|
|
|
|| desc->Height != 1 || desc->DepthOrArraySize != 1
|
|
|
|
|| desc->SampleDesc.Count != 1 || desc->SampleDesc.Quality != 0
|
|
|
|
|| (desc->Alignment != 0 && desc->Alignment != D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT))
|
|
|
|
{
|
|
|
|
WARN("Invalid parameters for a buffer resource.\n");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
break;
|
2018-01-11 08:03:44 -08:00
|
|
|
|
2018-07-20 05:30:14 -07:00
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
|
|
|
if (desc->Height != 1)
|
|
|
|
{
|
|
|
|
WARN("1D texture with a height of %u.\n", desc->Height);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
WARN("Invalid resource dimension %#x.\n", desc->Dimension);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
2018-01-11 08:03:44 -08:00
|
|
|
|
2019-05-06 05:47:38 -07:00
|
|
|
d3d12_validate_resource_flags(desc->Flags);
|
|
|
|
|
2019-01-18 01:25:50 -08:00
|
|
|
/* FIXME: Validate alignment for textures. */
|
|
|
|
|
2018-01-11 08:03:44 -08:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
static bool d3d12_resource_validate_heap_properties(const struct d3d12_resource *resource,
|
|
|
|
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_RESOURCE_STATES initial_state)
|
2016-09-26 02:13:30 -07:00
|
|
|
{
|
2018-11-09 09:06:24 -08:00
|
|
|
if (heap_properties->Type == D3D12_HEAP_TYPE_UPLOAD
|
|
|
|
|| heap_properties->Type == D3D12_HEAP_TYPE_READBACK)
|
2016-10-17 05:24:22 -07:00
|
|
|
{
|
2018-11-09 09:06:24 -08:00
|
|
|
if (d3d12_resource_is_texture(resource))
|
|
|
|
{
|
|
|
|
WARN("Textures cannot be created on upload/readback heaps.\n");
|
2019-06-05 04:02:21 -07:00
|
|
|
return false;
|
2018-11-09 09:06:24 -08:00
|
|
|
}
|
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
if (resource->desc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS))
|
2018-11-09 09:06:24 -08:00
|
|
|
{
|
|
|
|
WARN("Render target and unordered access buffers cannot be created on upload/readback heaps.\n");
|
2019-06-05 04:02:21 -07:00
|
|
|
return false;
|
2018-11-09 09:06:24 -08:00
|
|
|
}
|
2016-10-17 05:24:22 -07:00
|
|
|
}
|
|
|
|
|
2016-10-17 05:24:22 -07:00
|
|
|
if (heap_properties->Type == D3D12_HEAP_TYPE_UPLOAD && initial_state != D3D12_RESOURCE_STATE_GENERIC_READ)
|
|
|
|
{
|
|
|
|
WARN("For D3D12_HEAP_TYPE_UPLOAD the state must be D3D12_RESOURCE_STATE_GENERIC_READ.\n");
|
2019-06-05 04:02:21 -07:00
|
|
|
return false;
|
2016-10-17 05:24:22 -07:00
|
|
|
}
|
|
|
|
if (heap_properties->Type == D3D12_HEAP_TYPE_READBACK && initial_state != D3D12_RESOURCE_STATE_COPY_DEST)
|
|
|
|
{
|
|
|
|
WARN("For D3D12_HEAP_TYPE_READBACK the state must be D3D12_RESOURCE_STATE_COPY_DEST.\n");
|
2019-06-05 04:02:21 -07:00
|
|
|
return false;
|
2016-10-17 05:24:22 -07:00
|
|
|
}
|
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT d3d12_resource_init(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_CLEAR_VALUE *optimized_clear_value)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
resource->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
|
|
|
|
resource->refcount = 1;
|
|
|
|
resource->internal_refcount = 1;
|
|
|
|
|
|
|
|
resource->desc = *desc;
|
|
|
|
|
|
|
|
if (heap_properties && !d3d12_resource_validate_heap_properties(resource, heap_properties, initial_state))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2016-10-19 04:10:12 -07:00
|
|
|
if (!is_valid_resource_state(initial_state))
|
|
|
|
{
|
|
|
|
WARN("Invalid initial resource state %#x.\n", initial_state);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2016-10-24 04:20:09 -07:00
|
|
|
if (optimized_clear_value && d3d12_resource_is_buffer(resource))
|
2016-10-19 04:10:12 -07:00
|
|
|
{
|
|
|
|
WARN("Optimized clear value must be NULL for buffers.\n");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (optimized_clear_value)
|
2017-08-04 08:06:33 -07:00
|
|
|
WARN("Ignoring optimized clear value.\n");
|
2016-10-19 04:10:12 -07:00
|
|
|
|
2017-07-24 16:56:16 -07:00
|
|
|
resource->gpu_address = 0;
|
2016-10-25 04:23:18 -07:00
|
|
|
resource->flags = 0;
|
2016-10-20 07:38:04 -07:00
|
|
|
|
2018-07-20 05:30:14 -07:00
|
|
|
if (FAILED(hr = d3d12_resource_validate_desc(&resource->desc)))
|
|
|
|
return hr;
|
|
|
|
|
2016-09-27 03:13:37 -07:00
|
|
|
switch (desc->Dimension)
|
|
|
|
{
|
|
|
|
case D3D12_RESOURCE_DIMENSION_BUFFER:
|
2018-01-11 08:03:44 -08:00
|
|
|
if (FAILED(hr = vkd3d_create_buffer(device, heap_properties, heap_flags,
|
|
|
|
&resource->desc, &resource->u.vk_buffer)))
|
2016-09-27 03:13:37 -07:00
|
|
|
return hr;
|
2017-10-20 09:27:17 -07:00
|
|
|
if (!(resource->gpu_address = vkd3d_gpu_va_allocator_allocate(&device->gpu_va_allocator,
|
|
|
|
desc->Width, resource)))
|
|
|
|
{
|
|
|
|
ERR("Failed to allocate GPU VA.\n");
|
|
|
|
d3d12_resource_destroy(resource, device);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
2016-09-27 03:13:37 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
2018-07-20 05:30:14 -07:00
|
|
|
if (!resource->desc.MipLevels)
|
|
|
|
resource->desc.MipLevels = max_miplevel_count(desc);
|
2016-10-25 04:23:18 -07:00
|
|
|
resource->flags |= VKD3D_RESOURCE_INITIAL_STATE_TRANSITION;
|
2018-09-25 05:13:01 -07:00
|
|
|
if (FAILED(hr = vkd3d_create_image(device, heap_properties, heap_flags,
|
|
|
|
&resource->desc, &resource->u.vk_image)))
|
2016-09-27 03:13:37 -07:00
|
|
|
return hr;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
WARN("Invalid resource dimension %#x.\n", resource->desc.Dimension);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2016-09-28 00:42:49 -07:00
|
|
|
resource->map_count = 0;
|
2018-11-12 15:23:30 -08:00
|
|
|
resource->map_ptr = NULL;
|
2016-09-28 00:42:49 -07:00
|
|
|
|
2016-10-25 04:23:18 -07:00
|
|
|
resource->initial_state = initial_state;
|
2016-10-24 04:20:09 -07:00
|
|
|
|
2018-11-12 15:23:26 -08:00
|
|
|
resource->heap = NULL;
|
|
|
|
resource->heap_offset = 0;
|
|
|
|
|
2019-01-10 02:16:48 -08:00
|
|
|
if (FAILED(hr = vkd3d_private_store_init(&resource->private_store)))
|
|
|
|
{
|
|
|
|
d3d12_resource_destroy(resource, device);
|
|
|
|
return hr;
|
|
|
|
}
|
2019-01-04 05:34:16 -08:00
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
d3d12_device_add_ref(resource->device = device);
|
2016-09-27 03:13:37 -07:00
|
|
|
|
|
|
|
return S_OK;
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
2018-09-12 06:19:53 -07:00
|
|
|
static HRESULT d3d12_resource_create(struct d3d12_device *device,
|
2016-09-26 02:13:30 -07:00
|
|
|
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
|
|
|
|
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
|
|
|
|
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
|
|
|
|
{
|
|
|
|
struct d3d12_resource *object;
|
2016-09-27 03:13:37 -07:00
|
|
|
HRESULT hr;
|
2016-09-26 02:13:30 -07:00
|
|
|
|
|
|
|
if (!(object = vkd3d_malloc(sizeof(*object))))
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2018-09-12 06:19:53 -07:00
|
|
|
if (FAILED(hr = d3d12_resource_init(object, device, heap_properties, heap_flags,
|
2016-09-27 03:13:37 -07:00
|
|
|
desc, initial_state, optimized_clear_value)))
|
|
|
|
{
|
|
|
|
vkd3d_free(object);
|
|
|
|
return hr;
|
|
|
|
}
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2018-09-12 06:19:53 -07:00
|
|
|
*resource = object;
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2018-09-26 00:10:31 -07:00
|
|
|
static HRESULT vkd3d_allocate_resource_memory(
|
|
|
|
struct d3d12_device *device, struct d3d12_resource *resource,
|
|
|
|
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags)
|
|
|
|
{
|
2019-06-20 12:08:08 -07:00
|
|
|
D3D12_HEAP_DESC heap_desc;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
heap_desc.SizeInBytes = 0;
|
|
|
|
heap_desc.Properties = *heap_properties;
|
|
|
|
heap_desc.Alignment = 0;
|
|
|
|
heap_desc.Flags = heap_flags;
|
|
|
|
if (SUCCEEDED(hr = d3d12_heap_create(device, &heap_desc, resource, &resource->heap)))
|
|
|
|
resource->flags |= VKD3D_RESOURCE_DEDICATED_HEAP;
|
|
|
|
return hr;
|
2018-09-26 00:10:31 -07:00
|
|
|
}
|
|
|
|
|
2018-09-12 06:19:53 -07:00
|
|
|
HRESULT d3d12_committed_resource_create(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_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
|
|
|
|
{
|
|
|
|
struct d3d12_resource *object;
|
|
|
|
HRESULT hr;
|
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
if (!heap_properties)
|
|
|
|
{
|
|
|
|
WARN("Heap properties are NULL.\n");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2018-09-12 06:19:53 -07:00
|
|
|
if (FAILED(hr = d3d12_resource_create(device, heap_properties, heap_flags,
|
|
|
|
desc, initial_state, optimized_clear_value, &object)))
|
|
|
|
return hr;
|
|
|
|
|
2018-09-26 00:10:31 -07:00
|
|
|
if (FAILED(hr = vkd3d_allocate_resource_memory(device, object, heap_properties, heap_flags)))
|
2018-09-12 06:19:53 -07:00
|
|
|
{
|
2018-09-26 00:10:31 -07:00
|
|
|
d3d12_resource_Release(&object->ID3D12Resource_iface);
|
|
|
|
return hr;
|
2018-09-12 06:19:53 -07:00
|
|
|
}
|
2018-09-26 00:10:31 -07:00
|
|
|
|
|
|
|
TRACE("Created committed resource %p.\n", object);
|
|
|
|
|
|
|
|
*resource = object;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT vkd3d_bind_heap_memory(struct d3d12_device *device,
|
2019-06-11 01:13:32 -07:00
|
|
|
struct d3d12_resource *resource, struct d3d12_heap *heap, uint64_t heap_offset)
|
2018-09-26 00:10:31 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
VkDevice vk_device = device->vk_device;
|
|
|
|
VkMemoryRequirements requirements;
|
|
|
|
VkResult vr;
|
|
|
|
|
|
|
|
if (d3d12_resource_is_buffer(resource))
|
|
|
|
VK_CALL(vkGetBufferMemoryRequirements(vk_device, resource->u.vk_buffer, &requirements));
|
2018-09-12 06:19:53 -07:00
|
|
|
else
|
2018-09-26 00:10:31 -07:00
|
|
|
VK_CALL(vkGetImageMemoryRequirements(vk_device, resource->u.vk_image, &requirements));
|
|
|
|
|
|
|
|
if (heap_offset % requirements.alignment)
|
2018-09-12 06:19:53 -07:00
|
|
|
{
|
2019-06-11 01:13:32 -07:00
|
|
|
FIXME("Invalid heap offset %#"PRIx64" (alignment %#"PRIx64").\n",
|
|
|
|
heap_offset, requirements.alignment);
|
|
|
|
goto allocate_memory;
|
2018-09-12 06:19:53 -07:00
|
|
|
}
|
|
|
|
|
2018-09-26 00:10:31 -07:00
|
|
|
if (!(requirements.memoryTypeBits & (1u << heap->vk_memory_type)))
|
2018-09-12 06:19:53 -07:00
|
|
|
{
|
2019-06-11 01:13:32 -07:00
|
|
|
FIXME("Memory type %u cannot be bound to resource %p (allowed types %#x).\n",
|
2018-09-26 00:10:31 -07:00
|
|
|
heap->vk_memory_type, resource, requirements.memoryTypeBits);
|
2019-06-11 01:13:32 -07:00
|
|
|
goto allocate_memory;
|
2018-09-12 06:19:53 -07:00
|
|
|
}
|
|
|
|
|
2018-09-26 00:10:31 -07:00
|
|
|
if (d3d12_resource_is_buffer(resource))
|
|
|
|
vr = VK_CALL(vkBindBufferMemory(vk_device, resource->u.vk_buffer, heap->vk_memory, heap_offset));
|
|
|
|
else
|
|
|
|
vr = VK_CALL(vkBindImageMemory(vk_device, resource->u.vk_image, heap->vk_memory, heap_offset));
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2018-11-12 15:23:26 -08:00
|
|
|
if (vr == VK_SUCCESS)
|
|
|
|
{
|
|
|
|
resource->heap = heap;
|
|
|
|
resource->heap_offset = heap_offset;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-26 00:10:31 -07:00
|
|
|
WARN("Failed to bind memory, vr %d.\n", vr);
|
2018-11-12 15:23:26 -08:00
|
|
|
}
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2018-09-26 00:10:31 -07:00
|
|
|
return hresult_from_vk_result(vr);
|
2019-06-11 01:13:32 -07:00
|
|
|
|
|
|
|
allocate_memory:
|
|
|
|
FIXME("Allocating device memory.\n");
|
|
|
|
return vkd3d_allocate_resource_memory(device, resource, &heap->desc.Properties, heap->desc.Flags);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-06-11 01:13:35 -07:00
|
|
|
HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_heap *heap, uint64_t heap_offset,
|
2018-09-25 05:12:59 -07:00
|
|
|
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
|
|
|
|
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
|
|
|
|
{
|
2018-09-26 00:10:31 -07:00
|
|
|
struct d3d12_resource *object;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
if (FAILED(hr = d3d12_resource_create(device, &heap->desc.Properties, heap->desc.Flags,
|
|
|
|
desc, initial_state, optimized_clear_value, &object)))
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
if (FAILED(hr = vkd3d_bind_heap_memory(device, object, heap, heap_offset)))
|
|
|
|
{
|
|
|
|
d3d12_resource_Release(&object->ID3D12Resource_iface);
|
|
|
|
return hr;
|
|
|
|
}
|
2018-09-25 05:12:59 -07:00
|
|
|
|
2018-09-26 00:10:31 -07:00
|
|
|
TRACE("Created placed resource %p.\n", object);
|
2018-09-25 05:12:59 -07:00
|
|
|
|
2018-09-26 00:10:31 -07:00
|
|
|
*resource = object;
|
|
|
|
|
|
|
|
return S_OK;
|
2018-09-25 05:12:59 -07:00
|
|
|
}
|
|
|
|
|
2019-06-05 04:02:21 -07:00
|
|
|
HRESULT d3d12_reserved_resource_create(struct d3d12_device *device,
|
|
|
|
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
|
|
|
|
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
|
|
|
|
{
|
|
|
|
struct d3d12_resource *object;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
if (FAILED(hr = d3d12_resource_create(device, NULL, 0,
|
|
|
|
desc, initial_state, optimized_clear_value, &object)))
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
TRACE("Created reserved resource %p.\n", object);
|
|
|
|
|
|
|
|
*resource = object;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2018-03-29 09:21:46 -07:00
|
|
|
HRESULT vkd3d_create_image_resource(ID3D12Device *device,
|
|
|
|
const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource)
|
2016-10-17 09:38:39 -07:00
|
|
|
{
|
|
|
|
struct d3d12_device *d3d12_device = unsafe_impl_from_ID3D12Device(device);
|
|
|
|
struct d3d12_resource *object;
|
2019-01-10 02:16:48 -08:00
|
|
|
HRESULT hr;
|
2016-10-17 09:38:39 -07:00
|
|
|
|
2018-03-29 09:21:46 -07:00
|
|
|
TRACE("device %p, create_info %p, resource %p.\n", device, create_info, resource);
|
|
|
|
|
2018-04-03 02:49:13 -07:00
|
|
|
if (!create_info || !resource)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
if (create_info->type != VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO)
|
|
|
|
{
|
|
|
|
WARN("Invalid structure type %#x.\n", create_info->type);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
if (create_info->next)
|
|
|
|
WARN("Unhandled next %p.\n", create_info->next);
|
|
|
|
|
2016-10-17 09:38:39 -07:00
|
|
|
if (!(object = vkd3d_malloc(sizeof(*object))))
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2018-11-12 15:23:31 -08:00
|
|
|
memset(object, 0, sizeof(*object));
|
|
|
|
|
2016-10-17 09:38:39 -07:00
|
|
|
object->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
|
|
|
|
object->refcount = 1;
|
2018-01-24 05:33:37 -08:00
|
|
|
object->internal_refcount = 1;
|
2018-03-29 09:21:46 -07:00
|
|
|
object->desc = create_info->desc;
|
|
|
|
object->u.vk_image = create_info->vk_image;
|
2016-10-25 04:23:18 -07:00
|
|
|
object->flags = VKD3D_RESOURCE_EXTERNAL;
|
2018-03-29 09:21:46 -07:00
|
|
|
object->flags |= create_info->flags & VKD3D_RESOURCE_PUBLIC_FLAGS;
|
2016-10-25 04:23:18 -07:00
|
|
|
object->initial_state = D3D12_RESOURCE_STATE_COMMON;
|
2018-03-29 09:21:46 -07:00
|
|
|
if (create_info->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION)
|
|
|
|
object->present_state = create_info->present_state;
|
|
|
|
else
|
|
|
|
object->present_state = D3D12_RESOURCE_STATE_COMMON;
|
2019-01-10 02:16:48 -08:00
|
|
|
|
|
|
|
if (FAILED(hr = vkd3d_private_store_init(&object->private_store)))
|
|
|
|
{
|
|
|
|
vkd3d_free(object);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
d3d12_device_add_ref(object->device = d3d12_device);
|
2016-10-17 09:38:39 -07:00
|
|
|
|
|
|
|
TRACE("Created resource %p.\n", object);
|
|
|
|
|
|
|
|
*resource = &object->ID3D12Resource_iface;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2018-01-24 05:33:37 -08:00
|
|
|
ULONG vkd3d_resource_incref(ID3D12Resource *resource)
|
|
|
|
{
|
|
|
|
TRACE("resource %p.\n", resource);
|
|
|
|
return d3d12_resource_incref(impl_from_ID3D12Resource(resource));
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG vkd3d_resource_decref(ID3D12Resource *resource)
|
|
|
|
{
|
|
|
|
TRACE("resource %p.\n", resource);
|
|
|
|
return d3d12_resource_decref(impl_from_ID3D12Resource(resource));
|
|
|
|
}
|
|
|
|
|
2017-07-14 04:44:35 -07:00
|
|
|
/* CBVs, SRVs, UAVs */
|
2017-09-04 09:32:40 -07:00
|
|
|
static struct vkd3d_view *vkd3d_view_create(void)
|
|
|
|
{
|
|
|
|
struct vkd3d_view *view;
|
|
|
|
|
|
|
|
if ((view = vkd3d_malloc(sizeof(*view))))
|
2017-09-07 08:15:53 -07:00
|
|
|
{
|
2017-09-04 09:32:40 -07:00
|
|
|
view->refcount = 1;
|
2017-09-07 08:15:53 -07:00
|
|
|
view->vk_counter_view = VK_NULL_HANDLE;
|
|
|
|
}
|
2017-09-04 09:32:40 -07:00
|
|
|
return view;
|
|
|
|
}
|
|
|
|
|
2018-08-21 09:08:01 -07:00
|
|
|
void vkd3d_view_incref(struct vkd3d_view *view)
|
2017-09-04 09:32:40 -07:00
|
|
|
{
|
|
|
|
InterlockedIncrement(&view->refcount);
|
|
|
|
}
|
|
|
|
|
2018-08-21 09:08:01 -07:00
|
|
|
static void vkd3d_view_decref_descriptor(struct vkd3d_view *view,
|
2017-09-04 09:32:40 -07:00
|
|
|
const struct d3d12_desc *descriptor, struct d3d12_device *device)
|
2017-07-14 04:44:35 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
2017-09-04 09:32:40 -07:00
|
|
|
ULONG refcount = InterlockedDecrement(&view->refcount);
|
|
|
|
|
|
|
|
if (refcount)
|
|
|
|
return;
|
|
|
|
|
|
|
|
TRACE("Destroying view %p.\n", view);
|
2017-07-14 04:44:35 -07:00
|
|
|
|
2018-08-21 09:08:01 -07:00
|
|
|
if (!descriptor)
|
|
|
|
{
|
|
|
|
VK_CALL(vkDestroyImageView(device->vk_device, view->u.vk_image_view, NULL));
|
|
|
|
}
|
|
|
|
else if (descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SRV || descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_UAV)
|
2017-08-08 08:09:35 -07:00
|
|
|
{
|
|
|
|
if (descriptor->vk_descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
|
|
|
|
|| descriptor->vk_descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
|
2017-09-04 09:32:40 -07:00
|
|
|
VK_CALL(vkDestroyBufferView(device->vk_device, view->u.vk_buffer_view, NULL));
|
2017-08-08 08:09:35 -07:00
|
|
|
else
|
2017-09-04 09:32:40 -07:00
|
|
|
VK_CALL(vkDestroyImageView(device->vk_device, view->u.vk_image_view, NULL));
|
2017-09-07 08:15:53 -07:00
|
|
|
|
|
|
|
if (view->vk_counter_view)
|
|
|
|
VK_CALL(vkDestroyBufferView(device->vk_device, view->vk_counter_view, NULL));
|
2017-08-08 08:09:35 -07:00
|
|
|
}
|
2017-08-04 08:06:33 -07:00
|
|
|
else if (descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SAMPLER)
|
2017-08-08 08:09:35 -07:00
|
|
|
{
|
2017-09-04 09:32:40 -07:00
|
|
|
VK_CALL(vkDestroySampler(device->vk_device, view->u.vk_sampler, NULL));
|
|
|
|
}
|
|
|
|
|
|
|
|
vkd3d_free(view);
|
|
|
|
}
|
|
|
|
|
2018-08-21 09:08:01 -07:00
|
|
|
void vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device)
|
|
|
|
{
|
|
|
|
vkd3d_view_decref_descriptor(view, NULL, device);
|
|
|
|
}
|
|
|
|
|
2017-09-04 09:32:40 -07:00
|
|
|
static void d3d12_desc_destroy(struct d3d12_desc *descriptor,
|
|
|
|
struct d3d12_device *device)
|
|
|
|
{
|
|
|
|
/* Nothing to do for VKD3D_DESCRIPTOR_MAGIC_CBV. */
|
|
|
|
if (descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SRV
|
|
|
|
|| descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_UAV
|
|
|
|
|| descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SAMPLER)
|
|
|
|
{
|
2018-08-21 09:08:01 -07:00
|
|
|
vkd3d_view_decref_descriptor(descriptor->u.view, descriptor, device);
|
2017-08-08 08:09:35 -07:00
|
|
|
}
|
2017-08-04 08:06:33 -07:00
|
|
|
|
|
|
|
memset(descriptor, 0, sizeof(*descriptor));
|
2017-07-14 04:44:35 -07:00
|
|
|
}
|
|
|
|
|
2017-10-04 04:55:33 -07:00
|
|
|
void d3d12_desc_copy(struct d3d12_desc *dst, const struct d3d12_desc *src,
|
2017-09-04 09:32:40 -07:00
|
|
|
struct d3d12_device *device)
|
|
|
|
{
|
2019-04-02 03:15:52 -07:00
|
|
|
assert(dst != src);
|
|
|
|
|
2017-09-04 09:32:40 -07:00
|
|
|
d3d12_desc_destroy(dst, device);
|
|
|
|
|
|
|
|
*dst = *src;
|
|
|
|
|
|
|
|
if (src->magic == VKD3D_DESCRIPTOR_MAGIC_SRV
|
|
|
|
|| src->magic == VKD3D_DESCRIPTOR_MAGIC_UAV
|
|
|
|
|| src->magic == VKD3D_DESCRIPTOR_MAGIC_SAMPLER)
|
|
|
|
{
|
|
|
|
vkd3d_view_incref(src->u.view);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-22 03:39:56 -07:00
|
|
|
static bool vkd3d_create_vk_buffer_view(struct d3d12_device *device,
|
2019-06-04 05:28:56 -07:00
|
|
|
VkBuffer vk_buffer, const struct vkd3d_format *format,
|
2017-08-02 06:30:15 -07:00
|
|
|
VkDeviceSize offset, VkDeviceSize range, VkBufferView *vk_view)
|
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
2019-06-04 05:28:55 -07:00
|
|
|
const struct vkd3d_vulkan_info *vk_info = &device->vk_info;
|
2017-08-02 06:30:15 -07:00
|
|
|
struct VkBufferViewCreateInfo view_desc;
|
|
|
|
VkResult vr;
|
|
|
|
|
2017-08-18 08:08:56 -07:00
|
|
|
if (vkd3d_format_is_compressed(format))
|
|
|
|
{
|
|
|
|
WARN("Invalid format for buffer view %#x.\n", format->dxgi_format);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-06-04 05:28:55 -07:00
|
|
|
if (offset % vk_info->device_limits.minTexelBufferOffsetAlignment)
|
|
|
|
{
|
|
|
|
FIXME("Offset %#"PRIx64" violates the minimum required alignment %#"PRIx64".\n",
|
|
|
|
offset, vk_info->device_limits.minTexelBufferOffsetAlignment);
|
|
|
|
}
|
|
|
|
|
2017-08-02 06:30:15 -07:00
|
|
|
view_desc.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
|
|
|
|
view_desc.pNext = NULL;
|
|
|
|
view_desc.flags = 0;
|
2019-06-04 05:28:56 -07:00
|
|
|
view_desc.buffer = vk_buffer;
|
2017-08-02 06:30:15 -07:00
|
|
|
view_desc.format = format->vk_format;
|
|
|
|
view_desc.offset = offset;
|
|
|
|
view_desc.range = range;
|
|
|
|
if ((vr = VK_CALL(vkCreateBufferView(device->vk_device, &view_desc, NULL, vk_view))) < 0)
|
|
|
|
WARN("Failed to create Vulkan buffer view, vr %d.\n", vr);
|
2017-08-18 08:08:56 -07:00
|
|
|
return vr == VK_SUCCESS;
|
2017-08-02 06:30:15 -07:00
|
|
|
}
|
|
|
|
|
2019-06-04 05:28:56 -07:00
|
|
|
static bool vkd3d_create_buffer_view(struct d3d12_device *device,
|
|
|
|
VkBuffer vk_buffer, const struct vkd3d_format *format,
|
|
|
|
VkDeviceSize offset, VkDeviceSize size, struct vkd3d_view **view)
|
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
struct vkd3d_view *object;
|
|
|
|
VkBufferView vk_view;
|
|
|
|
|
|
|
|
if (!vkd3d_create_vk_buffer_view(device, vk_buffer, format, offset, size, &vk_view))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(object = vkd3d_view_create()))
|
|
|
|
{
|
|
|
|
VK_CALL(vkDestroyBufferView(device->vk_device, vk_view, NULL));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
object->u.vk_buffer_view = vk_view;
|
|
|
|
*view = object;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-08-22 03:39:56 -07:00
|
|
|
#define VKD3D_VIEW_RAW_BUFFER 0x1
|
|
|
|
|
2019-06-04 05:28:56 -07:00
|
|
|
static bool vkd3d_create_buffer_view_for_resource(struct d3d12_device *device,
|
2017-08-22 03:39:56 -07:00
|
|
|
struct d3d12_resource *resource, DXGI_FORMAT view_format,
|
|
|
|
unsigned int offset, unsigned int size, unsigned int structure_stride,
|
2018-08-30 05:12:54 -07:00
|
|
|
unsigned int flags, struct vkd3d_view **view)
|
2017-08-22 03:39:56 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_format *format;
|
2018-11-15 07:32:41 -08:00
|
|
|
VkDeviceSize element_size;
|
2017-08-22 03:39:56 -07:00
|
|
|
|
|
|
|
if (view_format == DXGI_FORMAT_R32_TYPELESS && (flags & VKD3D_VIEW_RAW_BUFFER))
|
|
|
|
{
|
2019-05-07 06:37:02 -07:00
|
|
|
format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
|
2017-08-22 03:39:56 -07:00
|
|
|
element_size = format->byte_count;
|
|
|
|
}
|
|
|
|
else if (view_format == DXGI_FORMAT_UNKNOWN && structure_stride)
|
|
|
|
{
|
2019-05-07 06:37:02 -07:00
|
|
|
format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
|
2017-08-22 03:39:56 -07:00
|
|
|
element_size = structure_stride;
|
|
|
|
}
|
2019-05-07 06:37:01 -07:00
|
|
|
else if ((format = vkd3d_format_from_d3d12_resource_desc(device, &resource->desc, view_format)))
|
2017-08-22 03:39:56 -07:00
|
|
|
{
|
|
|
|
element_size = format->byte_count;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WARN("Failed to find format for %#x.\n", resource->desc.Format);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-06-04 05:28:56 -07:00
|
|
|
assert(d3d12_resource_is_buffer(resource));
|
2018-08-30 05:12:54 -07:00
|
|
|
|
2019-06-04 05:28:56 -07:00
|
|
|
return vkd3d_create_buffer_view(device, resource->u.vk_buffer,
|
|
|
|
format, offset * element_size, size * element_size, view);
|
2017-08-22 03:39:56 -07:00
|
|
|
}
|
|
|
|
|
2018-02-13 04:15:04 -08:00
|
|
|
static void vkd3d_set_view_swizzle_for_format(VkComponentMapping *components,
|
|
|
|
const struct vkd3d_format *format, bool allowed_swizzle)
|
|
|
|
{
|
2019-03-22 07:11:37 -07:00
|
|
|
components->r = VK_COMPONENT_SWIZZLE_R;
|
|
|
|
components->g = VK_COMPONENT_SWIZZLE_G;
|
|
|
|
components->b = VK_COMPONENT_SWIZZLE_B;
|
|
|
|
components->a = VK_COMPONENT_SWIZZLE_A;
|
2018-05-29 03:50:33 -07:00
|
|
|
|
2018-02-13 04:15:04 -08:00
|
|
|
if (format->vk_aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT)
|
|
|
|
{
|
|
|
|
if (allowed_swizzle)
|
|
|
|
{
|
|
|
|
components->r = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
components->g = VK_COMPONENT_SWIZZLE_R;
|
|
|
|
components->b = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
components->a = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FIXME("Stencil swizzle is not supported for format %#x.\n",
|
|
|
|
format->dxgi_format);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (format->dxgi_format == DXGI_FORMAT_A8_UNORM)
|
|
|
|
{
|
|
|
|
if (allowed_swizzle)
|
|
|
|
{
|
|
|
|
components->r = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
components->g = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
components->b = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
components->a = VK_COMPONENT_SWIZZLE_R;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FIXME("Alpha swizzle is not supported.\n");
|
|
|
|
}
|
|
|
|
}
|
2019-03-07 02:01:11 -08:00
|
|
|
|
|
|
|
if (format->dxgi_format == DXGI_FORMAT_B8G8R8X8_UNORM
|
|
|
|
|| format->dxgi_format == DXGI_FORMAT_B8G8R8X8_UNORM_SRGB)
|
|
|
|
{
|
|
|
|
if (allowed_swizzle)
|
|
|
|
{
|
|
|
|
components->r = VK_COMPONENT_SWIZZLE_R;
|
|
|
|
components->g = VK_COMPONENT_SWIZZLE_G;
|
|
|
|
components->b = VK_COMPONENT_SWIZZLE_B;
|
|
|
|
components->a = VK_COMPONENT_SWIZZLE_ONE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FIXME("B8G8R8X8 swizzle is not supported.\n");
|
|
|
|
}
|
|
|
|
}
|
2018-02-13 04:15:04 -08:00
|
|
|
}
|
|
|
|
|
2019-03-22 07:11:37 -07:00
|
|
|
static VkComponentSwizzle vk_component_swizzle_from_d3d12(unsigned int component_mapping,
|
|
|
|
unsigned int component_index)
|
|
|
|
{
|
|
|
|
D3D12_SHADER_COMPONENT_MAPPING mapping
|
|
|
|
= D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(component_index, component_mapping);
|
|
|
|
|
|
|
|
switch (mapping)
|
|
|
|
{
|
|
|
|
case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0:
|
|
|
|
return VK_COMPONENT_SWIZZLE_R;
|
|
|
|
case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1:
|
|
|
|
return VK_COMPONENT_SWIZZLE_G;
|
|
|
|
case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2:
|
|
|
|
return VK_COMPONENT_SWIZZLE_B;
|
|
|
|
case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3:
|
|
|
|
return VK_COMPONENT_SWIZZLE_A;
|
|
|
|
case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0:
|
|
|
|
return VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1:
|
|
|
|
return VK_COMPONENT_SWIZZLE_ONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
FIXME("Invalid component mapping %#x.\n", mapping);
|
|
|
|
return VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vk_component_mapping_from_d3d12(VkComponentMapping *components,
|
|
|
|
unsigned int component_mapping)
|
|
|
|
{
|
|
|
|
components->r = vk_component_swizzle_from_d3d12(component_mapping, 0);
|
|
|
|
components->g = vk_component_swizzle_from_d3d12(component_mapping, 1);
|
|
|
|
components->b = vk_component_swizzle_from_d3d12(component_mapping, 2);
|
|
|
|
components->a = vk_component_swizzle_from_d3d12(component_mapping, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VkComponentSwizzle swizzle_vk_component(const VkComponentMapping *components,
|
|
|
|
VkComponentSwizzle component, VkComponentSwizzle swizzle)
|
|
|
|
{
|
|
|
|
switch (swizzle)
|
|
|
|
{
|
|
|
|
case VK_COMPONENT_SWIZZLE_IDENTITY:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_R:
|
|
|
|
component = components->r;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_G:
|
|
|
|
component = components->g;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_B:
|
|
|
|
component = components->b;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_A:
|
|
|
|
component = components->a;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_ONE:
|
|
|
|
case VK_COMPONENT_SWIZZLE_ZERO:
|
|
|
|
component = swizzle;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
FIXME("Invalid component swizzle %#x.\n", swizzle);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(component != VK_COMPONENT_SWIZZLE_IDENTITY);
|
|
|
|
return component;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vk_component_mapping_compose(VkComponentMapping *dst, const VkComponentMapping *b)
|
|
|
|
{
|
|
|
|
const VkComponentMapping a = *dst;
|
|
|
|
|
|
|
|
dst->r = swizzle_vk_component(&a, a.r, b->r);
|
|
|
|
dst->g = swizzle_vk_component(&a, a.g, b->g);
|
|
|
|
dst->b = swizzle_vk_component(&a, a.b, b->b);
|
|
|
|
dst->a = swizzle_vk_component(&a, a.a, b->a);
|
|
|
|
}
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
struct vkd3d_texture_view_desc
|
|
|
|
{
|
|
|
|
VkImageViewType view_type;
|
|
|
|
const struct vkd3d_format *format;
|
|
|
|
unsigned int miplevel_idx;
|
|
|
|
unsigned int miplevel_count;
|
|
|
|
unsigned int layer_idx;
|
|
|
|
unsigned int layer_count;
|
2019-03-22 07:11:37 -07:00
|
|
|
VkComponentMapping components;
|
2018-08-28 03:19:47 -07:00
|
|
|
bool allowed_swizzle;
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool init_default_texture_view_desc(struct vkd3d_texture_view_desc *desc,
|
|
|
|
struct d3d12_resource *resource, DXGI_FORMAT view_format)
|
|
|
|
{
|
2019-05-07 06:37:01 -07:00
|
|
|
const struct d3d12_device *device = resource->device;
|
|
|
|
|
|
|
|
if (!(desc->format = vkd3d_format_from_d3d12_resource_desc(device, &resource->desc, view_format)))
|
2018-08-28 03:19:47 -07:00
|
|
|
{
|
|
|
|
FIXME("Failed to find format (resource format %#x, view format %#x).\n",
|
|
|
|
resource->desc.Format, view_format);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-28 03:19:48 -07:00
|
|
|
desc->miplevel_idx = 0;
|
|
|
|
desc->miplevel_count = 1;
|
|
|
|
desc->layer_idx = 0;
|
2018-08-28 03:19:50 -07:00
|
|
|
desc->layer_count = d3d12_resource_desc_get_layer_count(&resource->desc);
|
2018-08-28 03:19:48 -07:00
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
switch (resource->desc.Dimension)
|
|
|
|
{
|
2018-08-28 03:19:48 -07:00
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
|
|
|
desc->view_type = resource->desc.DepthOrArraySize > 1
|
|
|
|
? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D;
|
|
|
|
break;
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
|
|
|
desc->view_type = resource->desc.DepthOrArraySize > 1
|
|
|
|
? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
break;
|
|
|
|
|
2018-08-28 03:19:49 -07:00
|
|
|
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
|
|
|
desc->view_type = VK_IMAGE_VIEW_TYPE_3D;
|
|
|
|
desc->layer_count = 1;
|
|
|
|
break;
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
default:
|
|
|
|
FIXME("Resource dimension %#x not implemented.\n", resource->desc.Dimension);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-22 07:11:37 -07:00
|
|
|
desc->components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
desc->components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
desc->components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
desc->components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
2018-08-28 03:19:47 -07:00
|
|
|
desc->allowed_swizzle = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-08-30 05:12:55 -07:00
|
|
|
static bool vkd3d_create_texture_view(struct d3d12_device *device,
|
2019-03-28 09:07:27 -07:00
|
|
|
VkImage vk_image, const struct vkd3d_texture_view_desc *desc,
|
2018-08-28 03:19:53 -07:00
|
|
|
struct vkd3d_view **view)
|
2017-08-01 07:56:44 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
2018-08-28 03:19:47 -07:00
|
|
|
const struct vkd3d_format *format = desc->format;
|
2017-08-01 07:56:44 -07:00
|
|
|
struct VkImageViewCreateInfo view_desc;
|
2018-08-28 03:19:53 -07:00
|
|
|
struct vkd3d_view *object;
|
|
|
|
VkImageView vk_view;
|
2017-08-01 07:56:44 -07:00
|
|
|
VkResult vr;
|
|
|
|
|
|
|
|
view_desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
|
view_desc.pNext = NULL;
|
|
|
|
view_desc.flags = 0;
|
2019-03-28 09:07:27 -07:00
|
|
|
view_desc.image = vk_image;
|
2018-08-28 03:19:47 -07:00
|
|
|
view_desc.viewType = desc->view_type;
|
2017-08-01 07:56:44 -07:00
|
|
|
view_desc.format = format->vk_format;
|
2018-08-28 03:19:47 -07:00
|
|
|
vkd3d_set_view_swizzle_for_format(&view_desc.components, format, desc->allowed_swizzle);
|
2019-03-22 07:11:37 -07:00
|
|
|
if (desc->allowed_swizzle)
|
|
|
|
vk_component_mapping_compose(&view_desc.components, &desc->components);
|
2017-08-01 07:56:44 -07:00
|
|
|
view_desc.subresourceRange.aspectMask = format->vk_aspect_mask;
|
2018-08-28 03:19:47 -07:00
|
|
|
view_desc.subresourceRange.baseMipLevel = desc->miplevel_idx;
|
|
|
|
view_desc.subresourceRange.levelCount = desc->miplevel_count;
|
|
|
|
view_desc.subresourceRange.baseArrayLayer = desc->layer_idx;
|
|
|
|
view_desc.subresourceRange.layerCount = desc->layer_count;
|
2018-08-28 03:19:53 -07:00
|
|
|
if ((vr = VK_CALL(vkCreateImageView(device->vk_device, &view_desc, NULL, &vk_view))) < 0)
|
|
|
|
{
|
2017-08-01 07:56:44 -07:00
|
|
|
WARN("Failed to create Vulkan image view, vr %d.\n", vr);
|
2018-08-30 05:12:55 -07:00
|
|
|
return false;
|
2018-08-28 03:19:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(object = vkd3d_view_create()))
|
|
|
|
{
|
|
|
|
VK_CALL(vkDestroyImageView(device->vk_device, vk_view, NULL));
|
2018-08-30 05:12:55 -07:00
|
|
|
return false;
|
2018-08-28 03:19:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
object->u.vk_image_view = vk_view;
|
|
|
|
*view = object;
|
2018-08-30 05:12:55 -07:00
|
|
|
return true;
|
2017-08-01 07:56:44 -07:00
|
|
|
}
|
|
|
|
|
2017-08-04 08:06:33 -07:00
|
|
|
void d3d12_desc_create_cbv(struct d3d12_desc *descriptor,
|
2017-08-04 08:06:33 -07:00
|
|
|
struct d3d12_device *device, const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc)
|
|
|
|
{
|
|
|
|
struct VkDescriptorBufferInfo *buffer_info;
|
|
|
|
struct d3d12_resource *resource;
|
|
|
|
|
2017-08-04 08:06:33 -07:00
|
|
|
d3d12_desc_destroy(descriptor, device);
|
2017-08-04 08:06:33 -07:00
|
|
|
|
|
|
|
if (!desc)
|
|
|
|
{
|
|
|
|
WARN("Constant buffer desc is NULL.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (desc->SizeInBytes & (D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1))
|
|
|
|
{
|
|
|
|
WARN("Size is not %u bytes aligned.\n", D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-04 04:15:14 -08:00
|
|
|
buffer_info = &descriptor->u.vk_cbv_info;
|
|
|
|
if (desc->BufferLocation)
|
2018-01-09 04:13:06 -08:00
|
|
|
{
|
2019-03-04 04:15:14 -08:00
|
|
|
resource = vkd3d_gpu_va_allocator_dereference(&device->gpu_va_allocator, desc->BufferLocation);
|
|
|
|
buffer_info->buffer = resource->u.vk_buffer;
|
|
|
|
buffer_info->offset = desc->BufferLocation - resource->gpu_address;
|
|
|
|
buffer_info->range = min(desc->SizeInBytes, resource->desc.Width - buffer_info->offset);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* NULL descriptor */
|
2019-05-15 04:17:58 -07:00
|
|
|
buffer_info->buffer = device->null_resources.vk_buffer;
|
2019-03-04 04:15:14 -08:00
|
|
|
buffer_info->offset = 0;
|
2019-05-15 04:17:58 -07:00
|
|
|
buffer_info->range = VKD3D_NULL_BUFFER_SIZE;
|
2018-01-09 04:13:06 -08:00
|
|
|
}
|
2017-08-04 08:06:33 -07:00
|
|
|
|
|
|
|
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_CBV;
|
|
|
|
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
|
|
}
|
|
|
|
|
2017-08-22 03:39:56 -07:00
|
|
|
static unsigned int vkd3d_view_flags_from_d3d12_buffer_srv_flags(D3D12_BUFFER_SRV_FLAGS flags)
|
|
|
|
{
|
|
|
|
if (flags == D3D12_BUFFER_SRV_FLAG_RAW)
|
|
|
|
return VKD3D_VIEW_RAW_BUFFER;
|
|
|
|
if (flags)
|
|
|
|
FIXME("Unhandled buffer SRV flags %#x.\n", flags);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
static void vkd3d_create_null_srv(struct d3d12_desc *descriptor,
|
|
|
|
struct d3d12_device *device, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc)
|
|
|
|
{
|
|
|
|
struct vkd3d_null_resources *null_resources = &device->null_resources;
|
|
|
|
struct vkd3d_texture_view_desc vkd3d_desc;
|
|
|
|
struct vkd3d_view *view;
|
|
|
|
VkImage vk_image;
|
|
|
|
|
|
|
|
if (!desc)
|
|
|
|
{
|
|
|
|
WARN("D3D12_SHADER_RESOURCE_VIEW_DESC is required for NULL view.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (desc->ViewDimension)
|
|
|
|
{
|
2019-06-04 05:28:57 -07:00
|
|
|
case D3D12_SRV_DIMENSION_BUFFER:
|
|
|
|
WARN("Creating NULL buffer SRV %#x.\n", desc->Format);
|
|
|
|
|
|
|
|
if (vkd3d_create_buffer_view(device, null_resources->vk_buffer,
|
|
|
|
vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false),
|
|
|
|
0, VKD3D_NULL_BUFFER_SIZE, &view))
|
|
|
|
{
|
|
|
|
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
|
|
|
|
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
|
|
|
descriptor->u.view = view;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2D:
|
|
|
|
vk_image = null_resources->vk_2d_image;
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
vk_image = null_resources->vk_2d_image;
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN("Creating NULL SRV %#x.\n", desc->ViewDimension);
|
|
|
|
|
2019-06-04 05:28:57 -07:00
|
|
|
vkd3d_desc.format = vkd3d_get_format(device, VKD3D_NULL_VIEW_FORMAT, false);
|
2019-03-28 09:07:27 -07:00
|
|
|
vkd3d_desc.miplevel_idx = 0;
|
|
|
|
vkd3d_desc.miplevel_count = 1;
|
|
|
|
vkd3d_desc.layer_idx = 0;
|
|
|
|
vkd3d_desc.layer_count = 1;
|
|
|
|
vkd3d_desc.components.r = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
vkd3d_desc.components.g = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
vkd3d_desc.components.b = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
vkd3d_desc.components.a = VK_COMPONENT_SWIZZLE_ZERO;
|
|
|
|
vkd3d_desc.allowed_swizzle = true;
|
|
|
|
|
|
|
|
if (!vkd3d_create_texture_view(device, vk_image, &vkd3d_desc, &view))
|
|
|
|
return;
|
|
|
|
|
|
|
|
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
|
|
|
|
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
|
|
|
descriptor->u.view = view;
|
|
|
|
}
|
|
|
|
|
2017-08-22 03:39:56 -07:00
|
|
|
static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
|
|
|
|
struct d3d12_device *device, struct d3d12_resource *resource,
|
|
|
|
const D3D12_SHADER_RESOURCE_VIEW_DESC *desc)
|
|
|
|
{
|
2017-09-04 09:32:40 -07:00
|
|
|
struct vkd3d_view *view;
|
2018-08-30 05:12:54 -07:00
|
|
|
unsigned int flags;
|
2017-09-04 09:32:40 -07:00
|
|
|
|
2017-08-22 03:39:56 -07:00
|
|
|
if (!desc)
|
|
|
|
{
|
|
|
|
FIXME("Default SRV views not supported.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (desc->ViewDimension != D3D12_SRV_DIMENSION_BUFFER)
|
|
|
|
{
|
|
|
|
WARN("Unexpected view dimension %#x.\n", desc->ViewDimension);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-30 05:12:54 -07:00
|
|
|
flags = vkd3d_view_flags_from_d3d12_buffer_srv_flags(desc->u.Buffer.Flags);
|
2019-06-04 05:28:56 -07:00
|
|
|
if (!vkd3d_create_buffer_view_for_resource(device, resource, desc->Format,
|
2017-08-22 03:39:56 -07:00
|
|
|
desc->u.Buffer.FirstElement, desc->u.Buffer.NumElements,
|
2018-08-30 05:12:54 -07:00
|
|
|
desc->u.Buffer.StructureByteStride, flags, &view))
|
2017-08-22 03:39:56 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
|
|
|
|
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
2017-09-04 09:32:40 -07:00
|
|
|
descriptor->u.view = view;
|
2017-08-22 03:39:56 -07:00
|
|
|
}
|
|
|
|
|
2017-08-04 08:06:33 -07:00
|
|
|
void d3d12_desc_create_srv(struct d3d12_desc *descriptor,
|
2017-07-14 04:44:35 -07:00
|
|
|
struct d3d12_device *device, struct d3d12_resource *resource,
|
|
|
|
const D3D12_SHADER_RESOURCE_VIEW_DESC *desc)
|
|
|
|
{
|
2018-08-28 03:19:47 -07:00
|
|
|
struct vkd3d_texture_view_desc vkd3d_desc;
|
2017-09-04 09:32:40 -07:00
|
|
|
struct vkd3d_view *view;
|
2017-07-14 04:44:35 -07:00
|
|
|
|
2017-08-04 08:06:33 -07:00
|
|
|
d3d12_desc_destroy(descriptor, device);
|
2017-07-14 04:44:35 -07:00
|
|
|
|
|
|
|
if (!resource)
|
|
|
|
{
|
2019-03-28 09:07:27 -07:00
|
|
|
vkd3d_create_null_srv(descriptor, device, desc);
|
2017-07-14 04:44:35 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-22 03:39:56 -07:00
|
|
|
if (d3d12_resource_is_buffer(resource))
|
|
|
|
{
|
|
|
|
vkd3d_create_buffer_srv(descriptor, device, resource, desc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
|
2017-07-14 04:44:35 -07:00
|
|
|
return;
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
vkd3d_desc.miplevel_count = VK_REMAINING_MIP_LEVELS;
|
|
|
|
vkd3d_desc.allowed_swizzle = true;
|
2017-07-14 04:44:35 -07:00
|
|
|
|
2018-06-27 06:19:22 -07:00
|
|
|
if (desc)
|
|
|
|
{
|
|
|
|
if (desc->Shader4ComponentMapping != D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING)
|
2019-03-22 07:11:37 -07:00
|
|
|
{
|
|
|
|
TRACE("Component mapping %s for format %#x.\n",
|
|
|
|
debug_d3d12_shader_component_mapping(desc->Shader4ComponentMapping), desc->Format);
|
|
|
|
|
|
|
|
vk_component_mapping_from_d3d12(&vkd3d_desc.components, desc->Shader4ComponentMapping);
|
|
|
|
}
|
2018-06-27 06:19:22 -07:00
|
|
|
|
|
|
|
switch (desc->ViewDimension)
|
|
|
|
{
|
2018-07-19 05:47:41 -07:00
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2D:
|
2018-08-28 03:19:47 -07:00
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture2D.MostDetailedMip;
|
|
|
|
vkd3d_desc.miplevel_count = desc->u.Texture2D.MipLevels;
|
2018-07-19 05:47:41 -07:00
|
|
|
if (desc->u.Texture2D.PlaneSlice)
|
|
|
|
FIXME("Ignoring plane slice %u.\n", desc->u.Texture2D.PlaneSlice);
|
|
|
|
if (desc->u.Texture2D.ResourceMinLODClamp)
|
|
|
|
FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.Texture2D.ResourceMinLODClamp);
|
|
|
|
break;
|
2018-08-28 03:19:51 -07:00
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture2DArray.MostDetailedMip;
|
|
|
|
vkd3d_desc.miplevel_count = desc->u.Texture2DArray.MipLevels;
|
|
|
|
vkd3d_desc.layer_idx = desc->u.Texture2DArray.FirstArraySlice;
|
|
|
|
vkd3d_desc.layer_count = desc->u.Texture2DArray.ArraySize;
|
|
|
|
if (desc->u.Texture2DArray.PlaneSlice)
|
|
|
|
FIXME("Ignoring plane slice %u.\n", desc->u.Texture2DArray.PlaneSlice);
|
|
|
|
if (desc->u.Texture2DArray.ResourceMinLODClamp)
|
|
|
|
FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.Texture2DArray.ResourceMinLODClamp);
|
|
|
|
break;
|
2018-11-26 05:22:25 -08:00
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DMS:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
vkd3d_desc.layer_idx = desc->u.Texture2DMSArray.FirstArraySlice;
|
|
|
|
vkd3d_desc.layer_count = desc->u.Texture2DMSArray.ArraySize;
|
|
|
|
break;
|
2018-08-28 03:19:50 -07:00
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE3D:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_3D;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture3D.MostDetailedMip;
|
|
|
|
vkd3d_desc.miplevel_count = desc->u.Texture3D.MipLevels;
|
|
|
|
if (desc->u.Texture3D.ResourceMinLODClamp)
|
|
|
|
FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.Texture2D.ResourceMinLODClamp);
|
|
|
|
break;
|
2018-06-27 06:19:22 -07:00
|
|
|
case D3D12_SRV_DIMENSION_TEXTURECUBE:
|
2018-08-28 03:19:47 -07:00
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_CUBE;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.TextureCube.MostDetailedMip;
|
|
|
|
vkd3d_desc.miplevel_count = desc->u.TextureCube.MipLevels;
|
|
|
|
vkd3d_desc.layer_count = 6;
|
2018-06-27 06:19:22 -07:00
|
|
|
if (desc->u.TextureCube.ResourceMinLODClamp)
|
|
|
|
FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.TextureCube.ResourceMinLODClamp);
|
|
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY:
|
2018-08-28 03:19:47 -07:00
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.TextureCubeArray.MostDetailedMip;
|
|
|
|
vkd3d_desc.miplevel_count = desc->u.TextureCubeArray.MipLevels;
|
|
|
|
vkd3d_desc.layer_idx = desc->u.TextureCubeArray.First2DArrayFace;
|
2018-10-26 06:06:55 -07:00
|
|
|
vkd3d_desc.layer_count = desc->u.TextureCubeArray.NumCubes;
|
|
|
|
if (vkd3d_desc.layer_count != VK_REMAINING_ARRAY_LAYERS)
|
|
|
|
vkd3d_desc.layer_count *= 6;
|
2018-06-27 06:19:22 -07:00
|
|
|
if (desc->u.TextureCubeArray.ResourceMinLODClamp)
|
|
|
|
FIXME("Unhandled min LOD clamp %.8e.\n", desc->u.TextureCubeArray.ResourceMinLODClamp);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
|
2017-07-14 04:44:35 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
|
2017-07-25 03:50:14 -07:00
|
|
|
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
2017-09-04 09:32:40 -07:00
|
|
|
descriptor->u.view = view;
|
2017-07-25 03:50:14 -07:00
|
|
|
}
|
|
|
|
|
2017-08-22 03:39:56 -07:00
|
|
|
static unsigned int vkd3d_view_flags_from_d3d12_buffer_uav_flags(D3D12_BUFFER_UAV_FLAGS flags)
|
|
|
|
{
|
|
|
|
if (flags == D3D12_BUFFER_UAV_FLAG_RAW)
|
|
|
|
return VKD3D_VIEW_RAW_BUFFER;
|
|
|
|
if (flags)
|
|
|
|
FIXME("Unhandled buffer UAV flags %#x.\n", flags);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-04 05:28:58 -07:00
|
|
|
static void vkd3d_create_null_uav(struct d3d12_desc *descriptor,
|
|
|
|
struct d3d12_device *device, const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
|
|
|
|
{
|
|
|
|
struct vkd3d_null_resources *null_resources = &device->null_resources;
|
2019-06-04 05:28:59 -07:00
|
|
|
struct vkd3d_texture_view_desc vkd3d_desc;
|
2019-06-04 05:28:58 -07:00
|
|
|
struct vkd3d_view *view;
|
2019-06-04 05:28:59 -07:00
|
|
|
VkImage vk_image;
|
2019-06-04 05:28:58 -07:00
|
|
|
|
|
|
|
if (!desc)
|
|
|
|
{
|
|
|
|
WARN("View desc is required for NULL view.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (desc->ViewDimension)
|
|
|
|
{
|
|
|
|
case D3D12_UAV_DIMENSION_BUFFER:
|
2019-06-04 05:28:59 -07:00
|
|
|
WARN("Creating NULL buffer UAV %#x.\n", desc->Format);
|
2019-06-04 05:28:58 -07:00
|
|
|
|
|
|
|
if (vkd3d_create_buffer_view(device, null_resources->vk_storage_buffer,
|
|
|
|
vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false),
|
|
|
|
0, VKD3D_NULL_BUFFER_SIZE, &view))
|
|
|
|
{
|
|
|
|
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
|
|
|
|
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
|
|
|
descriptor->u.view = view;
|
|
|
|
}
|
2019-06-04 05:28:59 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
case D3D12_UAV_DIMENSION_TEXTURE2D:
|
|
|
|
vk_image = null_resources->vk_2d_storage_image;
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
break;
|
|
|
|
case D3D12_UAV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
vk_image = null_resources->vk_2d_storage_image;
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
2019-06-04 05:28:58 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
|
2019-06-04 05:28:59 -07:00
|
|
|
return;
|
2019-06-04 05:28:58 -07:00
|
|
|
}
|
2019-06-04 05:28:59 -07:00
|
|
|
|
|
|
|
WARN("Creating NULL UAV %#x.\n", desc->ViewDimension);
|
|
|
|
|
|
|
|
vkd3d_desc.format = vkd3d_get_format(device, VKD3D_NULL_VIEW_FORMAT, false);
|
|
|
|
vkd3d_desc.miplevel_idx = 0;
|
|
|
|
vkd3d_desc.miplevel_count = 1;
|
|
|
|
vkd3d_desc.layer_idx = 0;
|
|
|
|
vkd3d_desc.layer_count = 1;
|
|
|
|
vkd3d_desc.components.r = VK_COMPONENT_SWIZZLE_R;
|
|
|
|
vkd3d_desc.components.g = VK_COMPONENT_SWIZZLE_G;
|
|
|
|
vkd3d_desc.components.b = VK_COMPONENT_SWIZZLE_B;
|
|
|
|
vkd3d_desc.components.a = VK_COMPONENT_SWIZZLE_A;
|
|
|
|
vkd3d_desc.allowed_swizzle = false;
|
|
|
|
|
|
|
|
if (!vkd3d_create_texture_view(device, vk_image, &vkd3d_desc, &view))
|
|
|
|
return;
|
|
|
|
|
|
|
|
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
|
|
|
|
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
descriptor->u.view = view;
|
2019-06-04 05:28:58 -07:00
|
|
|
}
|
|
|
|
|
2017-09-07 08:15:53 -07:00
|
|
|
static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_device *device,
|
|
|
|
struct d3d12_resource *resource, struct d3d12_resource *counter_resource,
|
2017-07-25 03:50:14 -07:00
|
|
|
const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
|
|
|
|
{
|
2017-09-04 09:32:40 -07:00
|
|
|
struct vkd3d_view *view;
|
2018-08-30 05:12:54 -07:00
|
|
|
unsigned int flags;
|
2017-09-04 09:32:40 -07:00
|
|
|
|
2017-08-21 03:41:07 -07:00
|
|
|
if (!desc)
|
|
|
|
{
|
|
|
|
FIXME("Default UAV views not supported.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-21 07:30:33 -07:00
|
|
|
if (desc->ViewDimension != D3D12_UAV_DIMENSION_BUFFER)
|
2017-07-25 03:50:14 -07:00
|
|
|
{
|
2017-08-21 07:30:33 -07:00
|
|
|
WARN("Unexpected view dimension %#x.\n", desc->ViewDimension);
|
2017-07-25 03:50:14 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-08 08:09:35 -07:00
|
|
|
if (desc->u.Buffer.CounterOffsetInBytes)
|
|
|
|
FIXME("Ignoring counter offset %"PRIu64".\n", desc->u.Buffer.CounterOffsetInBytes);
|
|
|
|
|
2018-08-30 05:12:54 -07:00
|
|
|
flags = vkd3d_view_flags_from_d3d12_buffer_uav_flags(desc->u.Buffer.Flags);
|
2019-06-04 05:28:56 -07:00
|
|
|
if (!vkd3d_create_buffer_view_for_resource(device, resource, desc->Format,
|
2017-08-22 03:39:56 -07:00
|
|
|
desc->u.Buffer.FirstElement, desc->u.Buffer.NumElements,
|
2018-08-30 05:12:54 -07:00
|
|
|
desc->u.Buffer.StructureByteStride, flags, &view))
|
2017-08-08 08:09:35 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
|
|
|
|
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
2017-09-04 09:32:40 -07:00
|
|
|
descriptor->u.view = view;
|
2017-09-07 08:15:53 -07:00
|
|
|
|
|
|
|
if (counter_resource)
|
|
|
|
{
|
2018-08-30 05:12:53 -07:00
|
|
|
const struct vkd3d_format *format;
|
|
|
|
|
2017-09-07 08:15:53 -07:00
|
|
|
assert(d3d12_resource_is_buffer(counter_resource));
|
|
|
|
assert(desc->u.Buffer.StructureByteStride);
|
2018-08-30 05:12:53 -07:00
|
|
|
|
2019-05-07 06:37:02 -07:00
|
|
|
format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
|
2019-06-04 05:28:56 -07:00
|
|
|
if (!vkd3d_create_vk_buffer_view(device, counter_resource->u.vk_buffer, format,
|
2018-08-30 05:12:53 -07:00
|
|
|
desc->u.Buffer.CounterOffsetInBytes, sizeof(uint32_t), &view->vk_counter_view))
|
2017-09-07 08:15:53 -07:00
|
|
|
{
|
2018-08-30 05:12:53 -07:00
|
|
|
WARN("Failed to create counter buffer view.\n");
|
2017-09-07 08:15:53 -07:00
|
|
|
view->vk_counter_view = VK_NULL_HANDLE;
|
|
|
|
d3d12_desc_destroy(descriptor, device);
|
|
|
|
}
|
|
|
|
}
|
2017-10-04 04:55:33 -07:00
|
|
|
|
|
|
|
/* FIXME: Clears are implemented only for R32_UINT buffer UAVs. */
|
|
|
|
if ((desc->Format == DXGI_FORMAT_R32_TYPELESS && (desc->u.Buffer.Flags & VKD3D_VIEW_RAW_BUFFER))
|
|
|
|
|| desc->Format == DXGI_FORMAT_R32_UINT)
|
|
|
|
{
|
2019-05-07 06:37:02 -07:00
|
|
|
const struct vkd3d_format *format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
|
2017-10-04 04:55:33 -07:00
|
|
|
|
2018-09-13 02:26:01 -07:00
|
|
|
descriptor->uav.buffer.offset = desc->u.Buffer.FirstElement * format->byte_count;
|
|
|
|
descriptor->uav.buffer.size = desc->u.Buffer.NumElements * format->byte_count;
|
2017-10-04 04:55:33 -07:00
|
|
|
}
|
2017-08-08 08:09:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor,
|
|
|
|
struct d3d12_device *device, struct d3d12_resource *resource,
|
|
|
|
const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
|
|
|
|
{
|
2018-08-28 03:19:47 -07:00
|
|
|
struct vkd3d_texture_view_desc vkd3d_desc;
|
2017-09-04 09:32:40 -07:00
|
|
|
struct vkd3d_view *view;
|
2017-08-08 08:09:35 -07:00
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
|
2017-07-25 03:50:14 -07:00
|
|
|
return;
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
if (vkd3d_format_is_compressed(vkd3d_desc.format))
|
2017-08-02 06:30:15 -07:00
|
|
|
{
|
2017-08-22 03:39:56 -07:00
|
|
|
WARN("UAVs cannot be created for compressed formats.\n");
|
2017-08-02 06:30:15 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-21 03:41:07 -07:00
|
|
|
if (desc)
|
2017-07-25 03:50:14 -07:00
|
|
|
{
|
2018-08-28 03:19:50 -07:00
|
|
|
switch (desc->ViewDimension)
|
2017-08-21 03:41:07 -07:00
|
|
|
{
|
2018-08-28 03:19:50 -07:00
|
|
|
case D3D12_UAV_DIMENSION_TEXTURE2D:
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture2D.MipSlice;
|
|
|
|
if (desc->u.Texture2D.PlaneSlice)
|
|
|
|
FIXME("Ignoring plane slice %u.\n", desc->u.Texture2D.PlaneSlice);
|
|
|
|
break;
|
|
|
|
case D3D12_UAV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture2DArray.MipSlice;
|
|
|
|
vkd3d_desc.layer_idx = desc->u.Texture2DArray.FirstArraySlice;
|
|
|
|
vkd3d_desc.layer_count = desc->u.Texture2DArray.ArraySize;
|
|
|
|
if (desc->u.Texture2DArray.PlaneSlice)
|
|
|
|
FIXME("Ignoring plane slice %u.\n", desc->u.Texture2DArray.PlaneSlice);
|
|
|
|
break;
|
|
|
|
case D3D12_UAV_DIMENSION_TEXTURE3D:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_3D;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture3D.MipSlice;
|
|
|
|
if (desc->u.Texture3D.FirstWSlice || desc->u.Texture3D.WSize != resource->desc.DepthOrArraySize)
|
|
|
|
FIXME("Unhandled depth view %u-%u.\n",
|
|
|
|
desc->u.Texture3D.FirstWSlice, desc->u.Texture3D.WSize);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
|
2017-08-21 03:41:07 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
|
2017-07-25 03:50:14 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
|
2017-08-08 08:09:35 -07:00
|
|
|
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
2017-09-04 09:32:40 -07:00
|
|
|
descriptor->u.view = view;
|
2018-09-13 02:26:01 -07:00
|
|
|
|
2018-09-14 05:19:53 -07:00
|
|
|
descriptor->uav.texture.vk_aspect_mask = vkd3d_desc.format->vk_aspect_mask;
|
2018-09-13 02:26:01 -07:00
|
|
|
descriptor->uav.texture.miplevel_idx = vkd3d_desc.miplevel_idx;
|
|
|
|
descriptor->uav.texture.layer_idx = vkd3d_desc.layer_idx;
|
|
|
|
descriptor->uav.texture.layer_count = vkd3d_desc.layer_count;
|
2017-08-08 08:09:35 -07:00
|
|
|
}
|
|
|
|
|
2017-09-07 08:15:53 -07:00
|
|
|
void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *device,
|
|
|
|
struct d3d12_resource *resource, struct d3d12_resource *counter_resource,
|
2017-08-08 08:09:35 -07:00
|
|
|
const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
|
|
|
|
{
|
|
|
|
d3d12_desc_destroy(descriptor, device);
|
|
|
|
|
|
|
|
if (!resource)
|
|
|
|
{
|
2019-06-04 05:28:58 -07:00
|
|
|
if (counter_resource)
|
|
|
|
FIXME("Ignoring counter resource %p.\n", counter_resource);
|
|
|
|
vkd3d_create_null_uav(descriptor, device, desc);
|
2017-08-08 08:09:35 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d3d12_resource_is_buffer(resource))
|
2017-09-07 08:15:53 -07:00
|
|
|
{
|
|
|
|
vkd3d_create_buffer_uav(descriptor, device, resource, counter_resource, desc);
|
|
|
|
}
|
2017-08-08 08:09:35 -07:00
|
|
|
else
|
2017-09-07 08:15:53 -07:00
|
|
|
{
|
|
|
|
if (counter_resource)
|
|
|
|
FIXME("Unexpected counter resource for texture view.\n");
|
2017-08-08 08:09:35 -07:00
|
|
|
vkd3d_create_texture_uav(descriptor, device, resource, desc);
|
2017-09-07 08:15:53 -07:00
|
|
|
}
|
2017-07-14 04:44:35 -07:00
|
|
|
}
|
|
|
|
|
2017-09-19 08:29:20 -07:00
|
|
|
bool vkd3d_create_raw_buffer_view(struct d3d12_device *device,
|
2017-08-09 09:44:16 -07:00
|
|
|
D3D12_GPU_VIRTUAL_ADDRESS gpu_address, VkBufferView *vk_buffer_view)
|
|
|
|
{
|
|
|
|
const struct vkd3d_format *format;
|
|
|
|
struct d3d12_resource *resource;
|
|
|
|
|
2019-05-07 06:37:02 -07:00
|
|
|
format = vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
|
2017-08-09 09:44:16 -07:00
|
|
|
resource = vkd3d_gpu_va_allocator_dereference(&device->gpu_va_allocator, gpu_address);
|
2019-06-04 05:28:56 -07:00
|
|
|
assert(d3d12_resource_is_buffer(resource));
|
|
|
|
return vkd3d_create_vk_buffer_view(device, resource->u.vk_buffer, format,
|
2017-08-09 09:44:16 -07:00
|
|
|
gpu_address - resource->gpu_address, VK_WHOLE_SIZE, vk_buffer_view);
|
|
|
|
}
|
|
|
|
|
2017-07-12 04:10:44 -07:00
|
|
|
/* samplers */
|
|
|
|
static VkFilter vk_filter_from_d3d12(D3D12_FILTER_TYPE type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case D3D12_FILTER_TYPE_POINT:
|
|
|
|
return VK_FILTER_NEAREST;
|
|
|
|
case D3D12_FILTER_TYPE_LINEAR:
|
|
|
|
return VK_FILTER_LINEAR;
|
|
|
|
default:
|
|
|
|
FIXME("Unhandled filter type %#x.\n", type);
|
|
|
|
return VK_FILTER_NEAREST;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static VkSamplerMipmapMode vk_mipmap_mode_from_d3d12(D3D12_FILTER_TYPE type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case D3D12_FILTER_TYPE_POINT:
|
|
|
|
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
|
|
|
case D3D12_FILTER_TYPE_LINEAR:
|
|
|
|
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
|
|
|
default:
|
|
|
|
FIXME("Unhandled filter type %#x.\n", type);
|
|
|
|
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static VkSamplerAddressMode vk_address_mode_from_d3d12(D3D12_TEXTURE_ADDRESS_MODE mode)
|
|
|
|
{
|
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case D3D12_TEXTURE_ADDRESS_MODE_WRAP:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
|
|
case D3D12_TEXTURE_ADDRESS_MODE_MIRROR:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
|
|
|
case D3D12_TEXTURE_ADDRESS_MODE_CLAMP:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
|
|
|
case D3D12_TEXTURE_ADDRESS_MODE_BORDER:
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
|
|
|
/* D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE requires VK_KHR_mirror_clamp_to_edge. */
|
|
|
|
default:
|
|
|
|
FIXME("Unhandled address mode %#x.\n", mode);
|
|
|
|
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-17 07:25:29 -07:00
|
|
|
static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER filter,
|
|
|
|
D3D12_TEXTURE_ADDRESS_MODE address_u, D3D12_TEXTURE_ADDRESS_MODE address_v,
|
|
|
|
D3D12_TEXTURE_ADDRESS_MODE address_w, float mip_lod_bias, unsigned int max_anisotropy,
|
|
|
|
D3D12_COMPARISON_FUNC comparison_func, float min_lod, float max_lod,
|
|
|
|
VkSampler *vk_sampler)
|
2017-07-12 04:10:44 -07:00
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs;
|
|
|
|
struct VkSamplerCreateInfo sampler_desc;
|
|
|
|
VkResult vr;
|
|
|
|
|
|
|
|
vk_procs = &device->vk_procs;
|
|
|
|
|
2017-07-17 07:25:29 -07:00
|
|
|
if (D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MINIMUM
|
|
|
|
|| D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MAXIMUM)
|
|
|
|
FIXME("Min/max reduction mode not supported.\n");
|
|
|
|
|
|
|
|
sampler_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
|
|
|
sampler_desc.pNext = NULL;
|
|
|
|
sampler_desc.flags = 0;
|
|
|
|
sampler_desc.magFilter = vk_filter_from_d3d12(D3D12_DECODE_MAG_FILTER(filter));
|
|
|
|
sampler_desc.minFilter = vk_filter_from_d3d12(D3D12_DECODE_MIN_FILTER(filter));
|
|
|
|
sampler_desc.mipmapMode = vk_mipmap_mode_from_d3d12(D3D12_DECODE_MIP_FILTER(filter));
|
|
|
|
sampler_desc.addressModeU = vk_address_mode_from_d3d12(address_u);
|
|
|
|
sampler_desc.addressModeV = vk_address_mode_from_d3d12(address_v);
|
|
|
|
sampler_desc.addressModeW = vk_address_mode_from_d3d12(address_w);
|
|
|
|
sampler_desc.mipLodBias = mip_lod_bias;
|
|
|
|
sampler_desc.anisotropyEnable = D3D12_DECODE_IS_ANISOTROPIC_FILTER(filter);
|
|
|
|
sampler_desc.maxAnisotropy = max_anisotropy;
|
|
|
|
sampler_desc.compareEnable = D3D12_DECODE_IS_COMPARISON_FILTER(filter);
|
|
|
|
sampler_desc.compareOp = sampler_desc.compareEnable ? vk_compare_op_from_d3d12(comparison_func) : 0;
|
|
|
|
sampler_desc.minLod = min_lod;
|
|
|
|
sampler_desc.maxLod = max_lod;
|
|
|
|
sampler_desc.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
|
|
|
sampler_desc.unnormalizedCoordinates = VK_FALSE;
|
|
|
|
if ((vr = VK_CALL(vkCreateSampler(device->vk_device, &sampler_desc, NULL, vk_sampler))) < 0)
|
|
|
|
WARN("Failed to create Vulkan sampler, vr %d.\n", vr);
|
|
|
|
|
|
|
|
return vr;
|
|
|
|
}
|
|
|
|
|
2017-08-04 08:06:33 -07:00
|
|
|
void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
|
2017-07-17 07:25:29 -07:00
|
|
|
struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc)
|
|
|
|
{
|
2017-09-04 09:32:40 -07:00
|
|
|
struct vkd3d_view *view;
|
|
|
|
|
2017-08-04 08:06:33 -07:00
|
|
|
d3d12_desc_destroy(sampler, device);
|
2017-07-12 04:10:44 -07:00
|
|
|
|
|
|
|
if (!desc)
|
|
|
|
{
|
|
|
|
WARN("NULL sampler desc.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER
|
|
|
|
|| desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER
|
|
|
|
|| desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER)
|
|
|
|
FIXME("Ignoring border color {%.8e, %.8e, %.8e, %.8e}.\n",
|
|
|
|
desc->BorderColor[0], desc->BorderColor[1], desc->BorderColor[2], desc->BorderColor[3]);
|
|
|
|
|
2017-09-04 09:32:40 -07:00
|
|
|
if (!(view = vkd3d_view_create()))
|
|
|
|
return;
|
|
|
|
|
2017-07-17 07:25:29 -07:00
|
|
|
if (d3d12_create_sampler(device, desc->Filter, desc->AddressU,
|
|
|
|
desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy,
|
2017-09-04 09:32:40 -07:00
|
|
|
desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, &view->u.vk_sampler) < 0)
|
|
|
|
{
|
|
|
|
vkd3d_free(view);
|
2017-07-12 04:10:44 -07:00
|
|
|
return;
|
2017-09-04 09:32:40 -07:00
|
|
|
}
|
2017-07-12 04:10:44 -07:00
|
|
|
|
|
|
|
sampler->magic = VKD3D_DESCRIPTOR_MAGIC_SAMPLER;
|
2017-08-04 08:06:33 -07:00
|
|
|
sampler->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLER;
|
2017-09-04 09:32:40 -07:00
|
|
|
sampler->u.view = view;
|
2017-07-12 04:10:44 -07:00
|
|
|
}
|
|
|
|
|
2017-08-09 09:44:16 -07:00
|
|
|
HRESULT vkd3d_create_static_sampler(struct d3d12_device *device,
|
2017-07-17 07:25:29 -07:00
|
|
|
const D3D12_STATIC_SAMPLER_DESC *desc, VkSampler *vk_sampler)
|
|
|
|
{
|
|
|
|
VkResult vr;
|
|
|
|
|
|
|
|
if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER
|
|
|
|
|| desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER
|
|
|
|
|| desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER)
|
|
|
|
FIXME("Ignoring border %#x.\n", desc->BorderColor);
|
|
|
|
|
|
|
|
vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU,
|
|
|
|
desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy,
|
|
|
|
desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, vk_sampler);
|
|
|
|
return hresult_from_vk_result(vr);
|
|
|
|
}
|
|
|
|
|
2016-09-28 04:00:39 -07:00
|
|
|
/* RTVs */
|
|
|
|
static void d3d12_rtv_desc_destroy(struct d3d12_rtv_desc *rtv, struct d3d12_device *device)
|
|
|
|
{
|
|
|
|
if (rtv->magic != VKD3D_DESCRIPTOR_MAGIC_RTV)
|
|
|
|
return;
|
|
|
|
|
2018-08-21 09:08:01 -07:00
|
|
|
vkd3d_view_decref(rtv->view, device);
|
2016-09-28 04:00:39 -07:00
|
|
|
memset(rtv, 0, sizeof(*rtv));
|
|
|
|
}
|
|
|
|
|
|
|
|
void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_device *device,
|
|
|
|
struct d3d12_resource *resource, const D3D12_RENDER_TARGET_VIEW_DESC *desc)
|
|
|
|
{
|
2018-08-28 03:19:47 -07:00
|
|
|
struct vkd3d_texture_view_desc vkd3d_desc;
|
2018-08-21 09:08:01 -07:00
|
|
|
struct vkd3d_view *view;
|
2016-09-28 04:00:39 -07:00
|
|
|
|
|
|
|
d3d12_rtv_desc_destroy(rtv_desc, device);
|
|
|
|
|
|
|
|
if (!resource)
|
|
|
|
{
|
|
|
|
FIXME("NULL resource RTV not implemented.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
|
2016-09-28 04:00:39 -07:00
|
|
|
return;
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
if (vkd3d_desc.format->vk_aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT)
|
2016-10-08 05:31:57 -07:00
|
|
|
{
|
2018-08-28 03:19:47 -07:00
|
|
|
WARN("Trying to create RTV for depth/stencil format %#x.\n", vkd3d_desc.format->dxgi_format);
|
2016-10-08 05:31:57 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
if (desc)
|
2016-10-08 05:31:57 -07:00
|
|
|
{
|
2018-08-28 03:19:47 -07:00
|
|
|
switch (desc->ViewDimension)
|
|
|
|
{
|
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE2D:
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture2D.MipSlice;
|
|
|
|
if (desc->u.Texture2D.PlaneSlice)
|
|
|
|
FIXME("Ignoring plane slice %u.\n", desc->u.Texture2D.PlaneSlice);
|
|
|
|
break;
|
2018-08-28 03:19:51 -07:00
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture2DArray.MipSlice;
|
|
|
|
vkd3d_desc.layer_idx = desc->u.Texture2DArray.FirstArraySlice;
|
|
|
|
vkd3d_desc.layer_count = desc->u.Texture2DArray.ArraySize;
|
|
|
|
if (desc->u.Texture2DArray.PlaneSlice)
|
|
|
|
FIXME("Ignoring plane slice %u.\n", desc->u.Texture2DArray.PlaneSlice);
|
|
|
|
break;
|
2018-11-26 05:22:25 -08:00
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE2DMS:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
break;
|
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
vkd3d_desc.layer_idx = desc->u.Texture2DMSArray.FirstArraySlice;
|
|
|
|
vkd3d_desc.layer_count = desc->u.Texture2DMSArray.ArraySize;
|
|
|
|
break;
|
2018-08-28 03:19:50 -07:00
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE3D:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture3D.MipSlice;
|
|
|
|
vkd3d_desc.layer_idx = desc->u.Texture3D.FirstWSlice;
|
|
|
|
vkd3d_desc.layer_count = desc->u.Texture3D.WSize;
|
|
|
|
break;
|
2018-08-28 03:19:47 -07:00
|
|
|
default:
|
|
|
|
FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
|
|
|
|
}
|
2016-10-08 05:31:57 -07:00
|
|
|
}
|
2018-08-28 03:19:50 -07:00
|
|
|
else if (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
|
|
|
|
{
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
vkd3d_desc.layer_idx = 0;
|
|
|
|
vkd3d_desc.layer_count = resource->desc.DepthOrArraySize;
|
|
|
|
}
|
2016-10-08 05:31:57 -07:00
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
assert(d3d12_resource_is_texture(resource));
|
|
|
|
|
|
|
|
if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
|
2018-08-21 09:08:01 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
rtv_desc->magic = VKD3D_DESCRIPTOR_MAGIC_RTV;
|
2018-08-28 03:19:47 -07:00
|
|
|
rtv_desc->format = vkd3d_desc.format->vk_format;
|
2018-10-25 02:24:00 -07:00
|
|
|
rtv_desc->sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
|
2018-08-28 03:19:47 -07:00
|
|
|
rtv_desc->width = d3d12_resource_desc_get_width(&resource->desc, vkd3d_desc.miplevel_idx);
|
|
|
|
rtv_desc->height = d3d12_resource_desc_get_height(&resource->desc, vkd3d_desc.miplevel_idx);
|
2018-08-28 03:19:50 -07:00
|
|
|
rtv_desc->layer_count = vkd3d_desc.layer_count;
|
2018-08-21 09:08:01 -07:00
|
|
|
rtv_desc->view = view;
|
2016-10-25 04:23:18 -07:00
|
|
|
rtv_desc->resource = resource;
|
2016-09-28 04:00:39 -07:00
|
|
|
}
|
|
|
|
|
2016-11-02 11:46:17 -07:00
|
|
|
/* DSVs */
|
|
|
|
static void d3d12_dsv_desc_destroy(struct d3d12_dsv_desc *dsv, struct d3d12_device *device)
|
|
|
|
{
|
|
|
|
if (dsv->magic != VKD3D_DESCRIPTOR_MAGIC_DSV)
|
|
|
|
return;
|
|
|
|
|
2018-08-21 09:08:01 -07:00
|
|
|
vkd3d_view_decref(dsv->view, device);
|
2016-11-02 11:46:17 -07:00
|
|
|
memset(dsv, 0, sizeof(*dsv));
|
|
|
|
}
|
|
|
|
|
|
|
|
void d3d12_dsv_desc_create_dsv(struct d3d12_dsv_desc *dsv_desc, struct d3d12_device *device,
|
|
|
|
struct d3d12_resource *resource, const D3D12_DEPTH_STENCIL_VIEW_DESC *desc)
|
|
|
|
{
|
2018-08-28 03:19:47 -07:00
|
|
|
struct vkd3d_texture_view_desc vkd3d_desc;
|
2018-08-21 09:08:01 -07:00
|
|
|
struct vkd3d_view *view;
|
2016-11-02 11:46:17 -07:00
|
|
|
|
|
|
|
d3d12_dsv_desc_destroy(dsv_desc, device);
|
|
|
|
|
|
|
|
if (!resource)
|
|
|
|
{
|
|
|
|
FIXME("NULL resource DSV not implemented.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-28 03:19:49 -07:00
|
|
|
if (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
|
|
|
|
{
|
|
|
|
WARN("Cannot create DSV for 3D texture.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
if (!init_default_texture_view_desc(&vkd3d_desc, resource, desc ? desc->Format : 0))
|
2016-11-02 11:46:17 -07:00
|
|
|
return;
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
if (!(vkd3d_desc.format->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))
|
2016-11-02 11:46:17 -07:00
|
|
|
{
|
2018-08-28 03:19:47 -07:00
|
|
|
WARN("Trying to create DSV for format %#x.\n", vkd3d_desc.format->dxgi_format);
|
2016-11-02 11:46:17 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
if (desc)
|
2016-11-02 11:46:17 -07:00
|
|
|
{
|
2018-08-28 03:19:47 -07:00
|
|
|
if (desc->Flags)
|
|
|
|
FIXME("Ignoring flags %#x.\n", desc->Flags);
|
2016-11-02 11:46:17 -07:00
|
|
|
|
2018-08-28 03:19:47 -07:00
|
|
|
switch (desc->ViewDimension)
|
|
|
|
{
|
|
|
|
case D3D12_DSV_DIMENSION_TEXTURE2D:
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture2D.MipSlice;
|
|
|
|
break;
|
2018-08-28 03:19:51 -07:00
|
|
|
case D3D12_DSV_DIMENSION_TEXTURE2DARRAY:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
vkd3d_desc.miplevel_idx = desc->u.Texture2DArray.MipSlice;
|
|
|
|
vkd3d_desc.layer_idx = desc->u.Texture2DArray.FirstArraySlice;
|
|
|
|
vkd3d_desc.layer_count = desc->u.Texture2DArray.ArraySize;
|
|
|
|
break;
|
2018-11-26 05:22:25 -08:00
|
|
|
case D3D12_DSV_DIMENSION_TEXTURE2DMS:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
break;
|
|
|
|
case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY:
|
|
|
|
vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
|
|
vkd3d_desc.layer_idx = desc->u.Texture2DMSArray.FirstArraySlice;
|
|
|
|
vkd3d_desc.layer_count = desc->u.Texture2DMSArray.ArraySize;
|
|
|
|
break;
|
2018-08-28 03:19:47 -07:00
|
|
|
default:
|
|
|
|
FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension);
|
|
|
|
}
|
|
|
|
}
|
2016-11-02 11:46:17 -07:00
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
assert(d3d12_resource_is_texture(resource));
|
|
|
|
|
|
|
|
if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
|
2016-11-02 11:46:17 -07:00
|
|
|
return;
|
|
|
|
|
2018-08-21 09:08:01 -07:00
|
|
|
dsv_desc->magic = VKD3D_DESCRIPTOR_MAGIC_DSV;
|
2018-08-28 03:19:47 -07:00
|
|
|
dsv_desc->format = vkd3d_desc.format->vk_format;
|
2018-10-25 02:24:00 -07:00
|
|
|
dsv_desc->sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
|
2018-08-28 03:19:47 -07:00
|
|
|
dsv_desc->width = d3d12_resource_desc_get_width(&resource->desc, vkd3d_desc.miplevel_idx);
|
|
|
|
dsv_desc->height = d3d12_resource_desc_get_height(&resource->desc, vkd3d_desc.miplevel_idx);
|
2018-09-28 03:16:37 -07:00
|
|
|
dsv_desc->layer_count = vkd3d_desc.layer_count;
|
2018-08-21 09:08:01 -07:00
|
|
|
dsv_desc->view = view;
|
2016-11-02 11:46:17 -07:00
|
|
|
dsv_desc->resource = resource;
|
|
|
|
}
|
|
|
|
|
2016-09-26 02:13:30 -07:00
|
|
|
/* ID3D12DescriptorHeap */
|
|
|
|
static inline struct d3d12_descriptor_heap *impl_from_ID3D12DescriptorHeap(ID3D12DescriptorHeap *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, struct d3d12_descriptor_heap, ID3D12DescriptorHeap_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_QueryInterface(ID3D12DescriptorHeap *iface,
|
|
|
|
REFIID riid, void **object)
|
|
|
|
{
|
|
|
|
TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
|
|
|
|
|
|
|
|
if (IsEqualGUID(riid, &IID_ID3D12DescriptorHeap)
|
|
|
|
|| IsEqualGUID(riid, &IID_ID3D12Pageable)
|
|
|
|
|| IsEqualGUID(riid, &IID_ID3D12DeviceChild)
|
|
|
|
|| IsEqualGUID(riid, &IID_ID3D12Object)
|
|
|
|
|| IsEqualGUID(riid, &IID_IUnknown))
|
|
|
|
{
|
|
|
|
ID3D12DescriptorHeap_AddRef(iface);
|
|
|
|
*object = iface;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
|
|
|
|
|
|
|
|
*object = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_AddRef(ID3D12DescriptorHeap *iface)
|
|
|
|
{
|
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
|
|
|
ULONG refcount = InterlockedIncrement(&heap->refcount);
|
|
|
|
|
|
|
|
TRACE("%p increasing refcount to %u.\n", heap, refcount);
|
|
|
|
|
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHeap *iface)
|
|
|
|
{
|
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
|
|
|
ULONG refcount = InterlockedDecrement(&heap->refcount);
|
|
|
|
|
|
|
|
TRACE("%p decreasing refcount to %u.\n", heap, refcount);
|
|
|
|
|
|
|
|
if (!refcount)
|
|
|
|
{
|
|
|
|
struct d3d12_device *device = heap->device;
|
2016-09-28 04:00:39 -07:00
|
|
|
unsigned int i;
|
|
|
|
|
2019-01-04 05:34:17 -08:00
|
|
|
vkd3d_private_store_destroy(&heap->private_store);
|
|
|
|
|
2017-07-14 04:44:35 -07:00
|
|
|
switch (heap->desc.Type)
|
2017-07-12 04:10:44 -07:00
|
|
|
{
|
2017-07-14 04:44:35 -07:00
|
|
|
case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
|
|
|
|
case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
|
2017-07-12 04:10:44 -07:00
|
|
|
{
|
2017-08-04 08:06:33 -07:00
|
|
|
struct d3d12_desc *descriptors = (struct d3d12_desc *)heap->descriptors;
|
2017-07-14 04:44:35 -07:00
|
|
|
|
|
|
|
for (i = 0; i < heap->desc.NumDescriptors; ++i)
|
|
|
|
{
|
2017-08-04 08:06:33 -07:00
|
|
|
d3d12_desc_destroy(&descriptors[i], device);
|
2017-07-14 04:44:35 -07:00
|
|
|
}
|
|
|
|
break;
|
2017-07-12 04:10:44 -07:00
|
|
|
}
|
2016-09-28 04:00:39 -07:00
|
|
|
|
2017-07-14 04:44:35 -07:00
|
|
|
case D3D12_DESCRIPTOR_HEAP_TYPE_RTV:
|
2016-09-28 04:00:39 -07:00
|
|
|
{
|
2017-07-14 04:44:35 -07:00
|
|
|
struct d3d12_rtv_desc *rtvs = (struct d3d12_rtv_desc *)heap->descriptors;
|
|
|
|
|
|
|
|
for (i = 0; i < heap->desc.NumDescriptors; ++i)
|
|
|
|
{
|
|
|
|
d3d12_rtv_desc_destroy(&rtvs[i], device);
|
|
|
|
}
|
|
|
|
break;
|
2016-09-28 04:00:39 -07:00
|
|
|
}
|
2016-11-02 11:46:17 -07:00
|
|
|
|
2017-07-14 04:44:35 -07:00
|
|
|
case D3D12_DESCRIPTOR_HEAP_TYPE_DSV:
|
2016-11-02 11:46:17 -07:00
|
|
|
{
|
2017-07-14 04:44:35 -07:00
|
|
|
struct d3d12_dsv_desc *dsvs = (struct d3d12_dsv_desc *)heap->descriptors;
|
|
|
|
|
|
|
|
for (i = 0; i < heap->desc.NumDescriptors; ++i)
|
|
|
|
{
|
|
|
|
d3d12_dsv_desc_destroy(&dsvs[i], device);
|
|
|
|
}
|
|
|
|
break;
|
2016-11-02 11:46:17 -07:00
|
|
|
}
|
2017-07-14 04:44:35 -07:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2016-11-02 11:46:17 -07:00
|
|
|
}
|
2016-09-26 02:13:30 -07:00
|
|
|
|
|
|
|
vkd3d_free(heap);
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
d3d12_device_release(device);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_GetPrivateData(ID3D12DescriptorHeap *iface,
|
|
|
|
REFGUID guid, UINT *data_size, void *data)
|
|
|
|
{
|
2019-01-04 05:34:17 -08:00
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-01-04 05:34:17 -08:00
|
|
|
TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
|
|
|
|
|
|
|
|
return vkd3d_get_private_data(&heap->private_store, guid, data_size, data);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_SetPrivateData(ID3D12DescriptorHeap *iface,
|
|
|
|
REFGUID guid, UINT data_size, const void *data)
|
|
|
|
{
|
2019-01-04 05:34:17 -08:00
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-01-04 05:34:17 -08:00
|
|
|
TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
|
|
|
|
|
|
|
|
return vkd3d_set_private_data(&heap->private_store, guid, data_size, data);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_SetPrivateDataInterface(ID3D12DescriptorHeap *iface,
|
|
|
|
REFGUID guid, const IUnknown *data)
|
|
|
|
{
|
2019-01-04 05:34:17 -08:00
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-01-04 05:34:17 -08:00
|
|
|
TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
|
|
|
|
|
|
|
|
return vkd3d_set_private_data_interface(&heap->private_store, guid, data);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_SetName(ID3D12DescriptorHeap *iface, const WCHAR *name)
|
|
|
|
{
|
2017-08-02 01:45:06 -07:00
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
|
|
|
|
2019-01-31 01:07:10 -08:00
|
|
|
TRACE("iface %p, name %s.\n", iface, debugstr_w(name, heap->device->wchar_size));
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-01-31 01:07:10 -08:00
|
|
|
return name ? S_OK : E_INVALIDARG;
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_GetDevice(ID3D12DescriptorHeap *iface, REFIID iid, void **device)
|
2016-09-26 02:13:30 -07:00
|
|
|
{
|
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
return d3d12_device_query_interface(heap->device, iid, device);
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static D3D12_DESCRIPTOR_HEAP_DESC * STDMETHODCALLTYPE d3d12_descriptor_heap_GetDesc(ID3D12DescriptorHeap *iface,
|
|
|
|
D3D12_DESCRIPTOR_HEAP_DESC *desc)
|
|
|
|
{
|
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
|
|
|
|
|
|
|
TRACE("iface %p, desc %p.\n", iface, desc);
|
|
|
|
|
|
|
|
*desc = heap->desc;
|
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static D3D12_CPU_DESCRIPTOR_HANDLE * STDMETHODCALLTYPE d3d12_descriptor_heap_GetCPUDescriptorHandleForHeapStart(
|
|
|
|
ID3D12DescriptorHeap *iface, D3D12_CPU_DESCRIPTOR_HANDLE *descriptor)
|
|
|
|
{
|
2016-09-29 08:55:55 -07:00
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
|
|
|
|
|
|
|
TRACE("iface %p, descriptor %p.\n", iface, descriptor);
|
|
|
|
|
|
|
|
descriptor->ptr = (SIZE_T)heap->descriptors;
|
2016-09-26 02:13:30 -07:00
|
|
|
|
|
|
|
return descriptor;
|
|
|
|
}
|
|
|
|
|
|
|
|
static D3D12_GPU_DESCRIPTOR_HANDLE * STDMETHODCALLTYPE d3d12_descriptor_heap_GetGPUDescriptorHandleForHeapStart(
|
|
|
|
ID3D12DescriptorHeap *iface, D3D12_GPU_DESCRIPTOR_HANDLE *descriptor)
|
|
|
|
{
|
2017-07-17 07:25:29 -07:00
|
|
|
struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface);
|
|
|
|
|
|
|
|
TRACE("iface %p, descriptor %p.\n", iface, descriptor);
|
|
|
|
|
2019-06-11 01:13:35 -07:00
|
|
|
descriptor->ptr = (uint64_t)(intptr_t)heap->descriptors;
|
2016-09-26 02:13:30 -07:00
|
|
|
|
|
|
|
return descriptor;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct ID3D12DescriptorHeapVtbl d3d12_descriptor_heap_vtbl =
|
|
|
|
{
|
|
|
|
/* IUnknown methods */
|
|
|
|
d3d12_descriptor_heap_QueryInterface,
|
|
|
|
d3d12_descriptor_heap_AddRef,
|
|
|
|
d3d12_descriptor_heap_Release,
|
|
|
|
/* ID3D12Object methods */
|
|
|
|
d3d12_descriptor_heap_GetPrivateData,
|
|
|
|
d3d12_descriptor_heap_SetPrivateData,
|
|
|
|
d3d12_descriptor_heap_SetPrivateDataInterface,
|
|
|
|
d3d12_descriptor_heap_SetName,
|
|
|
|
/* ID3D12DeviceChild methods */
|
|
|
|
d3d12_descriptor_heap_GetDevice,
|
|
|
|
/* ID3D12DescriptorHeap methods */
|
|
|
|
d3d12_descriptor_heap_GetDesc,
|
|
|
|
d3d12_descriptor_heap_GetCPUDescriptorHandleForHeapStart,
|
|
|
|
d3d12_descriptor_heap_GetGPUDescriptorHandleForHeapStart,
|
|
|
|
};
|
|
|
|
|
2019-01-10 02:16:48 -08:00
|
|
|
static HRESULT d3d12_descriptor_heap_init(struct d3d12_descriptor_heap *descriptor_heap,
|
2016-09-26 02:13:30 -07:00
|
|
|
struct d3d12_device *device, const D3D12_DESCRIPTOR_HEAP_DESC *desc)
|
|
|
|
{
|
2019-01-10 02:16:48 -08:00
|
|
|
HRESULT hr;
|
|
|
|
|
2016-09-26 02:13:30 -07:00
|
|
|
descriptor_heap->ID3D12DescriptorHeap_iface.lpVtbl = &d3d12_descriptor_heap_vtbl;
|
|
|
|
descriptor_heap->refcount = 1;
|
|
|
|
|
|
|
|
descriptor_heap->desc = *desc;
|
|
|
|
|
2019-01-10 02:16:48 -08:00
|
|
|
if (FAILED(hr = vkd3d_private_store_init(&descriptor_heap->private_store)))
|
|
|
|
return hr;
|
2019-01-04 05:34:17 -08:00
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
d3d12_device_add_ref(descriptor_heap->device = device);
|
2019-01-10 02:16:48 -08:00
|
|
|
|
|
|
|
return S_OK;
|
2016-09-26 02:13:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device,
|
|
|
|
const D3D12_DESCRIPTOR_HEAP_DESC *desc, struct d3d12_descriptor_heap **descriptor_heap)
|
|
|
|
{
|
2016-09-30 04:03:45 -07:00
|
|
|
size_t max_descriptor_count, descriptor_size;
|
2016-09-26 02:13:30 -07:00
|
|
|
struct d3d12_descriptor_heap *object;
|
2019-01-10 02:16:48 -08:00
|
|
|
HRESULT hr;
|
2016-09-26 02:13:30 -07:00
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
if (!(descriptor_size = d3d12_device_get_descriptor_handle_increment_size(device, desc->Type)))
|
2016-09-30 04:03:45 -07:00
|
|
|
{
|
|
|
|
WARN("No descriptor size for descriptor type %#x.\n", desc->Type);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2018-11-27 08:04:32 -08:00
|
|
|
if ((desc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
|
|
|
|
&& (desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_RTV || desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_DSV))
|
|
|
|
{
|
|
|
|
WARN("RTV/DSV descriptor heaps cannot be shader visible.\n");
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2016-09-30 04:03:45 -07:00
|
|
|
max_descriptor_count = (~(size_t)0 - sizeof(*object)) / descriptor_size;
|
|
|
|
if (desc->NumDescriptors > max_descriptor_count)
|
|
|
|
{
|
|
|
|
WARN("Invalid descriptor count %u (max %zu).\n", desc->NumDescriptors, max_descriptor_count);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(object = vkd3d_malloc(offsetof(struct d3d12_descriptor_heap,
|
|
|
|
descriptors[descriptor_size * desc->NumDescriptors]))))
|
2016-09-26 02:13:30 -07:00
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2019-01-10 02:16:48 -08:00
|
|
|
if (FAILED(hr = d3d12_descriptor_heap_init(object, device, desc)))
|
|
|
|
{
|
|
|
|
vkd3d_free(object);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2016-09-30 04:03:45 -07:00
|
|
|
memset(object->descriptors, 0, descriptor_size * desc->NumDescriptors);
|
2016-09-26 02:13:30 -07:00
|
|
|
|
|
|
|
TRACE("Created descriptor heap %p.\n", object);
|
|
|
|
|
|
|
|
*descriptor_heap = object;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
2017-07-23 06:02:41 -07:00
|
|
|
|
|
|
|
/* ID3D12QueryHeap */
|
|
|
|
static inline struct d3d12_query_heap *impl_from_ID3D12QueryHeap(ID3D12QueryHeap *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, struct d3d12_query_heap, ID3D12QueryHeap_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_query_heap_QueryInterface(ID3D12QueryHeap *iface,
|
|
|
|
REFIID iid, void **out)
|
|
|
|
{
|
|
|
|
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
|
|
|
|
|
|
|
|
if (IsEqualGUID(iid, &IID_ID3D12QueryHeap)
|
|
|
|
|| IsEqualGUID(iid, &IID_ID3D12Pageable)
|
|
|
|
|| IsEqualGUID(iid, &IID_ID3D12DeviceChild)
|
|
|
|
|| IsEqualGUID(iid, &IID_ID3D12Object)
|
|
|
|
|| IsEqualGUID(iid, &IID_IUnknown))
|
|
|
|
{
|
|
|
|
ID3D12QueryHeap_AddRef(iface);
|
|
|
|
*out = iface;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
|
|
|
|
|
|
|
|
*out = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE d3d12_query_heap_AddRef(ID3D12QueryHeap *iface)
|
|
|
|
{
|
|
|
|
struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
|
|
|
|
ULONG refcount = InterlockedIncrement(&heap->refcount);
|
|
|
|
|
|
|
|
TRACE("%p increasing refcount to %u.\n", heap, refcount);
|
|
|
|
|
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE d3d12_query_heap_Release(ID3D12QueryHeap *iface)
|
|
|
|
{
|
|
|
|
struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
|
|
|
|
ULONG refcount = InterlockedDecrement(&heap->refcount);
|
|
|
|
|
|
|
|
TRACE("%p decreasing refcount to %u.\n", heap, refcount);
|
|
|
|
|
|
|
|
if (!refcount)
|
|
|
|
{
|
|
|
|
struct d3d12_device *device = heap->device;
|
2017-08-23 07:18:15 -07:00
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
|
2019-01-04 05:34:18 -08:00
|
|
|
vkd3d_private_store_destroy(&heap->private_store);
|
|
|
|
|
2017-08-23 07:18:15 -07:00
|
|
|
VK_CALL(vkDestroyQueryPool(device->vk_device, heap->vk_query_pool, NULL));
|
2017-07-23 06:02:41 -07:00
|
|
|
|
|
|
|
vkd3d_free(heap);
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
d3d12_device_release(device);
|
2017-07-23 06:02:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return refcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_query_heap_GetPrivateData(ID3D12QueryHeap *iface,
|
|
|
|
REFGUID guid, UINT *data_size, void *data)
|
|
|
|
{
|
2019-01-04 05:34:18 -08:00
|
|
|
struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
|
2017-07-23 06:02:41 -07:00
|
|
|
|
2019-01-04 05:34:18 -08:00
|
|
|
TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
|
|
|
|
|
|
|
|
return vkd3d_get_private_data(&heap->private_store, guid, data_size, data);
|
2017-07-23 06:02:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_query_heap_SetPrivateData(ID3D12QueryHeap *iface,
|
|
|
|
REFGUID guid, UINT data_size, const void *data)
|
|
|
|
{
|
2019-01-04 05:34:18 -08:00
|
|
|
struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
|
2017-07-23 06:02:41 -07:00
|
|
|
|
2019-01-04 05:34:18 -08:00
|
|
|
TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
|
|
|
|
|
|
|
|
return vkd3d_set_private_data(&heap->private_store, guid, data_size, data);
|
2017-07-23 06:02:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_query_heap_SetPrivateDataInterface(ID3D12QueryHeap *iface,
|
|
|
|
REFGUID guid, const IUnknown *data)
|
|
|
|
{
|
2019-01-04 05:34:18 -08:00
|
|
|
struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
|
2017-07-23 06:02:41 -07:00
|
|
|
|
2019-01-04 05:34:18 -08:00
|
|
|
TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
|
|
|
|
|
|
|
|
return vkd3d_set_private_data_interface(&heap->private_store, guid, data);
|
2017-07-23 06:02:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_query_heap_SetName(ID3D12QueryHeap *iface, const WCHAR *name)
|
|
|
|
{
|
2017-08-02 01:45:06 -07:00
|
|
|
struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
|
|
|
|
|
2019-01-29 13:14:31 -08:00
|
|
|
TRACE("iface %p, name %s.\n", iface, debugstr_w(name, heap->device->wchar_size));
|
2017-07-23 06:02:41 -07:00
|
|
|
|
2019-01-29 13:14:31 -08:00
|
|
|
return vkd3d_set_vk_object_name(heap->device, (uint64_t)heap->vk_query_pool,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, name);
|
2017-07-23 06:02:41 -07:00
|
|
|
}
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
static HRESULT STDMETHODCALLTYPE d3d12_query_heap_GetDevice(ID3D12QueryHeap *iface, REFIID iid, void **device)
|
2017-07-23 06:02:41 -07:00
|
|
|
{
|
|
|
|
struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
|
|
|
|
|
|
|
|
TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
return d3d12_device_query_interface(heap->device, iid, device);
|
2017-07-23 06:02:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct ID3D12QueryHeapVtbl d3d12_query_heap_vtbl =
|
|
|
|
{
|
|
|
|
/* IUnknown methods */
|
|
|
|
d3d12_query_heap_QueryInterface,
|
|
|
|
d3d12_query_heap_AddRef,
|
|
|
|
d3d12_query_heap_Release,
|
|
|
|
/* ID3D12Object methods */
|
|
|
|
d3d12_query_heap_GetPrivateData,
|
|
|
|
d3d12_query_heap_SetPrivateData,
|
|
|
|
d3d12_query_heap_SetPrivateDataInterface,
|
|
|
|
d3d12_query_heap_SetName,
|
|
|
|
/* ID3D12DeviceChild methods */
|
|
|
|
d3d12_query_heap_GetDevice,
|
|
|
|
};
|
|
|
|
|
2017-08-25 06:09:31 -07:00
|
|
|
struct d3d12_query_heap *unsafe_impl_from_ID3D12QueryHeap(ID3D12QueryHeap *iface)
|
|
|
|
{
|
|
|
|
if (!iface)
|
|
|
|
return NULL;
|
|
|
|
assert(iface->lpVtbl == &d3d12_query_heap_vtbl);
|
|
|
|
return impl_from_ID3D12QueryHeap(iface);
|
|
|
|
}
|
|
|
|
|
2017-08-28 10:43:32 -07:00
|
|
|
HRESULT d3d12_query_heap_create(struct d3d12_device *device, const D3D12_QUERY_HEAP_DESC *desc,
|
|
|
|
struct d3d12_query_heap **heap)
|
2017-07-23 06:02:41 -07:00
|
|
|
{
|
2017-08-23 07:18:15 -07:00
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
2017-07-23 06:02:41 -07:00
|
|
|
struct d3d12_query_heap *object;
|
2017-08-23 07:18:15 -07:00
|
|
|
VkQueryPoolCreateInfo pool_info;
|
2017-09-14 05:57:09 -07:00
|
|
|
unsigned int element_count;
|
2017-08-23 07:18:15 -07:00
|
|
|
VkResult vr;
|
2019-01-10 02:16:48 -08:00
|
|
|
HRESULT hr;
|
2017-07-23 06:02:41 -07:00
|
|
|
|
2017-09-14 05:57:09 -07:00
|
|
|
element_count = DIV_ROUND_UP(desc->Count, sizeof(*object->availability_mask) * CHAR_BIT);
|
|
|
|
if (!(object = vkd3d_malloc(offsetof(struct d3d12_query_heap, availability_mask[element_count]))))
|
2017-07-23 06:02:41 -07:00
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
object->ID3D12QueryHeap_iface.lpVtbl = &d3d12_query_heap_vtbl;
|
|
|
|
object->refcount = 1;
|
|
|
|
object->device = device;
|
2017-09-14 05:57:09 -07:00
|
|
|
memset(object->availability_mask, 0, element_count * sizeof(*object->availability_mask));
|
2017-08-23 07:18:15 -07:00
|
|
|
|
|
|
|
pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
|
|
|
|
pool_info.pNext = NULL;
|
|
|
|
pool_info.flags = 0;
|
|
|
|
pool_info.queryCount = desc->Count;
|
|
|
|
|
|
|
|
switch (desc->Type)
|
|
|
|
{
|
|
|
|
case D3D12_QUERY_HEAP_TYPE_OCCLUSION:
|
|
|
|
pool_info.queryType = VK_QUERY_TYPE_OCCLUSION;
|
|
|
|
pool_info.pipelineStatistics = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D12_QUERY_HEAP_TYPE_TIMESTAMP:
|
|
|
|
pool_info.queryType = VK_QUERY_TYPE_TIMESTAMP;
|
|
|
|
pool_info.pipelineStatistics = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS:
|
|
|
|
pool_info.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS;
|
|
|
|
pool_info.pipelineStatistics = VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT
|
|
|
|
| VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D12_QUERY_HEAP_TYPE_SO_STATISTICS:
|
2019-02-20 04:42:50 -08:00
|
|
|
if (!device->vk_info.transform_feedback_queries)
|
|
|
|
{
|
|
|
|
FIXME("Transform feedback queries are not supported by Vulkan implementation.\n");
|
|
|
|
vkd3d_free(object);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pool_info.queryType = VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT;
|
|
|
|
pool_info.pipelineStatistics = 0;
|
|
|
|
break;
|
2017-08-23 07:18:15 -07:00
|
|
|
|
|
|
|
default:
|
|
|
|
WARN("Invalid query heap type %u.\n", desc->Type);
|
|
|
|
vkd3d_free(object);
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
|
2019-01-10 02:16:48 -08:00
|
|
|
if (FAILED(hr = vkd3d_private_store_init(&object->private_store)))
|
|
|
|
{
|
|
|
|
vkd3d_free(object);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2017-08-23 07:18:15 -07:00
|
|
|
if ((vr = VK_CALL(vkCreateQueryPool(device->vk_device, &pool_info, NULL, &object->vk_query_pool))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to create Vulkan query pool, vr %d.\n", vr);
|
2019-01-10 02:16:48 -08:00
|
|
|
vkd3d_private_store_destroy(&object->private_store);
|
2017-08-23 07:18:15 -07:00
|
|
|
vkd3d_free(object);
|
|
|
|
return hresult_from_vk_result(vr);
|
|
|
|
}
|
|
|
|
|
2019-06-07 05:38:03 -07:00
|
|
|
d3d12_device_add_ref(device);
|
2017-07-23 06:02:41 -07:00
|
|
|
|
|
|
|
TRACE("Created query heap %p.\n", object);
|
|
|
|
|
|
|
|
*heap = object;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
2019-03-04 04:15:14 -08:00
|
|
|
|
2019-03-28 09:07:26 -07:00
|
|
|
static HRESULT vkd3d_init_null_resources_data(struct vkd3d_null_resources *null_resource,
|
|
|
|
struct d3d12_device *device)
|
|
|
|
{
|
2019-06-05 04:02:23 -07:00
|
|
|
const bool use_sparse_resources = device->vk_info.sparse_properties.residencyNonResidentStrict;
|
2019-03-28 09:07:26 -07:00
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
2019-06-04 05:28:59 -07:00
|
|
|
static const VkClearColorValue clear_color = {{0}};
|
2019-03-28 09:07:26 -07:00
|
|
|
VkCommandBufferAllocateInfo command_buffer_info;
|
|
|
|
VkCommandPool vk_command_pool = VK_NULL_HANDLE;
|
|
|
|
VkCommandPoolCreateInfo command_pool_info;
|
|
|
|
VkDevice vk_device = device->vk_device;
|
|
|
|
VkCommandBufferBeginInfo begin_info;
|
|
|
|
VkCommandBuffer vk_command_buffer;
|
|
|
|
VkFence vk_fence = VK_NULL_HANDLE;
|
2019-06-04 05:28:59 -07:00
|
|
|
VkImageSubresourceRange range;
|
2019-03-28 09:07:27 -07:00
|
|
|
VkImageMemoryBarrier barrier;
|
2019-03-28 09:07:26 -07:00
|
|
|
VkFenceCreateInfo fence_info;
|
|
|
|
struct vkd3d_queue *queue;
|
|
|
|
VkSubmitInfo submit_info;
|
|
|
|
VkQueue vk_queue;
|
|
|
|
VkResult vr;
|
|
|
|
|
|
|
|
queue = d3d12_device_get_vkd3d_queue(device, D3D12_COMMAND_LIST_TYPE_DIRECT);
|
|
|
|
|
|
|
|
command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
|
|
|
command_pool_info.pNext = NULL;
|
|
|
|
command_pool_info.flags = 0;
|
|
|
|
command_pool_info.queueFamilyIndex = queue->vk_family_index;
|
|
|
|
|
|
|
|
if ((vr = VK_CALL(vkCreateCommandPool(vk_device, &command_pool_info, NULL, &vk_command_pool))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to create Vulkan command pool, vr %d.\n", vr);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
|
|
command_buffer_info.pNext = NULL;
|
|
|
|
command_buffer_info.commandPool = vk_command_pool;
|
|
|
|
command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
|
|
command_buffer_info.commandBufferCount = 1;
|
|
|
|
|
|
|
|
if ((vr = VK_CALL(vkAllocateCommandBuffers(vk_device, &command_buffer_info, &vk_command_buffer))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to allocate Vulkan command buffer, vr %d.\n", vr);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
|
|
begin_info.pNext = NULL;
|
|
|
|
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
|
|
|
begin_info.pInheritanceInfo = NULL;
|
|
|
|
|
|
|
|
if ((vr = VK_CALL(vkBeginCommandBuffer(vk_command_buffer, &begin_info))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to begin command buffer, vr %d.\n", vr);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2019-06-04 05:28:57 -07:00
|
|
|
/* fill buffer */
|
2019-05-15 04:17:58 -07:00
|
|
|
VK_CALL(vkCmdFillBuffer(vk_command_buffer, null_resource->vk_buffer, 0, VK_WHOLE_SIZE, 0x00000000));
|
2019-03-28 09:07:26 -07:00
|
|
|
|
2019-06-05 04:02:23 -07:00
|
|
|
if (use_sparse_resources)
|
|
|
|
{
|
|
|
|
/* transition 2D UAV image */
|
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
|
|
barrier.pNext = NULL;
|
|
|
|
barrier.srcAccessMask = 0;
|
|
|
|
barrier.dstAccessMask = 0;
|
|
|
|
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
barrier.image = null_resource->vk_2d_storage_image;
|
|
|
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
barrier.subresourceRange.baseMipLevel = 0;
|
|
|
|
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
|
|
|
barrier.subresourceRange.baseArrayLayer = 0;
|
|
|
|
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
|
|
|
|
|
|
|
VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
|
|
|
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
|
|
|
|
0, NULL, 0, NULL, 1, &barrier));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* fill UAV buffer */
|
|
|
|
VK_CALL(vkCmdFillBuffer(vk_command_buffer,
|
|
|
|
null_resource->vk_storage_buffer, 0, VK_WHOLE_SIZE, 0x00000000));
|
|
|
|
|
|
|
|
/* clear 2D UAV image */
|
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
|
|
barrier.pNext = NULL;
|
|
|
|
barrier.srcAccessMask = 0;
|
|
|
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
|
|
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
barrier.image = null_resource->vk_2d_storage_image;
|
|
|
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
barrier.subresourceRange.baseMipLevel = 0;
|
|
|
|
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
|
|
|
barrier.subresourceRange.baseArrayLayer = 0;
|
|
|
|
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
|
|
|
|
|
|
|
VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
|
|
|
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
|
|
|
0, NULL, 0, NULL, 1, &barrier));
|
|
|
|
|
|
|
|
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
range.baseMipLevel = 0;
|
|
|
|
range.levelCount = 1;
|
|
|
|
range.baseArrayLayer = 0;
|
|
|
|
range.layerCount = 1;
|
|
|
|
|
|
|
|
VK_CALL(vkCmdClearColorImage(vk_command_buffer,
|
|
|
|
null_resource->vk_2d_storage_image, VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range));
|
|
|
|
}
|
2019-06-04 05:28:59 -07:00
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
/* transition 2D SRV image */
|
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
|
|
barrier.pNext = NULL;
|
|
|
|
barrier.srcAccessMask = 0;
|
|
|
|
barrier.dstAccessMask = 0;
|
|
|
|
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
|
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
barrier.image = null_resource->vk_2d_image;
|
|
|
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
barrier.subresourceRange.baseMipLevel = 0;
|
|
|
|
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
|
|
|
barrier.subresourceRange.baseArrayLayer = 0;
|
|
|
|
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
|
|
|
|
|
|
|
VK_CALL(vkCmdPipelineBarrier(vk_command_buffer,
|
|
|
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
|
|
|
|
0, NULL, 0, NULL, 1, &barrier));
|
|
|
|
|
2019-03-28 09:07:26 -07:00
|
|
|
if ((vr = VK_CALL(vkEndCommandBuffer(vk_command_buffer))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to end command buffer, vr %d.\n", vr);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
|
|
|
fence_info.pNext = NULL;
|
|
|
|
fence_info.flags = 0;
|
|
|
|
|
|
|
|
if ((vr = VK_CALL(vkCreateFence(device->vk_device, &fence_info, NULL, &vk_fence))) < 0)
|
|
|
|
{
|
|
|
|
WARN("Failed to create Vulkan fence, vr %d.\n", vr);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
|
|
submit_info.pNext = NULL;
|
|
|
|
submit_info.waitSemaphoreCount = 0;
|
|
|
|
submit_info.pWaitSemaphores = NULL;
|
|
|
|
submit_info.pWaitDstStageMask = NULL;
|
|
|
|
submit_info.commandBufferCount = 1;
|
|
|
|
submit_info.pCommandBuffers = &vk_command_buffer;
|
|
|
|
submit_info.signalSemaphoreCount = 0;
|
|
|
|
submit_info.pSignalSemaphores = NULL;
|
|
|
|
|
|
|
|
if (!(vk_queue = vkd3d_queue_acquire(queue)))
|
|
|
|
{
|
|
|
|
WARN("Failed to acquire queue %p.\n", queue);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((vr = VK_CALL(vkQueueSubmit(vk_queue, 1, &submit_info, vk_fence))) < 0)
|
|
|
|
ERR("Failed to submit, vr %d.\n", vr);
|
|
|
|
|
|
|
|
vkd3d_queue_release(queue);
|
|
|
|
|
|
|
|
vr = VK_CALL(vkWaitForFences(device->vk_device, 1, &vk_fence, VK_FALSE, ~(uint64_t)0));
|
|
|
|
if (vr != VK_SUCCESS)
|
|
|
|
WARN("Failed to wait fo fence, vr %d.\n", vr);
|
|
|
|
|
|
|
|
done:
|
|
|
|
VK_CALL(vkDestroyCommandPool(vk_device, vk_command_pool, NULL));
|
|
|
|
VK_CALL(vkDestroyFence(vk_device, vk_fence, NULL));
|
|
|
|
|
|
|
|
return hresult_from_vk_result(vr);
|
|
|
|
}
|
|
|
|
|
2019-03-04 04:15:14 -08:00
|
|
|
HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources,
|
|
|
|
struct d3d12_device *device)
|
|
|
|
{
|
2019-06-05 04:02:23 -07:00
|
|
|
const bool use_sparse_resources = device->vk_info.sparse_properties.residencyNonResidentStrict;
|
2019-03-04 04:15:14 -08:00
|
|
|
D3D12_HEAP_PROPERTIES heap_properties;
|
2019-03-28 09:07:27 -07:00
|
|
|
D3D12_RESOURCE_DESC resource_desc;
|
2019-03-04 04:15:14 -08:00
|
|
|
HRESULT hr;
|
|
|
|
|
2019-03-28 09:07:26 -07:00
|
|
|
TRACE("Creating resources for NULL views.\n");
|
|
|
|
|
2019-03-04 04:15:14 -08:00
|
|
|
memset(null_resources, 0, sizeof(*null_resources));
|
|
|
|
|
|
|
|
memset(&heap_properties, 0, sizeof(heap_properties));
|
|
|
|
heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
|
|
|
2019-06-04 05:28:57 -07:00
|
|
|
/* buffer */
|
2019-03-28 09:07:27 -07:00
|
|
|
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
|
|
resource_desc.Alignment = 0;
|
2019-05-15 04:17:58 -07:00
|
|
|
resource_desc.Width = VKD3D_NULL_BUFFER_SIZE;
|
2019-03-28 09:07:27 -07:00
|
|
|
resource_desc.Height = 1;
|
|
|
|
resource_desc.DepthOrArraySize = 1;
|
|
|
|
resource_desc.MipLevels = 1;
|
|
|
|
resource_desc.Format = DXGI_FORMAT_UNKNOWN;
|
|
|
|
resource_desc.SampleDesc.Count = 1;
|
|
|
|
resource_desc.SampleDesc.Quality = 0;
|
|
|
|
resource_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
2019-06-04 05:28:57 -07:00
|
|
|
resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
2019-03-04 04:15:14 -08:00
|
|
|
|
|
|
|
if (FAILED(hr = vkd3d_create_buffer(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
|
2019-05-15 04:17:58 -07:00
|
|
|
&resource_desc, &null_resources->vk_buffer)))
|
2019-03-04 04:15:14 -08:00
|
|
|
goto fail;
|
2019-05-15 04:17:58 -07:00
|
|
|
if (FAILED(hr = vkd3d_allocate_buffer_memory(device, null_resources->vk_buffer,
|
2019-06-20 12:08:07 -07:00
|
|
|
&heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_buffer_memory, NULL, NULL)))
|
2019-03-04 04:15:14 -08:00
|
|
|
goto fail;
|
|
|
|
|
2019-06-04 05:28:58 -07:00
|
|
|
/* buffer UAV */
|
|
|
|
resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
|
|
|
|
2019-06-05 04:02:23 -07:00
|
|
|
if (FAILED(hr = vkd3d_create_buffer(device, use_sparse_resources ? NULL : &heap_properties, D3D12_HEAP_FLAG_NONE,
|
2019-06-04 05:28:58 -07:00
|
|
|
&resource_desc, &null_resources->vk_storage_buffer)))
|
|
|
|
goto fail;
|
2019-06-05 04:02:23 -07:00
|
|
|
if (!use_sparse_resources && FAILED(hr = vkd3d_allocate_buffer_memory(device, null_resources->vk_storage_buffer,
|
2019-06-20 12:08:07 -07:00
|
|
|
&heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_storage_buffer_memory, NULL, NULL)))
|
2019-06-04 05:28:58 -07:00
|
|
|
goto fail;
|
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
/* 2D SRV */
|
|
|
|
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
|
|
|
resource_desc.Alignment = 0;
|
|
|
|
resource_desc.Width = 1;
|
|
|
|
resource_desc.Height = 1;
|
|
|
|
resource_desc.DepthOrArraySize = 1;
|
|
|
|
resource_desc.MipLevels = 1;
|
|
|
|
resource_desc.Format = VKD3D_NULL_VIEW_FORMAT;
|
|
|
|
resource_desc.SampleDesc.Count = 1;
|
|
|
|
resource_desc.SampleDesc.Quality = 0;
|
|
|
|
resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
|
|
|
resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
|
|
|
|
|
|
|
if (FAILED(hr = vkd3d_create_image(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
|
|
|
|
&resource_desc, &null_resources->vk_2d_image)))
|
|
|
|
goto fail;
|
|
|
|
if (FAILED(hr = vkd3d_allocate_image_memory(device, null_resources->vk_2d_image,
|
2019-06-20 12:08:07 -07:00
|
|
|
&heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_2d_image_memory, NULL, NULL)))
|
2019-03-28 09:07:27 -07:00
|
|
|
goto fail;
|
|
|
|
|
2019-06-04 05:28:59 -07:00
|
|
|
/* 2D UAV */
|
|
|
|
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
|
|
|
resource_desc.Alignment = 0;
|
|
|
|
resource_desc.Width = 1;
|
|
|
|
resource_desc.Height = 1;
|
|
|
|
resource_desc.DepthOrArraySize = 1;
|
|
|
|
resource_desc.MipLevels = 1;
|
|
|
|
resource_desc.Format = VKD3D_NULL_VIEW_FORMAT;
|
|
|
|
resource_desc.SampleDesc.Count = 1;
|
|
|
|
resource_desc.SampleDesc.Quality = 0;
|
2019-06-05 04:02:23 -07:00
|
|
|
resource_desc.Layout = use_sparse_resources
|
|
|
|
? D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE : D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
2019-06-04 05:28:59 -07:00
|
|
|
resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
|
|
|
|
2019-06-05 04:02:23 -07:00
|
|
|
if (FAILED(hr = vkd3d_create_image(device, use_sparse_resources ? NULL : &heap_properties, D3D12_HEAP_FLAG_NONE,
|
2019-06-04 05:28:59 -07:00
|
|
|
&resource_desc, &null_resources->vk_2d_storage_image)))
|
|
|
|
goto fail;
|
2019-06-05 04:02:23 -07:00
|
|
|
if (!use_sparse_resources && FAILED(hr = vkd3d_allocate_image_memory(device, null_resources->vk_2d_storage_image,
|
2019-06-20 12:08:07 -07:00
|
|
|
&heap_properties, D3D12_HEAP_FLAG_NONE, &null_resources->vk_2d_storage_image_memory, NULL, NULL)))
|
2019-06-04 05:28:59 -07:00
|
|
|
goto fail;
|
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
/* set Vulkan object names */
|
2019-05-15 04:17:58 -07:00
|
|
|
vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_buffer,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "NULL buffer");
|
|
|
|
vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_buffer_memory,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, "NULL memory");
|
2019-06-04 05:28:58 -07:00
|
|
|
vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_storage_buffer,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "NULL UAV buffer");
|
2019-03-28 09:07:27 -07:00
|
|
|
vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_2d_image,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "NULL 2D SRV image");
|
|
|
|
vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_2d_image_memory,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, "NULL 2D SRV memory");
|
2019-06-04 05:28:59 -07:00
|
|
|
vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_2d_storage_image,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "NULL 2D UAV image");
|
2019-06-05 04:02:23 -07:00
|
|
|
if (!use_sparse_resources)
|
|
|
|
{
|
|
|
|
vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_storage_buffer_memory,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, "NULL UAV buffer memory");
|
|
|
|
vkd3d_set_vk_object_name_utf8(device, (uint64_t)null_resources->vk_2d_storage_image_memory,
|
|
|
|
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, "NULL 2D UAV memory");
|
|
|
|
}
|
2019-03-04 04:15:18 -08:00
|
|
|
|
2019-03-28 09:07:26 -07:00
|
|
|
return vkd3d_init_null_resources_data(null_resources, device);
|
2019-03-04 04:15:14 -08:00
|
|
|
|
|
|
|
fail:
|
|
|
|
ERR("Failed to initialize NULL resources, hr %#x.\n", hr);
|
|
|
|
vkd3d_destroy_null_resources(null_resources, device);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vkd3d_destroy_null_resources(struct vkd3d_null_resources *null_resources,
|
|
|
|
struct d3d12_device *device)
|
|
|
|
{
|
|
|
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
|
|
|
|
2019-05-15 04:17:58 -07:00
|
|
|
VK_CALL(vkDestroyBuffer(device->vk_device, null_resources->vk_buffer, NULL));
|
|
|
|
VK_CALL(vkFreeMemory(device->vk_device, null_resources->vk_buffer_memory, NULL));
|
2019-03-28 09:07:27 -07:00
|
|
|
|
2019-06-04 05:28:58 -07:00
|
|
|
VK_CALL(vkDestroyBuffer(device->vk_device, null_resources->vk_storage_buffer, NULL));
|
|
|
|
VK_CALL(vkFreeMemory(device->vk_device, null_resources->vk_storage_buffer_memory, NULL));
|
|
|
|
|
2019-03-28 09:07:27 -07:00
|
|
|
VK_CALL(vkDestroyImage(device->vk_device, null_resources->vk_2d_image, NULL));
|
|
|
|
VK_CALL(vkFreeMemory(device->vk_device, null_resources->vk_2d_image_memory, NULL));
|
|
|
|
|
2019-06-04 05:28:59 -07:00
|
|
|
VK_CALL(vkDestroyImage(device->vk_device, null_resources->vk_2d_storage_image, NULL));
|
|
|
|
VK_CALL(vkFreeMemory(device->vk_device, null_resources->vk_2d_storage_image_memory, NULL));
|
|
|
|
|
2019-03-04 04:15:14 -08:00
|
|
|
memset(null_resources, 0, sizeof(*null_resources));
|
|
|
|
}
|