Browse Source

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

fsr2
Nico de Poel 11 months 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