Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions Graphics/SuperResolution/interface/SuperResolutionFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "../../../Primitives/interface/DebugOutput.h"
#include "../../../Primitives/interface/MemoryAllocator.h"
#include "../../../Primitives/interface/FlagEnum.h"
#include "../../../Graphics/GraphicsEngine/interface/Dearchiver.h"
#include "../../../Graphics/GraphicsEngine/interface/RenderDevice.h"

#include "SuperResolution.h"
Expand All @@ -45,6 +46,31 @@ static DILIGENT_CONSTEXPR INTERFACE_ID IID_SuperResolutionFactory =

// clang-format off

/// FSR implementation creation attributes.
struct SuperResolutionFSRCreateInfo
{
/// Dearchiver that contains the FSR pipeline states.
IDearchiver* pDearchiver DEFAULT_INITIALIZER(nullptr);

/// Name of the edge-adaptive upsampling pipeline state in the archive.
const Char* EASUPSOName DEFAULT_INITIALIZER(nullptr);

/// Name of the contrast-adaptive sharpening pipeline state in the archive.
const Char* RCASPSOName DEFAULT_INITIALIZER(nullptr);
};
typedef struct SuperResolutionFSRCreateInfo SuperResolutionFSRCreateInfo;

/// Super resolution factory creation attributes.
struct SuperResolutionFactoryCreateInfo
{
/// Render device used by the super resolution implementations.
IRenderDevice* pDevice DEFAULT_INITIALIZER(nullptr);

/// Optional FSR implementation creation attributes.
const SuperResolutionFSRCreateInfo* pFSRCreateInfo DEFAULT_INITIALIZER(nullptr);
};
typedef struct SuperResolutionFactoryCreateInfo SuperResolutionFactoryCreateInfo;

/// Super resolution upscaler type.
DILIGENT_TYPED_ENUM(SUPER_RESOLUTION_TYPE, Uint8)
{
Expand Down Expand Up @@ -328,12 +354,17 @@ DILIGENT_END_INTERFACE

#endif

/// Creates a super resolution factory for the specified render device.
#include "../../../Primitives/interface/DefineGlobalFuncHelperMacros.h"

/// \param [in] pDevice - Render device to create the factory for.
/// Creates a super resolution factory using the specified creation attributes.

/// \param [in] CreateInfo - Factory creation attributes, see
/// Diligent::SuperResolutionFactoryCreateInfo.
/// \param [out] ppFactory - Address of the memory location where a pointer to the
/// super resolution factory interface will be written.
void DILIGENT_GLOBAL_FUNCTION(CreateSuperResolutionFactory)(IRenderDevice* pDevice,
ISuperResolutionFactory** ppFactory);
void DILIGENT_GLOBAL_FUNCTION(CreateSuperResolutionFactory)(const SuperResolutionFactoryCreateInfo REF CreateInfo,
ISuperResolutionFactory** ppFactory);

#include "../../../Primitives/interface/UndefGlobalFuncHelperMacros.h"

DILIGENT_END_NAMESPACE // namespace Diligent
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@

DILIGENT_BEGIN_NAMESPACE(Diligent)

typedef void (*CreateSuperResolutionFactoryType)(IRenderDevice* pDevice, ISuperResolutionFactory** ppFactory);
#include "../../../Primitives/interface/DefineGlobalFuncHelperMacros.h"

typedef void (*CreateSuperResolutionFactoryType)(const SuperResolutionFactoryCreateInfo REF CreateInfo, ISuperResolutionFactory** ppFactory);

#if DILIGENT_SUPER_RESOLUTION_EXPLICIT_LOAD

Expand All @@ -61,15 +63,15 @@ inline CreateSuperResolutionFactoryType DILIGENT_GLOBAL_FUNCTION(LoadSuperResolu
#else

API_QUALIFIER
void DILIGENT_GLOBAL_FUNCTION(CreateSuperResolutionFactory)(IRenderDevice* pDevice,
ISuperResolutionFactory** ppFactory);
void DILIGENT_GLOBAL_FUNCTION(CreateSuperResolutionFactory)(const SuperResolutionFactoryCreateInfo REF CreateInfo,
ISuperResolutionFactory** ppFactory);

#endif

/// Loads the SuperResolution implementation DLL if necessary and creates a SuperResolution factory
/// for the specified render device.
inline void DILIGENT_GLOBAL_FUNCTION(LoadAndCreateSuperResolutionFactory)(IRenderDevice* pDevice,
ISuperResolutionFactory** ppFactory)
/// using the specified creation attributes.
inline void DILIGENT_GLOBAL_FUNCTION(LoadAndCreateSuperResolutionFactory)(const SuperResolutionFactoryCreateInfo REF CreateInfo,
ISuperResolutionFactory** ppFactory)
{
CreateSuperResolutionFactoryType CreateFactoryFunc = NULL;
#if DILIGENT_SUPER_RESOLUTION_EXPLICIT_LOAD
Expand All @@ -82,7 +84,9 @@ inline void DILIGENT_GLOBAL_FUNCTION(LoadAndCreateSuperResolutionFactory)(IRende
#else
CreateFactoryFunc = DILIGENT_GLOBAL_FUNCTION(CreateSuperResolutionFactory);
#endif
CreateFactoryFunc(pDevice, ppFactory);
CreateFactoryFunc(CreateInfo, ppFactory);
}

#include "../../../Primitives/interface/UndefGlobalFuncHelperMacros.h"

DILIGENT_END_NAMESPACE // namespace Diligent
23 changes: 22 additions & 1 deletion Graphics/SuperResolution/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,30 @@ The factory is created per render device. On Windows, the module can be loaded a
#include "SuperResolutionFactoryLoader.h"

RefCntAutoPtr<ISuperResolutionFactory> pSRFactory;
LoadAndCreateSuperResolutionFactory(pDevice, &pSRFactory);
SuperResolutionFactoryCreateInfo FactoryCreateInfo;
FactoryCreateInfo.pDevice = pDevice;
LoadAndCreateSuperResolutionFactory(FactoryCreateInfo, &pSRFactory);
```

`SuperResolutionFSRCreateInfo` can provide archived pipeline states for FSR, avoiding runtime shader compilation:

```cpp
SuperResolutionFSRCreateInfo FSRCreateInfo;
FSRCreateInfo.pDearchiver = pDearchiver;
FSRCreateInfo.EASUPSOName = "FSR::EASU PSO";
FSRCreateInfo.RCASPSOName = "FSR::RCAS PSO";

SuperResolutionFactoryCreateInfo FactoryCI;
FactoryCI.pDevice = pDevice;
FactoryCI.pFSRCreateInfo = &FSRCreateInfo;

RefCntAutoPtr<ISuperResolutionFactory> pSRFactory;
LoadAndCreateSuperResolutionFactory(FactoryCI, &pSRFactory);
```

When the optional FSR attributes are omitted, FSR compiles the shaders and creates the pipeline states at runtime.
When they are provided, the dearchiver must contain both named graphics pipeline states. FSR unpacks and caches a separate pair for every requested output format, overriding the first render target format during unpacking.

### Enumerating Available Variants

Query the list of upscaler variants supported by the current device:
Expand Down
74 changes: 68 additions & 6 deletions Graphics/SuperResolution/src/FSRProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "CommonlyUsedStates.h"
#include "ShaderMacroHelper.hpp"
#include "BasicMath.hpp"
#include "Dearchiver.h"
#include "EngineMemory.h"

namespace Diligent
Expand Down Expand Up @@ -110,6 +111,10 @@ SuperResolutionFSR::SuperResolutionFSR(IReferenceCounters* pRefCounters,
m_pEASU_PSO{pEASU_PSO},
m_pRCAS_PSO{pRCAS_PSO}
{
VERIFY_SUPER_RESOLUTION(m_Desc.Name, pDevice != nullptr, "Render device must not be null");
VERIFY_SUPER_RESOLUTION(m_Desc.Name, m_pEASU_PSO != nullptr, "FSR EASU pipeline state must not be null");
VERIFY_SUPER_RESOLUTION(m_Desc.Name, m_pRCAS_PSO != nullptr, "FSR RCAS pipeline state must not be null");

{
const float InputWidth = static_cast<float>(Desc.InputWidth);
const float InputHeight = static_cast<float>(Desc.InputHeight);
Expand Down Expand Up @@ -199,7 +204,7 @@ void SuperResolutionFSR::Execute(const ExecuteSuperResolutionAttribs& Attribs)
class FSRProvider final : public SuperResolutionProvider
{
public:
FSRProvider(IRenderDevice* pDevice);
FSRProvider(IRenderDevice* pDevice, const SuperResolutionFSRCreateInfo* pCreateInfo);

virtual void EnumerateVariants(std::vector<SuperResolutionInfo>& Variants) override final
{
Expand All @@ -213,6 +218,8 @@ class FSRProvider final : public SuperResolutionProvider

virtual void CreateSuperResolution(const SuperResolutionDesc& Desc, const SuperResolutionInfo& Info, ISuperResolution** ppUpscaler) override final
{
DEV_CHECK_ERR(ppUpscaler != nullptr, "ppUpscaler must not be null");

auto& Pipelines = GetOrCreatePipelines(Desc.OutputFormat);
auto* pUpscaler = NEW_RC_OBJ(GetRawAllocator(), "SuperResolutionFSR instance", SuperResolutionFSR)(m_pDevice, Desc, Info, Pipelines.pEASU_PSO, Pipelines.pRCAS_PSO);
pUpscaler->QueryInterface(IID_SuperResolution, reinterpret_cast<IObject**>(ppUpscaler));
Expand All @@ -225,25 +232,55 @@ class FSRProvider final : public SuperResolutionProvider
RefCntAutoPtr<IPipelineState> pRCAS_PSO;
};

struct ArchivedPipelineInfo
{
explicit ArchivedPipelineInfo(const SuperResolutionFSRCreateInfo& CI) :
pDearchiver{CI.pDearchiver},
EASUPSOName{CI.EASUPSOName},
RCASPSOName{CI.RCASPSOName}
{}

RefCntAutoPtr<IDearchiver> pDearchiver;
std::string EASUPSOName;
std::string RCASPSOName;
};

PipelineData& GetOrCreatePipelines(TEXTURE_FORMAT OutputFormat);

RefCntAutoPtr<IRenderDevice> m_pDevice;
RefCntAutoPtr<IShaderSourceInputStreamFactory> m_pShaderSourceFactory;
RefCntAutoPtr<IShader> m_pVS;
RefCntAutoPtr<IShader> m_pEASU_PS;
RefCntAutoPtr<IShader> m_pRCAS_PS;
std::unique_ptr<ArchivedPipelineInfo> m_pArchivedPipelineInfo;
std::unordered_map<TEXTURE_FORMAT, PipelineData, std::hash<Uint32>> m_PipelineCache;
};


FSRProvider::FSRProvider(IRenderDevice* pDevice) :
FSRProvider::FSRProvider(IRenderDevice* pDevice, const SuperResolutionFSRCreateInfo* pCreateInfo) :
m_pDevice{pDevice}
{
if (pDevice == nullptr)
LOG_ERROR_AND_THROW("Device must not be null");

if (pCreateInfo != nullptr)
{
if (pCreateInfo->pDearchiver == nullptr)
LOG_ERROR_AND_THROW("FSR dearchiver must not be null");
if (pCreateInfo->EASUPSOName == nullptr || pCreateInfo->EASUPSOName[0] == '\0')
LOG_ERROR_AND_THROW("FSR EASU pipeline state name must not be null or empty");
if (pCreateInfo->RCASPSOName == nullptr || pCreateInfo->RCASPSOName[0] == '\0')
LOG_ERROR_AND_THROW("FSR RCAS pipeline state name must not be null or empty");

m_pArchivedPipelineInfo = std::make_unique<ArchivedPipelineInfo>(*pCreateInfo);
return;
}

MemoryShaderSourceFactoryCreateInfo CI{HLSL::g_Shaders, _countof(HLSL::g_Shaders)};
CreateMemoryShaderSourceFactory(CI, &m_pShaderSourceFactory);

ShaderMacroHelper Macros;
if (pDevice->GetDeviceInfo().Type != RENDER_DEVICE_TYPE_GLES)
if (m_pDevice->GetDeviceInfo().Type != RENDER_DEVICE_TYPE_GLES)
Macros.AddShaderMacro("FSR_FEATURE_TEXTURE_GATHER", 1);

auto CreateShader = [&](SHADER_TYPE Type, const char* Name, const char* EntryPoint, const char* FilePath, const ShaderMacroArray& ShaderMacros = {}) {
Expand All @@ -257,13 +294,16 @@ FSRProvider::FSRProvider(IRenderDevice* pDevice) :
ShaderCI.Macros = ShaderMacros;
ShaderCI.pShaderSourceStreamFactory = m_pShaderSourceFactory;
RefCntAutoPtr<IShader> pShader;
pDevice->CreateShader(ShaderCI, &pShader);
m_pDevice->CreateShader(ShaderCI, &pShader);
return pShader;
};

m_pVS = CreateShader(SHADER_TYPE_VERTEX, "FSR FullQuad VS", "FSR_FullQuadVS", "FSR_FullQuad.fx");
m_pEASU_PS = CreateShader(SHADER_TYPE_PIXEL, "FSR EASU PS", "ComputeEdgeAdaptiveUpsamplingPS", "FSR_EdgeAdaptiveUpsampling.fx", Macros);
m_pRCAS_PS = CreateShader(SHADER_TYPE_PIXEL, "FSR RCAS PS", "ComputeContrastAdaptiveSharpeningPS", "FSR_ContrastAdaptiveSharpening.fx");

if (!m_pVS || !m_pEASU_PS || !m_pRCAS_PS)
LOG_ERROR_AND_THROW("Failed to create FSR shaders");
}

FSRProvider::PipelineData& FSRProvider::GetOrCreatePipelines(TEXTURE_FORMAT OutputFormat)
Expand All @@ -274,6 +314,28 @@ FSRProvider::PipelineData& FSRProvider::GetOrCreatePipelines(TEXTURE_FORMAT Outp

PipelineData& Data = m_PipelineCache[OutputFormat];

if (m_pArchivedPipelineInfo)
{
auto ModifyPipelineStateCreateInfo = [](PipelineStateCreateInfo& PipelineCI, void* pUserData) {
auto& GraphicsPipelineCI = static_cast<GraphicsPipelineStateCreateInfo&>(PipelineCI);
GraphicsPipelineCI.GraphicsPipeline.RTVFormats[0] = *static_cast<const TEXTURE_FORMAT*>(pUserData);
};

PipelineStateUnpackInfo UnpackInfo;
UnpackInfo.pDevice = m_pDevice;
UnpackInfo.PipelineType = PIPELINE_TYPE_GRAPHICS;
UnpackInfo.ModifyPipelineStateCreateInfo = ModifyPipelineStateCreateInfo;
UnpackInfo.pUserData = &OutputFormat;

UnpackInfo.Name = m_pArchivedPipelineInfo->EASUPSOName.c_str();
m_pArchivedPipelineInfo->pDearchiver->UnpackPipelineState(UnpackInfo, &Data.pEASU_PSO);

UnpackInfo.Name = m_pArchivedPipelineInfo->RCASPSOName.c_str();
m_pArchivedPipelineInfo->pDearchiver->UnpackPipelineState(UnpackInfo, &Data.pRCAS_PSO);

return Data;
}

{
PipelineResourceLayoutDescX ResourceLayout;
ResourceLayout
Expand Down Expand Up @@ -318,9 +380,9 @@ FSRProvider::PipelineData& FSRProvider::GetOrCreatePipelines(TEXTURE_FORMAT Outp
} // anonymous namespace


std::unique_ptr<SuperResolutionProvider> CreateFSRProvider(IRenderDevice* pDevice)
std::unique_ptr<SuperResolutionProvider> CreateFSRProvider(IRenderDevice* pDevice, const SuperResolutionFSRCreateInfo* pCreateInfo)
{
return std::make_unique<FSRProvider>(pDevice);
return std::make_unique<FSRProvider>(pDevice, pCreateInfo);
}

} // namespace Diligent
37 changes: 18 additions & 19 deletions Graphics/SuperResolution/src/SuperResolutionFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ std::unique_ptr<SuperResolutionProvider> CreateMetalFXProvider(IRenderDevice* pD
#endif

#if DILIGENT_FSR_SUPPORTED
std::unique_ptr<SuperResolutionProvider> CreateFSRProvider(IRenderDevice* pDevice);
std::unique_ptr<SuperResolutionProvider> CreateFSRProvider(IRenderDevice* pDevice, const SuperResolutionFSRCreateInfo* pCreateInfo);
#endif

namespace
Expand All @@ -68,16 +68,14 @@ class SuperResolutionFactory : public ObjectBase<ISuperResolutionFactory>
public:
using TBase = ObjectBase<ISuperResolutionFactory>;

SuperResolutionFactory(IReferenceCounters* pRefCounters, IRenderDevice* pDevice) :
SuperResolutionFactory(IReferenceCounters* pRefCounters, const SuperResolutionFactoryCreateInfo& CI) :
TBase{pRefCounters}
{
auto AddProvider = [this](IRenderDevice* pDevice,
std::unique_ptr<SuperResolutionProvider> CreateProvider(IRenderDevice*),
const char* ProviderName) {
auto AddProvider = [this](auto&& CreateProvider, const char* ProviderName) {
try
{
ProviderInfo ProvInfo;
ProvInfo.Provider = CreateProvider(pDevice);
ProvInfo.Provider = CreateProvider();
if (ProvInfo.Provider)
{
ProvInfo.Provider->EnumerateVariants(ProvInfo.Variants);
Expand All @@ -95,22 +93,22 @@ class SuperResolutionFactory : public ObjectBase<ISuperResolutionFactory>
};

#ifdef DILIGENT_DLSS_D3D11_SUPPORTED
AddProvider(pDevice, CreateDLSSProviderD3D11, "DLSS D3D11");
AddProvider([&]() { return CreateDLSSProviderD3D11(CI.pDevice); }, "DLSS D3D11");
#endif
#ifdef DILIGENT_DLSS_D3D12_SUPPORTED
AddProvider(pDevice, CreateDLSSProviderD3D12, "DLSS D3D12");
AddProvider([&]() { return CreateDLSSProviderD3D12(CI.pDevice); }, "DLSS D3D12");
#endif
#ifdef DILIGENT_DLSS_VK_SUPPORTED
AddProvider(pDevice, CreateDLSSProviderVk, "DLSS Vulkan");
AddProvider([&]() { return CreateDLSSProviderVk(CI.pDevice); }, "DLSS Vulkan");
#endif
#ifdef DILIGENT_DSR_D3D12_SUPPORTED
AddProvider(pDevice, CreateDSRProviderD3D12, "DirectSR D3D12");
AddProvider([&]() { return CreateDSRProviderD3D12(CI.pDevice); }, "DirectSR D3D12");
#endif
#ifdef DILIGENT_METALFX_SUPPORTED
AddProvider(pDevice, CreateMetalFXProvider, "MetalFX");
AddProvider([&]() { return CreateMetalFXProvider(CI.pDevice); }, "MetalFX");
#endif
#ifdef DILIGENT_FSR_SUPPORTED
AddProvider(pDevice, CreateFSRProvider, "FSR Spatial");
AddProvider([&]() { return CreateFSRProvider(CI.pDevice, CI.pFSRCreateInfo); }, "FSR Spatial");
#endif
(void)AddProvider;
}
Expand Down Expand Up @@ -219,21 +217,22 @@ class SuperResolutionFactory : public ObjectBase<ISuperResolutionFactory>

} // namespace

API_QUALIFIER void CreateSuperResolutionFactory(IRenderDevice* pDevice, ISuperResolutionFactory** ppFactory)
API_QUALIFIER void CreateSuperResolutionFactory(const SuperResolutionFactoryCreateInfo& CreateInfo,
ISuperResolutionFactory** ppFactory)
{
DEV_CHECK_ERR(ppFactory != nullptr, "ppFactory must not be null");
if (ppFactory == nullptr)
return;

*ppFactory = nullptr;

DEV_CHECK_ERR(pDevice != nullptr, "pDevice must not be null");
if (pDevice == nullptr)
DEV_CHECK_ERR(CreateInfo.pDevice != nullptr, "CreateInfo.pDevice must not be null");
if (CreateInfo.pDevice == nullptr)
return;

try
{
SuperResolutionFactory* pFactory = NEW_RC_OBJ(GetRawAllocator(), "SuperResolutionFactory instance", SuperResolutionFactory)(pDevice);
SuperResolutionFactory* pFactory = NEW_RC_OBJ(GetRawAllocator(), "SuperResolutionFactory instance", SuperResolutionFactory)(CreateInfo);
pFactory->QueryInterface(IID_SuperResolutionFactory, reinterpret_cast<IObject**>(ppFactory));
}
catch (...)
Expand All @@ -247,9 +246,9 @@ API_QUALIFIER void CreateSuperResolutionFactory(IRenderDevice* pDevice, ISuperRe
extern "C"
{
API_QUALIFIER
void Diligent_CreateSuperResolutionFactory(Diligent::IRenderDevice* pDevice,
Diligent::ISuperResolutionFactory** ppFactory)
void Diligent_CreateSuperResolutionFactory(const Diligent::SuperResolutionFactoryCreateInfo& CreateInfo,
Diligent::ISuperResolutionFactory** ppFactory)
{
Diligent::CreateSuperResolutionFactory(pDevice, ppFactory);
Diligent::CreateSuperResolutionFactory(CreateInfo, ppFactory);
}
}
Loading
Loading