Skip to content

Commit

Permalink
[Renderer] Added support for SPD in AMD_FidelityFX (not used yet)
Browse files Browse the repository at this point in the history
  • Loading branch information
PanosK92 committed Jul 22, 2023
1 parent c0639c7 commit 017f397
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 45 deletions.
6 changes: 4 additions & 2 deletions build_scripts/premake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ API_LIBRARIES = {
"spirv-cross-hlsl",
"spirv-cross-reflect",
"ffx_backend_vk",
"ffx_fsr2"
"ffx_fsr2",
"ffx_spd"
},
debug = {
"spirv-cross-c_debug",
Expand All @@ -72,7 +73,8 @@ API_LIBRARIES = {
"spirv-cross-hlsl_debug",
"spirv-cross-reflect_debug",
"ffx_backend_vk_debug",
"ffx_fsr2_debug"
"ffx_fsr2_debug",
"ffx_spd_debug"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion license.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright(c) 2016-2022 Panos Karabelas
Copyright(c) 2016-2023 Panos Karabelas

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
5 changes: 4 additions & 1 deletion runtime/RHI/RHI_AMD_FidelityFX.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,12 @@ namespace Spartan
static void Initialize();
static void Destroy();

// SPD
static void SPD_Dispatch(RHI_CommandList* cmd_list, RHI_Texture* texture);

// FSR 2
static void FSR2_ResetHistory();
static void OnResize(const Math::Vector2& resolution_render, const Math::Vector2& resolution_output);
static void FSR2_Resize(const Math::Vector2& resolution_render, const Math::Vector2& resolution_output);
static void FSR2_GenerateJitterSample(float* x, float* y);
static void FSR2_Dispatch(
RHI_CommandList* cmd_list,
Expand Down
18 changes: 9 additions & 9 deletions runtime/RHI/RHI_Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ namespace Spartan
RHI_Texture_Slice& GetSlice(const uint32_t array_index);

// Flags
bool IsSrv() const { return m_flags & RHI_Texture_Srv; }
bool IsUav() const { return m_flags & RHI_Texture_Uav; }
bool IsRenderTarget() const { return m_flags & RHI_Texture_RenderTarget; }
bool IsRenderTargetDepthStencil() const { return IsRenderTarget() && IsDepthStencilFormat(); }
bool IsRenderTargetColor() const { return IsRenderTarget() && IsColorFormat(); }
bool HasPerMipViews() const { return m_flags & RHI_Texture_PerMipViews; }
bool HasMips() const { return m_flags & RHI_Texture_Mips; }
bool IsGrayscale() const { return m_flags & RHI_Texture_Greyscale; }
bool IsTransparent() const { return m_flags & RHI_Texture_Transparent; }
bool IsSrv() const { return m_flags & RHI_Texture_Srv; }
bool IsUav() const { return m_flags & RHI_Texture_Uav; }
bool IsRenderTarget() const { return m_flags & RHI_Texture_RenderTarget; }
bool IsRenderTargetDepthStencil() const { return IsRenderTarget() && IsDepthStencilFormat(); }
bool IsRenderTargetColor() const { return IsRenderTarget() && IsColorFormat(); }
bool HasPerMipViews() const { return m_flags & RHI_Texture_PerMipViews; }
bool HasMips() const { return m_flags & RHI_Texture_Mips; }
bool IsGrayscale() const { return m_flags & RHI_Texture_Greyscale; }
bool IsTransparent() const { return m_flags & RHI_Texture_Transparent; }

// Format type
bool IsDepthFormat() const { return m_format == RHI_Format::D16_Unorm || m_format == RHI_Format::D32_Float || m_format == RHI_Format::D32_Float_S8X24_Uint; }
Expand Down
123 changes: 92 additions & 31 deletions runtime/RHI/Vulkan/Vulkan_AMD_FidelityFX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "pch.h"
#include "../RHI_AMD_FidelityFX.h"
#include <FidelityFX/host/backends/vk/ffx_vk.h>
#include <FidelityFX/host/ffx_spd.h>
#include <FidelityFX/host/ffx_fsr2.h>
#include "../RHI_Implementation.h"
#include "../RHI_CommandList.h"
Expand All @@ -37,11 +38,19 @@ namespace Spartan
{
namespace
{
// FSR 2
// common
FfxInterface common_interface = {};

// spd
FfxSpdContext spd_context = {};
FfxSpdContextDescription spd_context_description = {};
bool spd_context_created = false;

// fsr 2
FfxFsr2Context fsr2_context = {};
FfxFsr2ContextDescription fsr2_context_description = {};
FfxFsr2DispatchDescription fsr2_dispatch_description = {};
bool fsr2_reset = false;
bool fsr2_reset_history = false;
bool fsr2_context_created = false;
uint32_t fsr2_jitter_index = 0;

Expand All @@ -57,7 +66,7 @@ namespace Spartan
}
}

static FfxSurfaceFormat get_ffx_format(const RHI_Format format)
static FfxSurfaceFormat to_ffx_surface_format(const RHI_Format format)
{
switch (format)
{
Expand Down Expand Up @@ -98,54 +107,106 @@ namespace Spartan
}
}

static FfxResource to_ffx_resource(RHI_Texture* texture, const wchar_t* name)
static FfxResource to_ffx_resource(RHI_Texture* texture, const wchar_t* name, FfxResourceUsage usage_additional = static_cast<FfxResourceUsage>(0))
{
FfxResourceDescription resource_description = {};
resource_description.type = FfxResourceType::FFX_RESOURCE_TYPE_TEXTURE2D;
resource_description.width = texture->GetWidth();
resource_description.height = texture->GetHeight();
resource_description.mipCount = texture->GetMipCount();
resource_description.format = get_ffx_format(texture->GetFormat());
resource_description.depth = texture->GetArrayLength(); // depth or array length
resource_description.format = to_ffx_surface_format(texture->GetFormat());
resource_description.flags = FfxResourceFlags::FFX_RESOURCE_FLAGS_NONE;
resource_description.usage = texture->IsDepthFormat() ? FfxResourceUsage::FFX_RESOURCE_USAGE_DEPTHTARGET : FfxResourceUsage::FFX_RESOURCE_USAGE_READ_ONLY;
if (texture->IsUav())
{
resource_description.usage = static_cast<FfxResourceUsage>(resource_description.usage | FfxResourceUsage::FFX_RESOURCE_USAGE_UAV);
}
resource_description.usage = texture->IsDepthFormat() ? FFX_RESOURCE_USAGE_DEPTHTARGET : FFX_RESOURCE_USAGE_READ_ONLY;
resource_description.usage = static_cast<FfxResourceUsage>(resource_description.usage | (texture->IsUav() ? FFX_RESOURCE_USAGE_UAV : 0));
resource_description.usage = static_cast<FfxResourceUsage>(resource_description.usage | usage_additional);

bool is_shader_read_only_optimal = texture->GetLayout(0) == RHI_Image_Layout::Shader_Read_Only_Optimal;
FfxResourceStates current_state = is_shader_read_only_optimal ? FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ : FFX_RESOURCE_STATE_UNORDERED_ACCESS;

return ffxGetResourceVK(
static_cast<VkImage>(texture->GetRhiResource()),
resource_description,
const_cast<wchar_t*>(name),
texture->GetLayout(0) == RHI_Image_Layout::Shader_Read_Only_Optimal ? FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ : FFX_RESOURCE_STATE_UNORDERED_ACCESS
current_state
);
}
}

void RHI_AMD_FidelityFX::Initialize()
{
VkDeviceContext device_context = {};
device_context.vkDevice = RHI_Context::device;
device_context.vkPhysicalDevice = RHI_Context::device_physical;
// common interface
{
const size_t size =
//FFX_SPD_CONTEXT_COUNT +
FFX_FSR2_CONTEXT_COUNT;

VkDeviceContext device_context = {};
device_context.vkDevice = RHI_Context::device;
device_context.vkPhysicalDevice = RHI_Context::device_physical;

const size_t scratch_buffer_size = ffxGetScratchMemorySizeVK(RHI_Context::device_physical, size);
void* scratch_buffer = malloc(scratch_buffer_size);

SP_ASSERT(ffxGetInterfaceVK(&common_interface, ffxGetDeviceVK(&device_context), scratch_buffer, scratch_buffer_size, size) == FFX_OK);
}

// spd
{
// interface
spd_context_description.backendInterface = common_interface;

// context
spd_context_description.flags = FFX_SPD_SAMPLER_LINEAR | FFX_SPD_WAVE_INTEROP_WAVE_OPS | FFX_SPD_MATH_PACKED;
//ffxSpdContextCreate(&spd_context, &spd_context_description);
spd_context_created = true;
}

const size_t scratch_buffer_size = ffxGetScratchMemorySizeVK(RHI_Context::device_physical, FFX_FSR2_CONTEXT_COUNT);
void* scratch_buffer = malloc(scratch_buffer_size);
// fsr 2
{
// interface
fsr2_context_description.backendInterface = common_interface;

SP_ASSERT(ffxGetInterfaceVK(&fsr2_context_description.backendInterface, ffxGetDeviceVK(&device_context), scratch_buffer, scratch_buffer_size, FFX_FSR2_CONTEXT_COUNT) == FFX_OK);
// context
// the context is (re)created below, in FSR2_Resize()
}
}

void RHI_AMD_FidelityFX::Destroy()
{
// spd
if (spd_context_created)
{
ffxSpdContextDestroy(&spd_context);
spd_context_created = false;
}

// fsr 2
if (fsr2_context_created)
{
ffxFsr2ContextDestroy(&fsr2_context);
fsr2_context_created = false;
}

// common
if (common_interface.scratchBuffer != nullptr)
{
free(common_interface.scratchBuffer);
}
}

void RHI_AMD_FidelityFX::SPD_Dispatch(RHI_CommandList* cmd_list, RHI_Texture* texture)
{
FfxSpdDispatchDescription dispatch_description = {};
dispatch_description.commandList = ffxGetCommandListVK(static_cast<VkCommandBuffer>(cmd_list->GetRhiResource()));
dispatch_description.resource = to_ffx_resource(texture, L"spd_texture", FFX_RESOURCE_USAGE_ARRAYVIEW);

//SP_ASSERT(ffxSpdContextDispatch(&spd_context, &dispatch_description) == FFX_OK);
}

void RHI_AMD_FidelityFX::FSR2_ResetHistory()
{
fsr2_reset = true;
fsr2_reset_history = true;
}

void RHI_AMD_FidelityFX::FSR2_GenerateJitterSample(float* x, float* y)
Expand All @@ -163,7 +224,7 @@ namespace Spartan
*y = fsr2_dispatch_description.jitterOffset.y;
}

void RHI_AMD_FidelityFX::OnResize(const Math::Vector2& resolution_render, const Math::Vector2& resolution_output)
void RHI_AMD_FidelityFX::FSR2_Resize(const Math::Vector2& resolution_render, const Math::Vector2& resolution_output)
{
// destroy context
if (fsr2_context_created)
Expand All @@ -182,7 +243,7 @@ namespace Spartan
FFX_FSR2_ENABLE_AUTO_EXPOSURE |
FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE;

// Debug check
// debug checking
#ifdef DEBUG
fsr2_context_description.flags |= FFX_FSR2_ENABLE_DEBUG_CHECKING;
fsr2_context_description.fpMessage = &ffx_message_callback;
Expand Down Expand Up @@ -210,23 +271,23 @@ namespace Spartan
float sharpness
)
{
// Get render and output resolution from the context description (safe to do as we are not using dynamic resolution)
// get render and output resolution from the context description (safe to do as we are not using dynamic resolution)
uint32_t resolution_render_x = static_cast<uint32_t>(fsr2_context_description.maxRenderSize.width);
uint32_t resolution_render_y = static_cast<uint32_t>(fsr2_context_description.maxRenderSize.height);
uint32_t resolution_output_x = static_cast<uint32_t>(fsr2_context_description.displaySize.width);
uint32_t resolution_output_y = static_cast<uint32_t>(fsr2_context_description.displaySize.height);

// Transition to the appropriate layouts (will only happen if needed)
// transition to the appropriate layouts (will only happen if needed)
tex_input->SetLayout(RHI_Image_Layout::Shader_Read_Only_Optimal, cmd_list);
tex_depth->SetLayout(RHI_Image_Layout::Shader_Read_Only_Optimal, cmd_list);
tex_velocity->SetLayout(RHI_Image_Layout::Shader_Read_Only_Optimal, cmd_list);
tex_mask_reactive->SetLayout(RHI_Image_Layout::Shader_Read_Only_Optimal, cmd_list);
tex_mask_transparency->SetLayout(RHI_Image_Layout::Shader_Read_Only_Optimal, cmd_list);
tex_output->SetLayout(RHI_Image_Layout::General, cmd_list);

// Dispatch description
// dispatch description
{
// Resources
// resources
fsr2_dispatch_description.color = to_ffx_resource(tex_input, L"fsr2_color");
fsr2_dispatch_description.depth = to_ffx_resource(tex_depth, L"fsr2_depth");
fsr2_dispatch_description.motionVectors = to_ffx_resource(tex_velocity, L"fsr2_velocity");
Expand All @@ -235,22 +296,22 @@ namespace Spartan
fsr2_dispatch_description.output = to_ffx_resource(tex_output, L"fsr2_output");
fsr2_dispatch_description.commandList = ffxGetCommandListVK(static_cast<VkCommandBuffer>(cmd_list->GetRhiResource()));

// Configuration
// configuration
fsr2_dispatch_description.motionVectorScale.x = -static_cast<float>(resolution_render_x);
fsr2_dispatch_description.motionVectorScale.y = -static_cast<float>(resolution_render_y);
fsr2_dispatch_description.reset = fsr2_reset; // A boolean value which when set to true, indicates the camera has moved discontinuously.
fsr2_dispatch_description.reset = fsr2_reset_history; // a boolean value which when set to true, indicates the camera has moved discontinuously
fsr2_dispatch_description.enableSharpening = sharpness != 0.0f;
fsr2_dispatch_description.sharpness = sharpness;
fsr2_dispatch_description.frameTimeDelta = delta_time_sec * 1000.0f; // Seconds to milliseconds.
fsr2_dispatch_description.preExposure = 1.0f; // The exposure value if not using FFX_FSR2_ENABLE_AUTO_EXPOSURE.
fsr2_dispatch_description.frameTimeDelta = delta_time_sec * 1000.0f; // seconds to milliseconds
fsr2_dispatch_description.preExposure = 1.0f; // the exposure value if not using FFX_FSR2_ENABLE_AUTO_EXPOSURE
fsr2_dispatch_description.renderSize.width = resolution_render_x;
fsr2_dispatch_description.renderSize.height = resolution_render_y;
fsr2_dispatch_description.cameraNear = camera->GetFarPlane(); // far for near because we are using reverse-z.
fsr2_dispatch_description.cameraFar = camera->GetNearPlane(); // near for far because we are using reverse-z.
fsr2_dispatch_description.cameraNear = camera->GetFarPlane(); // far as near because we are using reverse-z
fsr2_dispatch_description.cameraFar = camera->GetNearPlane(); // near as far because we are using reverse-z
fsr2_dispatch_description.cameraFovAngleVertical = camera->GetFovVerticalRad();
}

SP_ASSERT(ffxFsr2ContextDispatch(&fsr2_context, &fsr2_dispatch_description) == FFX_OK);
fsr2_reset = false;
fsr2_reset_history = false;
}
}
4 changes: 4 additions & 0 deletions runtime/RHI/Vulkan/Vulkan_Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,10 @@ namespace Spartan
SP_ASSERT(features_supported_1_3.dynamicRendering == VK_TRUE);
device_features_to_enable_1_3.dynamicRendering = VK_TRUE;

// Extended types (int8, int16, int64, etc) - SPD
SP_ASSERT(features_supported_1_2.shaderSubgroupExtendedTypes == VK_TRUE);
device_features_to_enable_1_2.shaderSubgroupExtendedTypes = VK_TRUE;

// Wave64
SP_ASSERT(features_supported_1_3.shaderDemoteToHelperInvocation == VK_TRUE);
device_features_to_enable_1_3.shaderDemoteToHelperInvocation = VK_TRUE;
Expand Down
1 change: 1 addition & 0 deletions runtime/Rendering/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ namespace Spartan
// switch to the next array of constant buffers
m_constant_buffer_index = (m_constant_buffer_index + 1) % 2;

RHI_Device::QueueWaitAll();
// Reset dynamic buffer indices
for (shared_ptr<RHI_ConstantBuffer> constant_buffer : GetConstantBuffers())
{
Expand Down
2 changes: 1 addition & 1 deletion runtime/Rendering/Renderer_Resources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ namespace Spartan
}

RHI_Device::QueueWaitAll();
RHI_AMD_FidelityFX::OnResize(GetResolutionRender(), GetResolutionOutput());
RHI_AMD_FidelityFX::FSR2_Resize(GetResolutionRender(), GetResolutionOutput());
}

void Renderer::CreateShaders()
Expand Down
Binary file modified third_party/libraries/libraries.7z
Binary file not shown.

0 comments on commit 017f397

Please sign in to comment.