diff options
| author | lucy96chen <47800040+lucy96chen@users.noreply.github.com> | 2021-12-08 11:38:14 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-08 11:38:14 -0800 |
| commit | 9606401e1de1002e3ad070bc5c6384fa5bc4d9ff (patch) | |
| tree | 7a557a14fadf5220a34f6df9faf1a5535100743f /tools/gfx | |
| parent | 90d8af888b40c83b33f9f0c037bd2ab8c19a35f4 (diff) | |
D3D12 and Vulkan to CUDA Texture Sharing (#2038)
Diffstat (limited to 'tools/gfx')
| -rw-r--r-- | tools/gfx/cuda/render-cuda.cpp | 232 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 17 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.cpp | 16 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.h | 5 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.cpp | 14 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.h | 6 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 162 |
7 files changed, 351 insertions, 101 deletions
diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index 7abf51ef3..b97fc819c 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -242,6 +242,8 @@ public: CUarray m_cudaArray = CUarray(); CUmipmappedArray m_cudaMipMappedArray = CUmipmappedArray(); + void* m_cudaExternalMemory = nullptr; + RefPtr<CUDAContext> m_cudaContext; virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override @@ -1439,6 +1441,62 @@ public: return SLANG_OK; } + Result getCUDAFormat(Format format, CUarray_format* outFormat) + { + // TODO: Expand to cover all available formats that can be supported in CUDA + switch (format) + { + case Format::R32G32B32A32_FLOAT: + case Format::R32G32B32_FLOAT: + case Format::R32G32_FLOAT: + case Format::R32_FLOAT: + case Format::D32_FLOAT: + *outFormat = CU_AD_FORMAT_FLOAT; + return SLANG_OK; + case Format::R16G16B16A16_FLOAT: + case Format::R16G16_FLOAT: + case Format::R16_FLOAT: + *outFormat = CU_AD_FORMAT_HALF; + return SLANG_OK; + case Format::R32G32B32A32_UINT: + case Format::R32G32B32_UINT: + case Format::R32G32_UINT: + case Format::R32_UINT: + *outFormat = CU_AD_FORMAT_UNSIGNED_INT32; + return SLANG_OK; + case Format::R16G16B16A16_UINT: + case Format::R16G16_UINT: + case Format::R16_UINT: + *outFormat = CU_AD_FORMAT_UNSIGNED_INT16; + return SLANG_OK; + case Format::R8G8B8A8_UINT: + case Format::R8G8_UINT: + case Format::R8_UINT: + case Format::R8G8B8A8_UNORM: + *outFormat = CU_AD_FORMAT_UNSIGNED_INT8; + return SLANG_OK; + case Format::R32G32B32A32_SINT: + case Format::R32G32B32_SINT: + case Format::R32G32_SINT: + case Format::R32_SINT: + *outFormat = CU_AD_FORMAT_SIGNED_INT32; + return SLANG_OK; + case Format::R16G16B16A16_SINT: + case Format::R16G16_SINT: + case Format::R16_SINT: + *outFormat = CU_AD_FORMAT_SIGNED_INT16; + return SLANG_OK; + case Format::R8G8B8A8_SINT: + case Format::R8G8_SINT: + case Format::R8_SINT: + *outFormat = CU_AD_FORMAT_SIGNED_INT8; + return SLANG_OK; + default: + SLANG_ASSERT(!"Only support R32_FLOAT/R8G8B8A8_UNORM formats for now"); + return SLANG_FAIL; + } + } + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource( const ITextureResource::Desc& desc, const ITextureResource::SubresourceData* initData, @@ -1489,45 +1547,34 @@ public: { CUarray_format format = CU_AD_FORMAT_FLOAT; int numChannels = 0; - - switch (desc.format) + + SLANG_RETURN_ON_FAIL(getCUDAFormat(desc.format, &format)); + FormatInfo info; + gfxGetFormatInfo(desc.format, &info); + numChannels = info.channelCount; + + switch (format) { - case Format::R32G32B32A32_FLOAT: - case Format::R32G32B32_FLOAT: - case Format::R32G32_FLOAT: - case Format::R32_FLOAT: - case Format::D32_FLOAT: - { - FormatInfo info; - gfxGetFormatInfo(desc.format, &info); - format = CU_AD_FORMAT_FLOAT; - numChannels = info.channelCount; - elementSize = sizeof(float) * numChannels; - break; - } - case Format::R16G16B16A16_FLOAT: - case Format::R16G16_FLOAT: - case Format::R16_FLOAT: - { - FormatInfo info; - gfxGetFormatInfo(desc.format, &info); - format = CU_AD_FORMAT_HALF; - numChannels = info.channelCount; - elementSize = sizeof(uint16_t) * numChannels; - break; - } - case Format::R8G8B8A8_UNORM: - { - format = CU_AD_FORMAT_UNSIGNED_INT8; - numChannels = 4; - elementSize = sizeof(uint32_t); - break; - } + case CU_AD_FORMAT_FLOAT: + { + elementSize = sizeof(float) * numChannels; + break; + } + case CU_AD_FORMAT_HALF: + { + elementSize = sizeof(uint16_t) * numChannels; + break; + } + case CU_AD_FORMAT_UNSIGNED_INT8: + { + elementSize = sizeof(uint32_t) * numChannels; + break; + } default: - { - SLANG_ASSERT(!"Only support R32_FLOAT/R8G8B8A8_UNORM formats for now"); - return SLANG_FAIL; - } + { + SLANG_ASSERT(!"Only support R32_FLOAT/R8G8B8A8_UNORM formats for now"); + return SLANG_FAIL; + } } if (desc.numMipLevels > 1) @@ -1951,6 +1998,83 @@ public: return SLANG_OK; } + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromSharedHandle( + InteropHandle handle, + const ITextureResource::Desc& desc, + const size_t size, + ITextureResource** outResource) override + { + if (handle.handleValue == 0) + { + *outResource = nullptr; + return SLANG_OK; + } + + RefPtr<TextureCUDAResource> resource = new TextureCUDAResource(desc); + resource->m_cudaContext = m_context; + + // CUDA manages sharing of buffers through the idea of an + // "external memory" object, which represents the relationship + // with another API's objects. In order to create this external + // memory association, we first need to fill in a descriptor struct. + CUDA_EXTERNAL_MEMORY_HANDLE_DESC externalMemoryHandleDesc; + memset(&externalMemoryHandleDesc, 0, sizeof(externalMemoryHandleDesc)); + switch (handle.api) + { + case InteropHandleAPI::D3D12: + externalMemoryHandleDesc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE; + break; + case InteropHandleAPI::Vulkan: + externalMemoryHandleDesc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32; + break; + default: + return SLANG_FAIL; + } + externalMemoryHandleDesc.handle.win32.handle = (void*)handle.handleValue; + externalMemoryHandleDesc.size = size; + externalMemoryHandleDesc.flags = cudaExternalMemoryDedicated; + + CUexternalMemory externalMemory; + SLANG_CUDA_RETURN_ON_FAIL(cuImportExternalMemory(&externalMemory, &externalMemoryHandleDesc)); + resource->m_cudaExternalMemory = externalMemory; + + FormatInfo formatInfo; + SLANG_RETURN_ON_FAIL(gfxGetFormatInfo(desc.format, &formatInfo)); + CUDA_ARRAY3D_DESCRIPTOR arrayDesc; + arrayDesc.Depth = desc.size.depth; + arrayDesc.Height = desc.size.height; + arrayDesc.Width = desc.size.width; + arrayDesc.NumChannels = formatInfo.channelCount; + getCUDAFormat(desc.format, &arrayDesc.Format); + arrayDesc.Flags = 0; // TODO: Flags? CUDA_ARRAY_LAYERED/SURFACE_LDST/CUBEMAP/TEXTURE_GATHER + + CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC externalMemoryMipDesc; + memset(&externalMemoryMipDesc, 0, sizeof(externalMemoryMipDesc)); + externalMemoryMipDesc.offset = 0; + externalMemoryMipDesc.arrayDesc = arrayDesc; + externalMemoryMipDesc.numLevels = desc.numMipLevels; + + CUmipmappedArray mipArray; + SLANG_CUDA_RETURN_ON_FAIL(cuExternalMemoryGetMappedMipmappedArray(&mipArray, externalMemory, &externalMemoryMipDesc)); + resource->m_cudaMipMappedArray = mipArray; + + CUarray cuArray; + SLANG_CUDA_RETURN_ON_FAIL(cuMipmappedArrayGetLevel(&cuArray, mipArray, 0)); + resource->m_cudaArray = cuArray; + + CUDA_RESOURCE_DESC surfDesc; + memset(&surfDesc, 0, sizeof(surfDesc)); + surfDesc.resType = CU_RESOURCE_TYPE_ARRAY; + surfDesc.res.array.hArray = cuArray; + + CUsurfObject surface; + SLANG_CUDA_RETURN_ON_FAIL(cuSurfObjectCreate(&surface, &surfDesc)); + resource->m_cudaSurfObj = surface; + + returnComPtr(outResource, resource); + return SLANG_OK; + } + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView( ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView) override { @@ -2183,12 +2307,36 @@ public: size_t* outRowPitch, size_t* outPixelSize) override { - SLANG_UNUSED(texture); - SLANG_UNUSED(outBlob); - SLANG_UNUSED(outRowPitch); - SLANG_UNUSED(outPixelSize); + auto textureImpl = static_cast<TextureCUDAResource*>(texture); + RefPtr<ListBlob> blob = new ListBlob(); - return SLANG_E_NOT_AVAILABLE; + auto desc = textureImpl->getDesc(); + auto width = desc->size.width; + auto height = desc->size.height; + FormatInfo sizeInfo; + SLANG_RETURN_ON_FAIL(gfxGetFormatInfo(desc->format, &sizeInfo)); + size_t pixelSize = sizeInfo.blockSizeInBytes / sizeInfo.pixelsPerBlock; + size_t rowPitch = width * pixelSize; + size_t size = height * rowPitch; + blob->m_data.setCount((Index)size); + + CUDA_MEMCPY2D copyParam; + memset(©Param, 0, sizeof(copyParam)); + + copyParam.srcMemoryType = CU_MEMORYTYPE_ARRAY; + copyParam.srcArray = textureImpl->m_cudaArray; + + copyParam.dstMemoryType = CU_MEMORYTYPE_HOST; + copyParam.dstHost = blob->m_data.getBuffer(); + copyParam.dstPitch = rowPitch; + copyParam.WidthInBytes = copyParam.dstPitch; + copyParam.Height = height; + SLANG_CUDA_RETURN_ON_FAIL(cuMemcpy2D(©Param)); + + *outRowPitch = rowPitch; + *outPixelSize = pixelSize; + returnComPtr(outBlob, blob); + return SLANG_OK; } virtual SLANG_NO_THROW Result SLANG_MCALL readBufferResource( diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index 371d22002..ebc894291 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -314,11 +314,19 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override { + // Check if a shared handle already exists for this resource. + if (sharedHandle.handleValue != 0) + { + *outHandle = sharedHandle; + return SLANG_OK; + } + + // If a shared handle doesn't exist, create one and store it. ComPtr<ID3D12Device> pDevice; auto pResource = m_resource.getResource(); pResource->GetDevice(IID_PPV_ARGS(pDevice.writeRef())); SLANG_RETURN_ON_FAIL(pDevice->CreateSharedHandle(pResource, NULL, GENERIC_ALL, nullptr, (HANDLE*)&outHandle->handleValue)); - outHandle->api = InteropHandleAPI::Win32; + outHandle->api = InteropHandleAPI::D3D12; return SLANG_OK; } }; @@ -5031,7 +5039,7 @@ Result D3D12Device::getTextureAllocationInfo( TextureResource::Desc srcDesc = fixupTextureDesc(desc); D3D12_RESOURCE_DESC resourceDesc = {}; setupResourceDesc(resourceDesc, srcDesc); - auto allocInfo = m_device->GetResourceAllocationInfo(0xFF, 1, &resourceDesc); + auto allocInfo = m_device->GetResourceAllocationInfo(0, 1, &resourceDesc); *outSize = (size_t)allocInfo.SizeInBytes; *outAlignment = (size_t)allocInfo.Alignment; return SLANG_OK; @@ -5061,6 +5069,9 @@ Result D3D12Device::createTextureResource(const ITextureResource::Desc& descIn, heapProps.CreationNodeMask = 1; heapProps.VisibleNodeMask = 1; + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE; + if (descIn.isShared) flags |= D3D12_HEAP_FLAG_SHARED; + D3D12_CLEAR_VALUE clearValue; D3D12_CLEAR_VALUE* clearValuePtr = &clearValue; if ((resourceDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | @@ -5075,7 +5086,7 @@ Result D3D12Device::createTextureResource(const ITextureResource::Desc& descIn, SLANG_RETURN_ON_FAIL(texture->m_resource.initCommitted( m_device, heapProps, - D3D12_HEAP_FLAG_NONE, + flags, resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, clearValuePtr)); diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp index 470b63599..60e726243 100644 --- a/tools/gfx/debug-layer.cpp +++ b/tools/gfx/debug-layer.cpp @@ -370,6 +370,22 @@ Result DebugDevice::createTextureFromNativeHandle( return result; } +Result DebugDevice::createTextureFromSharedHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + const size_t size, + ITextureResource** outResource) +{ + SLANG_GFX_API_FUNC; + + RefPtr<DebugTextureResource> outObject = new DebugTextureResource(); + auto result = baseObject->createTextureFromSharedHandle(handle, srcDesc, size, outObject->baseObject.writeRef()); + if (SLANG_FAILED(result)) + return result; + returnComPtr(outResource, outObject); + return result; +} + Result DebugDevice::createBufferResource( const IBufferResource::Desc& desc, const void* initData, diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h index e0a97ee1c..71cf74260 100644 --- a/tools/gfx/debug-layer.h +++ b/tools/gfx/debug-layer.h @@ -60,6 +60,11 @@ public: InteropHandle handle, const ITextureResource::Desc& srcDesc, ITextureResource** outResource) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromSharedHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + const size_t size, + ITextureResource** outResource) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource( const IBufferResource::Desc& desc, const void* initData, diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp index 101e02d47..df6ebd37e 100644 --- a/tools/gfx/renderer-shared.cpp +++ b/tools/gfx/renderer-shared.cpp @@ -365,6 +365,19 @@ SLANG_NO_THROW Result SLANG_MCALL RendererBase::createTextureFromNativeHandle( return SLANG_E_NOT_AVAILABLE; } +SLANG_NO_THROW Result SLANG_MCALL RendererBase::createTextureFromSharedHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + const size_t size, + ITextureResource** outResource) +{ + SLANG_UNUSED(handle); + SLANG_UNUSED(srcDesc); + SLANG_UNUSED(size); + SLANG_UNUSED(outResource); + return SLANG_E_NOT_AVAILABLE; +} + SLANG_NO_THROW Result SLANG_MCALL RendererBase::createBufferFromNativeHandle( InteropHandle handle, const IBufferResource::Desc& srcDesc, @@ -381,6 +394,7 @@ SLANG_NO_THROW Result SLANG_MCALL RendererBase::createBufferFromSharedHandle( const IBufferResource::Desc& srcDesc, IBufferResource** outResource) { + SLANG_UNUSED(handle); SLANG_UNUSED(srcDesc); SLANG_UNUSED(outResource); return SLANG_E_NOT_AVAILABLE; diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h index e7ea1b7f5..7859f1ad9 100644 --- a/tools/gfx/renderer-shared.h +++ b/tools/gfx/renderer-shared.h @@ -1206,6 +1206,12 @@ public: const ITextureResource::Desc& srcDesc, ITextureResource** outResource) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromSharedHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + const size_t size, + ITextureResource** outResource) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromNativeHandle( InteropHandle handle, const IBufferResource::Desc& srcDesc, diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 25609ec6e..b55c78ea0 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -381,6 +381,12 @@ public: vkAPI.vkFreeMemory(vkAPI.m_device, m_imageMemory, nullptr); vkAPI.vkDestroyImage(vkAPI.m_device, m_image, nullptr); } + if (sharedHandle.handleValue != 0) + { +#if SLANG_WINDOWS_FAMILY + CloseHandle((HANDLE)sharedHandle.handleValue); +#endif + } } VkImage m_image = VK_NULL_HANDLE; @@ -398,8 +404,31 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override { + // Check if a shared handle already exists for this resource. + if (sharedHandle.handleValue != 0) + { + *outHandle = sharedHandle; + return SLANG_OK; + } + + // If a shared handle doesn't exist, create one and store it. +#if SLANG_WINDOWS_FAMILY + VkMemoryGetWin32HandleInfoKHR info = {}; + info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR; + info.pNext = nullptr; + info.memory = m_imageMemory; + info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; + + auto& api = m_device->m_api; + PFN_vkGetMemoryWin32HandleKHR vkCreateSharedHandle; + vkCreateSharedHandle = api.vkGetMemoryWin32HandleKHR; + if (!vkCreateSharedHandle) + { + return SLANG_FAIL; + } + SLANG_RETURN_ON_FAIL(vkCreateSharedHandle(m_device->m_device, &info, (HANDLE*)&outHandle->handleValue) != VK_SUCCESS); +#endif outHandle->api = InteropHandleAPI::Vulkan; - outHandle->handleValue = 0; return SLANG_OK; } }; @@ -5712,7 +5741,7 @@ Result VKDevice::Buffer::init( exportMemoryAllocateInfo.pNext = extMemHandleType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR ? &exportMemoryWin32HandleInfo - : NULL; + : nullptr; exportMemoryAllocateInfo.handleTypes = extMemHandleType; allocateInfo.pNext = &exportMemoryAllocateInfo; } @@ -6921,78 +6950,99 @@ Result VKDevice::createTextureResource(const ITextureResource::Desc& descIn, con RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(desc, this)); texture->m_vkformat = format; // Create the image + + VkImageCreateInfo imageInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}; + switch (desc.type) { - VkImageCreateInfo imageInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}; - switch (desc.type) + case IResource::Type::Texture1D: { - case IResource::Type::Texture1D: - { - imageInfo.imageType = VK_IMAGE_TYPE_1D; - imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), 1, 1 }; - break; - } - case IResource::Type::Texture2D: - { - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), uint32_t(descIn.size.height), 1 }; - break; - } - case IResource::Type::TextureCube: - { - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), uint32_t(descIn.size.height), 1 }; - imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - break; - } - case IResource::Type::Texture3D: - { - // Can't have an array and 3d texture - assert(desc.arraySize <= 1); + imageInfo.imageType = VK_IMAGE_TYPE_1D; + imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), 1, 1 }; + break; + } + case IResource::Type::Texture2D: + { + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), uint32_t(descIn.size.height), 1 }; + break; + } + case IResource::Type::TextureCube: + { + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), uint32_t(descIn.size.height), 1 }; + imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + break; + } + case IResource::Type::Texture3D: + { + // Can't have an array and 3d texture + assert(desc.arraySize <= 1); - imageInfo.imageType = VK_IMAGE_TYPE_3D; - imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), uint32_t(descIn.size.height), uint32_t(descIn.size.depth) }; - break; - } - default: - { - assert(!"Unhandled type"); - return SLANG_FAIL; - } + imageInfo.imageType = VK_IMAGE_TYPE_3D; + imageInfo.extent = VkExtent3D{ uint32_t(descIn.size.width), uint32_t(descIn.size.height), uint32_t(descIn.size.depth) }; + break; + } + default: + { + assert(!"Unhandled type"); + return SLANG_FAIL; } + } - imageInfo.mipLevels = desc.numMipLevels; - imageInfo.arrayLayers = arraySize; + imageInfo.mipLevels = desc.numMipLevels; + imageInfo.arrayLayers = arraySize; - imageInfo.format = format; + imageInfo.format = format; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.usage = _calcImageUsageFlags(desc.allowedStates, desc.cpuAccessFlags, initData); - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.usage = _calcImageUsageFlags(desc.allowedStates, desc.cpuAccessFlags, initData); + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateImage(m_device, &imageInfo, nullptr, &texture->m_image)); + VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO }; +#if SLANG_WINDOWS_FAMILY + VkExternalMemoryHandleTypeFlags extMemoryHandleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; + if (descIn.isShared) + { + externalMemoryImageCreateInfo.pNext = nullptr; + externalMemoryImageCreateInfo.handleTypes = extMemoryHandleType; + imageInfo.pNext = &externalMemoryImageCreateInfo; } +#endif + SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateImage(m_device, &imageInfo, nullptr, &texture->m_image)); VkMemoryRequirements memRequirements; m_api.vkGetImageMemoryRequirements(m_device, texture->m_image, &memRequirements); // Allocate the memory - { - VkMemoryPropertyFlags reqMemoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - - VkMemoryAllocateInfo allocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; - - int memoryTypeIndex = m_api.findMemoryTypeIndex(memRequirements.memoryTypeBits, reqMemoryProperties); - assert(memoryTypeIndex >= 0); - - VkMemoryPropertyFlags actualMemoryProperites = m_api.m_deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags; + VkMemoryPropertyFlags reqMemoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + int memoryTypeIndex = m_api.findMemoryTypeIndex(memRequirements.memoryTypeBits, reqMemoryProperties); + assert(memoryTypeIndex >= 0); - allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = memoryTypeIndex; + VkMemoryPropertyFlags actualMemoryProperites = m_api.m_deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags; + VkMemoryAllocateInfo allocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; + allocInfo.allocationSize = memRequirements.size; + allocInfo.memoryTypeIndex = memoryTypeIndex; +#if SLANG_WINDOWS_FAMILY + VkExportMemoryWin32HandleInfoKHR exportMemoryWin32HandleInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR }; + VkExportMemoryAllocateInfoKHR exportMemoryAllocateInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR }; + if (descIn.isShared) + { + exportMemoryWin32HandleInfo.pNext = nullptr; + exportMemoryWin32HandleInfo.pAttributes = nullptr; + exportMemoryWin32HandleInfo.dwAccess = DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE; + exportMemoryWin32HandleInfo.name = NULL; - SLANG_VK_RETURN_ON_FAIL(m_api.vkAllocateMemory(m_device, &allocInfo, nullptr, &texture->m_imageMemory)); + exportMemoryAllocateInfo.pNext = + extMemoryHandleType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR + ? &exportMemoryWin32HandleInfo + : nullptr; + exportMemoryAllocateInfo.handleTypes = extMemoryHandleType; + allocInfo.pNext = &exportMemoryAllocateInfo; } +#endif + SLANG_VK_RETURN_ON_FAIL(m_api.vkAllocateMemory(m_device, &allocInfo, nullptr, &texture->m_imageMemory)); // Bind the memory to the image m_api.vkBindImageMemory(m_device, texture->m_image, texture->m_imageMemory, 0); |
