mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 13:08:50 +01:00
[d3d11,dxvk] Implement DXVK pieces required for DX11 DLSS support
Notably, fairly generic functions to create/launch/destroy Cuda kernels, and methods to fetch GPU virtual addresses and handles for DX11 resources. Note: Requires some corresponding dxvk-nvapi changes for DLSS to be initialized successfully.
This commit is contained in:
parent
3a712b766e
commit
86148ec070
@ -48,7 +48,8 @@ namespace dxvk {
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (riid == __uuidof(ID3D11VkExtContext)) {
|
if (riid == __uuidof(ID3D11VkExtContext)
|
||||||
|
|| riid == __uuidof(ID3D11VkExtContext1)) {
|
||||||
*ppvObject = ref(&m_contextExt);
|
*ppvObject = ref(&m_contextExt);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "d3d11_device.h"
|
||||||
#include "d3d11_context.h"
|
#include "d3d11_context.h"
|
||||||
|
#include "d3d11_cuda.h"
|
||||||
|
|
||||||
|
#include "../util/log/log.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
@ -137,4 +145,54 @@ namespace dxvk {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE D3D11DeviceContextExt::LaunchCubinShaderNVX(IUnknown* hShader, uint32_t GridX, uint32_t GridY, uint32_t GridZ,
|
||||||
|
const void* pParams, uint32_t ParamSize, void* const* pReadResources, uint32_t NumReadResources, void* const* pWriteResources, uint32_t NumWriteResources) {
|
||||||
|
D3D10DeviceLock lock = m_ctx->LockContext();
|
||||||
|
|
||||||
|
CubinShaderWrapper* cubinShader = static_cast<CubinShaderWrapper*>(hShader);
|
||||||
|
CubinShaderLaunchInfo launchInfo;
|
||||||
|
|
||||||
|
const uint32_t maxResources = NumReadResources + NumWriteResources;
|
||||||
|
launchInfo.buffers.reserve(maxResources);
|
||||||
|
launchInfo.images.reserve(maxResources);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < NumReadResources; i++)
|
||||||
|
launchInfo.insertResource(static_cast<ID3D11Resource*>(pReadResources[i]), DxvkAccess::Read);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < NumWriteResources; i++)
|
||||||
|
launchInfo.insertResource(static_cast<ID3D11Resource*>(pWriteResources[i]), DxvkAccess::Write);
|
||||||
|
|
||||||
|
launchInfo.paramSize = ParamSize;
|
||||||
|
launchInfo.params.resize(launchInfo.paramSize);
|
||||||
|
std::memcpy(launchInfo.params.data(), pParams, ParamSize);
|
||||||
|
|
||||||
|
launchInfo.cuLaunchConfig[0] = reinterpret_cast<void*>(0x01); // CU_LAUNCH_PARAM_BUFFER_POINTER
|
||||||
|
launchInfo.cuLaunchConfig[1] = launchInfo.params.data();
|
||||||
|
launchInfo.cuLaunchConfig[2] = reinterpret_cast<void*>(0x02); // CU_LAUNCH_PARAM_BUFFER_SIZE
|
||||||
|
launchInfo.cuLaunchConfig[3] = &launchInfo.paramSize; // yes, this actually requires a pointer to a size_t containing the parameter size
|
||||||
|
launchInfo.cuLaunchConfig[4] = reinterpret_cast<void*>(0x00); // CU_LAUNCH_PARAM_END
|
||||||
|
|
||||||
|
launchInfo.nvxLaunchInfo.function = cubinShader->cuFunction();
|
||||||
|
launchInfo.nvxLaunchInfo.gridDimX = GridX;
|
||||||
|
launchInfo.nvxLaunchInfo.gridDimY = GridY;
|
||||||
|
launchInfo.nvxLaunchInfo.gridDimZ = GridZ;
|
||||||
|
launchInfo.nvxLaunchInfo.blockDimX = cubinShader->blockDim().width;
|
||||||
|
launchInfo.nvxLaunchInfo.blockDimY = cubinShader->blockDim().height;
|
||||||
|
launchInfo.nvxLaunchInfo.blockDimZ = cubinShader->blockDim().depth;
|
||||||
|
launchInfo.nvxLaunchInfo.sharedMemBytes = 0;
|
||||||
|
launchInfo.nvxLaunchInfo.paramCount = 0;
|
||||||
|
launchInfo.nvxLaunchInfo.pParams = nullptr;
|
||||||
|
launchInfo.nvxLaunchInfo.extraCount = 1;
|
||||||
|
launchInfo.nvxLaunchInfo.pExtras = launchInfo.cuLaunchConfig.data();
|
||||||
|
|
||||||
|
launchInfo.shader = cubinShader;
|
||||||
|
|
||||||
|
/* Need to capture by value in case this gets called from a deferred context */
|
||||||
|
m_ctx->EmitCs([cLaunchInfo = std::move(launchInfo)] (DxvkContext* ctx) {
|
||||||
|
ctx->launchCuKernelNVX(cLaunchInfo.nvxLaunchInfo, cLaunchInfo.buffers, cLaunchInfo.images);
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
class D3D11DeviceContext;
|
class D3D11DeviceContext;
|
||||||
|
|
||||||
class D3D11DeviceContextExt : public ID3D11VkExtContext {
|
class D3D11DeviceContextExt : public ID3D11VkExtContext1 {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -57,6 +57,18 @@ namespace dxvk {
|
|||||||
void STDMETHODCALLTYPE SetBarrierControl(
|
void STDMETHODCALLTYPE SetBarrierControl(
|
||||||
UINT ControlFlags);
|
UINT ControlFlags);
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE LaunchCubinShaderNVX(
|
||||||
|
IUnknown* hShader,
|
||||||
|
uint32_t GridX,
|
||||||
|
uint32_t GridY,
|
||||||
|
uint32_t GridZ,
|
||||||
|
const void* pParams,
|
||||||
|
uint32_t paramSize,
|
||||||
|
void* const* pReadResources,
|
||||||
|
uint32_t NumReadResources,
|
||||||
|
void* const* pWriteResources,
|
||||||
|
uint32_t NumWriteResources);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
D3D11DeviceContext* m_ctx;
|
D3D11DeviceContext* m_ctx;
|
||||||
|
51
src/d3d11/d3d11_cuda.cpp
Normal file
51
src/d3d11/d3d11_cuda.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "d3d11_cuda.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
CubinShaderWrapper::CubinShaderWrapper(const Rc<dxvk::DxvkDevice>& dxvkDevice, VkCuModuleNVX cuModule, VkCuFunctionNVX cuFunction, VkExtent3D blockDim)
|
||||||
|
: m_dxvkDevice(dxvkDevice), m_module(cuModule), m_function(cuFunction), m_blockDim(blockDim) { };
|
||||||
|
|
||||||
|
|
||||||
|
CubinShaderWrapper::~CubinShaderWrapper() {
|
||||||
|
VkDevice vkDevice = m_dxvkDevice->handle();
|
||||||
|
m_dxvkDevice->vkd()->vkDestroyCuFunctionNVX(vkDevice, m_function, nullptr);
|
||||||
|
m_dxvkDevice->vkd()->vkDestroyCuModuleNVX(vkDevice, m_module, nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE CubinShaderWrapper::QueryInterface(REFIID riid, void **ppvObject) {
|
||||||
|
if (riid == __uuidof(IUnknown)) {
|
||||||
|
*ppvObject = ref(this);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::warn("CubinShaderWrapper::QueryInterface: Unknown interface query");
|
||||||
|
Logger::warn(str::format(riid));
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CubinShaderLaunchInfo::insertResource(ID3D11Resource* pResource, DxvkAccessFlags access) {
|
||||||
|
auto img = GetCommonTexture(pResource);
|
||||||
|
auto buf = GetCommonBuffer(pResource);
|
||||||
|
|
||||||
|
if (img)
|
||||||
|
insertUniqueResource(images, img->GetImage(), access);
|
||||||
|
if (buf)
|
||||||
|
insertUniqueResource(buffers, buf->GetBuffer(), access);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void CubinShaderLaunchInfo::insertUniqueResource(std::vector<std::pair<T, DxvkAccessFlags>>& list, const T& resource, DxvkAccessFlags access) {
|
||||||
|
for (auto& entry : list) {
|
||||||
|
if (entry.first == resource) {
|
||||||
|
entry.second.set(access);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list.push_back({ resource, access });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
83
src/d3d11/d3d11_cuda.h
Normal file
83
src/d3d11/d3d11_cuda.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../dxvk/dxvk_resource.h"
|
||||||
|
|
||||||
|
#include "../util/com/com_guid.h"
|
||||||
|
#include "../util/com/com_object.h"
|
||||||
|
|
||||||
|
#include "d3d11_buffer.h"
|
||||||
|
#include "d3d11_texture.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
class CubinShaderWrapper : public ComObject<IUnknown> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CubinShaderWrapper(const Rc<dxvk::DxvkDevice>& dxvkDevice, VkCuModuleNVX cuModule, VkCuFunctionNVX cuFunction, VkExtent3D blockDim);
|
||||||
|
~CubinShaderWrapper();
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
|
||||||
|
|
||||||
|
VkCuModuleNVX cuModule() const {
|
||||||
|
return m_module;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkCuFunctionNVX cuFunction() const {
|
||||||
|
return m_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkExtent3D blockDim() const {
|
||||||
|
return m_blockDim;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Rc<DxvkDevice> m_dxvkDevice;
|
||||||
|
VkCuModuleNVX m_module;
|
||||||
|
VkCuFunctionNVX m_function;
|
||||||
|
VkExtent3D m_blockDim;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct CubinShaderLaunchInfo {
|
||||||
|
|
||||||
|
CubinShaderLaunchInfo() = default;
|
||||||
|
|
||||||
|
CubinShaderLaunchInfo(CubinShaderLaunchInfo&& other) {
|
||||||
|
shader = std::move(other.shader);
|
||||||
|
params = std::move(other.params);
|
||||||
|
paramSize = std::move(other.paramSize);
|
||||||
|
nvxLaunchInfo = std::move(other.nvxLaunchInfo);
|
||||||
|
cuLaunchConfig = other.cuLaunchConfig;
|
||||||
|
buffers = std::move(other.buffers);
|
||||||
|
images = std::move(other.images);
|
||||||
|
other.cuLaunchConfig[1] = nullptr;
|
||||||
|
other.cuLaunchConfig[3] = nullptr;
|
||||||
|
other.nvxLaunchInfo.pExtras = nullptr;
|
||||||
|
// fix-up internally-pointing pointers
|
||||||
|
cuLaunchConfig[1] = params.data();
|
||||||
|
cuLaunchConfig[3] = ¶mSize;
|
||||||
|
nvxLaunchInfo.pExtras = cuLaunchConfig.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
Com<CubinShaderWrapper> shader;
|
||||||
|
std::vector<uint8_t> params;
|
||||||
|
size_t paramSize;
|
||||||
|
VkCuLaunchInfoNVX nvxLaunchInfo = { VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX };
|
||||||
|
std::array<void*, 5> cuLaunchConfig;
|
||||||
|
|
||||||
|
std::vector<std::pair<Rc<DxvkBuffer>, DxvkAccessFlags>> buffers;
|
||||||
|
std::vector<std::pair<Rc<DxvkImage>, DxvkAccessFlags>> images;
|
||||||
|
|
||||||
|
void insertResource(ID3D11Resource* pResource, DxvkAccessFlags access);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void insertUniqueResource(std::vector<std::pair<T, DxvkAccessFlags>>& list, const T& resource, DxvkAccessFlags access);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -2445,12 +2445,326 @@ namespace dxvk {
|
|||||||
case D3D11_VK_EXT_DEPTH_BOUNDS:
|
case D3D11_VK_EXT_DEPTH_BOUNDS:
|
||||||
return deviceFeatures.core.features.depthBounds;
|
return deviceFeatures.core.features.depthBounds;
|
||||||
|
|
||||||
|
case D3D11_VK_NVX_IMAGE_VIEW_HANDLE:
|
||||||
|
return deviceExtensions.nvxImageViewHandle;
|
||||||
|
|
||||||
|
case D3D11_VK_NVX_BINARY_IMPORT:
|
||||||
|
return deviceExtensions.nvxBinaryImport
|
||||||
|
&& deviceExtensions.khrBufferDeviceAddress;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE D3D11DeviceExt::GetCudaTextureObjectNVX(uint32_t srvDriverHandle, uint32_t samplerDriverHandle, uint32_t* pCudaTextureHandle) {
|
||||||
|
ID3D11ShaderResourceView* srv = HandleToSrvNVX(srvDriverHandle);
|
||||||
|
|
||||||
|
if (!srv) {
|
||||||
|
Logger::warn(str::format("GetCudaTextureObjectNVX() failure - srv handle wasn't found: ", srvDriverHandle));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D11SamplerState* samplerState = HandleToSamplerNVX(samplerDriverHandle);
|
||||||
|
|
||||||
|
if (!samplerState) {
|
||||||
|
Logger::warn(str::format("GetCudaTextureObjectNVX() failure - sampler handle wasn't found: ", samplerDriverHandle));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11SamplerState* pSS = static_cast<D3D11SamplerState*>(samplerState);
|
||||||
|
Rc<DxvkSampler> pDSS = pSS->GetDXVKSampler();
|
||||||
|
VkSampler vkSampler = pDSS->handle();
|
||||||
|
|
||||||
|
D3D11ShaderResourceView* pSRV = static_cast<D3D11ShaderResourceView*>(srv);
|
||||||
|
Rc<DxvkImageView> pIV = pSRV->GetImageView();
|
||||||
|
VkImageView vkImageView = pIV->handle();
|
||||||
|
|
||||||
|
VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
|
||||||
|
imageViewHandleInfo.imageView = vkImageView;
|
||||||
|
imageViewHandleInfo.sampler = vkSampler;
|
||||||
|
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
|
||||||
|
// note: there's no implicit lifetime management here; it's up to the
|
||||||
|
// app to keep the sampler and SRV alive as long as it wants to use this
|
||||||
|
// derived handle.
|
||||||
|
VkDevice vkDevice = m_device->GetDXVKDevice()->handle();
|
||||||
|
*pCudaTextureHandle = m_device->GetDXVKDevice()->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo);
|
||||||
|
|
||||||
|
if (!*pCudaTextureHandle) {
|
||||||
|
Logger::warn("GetCudaTextureObjectNVX() handle==0 - failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateCubinComputeShaderWithNameNVX(const void* pCubin, uint32_t size,
|
||||||
|
uint32_t blockX, uint32_t blockY, uint32_t blockZ, const char* pShaderName, IUnknown** phShader) {
|
||||||
|
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
|
||||||
|
VkDevice vkDevice = dxvkDevice->handle();
|
||||||
|
|
||||||
|
VkCuModuleCreateInfoNVX moduleCreateInfo = { VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX };
|
||||||
|
moduleCreateInfo.pData = pCubin;
|
||||||
|
moduleCreateInfo.dataSize = size;
|
||||||
|
|
||||||
|
VkCuModuleNVX cuModule;
|
||||||
|
VkCuFunctionNVX cuFunction;
|
||||||
|
VkResult result;
|
||||||
|
|
||||||
|
if ((result = dxvkDevice->vkd()->vkCreateCuModuleNVX(vkDevice, &moduleCreateInfo, nullptr, &cuModule))) {
|
||||||
|
Logger::warn(str::format("CreateCubinComputeShaderWithNameNVX() - failure to create module - result=", result, " pcubindata=", pCubin, " cubinsize=", size));
|
||||||
|
return false; // failure
|
||||||
|
}
|
||||||
|
|
||||||
|
VkCuFunctionCreateInfoNVX functionCreateInfo = { VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX };
|
||||||
|
functionCreateInfo.module = cuModule;
|
||||||
|
functionCreateInfo.pName = pShaderName;
|
||||||
|
|
||||||
|
if ((result = dxvkDevice->vkd()->vkCreateCuFunctionNVX(vkDevice, &functionCreateInfo, nullptr, &cuFunction))) {
|
||||||
|
dxvkDevice->vkd()->vkDestroyCuModuleNVX(vkDevice, cuModule, nullptr);
|
||||||
|
Logger::warn(str::format("CreateCubinComputeShaderWithNameNVX() - failure to create function - result=", result));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*phShader = ref(new CubinShaderWrapper(dxvkDevice,
|
||||||
|
cuModule, cuFunction, { blockX, blockY, blockZ }));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE D3D11DeviceExt::GetResourceHandleGPUVirtualAddressAndSizeNVX(void* hObject, uint64_t* gpuVAStart, uint64_t* gpuVASize) {
|
||||||
|
// The hObject 'opaque driver handle' is really just a straight cast
|
||||||
|
// of the corresponding ID3D11Resource* in dxvk/dxvknvapi
|
||||||
|
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));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
|
||||||
|
VkDevice vkDevice = dxvkDevice->handle();
|
||||||
|
|
||||||
|
if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
|
||||||
|
D3D11CommonTexture *texture = GetCommonTexture(pResource);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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...
|
||||||
|
|
||||||
|
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*gpuVAStart = imageViewAddressProperties.deviceAddress;
|
||||||
|
*gpuVASize = imageViewAddressProperties.size;
|
||||||
|
}
|
||||||
|
else if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
|
||||||
|
D3D11Buffer *buffer = GetCommonBuffer(pResource);
|
||||||
|
const DxvkBufferSliceHandle bufSliceHandle = buffer->GetBuffer()->getSliceHandle();
|
||||||
|
VkBuffer vkBuffer = bufSliceHandle.handle;
|
||||||
|
|
||||||
|
VkBufferDeviceAddressInfoKHR bdaInfo = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR };
|
||||||
|
bdaInfo.buffer = vkBuffer;
|
||||||
|
VkDeviceAddress bufAddr = dxvkDevice->vkd()->vkGetBufferDeviceAddressKHR(vkDevice, &bdaInfo);
|
||||||
|
*gpuVAStart = uint64_t(bufAddr) + bufSliceHandle.offset;
|
||||||
|
*gpuVASize = bufSliceHandle.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*gpuVAStart)
|
||||||
|
Logger::warn("GetResourceHandleGPUVirtualAddressAndSize() addr==0 - unexpected"); // ... but not explicitly a failure; continue
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateUnorderedAccessViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D11UnorderedAccessView** ppUAV, uint32_t* pDriverHandle) {
|
||||||
|
D3D11_COMMON_RESOURCE_DESC resourceDesc;
|
||||||
|
if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) {
|
||||||
|
Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
|
||||||
|
Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto texture = GetCommonTexture(pResource);
|
||||||
|
Rc<DxvkImage> dxvkImage = texture->GetImage();
|
||||||
|
if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))) {
|
||||||
|
Logger::warn(str::format("CreateUnorderedAccessViewAndGetDriverHandleNVX(res=", pResource, ") image info missing required usage bit(s); can't be used for vkGetImageViewHandleNVX - failure"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SUCCEEDED(m_device->CreateUnorderedAccessView(pResource, pDesc, ppUAV))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11UnorderedAccessView *pUAV = static_cast<D3D11UnorderedAccessView *>(*ppUAV);
|
||||||
|
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
|
||||||
|
VkDevice vkDevice = dxvkDevice->handle();
|
||||||
|
|
||||||
|
VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
|
||||||
|
Rc<DxvkImageView> dxvkImageView = pUAV->GetImageView();
|
||||||
|
VkImageView vkImageView = dxvkImageView->handle();
|
||||||
|
|
||||||
|
imageViewHandleInfo.imageView = vkImageView;
|
||||||
|
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||||
|
|
||||||
|
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo);
|
||||||
|
|
||||||
|
if (!*pDriverHandle) {
|
||||||
|
Logger::warn("CreateUnorderedAccessViewAndGetDriverHandleNVX() handle==0 - failure");
|
||||||
|
pUAV->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateShaderResourceViewAndGetDriverHandleNVX(ID3D11Resource* pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D11ShaderResourceView** ppSRV, uint32_t* pDriverHandle) {
|
||||||
|
D3D11_COMMON_RESOURCE_DESC resourceDesc;
|
||||||
|
if (!SUCCEEDED(GetCommonResourceDesc(pResource, &resourceDesc))) {
|
||||||
|
Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() - GetCommonResourceDesc() failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (resourceDesc.Dim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
|
||||||
|
Logger::warn(str::format("CreateShaderResourceViewAndGetDriverHandleNVX() - failure - unsupported dimension: ", resourceDesc.Dim));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto texture = GetCommonTexture(pResource);
|
||||||
|
Rc<DxvkImage> dxvkImage = texture->GetImage();
|
||||||
|
if (0 == (dxvkImage->info().usage & (VK_IMAGE_USAGE_STORAGE_BIT | 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"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SUCCEEDED(m_device->CreateShaderResourceView(pResource, pDesc, ppSRV))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11ShaderResourceView* pSRV = static_cast<D3D11ShaderResourceView*>(*ppSRV);
|
||||||
|
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
|
||||||
|
VkDevice vkDevice = dxvkDevice->handle();
|
||||||
|
|
||||||
|
VkImageViewHandleInfoNVX imageViewHandleInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX};
|
||||||
|
Rc<DxvkImageView> dxvkImageView = pSRV->GetImageView();
|
||||||
|
VkImageView vkImageView = dxvkImageView->handle();
|
||||||
|
|
||||||
|
imageViewHandleInfo.imageView = vkImageView;
|
||||||
|
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||||
|
|
||||||
|
*pDriverHandle = dxvkDevice->vkd()->vkGetImageViewHandleNVX(vkDevice, &imageViewHandleInfo);
|
||||||
|
|
||||||
|
if (!*pDriverHandle) {
|
||||||
|
Logger::warn("CreateShaderResourceViewAndGetDriverHandleNVX() handle==0 - failure");
|
||||||
|
pSRV->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// will need to look-up resource from uint32 handle later
|
||||||
|
AddSrvAndHandleNVX(*ppSRV, *pDriverHandle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE D3D11DeviceExt::CreateSamplerStateAndGetDriverHandleNVX(const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState, uint32_t* pDriverHandle) {
|
||||||
|
if (!SUCCEEDED(m_device->CreateSamplerState(pSamplerDesc, ppSamplerState))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for our purposes the actual value doesn't matter, only its uniqueness
|
||||||
|
static ULONG seqNum = 1;
|
||||||
|
*pDriverHandle = InterlockedIncrement(&seqNum);
|
||||||
|
|
||||||
|
// will need to look-up sampler from uint32 handle later
|
||||||
|
AddSamplerAndHandleNVX(*ppSamplerState, *pDriverHandle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11DeviceExt::AddSamplerAndHandleNVX(ID3D11SamplerState* pSampler, uint32_t Handle) {
|
||||||
|
std::lock_guard lock(m_mapLock);
|
||||||
|
m_samplerHandleToPtr[Handle] = pSampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ID3D11SamplerState* D3D11DeviceExt::HandleToSamplerNVX(uint32_t Handle) {
|
||||||
|
std::lock_guard lock(m_mapLock);
|
||||||
|
auto got = m_samplerHandleToPtr.find(Handle);
|
||||||
|
|
||||||
|
if (got == m_samplerHandleToPtr.end())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return static_cast<ID3D11SamplerState*>(got->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11DeviceExt::AddSrvAndHandleNVX(ID3D11ShaderResourceView* pSrv, uint32_t Handle) {
|
||||||
|
std::lock_guard lock(m_mapLock);
|
||||||
|
m_srvHandleToPtr[Handle] = pSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView* D3D11DeviceExt::HandleToSrvNVX(uint32_t Handle) {
|
||||||
|
std::lock_guard lock(m_mapLock);
|
||||||
|
auto got = m_srvHandleToPtr.find(Handle);
|
||||||
|
|
||||||
|
if (got == m_srvHandleToPtr.end())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return static_cast<ID3D11ShaderResourceView*>(got->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
D3D11VideoDevice::D3D11VideoDevice(
|
D3D11VideoDevice::D3D11VideoDevice(
|
||||||
@ -2827,7 +3141,8 @@ namespace dxvk {
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (riid == __uuidof(ID3D11VkExtDevice)) {
|
if (riid == __uuidof(ID3D11VkExtDevice)
|
||||||
|
|| riid == __uuidof(ID3D11VkExtDevice1)) {
|
||||||
*ppvObject = ref(&m_d3d11DeviceExt);
|
*ppvObject = ref(&m_d3d11DeviceExt);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "../util/com/com_private_data.h"
|
#include "../util/com/com_private_data.h"
|
||||||
|
|
||||||
#include "d3d11_cmdlist.h"
|
#include "d3d11_cmdlist.h"
|
||||||
|
#include "d3d11_cuda.h"
|
||||||
#include "d3d11_initializer.h"
|
#include "d3d11_initializer.h"
|
||||||
#include "d3d11_interfaces.h"
|
#include "d3d11_interfaces.h"
|
||||||
#include "d3d11_interop.h"
|
#include "d3d11_interop.h"
|
||||||
@ -494,7 +495,7 @@ namespace dxvk {
|
|||||||
/**
|
/**
|
||||||
* \brief Extended D3D11 device
|
* \brief Extended D3D11 device
|
||||||
*/
|
*/
|
||||||
class D3D11DeviceExt : public ID3D11VkExtDevice {
|
class D3D11DeviceExt : public ID3D11VkExtDevice1 {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -513,11 +514,64 @@ namespace dxvk {
|
|||||||
BOOL STDMETHODCALLTYPE GetExtensionSupport(
|
BOOL STDMETHODCALLTYPE GetExtensionSupport(
|
||||||
D3D11_VK_EXTENSION Extension);
|
D3D11_VK_EXTENSION Extension);
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE GetCudaTextureObjectNVX(
|
||||||
|
uint32_t srvDriverHandle,
|
||||||
|
uint32_t samplerDriverHandle,
|
||||||
|
uint32_t* pCudaTextureHandle);
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE CreateCubinComputeShaderWithNameNVX(
|
||||||
|
const void* pCubin,
|
||||||
|
uint32_t size,
|
||||||
|
uint32_t blockX,
|
||||||
|
uint32_t blockY,
|
||||||
|
uint32_t blockZ,
|
||||||
|
const char* pShaderName,
|
||||||
|
IUnknown** phShader);
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE GetResourceHandleGPUVirtualAddressAndSizeNVX(
|
||||||
|
void* hObject,
|
||||||
|
uint64_t* gpuVAStart,
|
||||||
|
uint64_t* gpuVASize);
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
|
||||||
|
ID3D11Resource* pResource,
|
||||||
|
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
|
||||||
|
ID3D11UnorderedAccessView** ppUAV,
|
||||||
|
uint32_t* pDriverHandle);
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
|
||||||
|
ID3D11Resource* pResource,
|
||||||
|
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
|
||||||
|
ID3D11ShaderResourceView** ppSRV,
|
||||||
|
uint32_t* pDriverHandle);
|
||||||
|
|
||||||
|
bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
|
||||||
|
const D3D11_SAMPLER_DESC* pSamplerDesc,
|
||||||
|
ID3D11SamplerState** ppSamplerState,
|
||||||
|
uint32_t* pDriverHandle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
D3D11DXGIDevice* m_container;
|
D3D11DXGIDevice* m_container;
|
||||||
D3D11Device* m_device;
|
D3D11Device* m_device;
|
||||||
|
|
||||||
|
void AddSamplerAndHandleNVX(
|
||||||
|
ID3D11SamplerState* pSampler,
|
||||||
|
uint32_t Handle);
|
||||||
|
|
||||||
|
ID3D11SamplerState* HandleToSamplerNVX(
|
||||||
|
uint32_t Handle);
|
||||||
|
|
||||||
|
void AddSrvAndHandleNVX(
|
||||||
|
ID3D11ShaderResourceView* pSrv,
|
||||||
|
uint32_t Handle);
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView* HandleToSrvNVX(
|
||||||
|
uint32_t Handle);
|
||||||
|
|
||||||
|
dxvk::mutex m_mapLock;
|
||||||
|
std::unordered_map<uint32_t, ID3D11SamplerState*> m_samplerHandleToPtr;
|
||||||
|
std::unordered_map<uint32_t, ID3D11ShaderResourceView*> m_srvHandleToPtr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -264,12 +264,7 @@ namespace dxvk {
|
|||||||
// Initialize the image on the GPU
|
// Initialize the image on the GPU
|
||||||
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
std::lock_guard<dxvk::mutex> lock(m_mutex);
|
||||||
|
|
||||||
VkImageSubresourceRange subresources;
|
VkImageSubresourceRange subresources = image->getAvailableSubresources();
|
||||||
subresources.aspectMask = image->formatInfo()->aspectMask;
|
|
||||||
subresources.baseMipLevel = 0;
|
|
||||||
subresources.levelCount = image->info().mipLevels;
|
|
||||||
subresources.baseArrayLayer = 0;
|
|
||||||
subresources.layerCount = image->info().numLayers;
|
|
||||||
|
|
||||||
m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_PREINITIALIZED);
|
m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_PREINITIALIZED);
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ enum D3D11_VK_EXTENSION : uint32_t {
|
|||||||
D3D11_VK_EXT_MULTI_DRAW_INDIRECT_COUNT = 1,
|
D3D11_VK_EXT_MULTI_DRAW_INDIRECT_COUNT = 1,
|
||||||
D3D11_VK_EXT_DEPTH_BOUNDS = 2,
|
D3D11_VK_EXT_DEPTH_BOUNDS = 2,
|
||||||
D3D11_VK_EXT_BARRIER_CONTROL = 3,
|
D3D11_VK_EXT_BARRIER_CONTROL = 3,
|
||||||
|
D3D11_VK_NVX_BINARY_IMPORT = 4,
|
||||||
|
D3D11_VK_NVX_IMAGE_VIEW_HANDLE = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -45,6 +47,54 @@ ID3D11VkExtDevice : public IUnknown {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Extended extended D3D11 device
|
||||||
|
*
|
||||||
|
* Introduces methods to get virtual addresses and driver
|
||||||
|
* handles for resources, and create and destroy objects
|
||||||
|
* for D3D11-Cuda interop.
|
||||||
|
*/
|
||||||
|
MIDL_INTERFACE("cfcf64ef-9586-46d0-bca4-97cf2ca61b06")
|
||||||
|
ID3D11VkExtDevice1 : public ID3D11VkExtDevice {
|
||||||
|
|
||||||
|
virtual bool STDMETHODCALLTYPE GetResourceHandleGPUVirtualAddressAndSizeNVX(
|
||||||
|
void* hObject,
|
||||||
|
uint64_t* gpuVAStart,
|
||||||
|
uint64_t* gpuVASize) = 0;
|
||||||
|
|
||||||
|
virtual bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
|
||||||
|
ID3D11Resource* pResource,
|
||||||
|
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
|
||||||
|
ID3D11UnorderedAccessView** ppUAV,
|
||||||
|
uint32_t* pDriverHandle) = 0;
|
||||||
|
|
||||||
|
virtual bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
|
||||||
|
ID3D11Resource* pResource,
|
||||||
|
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
|
||||||
|
ID3D11ShaderResourceView** ppSRV,
|
||||||
|
uint32_t* pDriverHandle) = 0;
|
||||||
|
|
||||||
|
virtual bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
|
||||||
|
const D3D11_SAMPLER_DESC* pSamplerDesc,
|
||||||
|
ID3D11SamplerState** ppSamplerState,
|
||||||
|
uint32_t* pDriverHandle) = 0;
|
||||||
|
|
||||||
|
virtual bool STDMETHODCALLTYPE CreateCubinComputeShaderWithNameNVX(
|
||||||
|
const void* pCubin,
|
||||||
|
uint32_t size,
|
||||||
|
uint32_t blockX,
|
||||||
|
uint32_t blockY,
|
||||||
|
uint32_t blockZ,
|
||||||
|
const char* pShaderName,
|
||||||
|
IUnknown** phShader) = 0;
|
||||||
|
|
||||||
|
virtual bool STDMETHODCALLTYPE GetCudaTextureObjectNVX(
|
||||||
|
uint32_t srvDriverHandle,
|
||||||
|
uint32_t samplerDriverHandle,
|
||||||
|
uint32_t* pCudaTextureHandle) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Extended D3D11 context
|
* \brief Extended D3D11 context
|
||||||
*
|
*
|
||||||
@ -88,13 +138,39 @@ ID3D11VkExtContext : public IUnknown {
|
|||||||
|
|
||||||
virtual void STDMETHODCALLTYPE SetBarrierControl(
|
virtual void STDMETHODCALLTYPE SetBarrierControl(
|
||||||
UINT ControlFlags) = 0;
|
UINT ControlFlags) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Extended extended D3D11 context
|
||||||
|
*
|
||||||
|
* Provides functionality to launch a Cuda kernel
|
||||||
|
*/
|
||||||
|
MIDL_INTERFACE("874b09b2-ae0b-41d8-8476-5f3b7a0e879d")
|
||||||
|
ID3D11VkExtContext1 : public ID3D11VkExtContext {
|
||||||
|
|
||||||
|
virtual bool STDMETHODCALLTYPE LaunchCubinShaderNVX(
|
||||||
|
IUnknown* hShader,
|
||||||
|
uint32_t gridX,
|
||||||
|
uint32_t gridY,
|
||||||
|
uint32_t gridZ,
|
||||||
|
const void* pParams,
|
||||||
|
uint32_t paramSize,
|
||||||
|
void* const* pReadResources,
|
||||||
|
uint32_t numReadResources,
|
||||||
|
void* const* pWriteResources,
|
||||||
|
uint32_t numWriteResources) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
struct __declspec(uuid("8a6e3c42-f74c-45b7-8265-a231b677ca17")) ID3D11VkExtDevice;
|
struct __declspec(uuid("8a6e3c42-f74c-45b7-8265-a231b677ca17")) ID3D11VkExtDevice;
|
||||||
|
struct __declspec(uuid("cfcf64ef-9586-46d0-bca4-97cf2ca61b06")) ID3D11VkExtDevice1;
|
||||||
struct __declspec(uuid("fd0bca13-5cb6-4c3a-987e-4750de2ca791")) ID3D11VkExtContext;
|
struct __declspec(uuid("fd0bca13-5cb6-4c3a-987e-4750de2ca791")) ID3D11VkExtContext;
|
||||||
|
struct __declspec(uuid("874b09b2-ae0b-41d8-8476-5f3b7a0e879d")) ID3D11VkExtContext1;
|
||||||
#else
|
#else
|
||||||
__CRT_UUID_DECL(ID3D11VkExtDevice, 0x8a6e3c42,0xf74c,0x45b7,0x82,0x65,0xa2,0x31,0xb6,0x77,0xca,0x17);
|
__CRT_UUID_DECL(ID3D11VkExtDevice, 0x8a6e3c42,0xf74c,0x45b7,0x82,0x65,0xa2,0x31,0xb6,0x77,0xca,0x17);
|
||||||
|
__CRT_UUID_DECL(ID3D11VkExtDevice1, 0xcfcf64ef,0x9586,0x46d0,0xbc,0xa4,0x97,0xcf,0x2c,0xa6,0x1b,0x06);
|
||||||
__CRT_UUID_DECL(ID3D11VkExtContext, 0xfd0bca13,0x5cb6,0x4c3a,0x98,0x7e,0x47,0x50,0xde,0x2c,0xa7,0x91);
|
__CRT_UUID_DECL(ID3D11VkExtContext, 0xfd0bca13,0x5cb6,0x4c3a,0x98,0x7e,0x47,0x50,0xde,0x2c,0xa7,0x91);
|
||||||
|
__CRT_UUID_DECL(ID3D11VkExtContext1, 0x874b09b2,0xae0b,0x41d8,0x84,0x76,0x5f,0x3b,0x7a,0x0e,0x87,0x9d);
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,6 +33,7 @@ d3d11_src = [
|
|||||||
'd3d11_context_def.cpp',
|
'd3d11_context_def.cpp',
|
||||||
'd3d11_context_ext.cpp',
|
'd3d11_context_ext.cpp',
|
||||||
'd3d11_context_imm.cpp',
|
'd3d11_context_imm.cpp',
|
||||||
|
'd3d11_cuda.cpp',
|
||||||
'd3d11_depth_stencil.cpp',
|
'd3d11_depth_stencil.cpp',
|
||||||
'd3d11_device.cpp',
|
'd3d11_device.cpp',
|
||||||
'd3d11_enums.cpp',
|
'd3d11_enums.cpp',
|
||||||
|
@ -263,7 +263,7 @@ namespace dxvk {
|
|||||||
DxvkDeviceFeatures enabledFeatures) {
|
DxvkDeviceFeatures enabledFeatures) {
|
||||||
DxvkDeviceExtensions devExtensions;
|
DxvkDeviceExtensions devExtensions;
|
||||||
|
|
||||||
std::array<DxvkExt*, 25> devExtensionList = {{
|
std::array<DxvkExt*, 28> devExtensionList = {{
|
||||||
&devExtensions.amdMemoryOverallocationBehaviour,
|
&devExtensions.amdMemoryOverallocationBehaviour,
|
||||||
&devExtensions.amdShaderFragmentMask,
|
&devExtensions.amdShaderFragmentMask,
|
||||||
&devExtensions.ext4444Formats,
|
&devExtensions.ext4444Formats,
|
||||||
@ -289,8 +289,17 @@ namespace dxvk {
|
|||||||
&devExtensions.khrSamplerMirrorClampToEdge,
|
&devExtensions.khrSamplerMirrorClampToEdge,
|
||||||
&devExtensions.khrShaderFloatControls,
|
&devExtensions.khrShaderFloatControls,
|
||||||
&devExtensions.khrSwapchain,
|
&devExtensions.khrSwapchain,
|
||||||
|
&devExtensions.nvxBinaryImport,
|
||||||
|
&devExtensions.nvxImageViewHandle,
|
||||||
|
&devExtensions.khrBufferDeviceAddress,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
// VK_KHR_buffer_device_address can be expensive to enable on
|
||||||
|
// some drivers; only enable selectively for Cuda interop
|
||||||
|
if (m_deviceExtensions.supports(devExtensions.nvxBinaryImport.name()) &&
|
||||||
|
m_deviceExtensions.supports(devExtensions.nvxImageViewHandle.name()))
|
||||||
|
devExtensions.khrBufferDeviceAddress.setMode(DxvkExtMode::Optional);
|
||||||
|
|
||||||
DxvkNameSet extensionsEnabled;
|
DxvkNameSet extensionsEnabled;
|
||||||
|
|
||||||
if (!m_deviceExtensions.enableExtensions(
|
if (!m_deviceExtensions.enableExtensions(
|
||||||
|
@ -340,6 +340,9 @@ namespace dxvk {
|
|||||||
pSizes, pStrides);
|
pSizes, pStrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmdLaunchCuKernel(VkCuLaunchInfoNVX launchInfo) {
|
||||||
|
m_vkd->vkCmdCuLaunchKernelNVX(m_execBuffer, &launchInfo);
|
||||||
|
}
|
||||||
|
|
||||||
void cmdBlitImage(
|
void cmdBlitImage(
|
||||||
VkImage srcImage,
|
VkImage srcImage,
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "dxvk_device.h"
|
#include "dxvk_device.h"
|
||||||
#include "dxvk_context.h"
|
#include "dxvk_context.h"
|
||||||
@ -302,12 +304,7 @@ namespace dxvk {
|
|||||||
if (image->info().layout != layout) {
|
if (image->info().layout != layout) {
|
||||||
this->spillRenderPass(true);
|
this->spillRenderPass(true);
|
||||||
|
|
||||||
VkImageSubresourceRange subresources;
|
VkImageSubresourceRange subresources = image->getAvailableSubresources();
|
||||||
subresources.aspectMask = image->formatInfo()->aspectMask;
|
|
||||||
subresources.baseArrayLayer = 0;
|
|
||||||
subresources.baseMipLevel = 0;
|
|
||||||
subresources.layerCount = image->info().numLayers;
|
|
||||||
subresources.levelCount = image->info().mipLevels;
|
|
||||||
|
|
||||||
this->prepareImage(m_execBarriers, image, subresources);
|
this->prepareImage(m_execBarriers, image, subresources);
|
||||||
|
|
||||||
@ -2610,6 +2607,73 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::launchCuKernelNVX(
|
||||||
|
const VkCuLaunchInfoNVX& nvxLaunchInfo,
|
||||||
|
const std::vector<std::pair<Rc<DxvkBuffer>, DxvkAccessFlags>>& buffers,
|
||||||
|
const std::vector<std::pair<Rc<DxvkImage>, DxvkAccessFlags>>& images) {
|
||||||
|
// The resources in the std::vectors above are called-out
|
||||||
|
// explicitly in the API for barrier and tracking purposes
|
||||||
|
// since they're being used bindlessly.
|
||||||
|
this->spillRenderPass(true);
|
||||||
|
|
||||||
|
VkPipelineStageFlags srcStages = 0;
|
||||||
|
VkAccessFlags srcAccess = 0;
|
||||||
|
|
||||||
|
for (auto& r : buffers) {
|
||||||
|
srcStages |= r.first->info().stages;
|
||||||
|
srcAccess |= r.first->info().access;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& r : images) {
|
||||||
|
srcStages |= r.first->info().stages;
|
||||||
|
srcAccess |= r.first->info().access;
|
||||||
|
|
||||||
|
this->prepareImage(m_execBarriers, r.first, r.first->getAvailableSubresources());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_execBarriers.accessMemory(srcStages, srcAccess,
|
||||||
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
|
||||||
|
m_execBarriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
|
m_cmd->cmdLaunchCuKernel(nvxLaunchInfo);
|
||||||
|
|
||||||
|
for (auto& r : buffers) {
|
||||||
|
VkAccessFlags accessFlags = (r.second.test(DxvkAccess::Read) * VK_ACCESS_SHADER_READ_BIT)
|
||||||
|
| (r.second.test(DxvkAccess::Write) * VK_ACCESS_SHADER_WRITE_BIT);
|
||||||
|
DxvkBufferSliceHandle bufferSlice = r.first->getSliceHandle();
|
||||||
|
m_execBarriers.accessBuffer(bufferSlice,
|
||||||
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
accessFlags,
|
||||||
|
r.first->info().stages,
|
||||||
|
r.first->info().access);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& r : images) {
|
||||||
|
VkAccessFlags accessFlags = (r.second.test(DxvkAccess::Read) * VK_ACCESS_SHADER_READ_BIT)
|
||||||
|
| (r.second.test(DxvkAccess::Write) * VK_ACCESS_SHADER_WRITE_BIT);
|
||||||
|
m_execBarriers.accessImage(r.first,
|
||||||
|
r.first->getAvailableSubresources(),
|
||||||
|
r.first->info().layout,
|
||||||
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
accessFlags,
|
||||||
|
r.first->info().layout,
|
||||||
|
r.first->info().stages,
|
||||||
|
r.first->info().access);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& r : images) {
|
||||||
|
if (r.second.test(DxvkAccess::Read)) m_cmd->trackResource<DxvkAccess::Read>(r.first);
|
||||||
|
if (r.second.test(DxvkAccess::Write)) m_cmd->trackResource<DxvkAccess::Write>(r.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& r : buffers) {
|
||||||
|
if (r.second.test(DxvkAccess::Read)) m_cmd->trackResource<DxvkAccess::Read>(r.first);
|
||||||
|
if (r.second.test(DxvkAccess::Write)) m_cmd->trackResource<DxvkAccess::Write>(r.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::writeTimestamp(const Rc<DxvkGpuQuery>& query) {
|
void DxvkContext::writeTimestamp(const Rc<DxvkGpuQuery>& query) {
|
||||||
m_queryManager.writeTimestamp(m_cmd, query);
|
m_queryManager.writeTimestamp(m_cmd, query);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "dxvk_context_state.h"
|
#include "dxvk_context_state.h"
|
||||||
#include "dxvk_data.h"
|
#include "dxvk_data.h"
|
||||||
#include "dxvk_objects.h"
|
#include "dxvk_objects.h"
|
||||||
|
#include "dxvk_resource.h"
|
||||||
#include "dxvk_util.h"
|
#include "dxvk_util.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
@ -988,6 +989,23 @@ namespace dxvk {
|
|||||||
void setBarrierControl(
|
void setBarrierControl(
|
||||||
DxvkBarrierControlFlags control);
|
DxvkBarrierControlFlags control);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Launches a Cuda kernel
|
||||||
|
*
|
||||||
|
* Since the kernel is launched with an opaque set of
|
||||||
|
* kernel-specific parameters which may reference
|
||||||
|
* resources bindlessly, such resources must be listed by
|
||||||
|
* the caller in the 'buffers' and 'images' parameters so
|
||||||
|
* that their access may be tracked appropriately.
|
||||||
|
* \param [in] nvxLaunchInfo Kernel launch parameter struct
|
||||||
|
* \param [in] buffers List of {buffer,read,write} used by kernel
|
||||||
|
* \param [in] images List of {image,read,write} used by kernel
|
||||||
|
*/
|
||||||
|
void launchCuKernelNVX(
|
||||||
|
const VkCuLaunchInfoNVX& nvxLaunchInfo,
|
||||||
|
const std::vector<std::pair<Rc<DxvkBuffer>, DxvkAccessFlags>>& buffers,
|
||||||
|
const std::vector<std::pair<Rc<DxvkImage>, DxvkAccessFlags>>& images);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Signals a GPU event
|
* \brief Signals a GPU event
|
||||||
* \param [in] event The event
|
* \param [in] event The event
|
||||||
|
@ -283,6 +283,9 @@ namespace dxvk {
|
|||||||
DxvkExt khrSamplerMirrorClampToEdge = { VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, DxvkExtMode::Optional };
|
DxvkExt khrSamplerMirrorClampToEdge = { VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, DxvkExtMode::Optional };
|
||||||
DxvkExt khrShaderFloatControls = { VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, DxvkExtMode::Optional };
|
DxvkExt khrShaderFloatControls = { VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, DxvkExtMode::Optional };
|
||||||
DxvkExt khrSwapchain = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtMode::Required };
|
DxvkExt khrSwapchain = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtMode::Required };
|
||||||
|
DxvkExt nvxBinaryImport = { VK_NVX_BINARY_IMPORT_EXTENSION_NAME, DxvkExtMode::Optional };
|
||||||
|
DxvkExt nvxImageViewHandle = { VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, DxvkExtMode::Optional };
|
||||||
|
DxvkExt khrBufferDeviceAddress = { VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, DxvkExtMode::Disabled };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -299,6 +299,21 @@ namespace dxvk {
|
|||||||
return m_image.memory.length();
|
return m_image.memory.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get full subresource range of the image
|
||||||
|
*
|
||||||
|
* \returns Resource range of the whole image
|
||||||
|
*/
|
||||||
|
VkImageSubresourceRange getAvailableSubresources() const {
|
||||||
|
VkImageSubresourceRange result;
|
||||||
|
result.aspectMask = formatInfo()->aspectMask;
|
||||||
|
result.baseMipLevel = 0;
|
||||||
|
result.levelCount = info().mipLevels;
|
||||||
|
result.baseArrayLayer = 0;
|
||||||
|
result.layerCount = info().numLayers;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Rc<vk::DeviceFn> m_vkd;
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
|
@ -347,6 +347,23 @@ namespace dxvk::vk {
|
|||||||
VULKAN_FN(vkCmdBeginQueryIndexedEXT);
|
VULKAN_FN(vkCmdBeginQueryIndexedEXT);
|
||||||
VULKAN_FN(vkCmdEndQueryIndexedEXT);
|
VULKAN_FN(vkCmdEndQueryIndexedEXT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef VK_NVX_image_view_handle
|
||||||
|
VULKAN_FN(vkGetImageViewHandleNVX);
|
||||||
|
VULKAN_FN(vkGetImageViewAddressNVX);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VK_NVX_binary_import
|
||||||
|
VULKAN_FN(vkCreateCuModuleNVX);
|
||||||
|
VULKAN_FN(vkCreateCuFunctionNVX);
|
||||||
|
VULKAN_FN(vkDestroyCuModuleNVX);
|
||||||
|
VULKAN_FN(vkDestroyCuFunctionNVX);
|
||||||
|
VULKAN_FN(vkCmdCuLaunchKernelNVX);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VK_KHR_buffer_device_address
|
||||||
|
VULKAN_FN(vkGetBufferDeviceAddressKHR);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user