Browse Source

Implemented FSR2 for Vulkan, along with some initial bits for DX11

fsr2
Nico de Poel 1 year ago
parent
commit
112beaa592
  1. 166
      FSR2UnityPlugin.cpp
  2. 26
      FSR2UnityTypes.h

166
FSR2UnityPlugin.cpp

@ -28,7 +28,9 @@ static const int32_t BaseEventId = 0;
static IUnityInterfaces* s_UnityInterfaces = nullptr; static IUnityInterfaces* s_UnityInterfaces = nullptr;
static IUnityLog* s_Log = nullptr; static IUnityLog* s_Log = nullptr;
static IUnityGraphics* s_Graphics = nullptr; static IUnityGraphics* s_Graphics = nullptr;
static IUnityGraphicsD3D11* s_GraphicsD3D11 = nullptr;
static IUnityGraphicsD3D12v7* s_GraphicsD3D12 = nullptr; static IUnityGraphicsD3D12v7* s_GraphicsD3D12 = nullptr;
static IUnityGraphicsVulkanV2* s_GraphicsVulkan = nullptr;
static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull; static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull;
static FfxDevice s_Device = nullptr; static FfxDevice s_Device = nullptr;
@ -80,6 +82,16 @@ static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType ev
s_RendererType = s_Graphics->GetRenderer(); s_RendererType = s_Graphics->GetRenderer();
switch (s_RendererType) switch (s_RendererType)
{ {
case kUnityGfxRendererD3D11:
{
s_GraphicsD3D11 = s_UnityInterfaces->Get<IUnityGraphicsD3D11>();
if (s_GraphicsD3D11 == nullptr)
{
UNITY_LOG_ERROR(s_Log, "Could not obtain D3D11 Graphics interface!");
return;
}
break;
}
case kUnityGfxRendererD3D12: case kUnityGfxRendererD3D12:
{ {
s_GraphicsD3D12 = s_UnityInterfaces->Get<IUnityGraphicsD3D12v7>(); s_GraphicsD3D12 = s_UnityInterfaces->Get<IUnityGraphicsD3D12v7>();
@ -90,13 +102,25 @@ static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType ev
} }
break; break;
} }
case kUnityGfxRendererVulkan:
{
s_GraphicsVulkan = s_UnityInterfaces->Get<IUnityGraphicsVulkanV2>();
if (s_GraphicsVulkan == nullptr)
{
UNITY_LOG_ERROR(s_Log, "Could not obtain Vulkan Graphics interface!");
return;
}
break;
}
}; };
break; break;
} }
case kUnityGfxDeviceEventShutdown: case kUnityGfxDeviceEventShutdown:
{ {
s_GraphicsVulkan = nullptr;
s_GraphicsD3D12 = nullptr; s_GraphicsD3D12 = nullptr;
s_GraphicsD3D11 = nullptr;
s_RendererType = kUnityGfxRendererNull; s_RendererType = kUnityGfxRendererNull;
break; break;
} }
@ -139,9 +163,28 @@ static void FreeFeatureSlot(uint32_t featureSlot)
memset(&s_Features[featureSlot], 0, sizeof(FSR2Feature)); memset(&s_Features[featureSlot], 0, sizeof(FSR2Feature));
} }
static PFN_vkVoidFunction GetVulkanDeviceProcAddr(VkDevice device, const char* pName)
{
UnityVulkanInstance instance = s_GraphicsVulkan->Instance();
return instance.getInstanceProcAddr(instance.instance, pName);
}
extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi() extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi()
{ {
if (s_GraphicsD3D12 != nullptr)
if (s_GraphicsD3D11 != nullptr)
{
//ID3D11Device* device = s_GraphicsD3D11->GetDevice();
//if (device == nullptr)
// return false;
//s_Device = ffxGetDeviceDX11(device);
//size_t scratchBufferSize = ffxFsr2GetScratchMemorySizeDX11();
//void* scratchBuffer = malloc(scratchBufferSize);
//ffxFsr2GetInterfaceDX11(&s_Fsr2Interface, device, scratchBuffer, scratchBufferSize);
//return true;
}
else if (s_GraphicsD3D12 != nullptr)
{ {
ID3D12Device* device = s_GraphicsD3D12->GetDevice(); ID3D12Device* device = s_GraphicsD3D12->GetDevice();
if (device == nullptr) if (device == nullptr)
@ -154,6 +197,19 @@ extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_InitApi()
ffxFsr2GetInterfaceDX12(&s_Fsr2Interface, device, scratchBuffer, scratchBufferSize); ffxFsr2GetInterfaceDX12(&s_Fsr2Interface, device, scratchBuffer, scratchBufferSize);
return true; return true;
} }
else if (s_GraphicsVulkan != nullptr)
{
UnityVulkanInstance instance = s_GraphicsVulkan->Instance();
if (instance.device == nullptr)
return false;
s_Device = ffxGetDeviceVK(instance.device);
size_t scratchBufferSize = ffxFsr2GetScratchMemorySizeVK(instance.physicalDevice);
void* scratchBuffer = malloc(scratchBufferSize);
ffxFsr2GetInterfaceVK(&s_Fsr2Interface, scratchBuffer, scratchBufferSize, instance.physicalDevice, &GetVulkanDeviceProcAddr);
return true;
}
return false; return false;
} }
@ -232,6 +288,37 @@ extern "C" int32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API AMDUP_GetBaseEvent
return BaseEventId; return BaseEventId;
} }
static FfxResource GetVulkanTextureResource(UnityVulkanInstance& instance, FSR2Feature& feature, FSR2TextureDesc& texture, FfxResourceStates state = FFX_RESOURCE_STATE_COMPUTE_READ)
{
VkImageView imageView = nullptr;
if (texture.image != 0)
{
VkImageViewCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = (VkImage)texture.image;
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = (VkFormat)texture.format;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(instance.device, &createInfo, nullptr, &imageView);
}
texture.view = (intptr_t)imageView;
return ffxGetTextureResourceVK(&feature.upscalingContext, (VkImage)texture.image, imageView, texture.width, texture.height, (VkFormat)texture.format, nullptr, state);
}
static void DestroyVulkanImageView(UnityVulkanInstance& instance, FSR2TextureDesc& texture)
{
if (texture.view == 0)
return;
vkDestroyImageView(instance.device, (VkImageView)texture.view, nullptr);
texture.view = 0;
}
// Plugin function to handle a specific rendering event // Plugin function to handle a specific rendering event
static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data) static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
{ {
@ -271,13 +358,28 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
s_GraphicsD3D12->CommandRecordingState(&state); s_GraphicsD3D12->CommandRecordingState(&state);
dispatchDescription.commandList = ffxGetCommandListDX12(state.commandList); dispatchDescription.commandList = ffxGetCommandListDX12(state.commandList);
dispatchDescription.color = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.colorInput);
dispatchDescription.depth = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.depth);
dispatchDescription.motionVectors = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.motionVectors);
dispatchDescription.exposure = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.exposureTexture);
dispatchDescription.reactive = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.reactiveMask);
dispatchDescription.transparencyAndComposition = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.transparencyMask);
dispatchDescription.output = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.colorOutput, nullptr, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
dispatchDescription.color = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.colorInput.image);
dispatchDescription.depth = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.depth.image);
dispatchDescription.motionVectors = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.motionVectors.image);
dispatchDescription.exposure = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.exposureTexture.image);
dispatchDescription.reactive = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.reactiveMask.image);
dispatchDescription.transparencyAndComposition = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.transparencyMask.image);
dispatchDescription.output = ffxGetResourceDX12(&feature.upscalingContext, (ID3D12Resource*)feature.textureTable.colorOutput.image, nullptr, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
}
else if (s_GraphicsVulkan != nullptr)
{
UnityVulkanRecordingState state;
s_GraphicsVulkan->CommandRecordingState(&state, kUnityVulkanGraphicsQueueAccess_DontCare);
dispatchDescription.commandList = ffxGetCommandListVK(state.commandBuffer);
UnityVulkanInstance instance = s_GraphicsVulkan->Instance();
dispatchDescription.color = GetVulkanTextureResource(instance, feature, feature.textureTable.colorInput);
dispatchDescription.depth = GetVulkanTextureResource(instance, feature, feature.textureTable.depth);
dispatchDescription.motionVectors = GetVulkanTextureResource(instance, feature, feature.textureTable.motionVectors);
dispatchDescription.exposure = GetVulkanTextureResource(instance, feature, feature.textureTable.exposureTexture);
dispatchDescription.reactive = GetVulkanTextureResource(instance, feature, feature.textureTable.reactiveMask);
dispatchDescription.transparencyAndComposition = GetVulkanTextureResource(instance, feature, feature.textureTable.transparencyMask);
dispatchDescription.output = GetVulkanTextureResource(instance, feature, feature.textureTable.colorOutput, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
} }
dispatchDescription.jitterOffset.x = params->jitterOffsetX; dispatchDescription.jitterOffset.x = params->jitterOffsetX;
@ -310,6 +412,23 @@ static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data)
case BaseEventId + FSR2PluginEvent::ePostExecute: case BaseEventId + FSR2PluginEvent::ePostExecute:
{ {
auto* params = (FSR2CommandExecutionData*)data; auto* params = (FSR2CommandExecutionData*)data;
if (params->featureSlot < 0 || params->featureSlot >= s_Features.size())
return;
auto& feature = s_Features[params->featureSlot];
if (s_GraphicsVulkan != nullptr)
{
UnityVulkanInstance instance = s_GraphicsVulkan->Instance();
DestroyVulkanImageView(instance, feature.textureTable.colorInput);
DestroyVulkanImageView(instance, feature.textureTable.depth);
DestroyVulkanImageView(instance, feature.textureTable.motionVectors);
DestroyVulkanImageView(instance, feature.textureTable.exposureTexture);
DestroyVulkanImageView(instance, feature.textureTable.reactiveMask);
DestroyVulkanImageView(instance, feature.textureTable.transparencyMask);
DestroyVulkanImageView(instance, feature.textureTable.colorOutput);
}
break; break;
} }
case BaseEventId + FSR2PluginEvent::eInit: case BaseEventId + FSR2PluginEvent::eInit:
@ -361,15 +480,36 @@ static void UNITY_INTERFACE_API OnSetTextureEvent(int eventID, void* data)
} }
case kUnityRenderingExtEventUpdateTextureEndV2: case kUnityRenderingExtEventUpdateTextureEndV2:
{ {
intptr_t texturePtr = 0;
// We organized the texture table struct to be ordered the same as the texture slot enum
// This way we can use the texture slot value simply as a pointer offset into the texture table
FSR2TextureDesc* textureDesc = ((FSR2TextureDesc*)&feature.textureTable) + textureSlot;
if (s_GraphicsD3D12 != nullptr) if (s_GraphicsD3D12 != nullptr)
{ {
texturePtr = (intptr_t)s_GraphicsD3D12->TextureFromNativeTexture((UnityTextureID)params->textureID);
textureDesc->image = (intptr_t)s_GraphicsD3D12->TextureFromNativeTexture((UnityTextureID)params->textureID);
}
else if (s_GraphicsVulkan != nullptr)
{
VkAccessFlags accessFlags = (textureSlot == FSR2Textures::tColorOutput) ? VK_ACCESS_SHADER_WRITE_BIT : VK_ACCESS_SHADER_READ_BIT;
UnityVulkanImage image;
if (s_GraphicsVulkan->AccessTextureByID((UnityTextureID)params->textureID, UnityVulkanWholeImage,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, accessFlags,
kUnityVulkanResourceAccess_PipelineBarrier, &image))
{
textureDesc->image = (intptr_t)image.image;
textureDesc->view = 0;
textureDesc->width = params->width;
textureDesc->height = params->height;
textureDesc->format = (uint32_t)image.format;
}
else
{
textureDesc->image = 0;
textureDesc->view = 0;
}
} }
// We organized the texture table struct to be ordered the same as the texture slot enum
// This way we can use the texture slot value simply as a pointer offset into the texture table
*(((intptr_t*)&feature.textureTable) + textureSlot) = texturePtr;
break; break;
} }
} }

26
FSR2UnityTypes.h

@ -59,14 +59,24 @@ struct FSR2CommandExecutionData
uint32_t featureSlot; uint32_t featureSlot;
}; };
struct FSR2TextureDesc
{
intptr_t image;
intptr_t view;
uint32_t width;
uint32_t height;
uint32_t format;
};
struct FSR2TextureTable struct FSR2TextureTable
{ {
intptr_t colorInput;
intptr_t colorOutput;
intptr_t depth;
intptr_t motionVectors;
intptr_t transparencyMask;
intptr_t exposureTexture;
intptr_t reactiveMask;
intptr_t biasColorMask;
FSR2TextureDesc colorInput;
FSR2TextureDesc colorOutput;
FSR2TextureDesc depth;
FSR2TextureDesc motionVectors;
FSR2TextureDesc transparencyMask;
FSR2TextureDesc exposureTexture;
FSR2TextureDesc reactiveMask;
FSR2TextureDesc biasColorMask;
}; };
Loading…
Cancel
Save