1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[d3d11] Lock textures in place when used with CUDA interop

Prevents images from being relocated by the backend.
This commit is contained in:
Philip Rebohle 2024-09-29 15:10:19 +02:00 committed by Philip Rebohle
parent c59d6bd12c
commit 9f0bd8e17f

View File

@ -2558,21 +2558,9 @@ namespace dxvk {
ID3D11Resource* pResource = static_cast<ID3D11Resource*>(hObject);
D3D11_COMMON_RESOURCE_DESC resourceDesc;
if (FAILED(GetCommonResourceDesc(pResource, &resourceDesc))) {
Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() - GetCommonResourceDesc() failed");
return false;
}
switch (resourceDesc.Dim) {
case D3D11_RESOURCE_DIMENSION_BUFFER:
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
// okay - we can deal with those two dimensions
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
case D3D11_RESOURCE_DIMENSION_UNKNOWN:
default:
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(?) - failure - unsupported dimension: ", resourceDesc.Dim));
if (FAILED(GetCommonResourceDesc(pResource, &resourceDesc))) {
Logger::warn("GetResourceHandleGPUVirtualAddressAndSize: Invalid resource");
return false;
}
@ -2581,47 +2569,58 @@ namespace dxvk {
if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
D3D11CommonTexture *texture = GetCommonTexture(pResource);
// Ensure that the image has a stable GPU address and
// won't be relocated by the backend going forward
Rc<DxvkImage> dxvkImage = texture->GetImage();
if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) {
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(res=", pResource,") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure"));
return false;
if (dxvkImage->canRelocate()) {
auto chunk = m_device->AllocCsChunk(DxvkCsChunkFlag::SingleUse);
bool feedback = false;
chunk->push([cImage = dxvkImage, &feedback] (DxvkContext* ctx) {
DxvkImageUsageInfo usageInfo;
usageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
usageInfo.stableGpuAddress = VK_TRUE;
feedback = ctx->ensureImageCompatibility(cImage, usageInfo);
});
m_device->GetContext()->EmitCsChunkExternal(std::move(chunk), true);
if (!feedback) {
Logger::err(str::format("GetResourceHandleGPUVirtualAddressAndSize(res=", pResource,"): Failed to lock resource"));
return false;
}
}
// The d3d11 nvapi provides us a texture but vulkan only lets us get the GPU address from an imageview. So, make a private imageview and get the address from that...
// The d3d11 nvapi provides us a texture, but vulkan only lets us
// get the GPU address from an image view. So, make a private image
// view and get the address from that.
DxvkImageViewKey viewInfo;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = dxvkImage->info().format;
viewInfo.aspects = dxvkImage->formatInfo()->aspectMask;
viewInfo.mipIndex = 0;
viewInfo.mipCount = dxvkImage->info().mipLevels;
viewInfo.layerIndex = 0;
viewInfo.layerCount = 1;
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
auto dxvkView = dxvkImage->createView(viewInfo);
VkImageViewAddressPropertiesNVX imageViewAddressProperties = { VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX };
const D3D11_COMMON_TEXTURE_DESC *texDesc = texture->Desc();
if (texDesc->ArraySize != 1) {
Logger::debug(str::format("GetResourceHandleGPUVirtualAddressAndSize(?) - unexpected array size: ", texDesc->ArraySize));
}
resourceViewDesc.Format = texDesc->Format;
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceViewDesc.Texture2D.MostDetailedMip = 0;
resourceViewDesc.Texture2D.MipLevels = texDesc->MipLevels;
VkResult vr = dxvkDevice->vkd()->vkGetImageViewAddressNVX(vkDevice,
dxvkView->handle(), &imageViewAddressProperties);
Com<ID3D11ShaderResourceView> pNewSRV;
HRESULT hr = m_device->CreateShaderResourceView(pResource, &resourceViewDesc, &pNewSRV);
if (FAILED(hr)) {
Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() - private CreateShaderResourceView() failed");
return false;
}
Rc<DxvkImageView> dxvkImageView = static_cast<D3D11ShaderResourceView*>(pNewSRV.ptr())->GetImageView();
VkImageView vkImageView = dxvkImageView->handle();
VkImageViewAddressPropertiesNVX imageViewAddressProperties = {VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX};
VkResult res = dxvkDevice->vkd()->vkGetImageViewAddressNVX(vkDevice, vkImageView, &imageViewAddressProperties);
if (res != VK_SUCCESS) {
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(): vkGetImageViewAddressNVX() result is failure: ", res));
if (vr != VK_SUCCESS) {
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(): Failed: vr = ", vr));
return false;
}
*gpuVAStart = imageViewAddressProperties.deviceAddress;
*gpuVASize = imageViewAddressProperties.size;
}
else if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
} else if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
D3D11Buffer *buffer = GetCommonBuffer(pResource);
const DxvkBufferSliceHandle bufSliceHandle = buffer->GetBuffer()->getSliceHandle();
VkBuffer vkBuffer = bufSliceHandle.handle;
@ -2632,6 +2631,9 @@ namespace dxvk {
VkDeviceAddress bufAddr = dxvkDevice->vkd()->vkGetBufferDeviceAddress(vkDevice, &bdaInfo);
*gpuVAStart = uint64_t(bufAddr) + bufSliceHandle.offset;
*gpuVASize = bufSliceHandle.length;
} else {
Logger::warn(str::format("GetResourceHandleGPUVirtualAddressAndSize(): Unsupported resource type: ", resourceDesc.Dim));
return false;
}
if (!*gpuVAStart)