From e1e1fc50d6bea2b89a46cd16b72c312b8cedaa18 Mon Sep 17 00:00:00 2001 From: cdozdil Date: Tue, 26 Mar 2024 01:36:49 +0300 Subject: [PATCH] colorspacefix for aw2 --- CyberXeSS/Config.cpp | 1 + CyberXeSS/Config.h | 1 + CyberXeSS/CyberXeSS.vcxproj | 6 +- CyberXeSS/backends/IFeature_Dx11wDx12.cpp | 10 + CyberXeSS/backends/IFeature_Dx11wDx12.h | 1 + CyberXeSS/backends/xess/XeSSFeature.cpp | 438 ++++++++++++++++++- CyberXeSS/backends/xess/XeSSFeature.h | 14 + CyberXeSS/backends/xess/XeSSFeature_Dx11.cpp | 79 +++- CyberXeSS/backends/xess/XeSSFeature_Dx12.cpp | 67 ++- CyberXeSS/imgui/Imgui_Base.cpp | 2 + 10 files changed, 594 insertions(+), 25 deletions(-) diff --git a/CyberXeSS/Config.cpp b/CyberXeSS/Config.cpp index 70c70358..836651f7 100644 --- a/CyberXeSS/Config.cpp +++ b/CyberXeSS/Config.cpp @@ -57,6 +57,7 @@ void Config::Reload() // Color AutoExposure = readBool("Color", "AutoExposure"); HDR = readBool("Color", "HDR"); + ColorSpaceFix = readBool("Color", "ColorSpaceFix"); // MotionVectors JitterCancellation = readBool("MotionVectors", "JitterCancellation"); diff --git a/CyberXeSS/Config.h b/CyberXeSS/Config.h index 56e11aa8..6ae485a8 100644 --- a/CyberXeSS/Config.h +++ b/CyberXeSS/Config.h @@ -23,6 +23,7 @@ public: // Color std::optional AutoExposure; + std::optional ColorSpaceFix; std::optional HDR; // Motion diff --git a/CyberXeSS/CyberXeSS.vcxproj b/CyberXeSS/CyberXeSS.vcxproj index 785f4893..6e3d8128 100644 --- a/CyberXeSS/CyberXeSS.vcxproj +++ b/CyberXeSS/CyberXeSS.vcxproj @@ -82,7 +82,7 @@ $(SolutionDir)external\vulkan\include;$(SolutionDir)external\nvngx_dlss_sdk;$(SolutionDir)external\xess\inc\xess;$(SolutionDir)external\simpleini;$(SolutionDir)external\unordered_dense\include;$(SolutionDir)external\spdlog\include;$(IncludePath) $(SolutionDir)CyberXess\cas\lib;$(SolutionDir)CyberXess\fsr2\lib;$(SolutionDir)CyberXess\fsr2_212\lib;$(SolutionDir)CyberXess\vulkan;$(SolutionDir)external\xess\lib;$(LibraryPath) nvngx - E:\Games\Deep Rock Galactic\FSD\Binaries\Win64\ + D:\Games\Stranger of Paradise - Final Fantasy Origin\ .\x64\Debug @@ -142,7 +142,7 @@ Windows true false - dxgi.lib;d3d11.lib;d3d12.lib;vulkan-1.lib;dxguid.lib;libxess.lib;ffx_fsr2_api_x64d.lib;ffx_fsr2_api_dx11_x64d.lib;ffx_fsr2_api_dx12_x64d.lib;ffx_fsr2_api_vk_x64d.lib;ffx_cas_backend_dx12_x64d.lib;ffx_cas_x64d.lib;ffx_fsr2_212_api_dx12_x64d.lib;ffx_fsr2_212_api_vk_x64d.lib;ffx_fsr2_212_api_x64d.lib;%(AdditionalDependencies) + dxgi.lib;d3d11.lib;d3d12.lib;vulkan-1.lib;dxguid.lib;libxess.lib;ffx_fsr2_api_x64d.lib;ffx_fsr2_api_dx11_x64d.lib;ffx_fsr2_api_dx12_x64d.lib;ffx_fsr2_api_vk_x64d.lib;ffx_cas_backend_dx12_x64d.lib;ffx_cas_x64d.lib;ffx_fsr2_212_api_dx12_x64d.lib;ffx_fsr2_212_api_vk_x64d.lib;ffx_fsr2_212_api_x64d.lib;d3dcompiler.lib;%(AdditionalDependencies) @@ -164,7 +164,7 @@ true true false - dxgi.lib;d3d11.lib;d3d12.lib;vulkan-1.lib;dxguid.lib;libxess.lib;ffx_fsr2_api_x64.lib;ffx_fsr2_api_dx11_x64.lib;ffx_fsr2_api_dx12_x64.lib;ffx_fsr2_api_vk_x64.lib;ffx_cas_backend_dx12_x64.lib;ffx_cas_x64.lib;ffx_fsr2_212_api_dx12_x64.lib;ffx_fsr2_212_api_vk_x64.lib;ffx_fsr2_212_api_x64.lib;%(AdditionalDependencies) + dxgi.lib;d3d11.lib;d3d12.lib;vulkan-1.lib;dxguid.lib;libxess.lib;ffx_fsr2_api_x64.lib;ffx_fsr2_api_dx11_x64.lib;ffx_fsr2_api_dx12_x64.lib;ffx_fsr2_api_vk_x64.lib;ffx_cas_backend_dx12_x64.lib;ffx_cas_x64.lib;ffx_fsr2_212_api_dx12_x64.lib;ffx_fsr2_212_api_vk_x64.lib;ffx_fsr2_212_api_x64.lib;d3dcompiler.lib;%(AdditionalDependencies) UseLinkTimeCodeGeneration diff --git a/CyberXeSS/backends/IFeature_Dx11wDx12.cpp b/CyberXeSS/backends/IFeature_Dx11wDx12.cpp index 165c48ae..66559bd2 100644 --- a/CyberXeSS/backends/IFeature_Dx11wDx12.cpp +++ b/CyberXeSS/backends/IFeature_Dx11wDx12.cpp @@ -12,6 +12,16 @@ do { \ } \ } while((void)0, 0); +void IFeature_Dx11wDx12::ResourceBarrier(ID3D12GraphicsCommandList * commandList, ID3D12Resource * resource, D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState) +{ + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = resource; + barrier.Transition.StateBefore = beforeState; + barrier.Transition.StateAfter = afterState; + barrier.Transition.Subresource = 0; + commandList->ResourceBarrier(1, &barrier); +} bool IFeature_Dx11wDx12::CopyTextureFrom11To12(ID3D11Resource* InResource, D3D11_TEXTURE2D_RESOURCE_C* OutResource, bool InCopy) { ID3D11Texture2D* originalTexture = nullptr; diff --git a/CyberXeSS/backends/IFeature_Dx11wDx12.h b/CyberXeSS/backends/IFeature_Dx11wDx12.h index 3bb1f941..abe1ec9b 100644 --- a/CyberXeSS/backends/IFeature_Dx11wDx12.h +++ b/CyberXeSS/backends/IFeature_Dx11wDx12.h @@ -58,6 +58,7 @@ protected: HRESULT CreateDx12Device(D3D_FEATURE_LEVEL InFeatureLevel); bool ProcessDx11Textures(const NVSDK_NGX_Parameter* InParameters); bool CopyBackOutput(); + void ResourceBarrier(ID3D12GraphicsCommandList* InCommandList, ID3D12Resource* InResource, D3D12_RESOURCE_STATES InBeforeState, D3D12_RESOURCE_STATES InAfterState); public: virtual bool Init(ID3D11Device* InDevice, ID3D11DeviceContext* InContext, const NVSDK_NGX_Parameter* InParameters) = 0; diff --git a/CyberXeSS/backends/xess/XeSSFeature.cpp b/CyberXeSS/backends/xess/XeSSFeature.cpp index a93e6ad7..b217aa5f 100644 --- a/CyberXeSS/backends/xess/XeSSFeature.cpp +++ b/CyberXeSS/backends/xess/XeSSFeature.cpp @@ -1,9 +1,46 @@ #pragma once #include "../../pch.h" #include "../../Config.h" +#include "../../imgui/d3dx12.h" #include "XeSSFeature.h" +#include + +struct Constants +{ + float Multiplier; +}; + +// pixel.rgb = pow(abs(pixel.rgb) * 4.0, 2.4) * sign(pixel.rgb); +const std::string _recEncodeShaderCode = R"( +Texture2D InputTexture : register(t0); +RWTexture2D OutputTexture : register(u0); + +// Companding shader +[numthreads(16,16,1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + float4 pixel = InputTexture[DTid.xy]; + pixel.rgb *= 10.0; + OutputTexture[DTid.xy] = pixel; +})"; + +// +// pixel.rgb = pow(abs(pixel.rgb), 0.4166666666666667) * sign(pixel.rgb) * 0.25; +const std::string _recDecodeShaderCode = R"( +Texture2D InputTexture : register(t0); +RWTexture2D OutputTexture : register(u0); + +// Inverse companding shader +[numthreads(16,16,1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + float4 pixel = InputTexture[DTid.xy]; + pixel.rgb *= 0.1; + OutputTexture[DTid.xy] = pixel; +})"; + inline static std::string ResultToString(FfxCas::FfxErrorCode result) { switch (result) @@ -193,6 +230,52 @@ inline void XeSSLogCallback(const char* Message, xess_logging_level_t Level) spdlog::log((spdlog::level::level_enum)((int)Level + 1), "FeatureContext::LogCallback XeSS Runtime ({0})", Message); } +static ID3DBlob* CompileShader(const char* shaderCode, const char* entryPoint, const char* target) +{ + ID3DBlob* shaderBlob = nullptr; + ID3DBlob* errorBlob = nullptr; + + HRESULT hr = D3DCompile(shaderCode, strlen(shaderCode), nullptr, nullptr, nullptr, entryPoint, target, 0, 0, &shaderBlob, &errorBlob); + + if (FAILED(hr)) + { + if (errorBlob) + { + OutputDebugStringA((char*)errorBlob->GetBufferPointer()); + errorBlob->Release(); + } + + if (shaderBlob) + shaderBlob->Release(); + + return nullptr; + } + + if (errorBlob) + errorBlob->Release(); + + return shaderBlob; +} + +static bool CreateComputeShader(ID3D12Device* device, ID3D12RootSignature* rootSignature, ID3D12PipelineState** pipelineState, ID3DBlob* shaderBlob) +{ + D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = rootSignature; + psoDesc.CS = CD3DX12_SHADER_BYTECODE(const_cast(shaderBlob->GetBufferPointer()), shaderBlob->GetBufferSize()); + //psoDesc.CS = { reinterpret_cast(shaderBlob->GetBufferPointer()), shaderBlob->GetBufferSize() }; + psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + HRESULT hr = device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(pipelineState)); + + if (FAILED(hr)) + { + // Handle error + return false; + } + + return true; +} + bool XeSSFeature::InitXeSS(ID3D12Device* device, const NVSDK_NGX_Parameter* InParameters) { spdlog::debug("XeSSFeature::InitXeSS!"); @@ -369,6 +452,8 @@ bool XeSSFeature::InitXeSS(ID3D12Device* device, const NVSDK_NGX_Parameter* InPa CasInit(); CreateCasContext(device); + RecInit(device); + SetInit(true); return true; @@ -502,6 +587,8 @@ bool XeSSFeature::CreateCasBufferResource(ID3D12Resource* source, ID3D12Device* if (casBuffer != nullptr) casBuffer->Release(); + texDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + hr = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &texDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&casBuffer)); if (hr != S_OK) @@ -541,7 +628,7 @@ bool XeSSFeature::CasDispatch(ID3D12CommandList* commandList, const NVSDK_NGX_Pa dispatchParameters.sharpness = casSharpness; dispatchParameters.color = FfxCas::ffxGetResourceDX12Cas(input, GetFfxResourceDescriptionDX12(input), nullptr, FfxCas::FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); - dispatchParameters.output = FfxCas::ffxGetResourceDX12Cas(output, GetFfxResourceDescriptionDX12(output), nullptr, FfxCas::FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchParameters.output = FfxCas::ffxGetResourceDX12Cas(output, GetFfxResourceDescriptionDX12(output), nullptr, FfxCas::FFX_RESOURCE_STATE_UNORDERED_ACCESS); if (auto errorCode = FfxCas::ffxCasContextDispatch(&casContext, &dispatchParameters); errorCode != FfxCas::FFX_OK) { @@ -549,5 +636,354 @@ bool XeSSFeature::CasDispatch(ID3D12CommandList* commandList, const NVSDK_NGX_Pa return false; } + return true; +} + +bool XeSSFeature::RecInit(ID3D12Device* InDevice) +{ + // Describe and create the root signature + // --------------------------------------------------- + D3D12_DESCRIPTOR_RANGE descriptorRange[2]; + + // SRV Range (Input Texture) + descriptorRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + descriptorRange[0].NumDescriptors = 1; + descriptorRange[0].BaseShaderRegister = 0; // Assuming t0 register in HLSL for SRV + descriptorRange[0].RegisterSpace = 0; + descriptorRange[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + // UAV Range (Output Texture) + descriptorRange[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + descriptorRange[1].NumDescriptors = 1; + descriptorRange[1].BaseShaderRegister = 0; // Assuming u0 register in HLSL for UAV + descriptorRange[1].RegisterSpace = 0; + descriptorRange[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + // Define the root parameter (descriptor table) + // --------------------------------------------------- + D3D12_ROOT_PARAMETER rootParameters[2]; + + // Root Parameter for SRV + rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters[0].DescriptorTable.NumDescriptorRanges = 1; // One range (SRV) + rootParameters[0].DescriptorTable.pDescriptorRanges = &descriptorRange[0]; // Point to the SRV range + rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // Root Parameter for UAV + rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters[1].DescriptorTable.NumDescriptorRanges = 1; // One range (UAV) + rootParameters[1].DescriptorTable.pDescriptorRanges = &descriptorRange[1]; // Point to the UAV range + rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // A root signature is an array of root parameters + // --------------------------------------------------- + D3D12_ROOT_SIGNATURE_DESC rootSigDesc; + rootSigDesc.NumParameters = 2; // Two root parameters + rootSigDesc.pParameters = rootParameters; + rootSigDesc.NumStaticSamplers = 0; + rootSigDesc.pStaticSamplers = nullptr; + rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + + ID3DBlob* errorBlob; + ID3DBlob* signatureBlob; + + do + { + auto hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signatureBlob, &errorBlob); + + if (FAILED(hr)) + { + break; + } + + hr = InDevice->CreateRootSignature(0, signatureBlob->GetBufferPointer(), signatureBlob->GetBufferSize(), IID_PPV_ARGS(&_recRootSignatureDecode)); + + if (FAILED(hr)) + { + break; + } + + } while (false); + + if (errorBlob != nullptr) + { + errorBlob->Release(); + errorBlob = nullptr; + } + + if (signatureBlob != nullptr) + { + signatureBlob->Release(); + signatureBlob = nullptr; + } + + if (_recRootSignatureDecode == nullptr) + return false; + + ID3DBlob* errorBlob2; + ID3DBlob* signatureBlob2; + + do + { + auto hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signatureBlob2, &errorBlob2); + + if (FAILED(hr)) + { + break; + } + + hr = InDevice->CreateRootSignature(0, signatureBlob2->GetBufferPointer(), signatureBlob2->GetBufferSize(), IID_PPV_ARGS(&_recRootSignatureEncode)); + + if (FAILED(hr)) + { + break; + } + + } while (false); + + if (errorBlob2 != nullptr) + { + errorBlob2->Release(); + errorBlob2 = nullptr; + } + + if (signatureBlob2 != nullptr) + { + signatureBlob2->Release(); + signatureBlob2 = nullptr; + } + + if (_recRootSignatureEncode == nullptr) + return false; + + // Compile shader blobs + auto _recEncodeShader = CompileShader(_recEncodeShaderCode.c_str(), "main", "cs_5_0"); + + if (_recEncodeShader == nullptr) + { + return false; + } + + auto _recDecodeShader = CompileShader(_recDecodeShaderCode.c_str(), "main", "cs_5_0"); + + if (_recDecodeShader == nullptr) + { + return false; + } + + do + { + // create pso objects + if (!CreateComputeShader(InDevice, _recRootSignatureEncode, &_recPSOEncode, _recEncodeShader)) + { + break; + } + + if (!CreateComputeShader(InDevice, _recRootSignatureDecode, &_recPSODecode, _recDecodeShader)) + { + break; + } + } while (false); + + if (_recEncodeShader != nullptr) + { + _recEncodeShader->Release(); + _recEncodeShader = nullptr; + } + + if (_recDecodeShader != nullptr) + { + _recDecodeShader->Release(); + _recDecodeShader = nullptr; + } + + _recInit = _recPSOEncode != nullptr && _recPSODecode != nullptr; + + return _recInit; +} + +bool XeSSFeature::RecDecode(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* input, ID3D12Resource* output) +{ + if (!_recInit) + return false; + + ID3D12DescriptorHeap* srvHeap; + D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; + heapDesc.NumDescriptors = 2; // One for SRV and one for UAV + heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + + auto hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&srvHeap)); + + if (FAILED(hr)) + { + return false; + } + + auto srvHandle = srvHeap->GetCPUDescriptorHandleForHeapStart(); + auto uavHandle = srvHandle; + uavHandle.ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + D3D12_GPU_DESCRIPTOR_HANDLE gpuSrvHandle = srvHeap->GetGPUDescriptorHandleForHeapStart(); + D3D12_GPU_DESCRIPTOR_HANDLE gpuUavHandle = gpuSrvHandle; + gpuUavHandle.ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + // Create SRV for Input Texture + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = input->GetDesc().Format; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + + InDevice->CreateShaderResourceView(input, &srvDesc, srvHandle); + + // Create UAV for Output Texture + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.Format = output->GetDesc().Format; + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = 0; + + InDevice->CreateUnorderedAccessView(output, nullptr, &uavDesc, uavHandle); + + ID3D12DescriptorHeap* heaps[] = { srvHeap }; + InCmdList->SetDescriptorHeaps(_countof(heaps), heaps); + + InCmdList->SetComputeRootSignature(_recRootSignatureDecode); + InCmdList->SetPipelineState(_recPSODecode); + + InCmdList->SetComputeRootDescriptorTable(0, gpuSrvHandle); + InCmdList->SetComputeRootDescriptorTable(1, gpuUavHandle); + + UINT dispatchWidth = (input->GetDesc().Width + 7) / 16; + UINT dispatchHeight = (input->GetDesc().Height + 7) / 16; + InCmdList->Dispatch(dispatchWidth, dispatchHeight, 1); + + //ID3D12Fence* d3d12Fence; + //InDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3d12Fence)); + //d3d12Fence->Signal(999); + + //auto fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + + //if (d3d12Fence->SetEventOnCompletion(999, fenceEvent) == S_OK) + //{ + // WaitForSingleObject(fenceEvent, INFINITE); + // CloseHandle(fenceEvent); + //} + //else + // spdlog::warn("IFeature_Dx11wDx12::~IFeature_Dx11wDx12 can't get fenceEvent handle"); + + //d3d12Fence->Release(); + + return true; +} + +bool XeSSFeature::RecEncode(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* input, ID3D12Resource* output) +{ + if (!_recInit) + return false; + + ID3D12DescriptorHeap* srvHeap; + D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; + heapDesc.NumDescriptors = 2; // One for SRV and one for UAV + heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + + auto hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&srvHeap)); + + if (FAILED(hr)) + { + return false; + } + + auto srvHandle = srvHeap->GetCPUDescriptorHandleForHeapStart(); + auto uavHandle = srvHandle; + uavHandle.ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + D3D12_GPU_DESCRIPTOR_HANDLE gpuSrvHandle = srvHeap->GetGPUDescriptorHandleForHeapStart(); + D3D12_GPU_DESCRIPTOR_HANDLE gpuUavHandle = gpuSrvHandle; + gpuUavHandle.ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + // Create SRV for Input Texture + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = input->GetDesc().Format; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + + InDevice->CreateShaderResourceView(input, &srvDesc, srvHandle); + + // Create UAV for Output Texture + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.Format = output->GetDesc().Format; + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = 0; + + InDevice->CreateUnorderedAccessView(output, nullptr, &uavDesc, uavHandle); + + ID3D12DescriptorHeap* heaps[] = { srvHeap }; + InCmdList->SetDescriptorHeaps(_countof(heaps), heaps); + + InCmdList->SetComputeRootSignature(_recRootSignatureEncode); + InCmdList->SetPipelineState(_recPSOEncode); + + InCmdList->SetComputeRootDescriptorTable(0, gpuSrvHandle); + InCmdList->SetComputeRootDescriptorTable(1, gpuUavHandle); + + UINT dispatchWidth = (input->GetDesc().Width + 7) / 16; + UINT dispatchHeight = (input->GetDesc().Height + 7) / 16; + InCmdList->Dispatch(dispatchWidth, dispatchHeight, 1); + + return true; +} + +bool XeSSFeature::CreateRecBufferResource(ID3D12Resource* source, ID3D12Device* device, ID3D12Resource** output) +{ + if (!_recInit) + return false; + + if (source == nullptr) + return false; + + D3D12_RESOURCE_DESC texDesc = source->GetDesc(); + + if (*output != nullptr) + { + D3D12_RESOURCE_DESC outDesc = (*output)->GetDesc(); + + if (outDesc.Width != texDesc.Width || outDesc.Height != texDesc.Height || outDesc.Format != texDesc.Format) + { + (*output)->Release(); + (*output) = nullptr; + } + else + { + return true; + } + } + spdlog::debug("XeSSFeature::CreateRecBufferResource Start!"); + + D3D12_HEAP_PROPERTIES heapProperties; + D3D12_HEAP_FLAGS heapFlags; + HRESULT hr = source->GetHeapProperties(&heapProperties, &heapFlags); + + if (hr != S_OK) + { + spdlog::error("XeSSFeature::CreateRecBufferResource GetHeapProperties result: {0:x}", hr); + return false; + } + + if (*output != nullptr) + (*output)->Release(); + + texDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + + hr = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &texDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(output)); + + if (hr != S_OK) + { + spdlog::error("XeSSFeature::CreateRecBufferResource CreateCommittedResource result: {0:x}", hr); + return false; + } + return true; } \ No newline at end of file diff --git a/CyberXeSS/backends/xess/XeSSFeature.h b/CyberXeSS/backends/xess/XeSSFeature.h index aeb05115..2a582317 100644 --- a/CyberXeSS/backends/xess/XeSSFeature.h +++ b/CyberXeSS/backends/xess/XeSSFeature.h @@ -51,6 +51,15 @@ protected: ID3D12Resource* casBuffer = nullptr; FfxCas::FfxCasContextDescription casContextDesc = {}; + //rec709 + bool _recInit = false; + ID3D12RootSignature* _recRootSignatureEncode = nullptr; + ID3D12RootSignature* _recRootSignatureDecode = nullptr; + ID3D12PipelineState* _recPSOEncode = nullptr; + ID3D12PipelineState* _recPSODecode = nullptr; + ID3D12Resource* _recBufferEncode = nullptr; + ID3D12Resource* _recBufferDecode = nullptr; + bool InitXeSS(ID3D12Device* device, const NVSDK_NGX_Parameter* InParameters); void CasInit(); @@ -59,6 +68,11 @@ protected: bool CreateCasBufferResource(ID3D12Resource* source, ID3D12Device* device); bool CasDispatch(ID3D12CommandList* commandList, const NVSDK_NGX_Parameter* initParams, ID3D12Resource* input, ID3D12Resource* output); + bool RecInit(ID3D12Device* InDevice); + bool RecDecode(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* input, ID3D12Resource* output); + bool RecEncode(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* input, ID3D12Resource* output); + bool CreateRecBufferResource(ID3D12Resource* source, ID3D12Device* device, ID3D12Resource** output); + public: XeSSFeature(unsigned int handleId, const NVSDK_NGX_Parameter* InParameters) : IFeature(handleId, InParameters) diff --git a/CyberXeSS/backends/xess/XeSSFeature_Dx11.cpp b/CyberXeSS/backends/xess/XeSSFeature_Dx11.cpp index 20d28425..571fc8d8 100644 --- a/CyberXeSS/backends/xess/XeSSFeature_Dx11.cpp +++ b/CyberXeSS/backends/xess/XeSSFeature_Dx11.cpp @@ -86,7 +86,19 @@ bool XeSSFeatureDx11::Evaluate(ID3D11DeviceContext* InDeviceContext, const NVSDK return false; } - params.pColorTexture = dx11Color.Dx12Resource; + if (Config::Instance()->ColorSpaceFix.value_or(false)) + { + CreateRecBufferResource(dx11Color.Dx12Resource, Dx12on11Device, &_recBufferDecode); + ResourceBarrier(Dx12CommandList, _recBufferDecode, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + + if (RecDecode(Dx12on11Device, Dx12CommandList, dx11Color.Dx12Resource, _recBufferDecode)) + params.pColorTexture = _recBufferDecode; + else + params.pColorTexture = dx11Color.Dx12Resource; + } + else + params.pColorTexture = dx11Color.Dx12Resource; + _hasColor = params.pColorTexture != nullptr; params.pVelocityTexture = dx11Mv.Dx12Resource; _hasMV = params.pVelocityTexture != nullptr; @@ -110,8 +122,21 @@ bool XeSSFeatureDx11::Evaluate(ID3D11DeviceContext* InDeviceContext, const NVSDK params.pOutputTexture = casBuffer; } else - params.pOutputTexture = dx11Out.Dx12Resource; - + { + if (Config::Instance()->ColorSpaceFix.value_or(false)) + { + if (CreateRecBufferResource(dx11Out.Dx12Resource, Dx12on11Device, &_recBufferEncode)) + { + ResourceBarrier(Dx12CommandList, dx11Out.Dx12Resource, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + params.pOutputTexture = _recBufferEncode; + } + else + params.pOutputTexture = dx11Out.Dx12Resource; + } + else + params.pOutputTexture = dx11Out.Dx12Resource; + } + _hasOutput = params.pOutputTexture != nullptr; params.pDepthTexture = dx11Depth.Dx12Resource; @@ -157,18 +182,43 @@ bool XeSSFeatureDx11::Evaluate(ID3D11DeviceContext* InDeviceContext, const NVSDK } //apply cas - if (Config::Instance()->CasEnabled.value_or(true) && !CasDispatch(Dx12CommandList, InParameters, casBuffer, dx11Out.Dx12Resource)) + if (Config::Instance()->CasEnabled.value_or(true) && casSharpness > 0.0f) { - Config::Instance()->CasEnabled = false; + if (Config::Instance()->ColorSpaceFix.value_or(false)) + { + CreateRecBufferResource(casBuffer, Dx12on11Device, &_recBufferEncode); + ResourceBarrier(Dx12CommandList, _recBufferEncode, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); - Dx12CommandList->Close(); - ID3D12CommandList* ppCommandLists[] = { Dx12CommandList }; - Dx12CommandQueue->ExecuteCommandLists(1, ppCommandLists); + if (!CasDispatch(Dx12CommandList, InParameters, casBuffer, _recBufferEncode)) + { + Config::Instance()->CasEnabled = false; - Dx12CommandAllocator->Reset(); - Dx12CommandList->Reset(Dx12CommandAllocator, nullptr); + Dx12CommandList->Close(); + ID3D12CommandList* ppCommandLists[] = { Dx12CommandList }; + Dx12CommandQueue->ExecuteCommandLists(1, ppCommandLists); - return true; + Dx12CommandAllocator->Reset(); + Dx12CommandList->Reset(Dx12CommandAllocator, nullptr); + + return true; + } + } + else + { + if (!CasDispatch(Dx12CommandList, InParameters, casBuffer, dx11Out.Dx12Resource)) + { + Config::Instance()->CasEnabled = false; + + Dx12CommandList->Close(); + ID3D12CommandList* ppCommandLists[] = { Dx12CommandList }; + Dx12CommandQueue->ExecuteCommandLists(1, ppCommandLists); + + Dx12CommandAllocator->Reset(); + Dx12CommandList->Reset(Dx12CommandAllocator, nullptr); + + return true; + } + } } // Execute dx12 commands to process xess @@ -176,6 +226,13 @@ bool XeSSFeatureDx11::Evaluate(ID3D11DeviceContext* InDeviceContext, const NVSDK ID3D12CommandList* ppCommandLists[] = { Dx12CommandList }; Dx12CommandQueue->ExecuteCommandLists(1, ppCommandLists); + if (Config::Instance()->ColorSpaceFix.value_or(false)) + { + ResourceBarrier(Dx12CommandList, _recBufferEncode, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + ResourceBarrier(Dx12CommandList, dx11Out.Dx12Resource, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + RecEncode(Dx12on11Device, Dx12CommandList, _recBufferEncode, dx11Out.Dx12Resource); + } + if (!CopyBackOutput()) { spdlog::error("XeSSFeatureDx11::Evaluate Can't copy output texture back!"); diff --git a/CyberXeSS/backends/xess/XeSSFeature_Dx12.cpp b/CyberXeSS/backends/xess/XeSSFeature_Dx12.cpp index b8842d5d..761b6603 100644 --- a/CyberXeSS/backends/xess/XeSSFeature_Dx12.cpp +++ b/CyberXeSS/backends/xess/XeSSFeature_Dx12.cpp @@ -44,25 +44,39 @@ bool XeSSFeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, const N spdlog::debug("XeSSFeatureDx12::Evaluate Input Resolution: {0}x{1}", params.inputWidth, params.inputHeight); - if (InParameters->Get(NVSDK_NGX_Parameter_Color, ¶ms.pColorTexture) != NVSDK_NGX_Result_Success) - InParameters->Get(NVSDK_NGX_Parameter_Color, (void**)¶ms.pColorTexture); + ID3D12Resource* paramColor; + if (InParameters->Get(NVSDK_NGX_Parameter_Color, ¶mColor) != NVSDK_NGX_Result_Success) + InParameters->Get(NVSDK_NGX_Parameter_Color, (void**)¶mColor); - if (params.pColorTexture) + if (paramColor) { spdlog::debug("XeSSFeatureDx12::Evaluate Color exist.."); if (Config::Instance()->ColorResourceBarrier.has_value()) - ResourceBarrier(InCommandList, params.pColorTexture, + ResourceBarrier(InCommandList, paramColor, (D3D12_RESOURCE_STATES)Config::Instance()->ColorResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); else if (Config::Instance()->NVNGX_Engine == NVSDK_NGX_ENGINE_TYPE_UNREAL) { Config::Instance()->ColorResourceBarrier = (int)D3D12_RESOURCE_STATE_RENDER_TARGET; - ResourceBarrier(InCommandList, params.pColorTexture, + ResourceBarrier(InCommandList, paramColor, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); } + + if (Config::Instance()->ColorSpaceFix.value_or(false) && + CreateRecBufferResource(paramColor, Device, &_recBufferDecode) && + RecDecode(Device, InCommandList, paramColor, _recBufferDecode)) + { + ResourceBarrier(InCommandList, _recBufferDecode, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + + params.pColorTexture = _recBufferDecode; + } + else + params.pColorTexture = paramColor; } else { @@ -112,7 +126,15 @@ bool XeSSFeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, const N params.pOutputTexture = casBuffer; } else - params.pOutputTexture = paramOutput; + { + if (Config::Instance()->ColorSpaceFix.value_or(false)) + { + CreateRecBufferResource(paramOutput, Device, &_recBufferEncode); + params.pOutputTexture = _recBufferEncode; + } + else + params.pOutputTexture = paramOutput; + } } else { @@ -210,10 +232,24 @@ bool XeSSFeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, const N } //apply cas - if (Config::Instance()->CasEnabled.value_or(true) && !CasDispatch(InCommandList, InParameters, casBuffer, paramOutput)) + if (Config::Instance()->CasEnabled.value_or(true) && casSharpness > 0.0f) { - Config::Instance()->CasEnabled = false; - return true; + if (Config::Instance()->ColorSpaceFix.value_or(false)) + { + if (!CreateRecBufferResource(casBuffer, Device, &_recBufferEncode) || !CasDispatch(InCommandList, InParameters, casBuffer, _recBufferEncode)) + { + Config::Instance()->CasEnabled = false; + return true; + } + } + else + { + if (!CasDispatch(InCommandList, InParameters, casBuffer, paramOutput)) + { + Config::Instance()->CasEnabled = false; + return true; + } + } } // imgui @@ -222,11 +258,22 @@ bool XeSSFeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, const N if (Imgui->IsHandleDifferent()) Imgui.reset(); else - Imgui->Render(InCommandList, paramOutput); + { + if (Config::Instance()->ColorSpaceFix.value_or(false)) + Imgui->Render(InCommandList, _recBufferEncode); + else + Imgui->Render(InCommandList, paramOutput); + } } else Imgui = std::make_unique(GetForegroundWindow(), Device); + if (Config::Instance()->ColorSpaceFix.value_or(false)) + { + ResourceBarrier(InCommandList, _recBufferEncode, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + RecEncode(Device, InCommandList, _recBufferEncode, paramOutput); + } + // restore resource states if (params.pColorTexture && Config::Instance()->ColorResourceBarrier.has_value()) ResourceBarrier(InCommandList, params.pColorTexture, diff --git a/CyberXeSS/imgui/Imgui_Base.cpp b/CyberXeSS/imgui/Imgui_Base.cpp index a2e547a6..1400f8ea 100644 --- a/CyberXeSS/imgui/Imgui_Base.cpp +++ b/CyberXeSS/imgui/Imgui_Base.cpp @@ -741,6 +741,7 @@ Imgui_Base::Imgui_Base(HWND handle) context = ImGui::CreateContext(); ImGui::SetCurrentContext(context); ImGui::StyleColorsDark(); + auto style = ImGui::GetStyle(); style.Colors[ImGuiCol_WindowBg] = ImVec4(0.1f, 0.1f, 0.1f, 0.20f); @@ -749,6 +750,7 @@ Imgui_Base::Imgui_Base(HWND handle) ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; + io.ConfigFlags |= ImGuiConfigFlags_IsSRGB; io.MouseDrawCursor = _isVisible; io.WantCaptureKeyboard = _isVisible;