1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-04 16:24:29 +01:00

[d3d11] Fix remaining synchronization issues with CUDA interop

This commit is contained in:
Philip Rebohle 2024-09-29 19:43:27 +02:00 committed by Philip Rebohle
parent c26c21edb4
commit e83446f5c9
2 changed files with 113 additions and 86 deletions

View File

@ -2492,15 +2492,15 @@ namespace dxvk {
D3D11SamplerState* pSS = static_cast<D3D11SamplerState*>(samplerState); D3D11SamplerState* pSS = static_cast<D3D11SamplerState*>(samplerState);
Rc<DxvkSampler> pDSS = pSS->GetDXVKSampler(); Rc<DxvkSampler> pDSS = pSS->GetDXVKSampler();
VkSampler vkSampler = pDSS->handle();
D3D11ShaderResourceView* pSRV = static_cast<D3D11ShaderResourceView*>(srv); D3D11ShaderResourceView* pSRV = static_cast<D3D11ShaderResourceView*>(srv);
Rc<DxvkImageView> pIV = pSRV->GetImageView(); Rc<DxvkImageView> pIV = pSRV->GetImageView();
VkImageView vkImageView = pIV->handle();
LockImage(pIV->image(), 0u);
VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX }; VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX };
imageViewHandleInfo.imageView = vkImageView; imageViewHandleInfo.imageView = pIV->handle();
imageViewHandleInfo.sampler = vkSampler; imageViewHandleInfo.sampler = pDSS->handle();
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
// note: there's no implicit lifetime management here; it's up to the // note: there's no implicit lifetime management here; it's up to the
@ -2574,25 +2574,8 @@ namespace dxvk {
// won't be relocated by the backend going forward // won't be relocated by the backend going forward
Rc<DxvkImage> dxvkImage = texture->GetImage(); Rc<DxvkImage> dxvkImage = texture->GetImage();
if (dxvkImage->canRelocate()) { if (!LockImage(dxvkImage, VK_IMAGE_USAGE_SAMPLED_BIT))
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; return false;
}
}
// The d3d11 nvapi provides us a texture, but vulkan only lets us // 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 // get the GPU address from an image view. So, make a private image
@ -2622,16 +2605,7 @@ namespace dxvk {
*gpuVASize = imageViewAddressProperties.size; *gpuVASize = imageViewAddressProperties.size;
} else if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) { } else if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
Rc<DxvkBuffer> dxvkBuffer = GetCommonBuffer(pResource)->GetBuffer(); Rc<DxvkBuffer> dxvkBuffer = GetCommonBuffer(pResource)->GetBuffer();
LockBuffer(dxvkBuffer);
if (dxvkBuffer->canRelocate()) {
auto chunk = m_device->AllocCsChunk(DxvkCsChunkFlag::SingleUse);
chunk->push([cBuffer = dxvkBuffer] (DxvkContext* ctx) {
ctx->ensureBufferAddress(cBuffer);
});
m_device->GetContext()->EmitCsChunkExternal(std::move(chunk), true);
}
*gpuVAStart = dxvkBuffer->gpuAddress(); *gpuVAStart = dxvkBuffer->gpuAddress();
*gpuVASize = dxvkBuffer->info().size; *gpuVASize = dxvkBuffer->info().size;
@ -2647,102 +2621,99 @@ namespace dxvk {
} }
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateUnorderedAccessViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D11UnorderedAccessView** ppUAV, uint32_t* pDriverHandle) { bool STDMETHODCALLTYPE D3D11DeviceExt::CreateUnorderedAccessViewAndGetDriverHandleNVX(
D3D11_COMMON_RESOURCE_DESC resourceDesc; ID3D11Resource* pResource,
if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) { const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed"); ID3D11UnorderedAccessView** ppUAV,
return false; uint32_t* pDriverHandle) {
} D3D11_COMMON_RESOURCE_DESC resourceDesc = { };
GetCommonResourceDesc(pResource, &resourceDesc);
if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) { if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim)); Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX(): Unsupported dimension: ", resourceDesc.Dim));
return false; return false;
} }
auto texture = GetCommonTexture(pResource); Rc<DxvkImage> dxvkImage = GetCommonTexture(pResource)->GetImage();
Rc<DxvkImage> dxvkImage = texture->GetImage();
if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) { if (!(dxvkImage->info().usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX(res=", pResource, ") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure")); Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX(res=", pResource, "): Image not UAV compatible"));
return false; return false;
} }
if (!SUCCEEDED(m_device->CreateUnorderedAccessView(pResource, pDesc, ppUAV))) { Com<ID3D11UnorderedAccessView> uav;
return false;
}
D3D11UnorderedAccessView *pUAV = static_cast<D3D11UnorderedAccessView *>(*ppUAV); if (FAILED(m_device->CreateUnorderedAccessView(pResource, pDesc, &uav)))
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice(); return false;
VkDevice vkDevice = dxvkDevice->handle();
Rc<DxvkImageView> dxvkImageView = static_cast<D3D11UnorderedAccessView*>(uav.ptr())->GetImageView();
LockImage(dxvkImageView->image(), 0u);
VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX}; VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
Rc<DxvkImageView> dxvkImageView = pUAV->GetImageView(); imageViewHandleInfo.imageView = dxvkImageView->handle();
VkImageView vkImageView = dxvkImageView->handle();
imageViewHandleInfo.imageView = vkImageView;
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo); Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(
dxvkDevice->handle(), &imageViewHandleInfo);
if (!*pDriverHandle) { if (!*pDriverHandle) {
Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() handle==0 - failure"); Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX(): Handle is 0");
pUAV->Release();
return false; return false;
} }
*ppUAV = uav.ref();
return true; return true;
} }
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateShaderResourceViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D11ShaderResourceView** ppSRV, uint32_t* pDriverHandle) { bool STDMETHODCALLTYPE D3D11DeviceExt::CreateShaderResourceViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D11ShaderResourceView** ppSRV, uint32_t* pDriverHandle) {
D3D11_COMMON_RESOURCE_DESC resourceDesc; D3D11_COMMON_RESOURCE_DESC resourceDesc = { };
if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) { GetCommonResourceDesc(pResource, &resourceDesc);
Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed");
return false;
}
if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) { if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim)); Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX(): Unsupported dimension: ", resourceDesc.Dim));
return false; return false;
} }
auto texture = GetCommonTexture(pResource); Rc<DxvkImage> dxvkImage = GetCommonTexture(pResource)->GetImage();
Rc<DxvkImage> dxvkImage = texture->GetImage();
if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) { if (!(dxvkImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX(res=", pResource, ") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure")); Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX(res=", pResource, "): Image not SRV compatible"));
return false; return false;
} }
if (!SUCCEEDED(m_device->CreateShaderResourceView(pResource, pDesc, ppSRV))) { Com<ID3D11ShaderResourceView> srv;
return false;
}
D3D11ShaderResourceView* pSRV = static_cast<D3D11ShaderResourceView*>(*ppSRV); if (FAILED(m_device->CreateShaderResourceView(pResource, pDesc, &srv)))
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice(); return false;
VkDevice vkDevice = dxvkDevice->handle();
Rc<DxvkImageView> dxvkImageView = static_cast<D3D11ShaderResourceView*>(srv.ptr())->GetImageView();
LockImage(dxvkImageView->image(), 0u);
VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX}; VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
Rc<DxvkImageView> dxvkImageView = pSRV->GetImageView(); imageViewHandleInfo.imageView = dxvkImageView->handle();
VkImageView vkImageView = dxvkImageView->handle();
imageViewHandleInfo.imageView = vkImageView;
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo); Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(
dxvkDevice->handle(), &imageViewHandleInfo);
if (!*pDriverHandle) { if (!*pDriverHandle) {
Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() handle==0 - failure"); Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX(): Handle is 0");
pSRV->Release();
return false; return false;
} }
// will need to look-up resource from uint32 handle later // will need to look-up resource from uint32 handle later
AddSrvAndHandleNVX(*ppSRV, *pDriverHandle); *ppSRV = srv.ref();
AddSrvAndHandleNVX(srv.ptr(), *pDriverHandle);
return true; return true;
} }
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateSamplerStateAndGetDriverHandleNVX(const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState, uint32_t* pDriverHandle) { bool STDMETHODCALLTYPE D3D11DeviceExt::CreateSamplerStateAndGetDriverHandleNVX(const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState, uint32_t* pDriverHandle) {
if (!SUCCEEDED(m_device->CreateSamplerState(pSamplerDesc, ppSamplerState))) { if (FAILED(m_device->CreateSamplerState(pSamplerDesc, ppSamplerState)))
return false; return false;
}
// for our purposes the actual value doesn't matter, only its uniqueness // for our purposes the actual value doesn't matter, only its uniqueness
static std::atomic<ULONG> s_seqNum = 0; static std::atomic<ULONG> s_seqNum = 0;
@ -2788,6 +2759,55 @@ namespace dxvk {
} }
bool D3D11DeviceExt::LockImage(
const Rc<DxvkImage>& Image,
VkImageUsageFlags Usage) {
if (!Image->canRelocate() && (Image->info().usage & Usage))
return true;
bool feedback = false;
auto chunk = m_device->AllocCsChunk(DxvkCsChunkFlag::SingleUse);
chunk->push([
cImage = Image,
cUsage = Usage,
&feedback
] (DxvkContext* ctx) {
DxvkImageUsageInfo usageInfo;
usageInfo.usage = cUsage;
usageInfo.stableGpuAddress = VK_TRUE;
feedback = ctx->ensureImageCompatibility(cImage, usageInfo);
});
m_device->GetContext()->EmitCsChunkExternal(std::move(chunk), true);
if (!feedback) {
Logger::err(str::format("Failed to lock image:"
"\n Image format: ", Image->info().format,
"\n Image usage: ", std::hex, Image->info().usage,
"\n Desired usage: ", std::hex, Usage));
}
return feedback;
}
void D3D11DeviceExt::LockBuffer(
const Rc<DxvkBuffer>& Buffer) {
if (!Buffer->canRelocate())
return;
auto chunk = m_device->AllocCsChunk(DxvkCsChunkFlag::SingleUse);
chunk->push([cBuffer = Buffer] (DxvkContext* ctx) {
ctx->ensureBufferAddress(cBuffer);
});
m_device->GetContext()->EmitCsChunkExternal(std::move(chunk), true);
}

View File

@ -593,6 +593,13 @@ namespace dxvk {
ID3D11ShaderResourceView* HandleToSrvNVX( ID3D11ShaderResourceView* HandleToSrvNVX(
uint32_t Handle); uint32_t Handle);
bool LockImage(
const Rc<DxvkImage>& Image,
VkImageUsageFlags Usage);
void LockBuffer(
const Rc<DxvkBuffer>& Buffer);
dxvk::mutex m_mapLock; dxvk::mutex m_mapLock;
std::unordered_map<uint32_t, ID3D11SamplerState*> m_samplerHandleToPtr; std::unordered_map<uint32_t, ID3D11SamplerState*> m_samplerHandleToPtr;
std::unordered_map<uint32_t, ID3D11ShaderResourceView*> m_srvHandleToPtr; std::unordered_map<uint32_t, ID3D11ShaderResourceView*> m_srvHandleToPtr;