This commit is contained in:
cdozdil
2024-10-21 02:44:08 +03:00
parent 79c5f3f8d3
commit 8828fa65f8
12 changed files with 676 additions and 65 deletions
+2 -4
View File
@@ -55,9 +55,8 @@ bool Config::Reload(std::filesystem::path iniPath)
FGDebugView = readBool("FrameGen", "DebugView");
FGAsync = readBool("FrameGen", "AllowAsync");
FGHUDFix = readBool("FrameGen", "HUDFix");
FGHUDFixExtended = readBool("FrameGen", "HUDFixExtended");
FGHUDLimit = readInt("FrameGen", "HUDLimit");
FGSkipInstanced = readBool("FrameGen", "HUDSkipInstanced");
FGSkipIndexedInstanced = readBool("FrameGen", "HUDSkipIndexed");
}
// FSR
@@ -479,9 +478,8 @@ bool Config::SaveIni()
ini.SetValue("FrameGen", "DebugView", GetBoolValue(Instance()->FGDebugView).c_str());
ini.SetValue("FrameGen", "AllowAsync", GetBoolValue(Instance()->FGAsync).c_str());
ini.SetValue("FrameGen", "HUDFix", GetBoolValue(Instance()->FGHUDFix).c_str());
ini.SetValue("FrameGen", "HUDFixExtended", GetBoolValue(Instance()->FGHUDFixExtended).c_str());
ini.SetValue("FrameGen", "HUDLimit", GetIntValue(Instance()->FGHUDLimit).c_str());
ini.SetValue("FrameGen", "HUDSkipInstanced", GetBoolValue(Instance()->FGSkipInstanced).c_str());
ini.SetValue("FrameGen", "HUDSkipIndexed", GetBoolValue(Instance()->FGSkipIndexedInstanced).c_str());
}
// Output Scaling
+2 -3
View File
@@ -164,12 +164,11 @@ public:
std::optional<bool> FGDebugView;
std::optional<bool> FGAsync;
std::optional<bool> FGHUDFix;
std::optional<bool> FGSkipInstanced;
std::optional<bool> FGSkipIndexedInstanced;
std::optional<bool> FGHUDFixExtended;
std::optional<int> FGHUDLimit;
bool FGOnlyGenerated = false;
bool FGChanged = false;
bool SCChanged = false;
bool SCChanged = true;
bool SkipHeapCapture = false;
+12 -9
View File
@@ -72,6 +72,12 @@ static void ReleaseFGObjects()
ImGuiOverlayDx::fgCopyCommandQueue->Release();
ImGuiOverlayDx::fgCopyCommandQueue = nullptr;
}
if (ImGuiOverlayDx::fgFormatTransfer != nullptr)
{
delete ImGuiOverlayDx::fgFormatTransfer;
ImGuiOverlayDx::fgFormatTransfer = nullptr;
}
}
static void CreateFGObjects()
@@ -112,7 +118,7 @@ static void CreateFGObjects()
// Create a command queue for copy operations
D3D12_COMMAND_QUEUE_DESC copyQueueDesc = {};
copyQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
copyQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
copyQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH;
copyQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
copyQueueDesc.NodeMask = 0;
@@ -123,6 +129,9 @@ static void CreateFGObjects()
break;
}
ImGuiOverlayDx::fgCopyCommandQueue->SetName(L"fgCopyCommandQueue");
ImGuiOverlayDx::fgFormatTransfer = new FT_Dx12("FormatTransfer", D3D12Device, ImGuiOverlayDx::swapchainFormat);
} while (false);
}
@@ -1575,8 +1584,6 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom
};
m_FrameGenerationConfig.frameGenerationCallbackUserContext = &ImGuiOverlayDx::fgContext;
m_FrameGenerationConfig.onlyPresentGenerated = Config::Instance()->FGOnlyGenerated; // check here
m_FrameGenerationConfig.frameID = deviceContext->FrameCount();
m_FrameGenerationConfig.swapChain = ImGuiOverlayDx::currentSwapchain;
@@ -1679,8 +1686,6 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom
ImGuiOverlayDx::fgUpscaledImage[frameIndex] = output;
LOG_DEBUG("Set fgUpscaledImage[{}]", frameIndex);
ImGuiOverlayDx::upscaleRan = true;
auto allocator = ImGuiOverlayDx::fgCopyCommandAllocators[frameIndex];
auto result = allocator->Reset();
result = ImGuiOverlayDx::fgCopyCommandList->Reset(allocator, nullptr);
@@ -1694,18 +1699,14 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom
InParameters->Get(NVSDK_NGX_Parameter_MotionVectors, (void**)&paramVelocity);
if (CreateBufferResource(L"fgVelocity", D3D12Device, paramVelocity, D3D12_RESOURCE_STATE_COPY_DEST, &ImGuiOverlayDx::paramVelocity[frameIndex]))
{
InCmdList->CopyResource(ImGuiOverlayDx::paramVelocity[frameIndex], paramVelocity);
}
ID3D12Resource* paramDepth;
if (InParameters->Get(NVSDK_NGX_Parameter_Depth, &paramDepth) != NVSDK_NGX_Result_Success)
InParameters->Get(NVSDK_NGX_Parameter_Depth, (void**)&paramDepth);
if (CreateBufferResource(L"fgDepth", D3D12Device, paramDepth, D3D12_RESOURCE_STATE_COPY_DEST, &ImGuiOverlayDx::paramDepth[frameIndex]))
{
InCmdList->CopyResource(ImGuiOverlayDx::paramDepth[frameIndex], paramDepth);
}
InParameters->Get(NVSDK_NGX_Parameter_MV_Scale_X, &ImGuiOverlayDx::mvScaleX);
InParameters->Get(NVSDK_NGX_Parameter_MV_Scale_Y, &ImGuiOverlayDx::mvScaleY);
@@ -1721,6 +1722,8 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom
fgLastFrameTime = now;
ImGuiOverlayDx::fgFrameTime = msDelta;
ImGuiOverlayDx::upscaleRan = true;
LOG_DEBUG(" FG HUDFix done, frame: {0}", deviceContext->FrameCount());
}
+3
View File
@@ -206,6 +206,8 @@ copy $(SolutionDir)nvngx.ini $(SolutionDir)x64\Release\a\</Command>
<ClInclude Include="bias\Bias_Dx12.h" />
<ClInclude Include="bias\Bias_Dx11.h" />
<ClInclude Include="bias\precompile\Bias_Shader.h" />
<ClInclude Include="format_transfer\FT_Common.h" />
<ClInclude Include="format_transfer\FT_Dx12.h" />
<ClInclude Include="output_scaling\OS_Common.h" />
<ClInclude Include="output_scaling\OS_Dx12.h" />
<ClInclude Include="output_scaling\precompile\BCDS_Shader.h" />
@@ -292,6 +294,7 @@ copy $(SolutionDir)nvngx.ini $(SolutionDir)x64\Release\a\</Command>
<ClCompile Include="backends\fsr2\FSR2Feature_Vk.cpp" />
<ClCompile Include="backends\IFeature.cpp" />
<ClCompile Include="backends\IFeature_Dx12.cpp" />
<ClCompile Include="format_transfer\FT_Dx12.cpp" />
<ClCompile Include="imgui\imgui\imgui.cpp" />
<ClCompile Include="imgui\imgui\imgui_demo.cpp" />
<ClCompile Include="imgui\imgui\imgui_draw.cpp" />
+3 -9
View File
@@ -242,15 +242,6 @@
<ClInclude Include="backends\fsr31\FSR31Feature_Dx11.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="XeSS_Proxy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="depth_upscale\DU_Common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="depth_upscale\DU_Dx12.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="format_transfer\FT_Common.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -446,6 +437,9 @@
<ClCompile Include="backends\fsr31\FSR31Feature_Dx11.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="format_transfer\FT_Dx12.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XeSS_Debug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+118
View File
@@ -0,0 +1,118 @@
#pragma once
#include "../pch.h"
#include <d3dcompiler.h>
#include <DirectXMath.h>
inline static std::string ftR10G10B10A2Code = R"(
Texture2D<float4> SourceTexture : register(t0);
RWTexture2D<uint> DestinationTexture : register(u0); // R10G10B10A2_UNORM destination texture
// Shader to perform the conversion
[numthreads(512, 1, 1)]
void CSMain(uint3 dispatchThreadID : SV_DispatchThreadID)
{
// Read from the source texture
float4 srcColor = SourceTexture.Load(int3(dispatchThreadID.xy, 0));
// Clamp color channels to [0, 1] range, as R10G10B10A2_UNORM is normalized
srcColor = saturate(srcColor); // Ensures all values are between 0 and 1
// Convert each channel to its corresponding bit range
uint R = (uint)(srcColor.r * 1023.0f); // 10 bits for Red
uint G = (uint)(srcColor.g * 1023.0f); // 10 bits for Green
uint B = (uint)(srcColor.b * 1023.0f); // 10 bits for Blue
uint A = (uint)(srcColor.a * 3.0f); // 2 bits for Alpha
// Pack the values into a single 32-bit unsigned int
uint packedColor = R | G << 10 | B << 20 | A << 30;
// Write the packed color to the destination texture
DestinationTexture[dispatchThreadID.xy] = packedColor;
}
)";
inline static std::string ftR8G8B8A8Code = R"(
Texture2D<float4> SourceTexture : register(t0);
RWTexture2D<uint> DestinationTexture : register(u0); // R8G8B8A8_UNORM destination texture
// Shader to perform the conversion
[numthreads(512, 1, 1)]
void CSMain(uint3 dispatchThreadID : SV_DispatchThreadID)
{
// Read from the source texture
float4 srcColor = SourceTexture.Load(int3(dispatchThreadID.xy, 0));
// Clamp color channels to [0, 1] range, as R8G8B8A8_UNORM is normalized
srcColor = saturate(srcColor); // Ensures all values are between 0 and 1
// Convert each channel to its corresponding bit range
uint R = (uint)(srcColor.r * 255.0f); // 8 bits for Red
uint G = (uint)(srcColor.g * 255.0f); // 8 bits for Green
uint B = (uint)(srcColor.b * 255.0f); // 8 bits for Blue
uint A = (uint)(srcColor.a * 255.0f); // 8 bits for Alpha
// Pack the values into a single 32-bit unsigned int
uint packedColor = R | G << 8 | B << 16 | A << 24;
// Write the packed color to the destination texture
DestinationTexture[dispatchThreadID.xy] = packedColor;
}
)";
inline static std::string ftB8G8R8A8Code = R"(
Texture2D<float4> SourceTexture : register(t0);
RWTexture2D<uint> DestinationTexture : register(u0); // R8G8B8A8_UNORM destination texture
// Shader to perform the conversion
[numthreads(512, 1, 1)]
void CSMain(uint3 dispatchThreadID : SV_DispatchThreadID)
{
// Read from the source texture
float4 srcColor = SourceTexture.Load(int3(dispatchThreadID.xy, 0));
// Clamp color channels to [0, 1] range, as R8G8B8A8_UNORM is normalized
srcColor = saturate(srcColor); // Ensures all values are between 0 and 1
// Convert each channel to its corresponding bit range
uint R = (uint)(srcColor.r * 255.0f); // 8 bits for Red
uint G = (uint)(srcColor.g * 255.0f); // 8 bits for Green
uint B = (uint)(srcColor.b * 255.0f); // 8 bits for Blue
uint A = (uint)(srcColor.a * 255.0f); // 8 bits for Alpha
// Pack the values into a single 32-bit unsigned int
uint packedColor = B | R << 8 | G << 16 | A << 24;
// Write the packed color to the destination texture
DestinationTexture[dispatchThreadID.xy] = packedColor;
}
)";
inline static ID3DBlob* FT_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, D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &shaderBlob, &errorBlob);
if (FAILED(hr))
{
LOG_ERROR("error while compiling shader");
if (errorBlob)
{
LOG_ERROR("error while compiling shader : {0}", (char*)errorBlob->GetBufferPointer());
errorBlob->Release();
}
if (shaderBlob)
shaderBlob->Release();
return nullptr;
}
if (errorBlob)
errorBlob->Release();
return shaderBlob;
}
+422
View File
@@ -0,0 +1,422 @@
#include "FT_Dx12.h"
#include "../Config.h"
inline static DXGI_FORMAT TranslateTypelessFormats(DXGI_FORMAT format)
{
switch (format) {
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
return DXGI_FORMAT_R32G32B32A32_FLOAT;
case DXGI_FORMAT_R32G32B32_TYPELESS:
return DXGI_FORMAT_R32G32B32_FLOAT;
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
return DXGI_FORMAT_R16G16B16A16_FLOAT;
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
return DXGI_FORMAT_R10G10B10A2_UINT;
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
return DXGI_FORMAT_R8G8B8A8_UNORM;
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
return DXGI_FORMAT_B8G8R8A8_UNORM;
case DXGI_FORMAT_R16G16_TYPELESS:
return DXGI_FORMAT_R16G16_FLOAT;
case DXGI_FORMAT_R32G32_TYPELESS:
return DXGI_FORMAT_R32G32_FLOAT;
case DXGI_FORMAT_R32G8X24_TYPELESS:
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
case DXGI_FORMAT_R32_TYPELESS:
return DXGI_FORMAT_R32_FLOAT;
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
default:
return format;
}
}
static bool CreateComputeShader(ID3D12Device* device, ID3D12RootSignature* rootSignature, ID3D12PipelineState** pipelineState, ID3DBlob* shaderBlob)
{
D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.pRootSignature = rootSignature;
psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
psoDesc.CS = CD3DX12_SHADER_BYTECODE(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize());
HRESULT hr = device->CreateComputePipelineState(&psoDesc, __uuidof(ID3D12PipelineState*), (void**)pipelineState);
if (FAILED(hr))
{
LOG_ERROR("CreateComputePipelineState error {0:x}", hr);
return false;
}
return true;
}
bool FT_Dx12::CreateBufferResource(ID3D12Device* InDevice, ID3D12Resource* InSource, D3D12_RESOURCE_STATES InState)
{
if (InDevice == nullptr || InSource == nullptr)
return false;
LOG_FUNC();
D3D12_RESOURCE_DESC texDesc = InSource->GetDesc();
if (_buffer != nullptr)
{
auto bufDesc = _buffer->GetDesc();
if (bufDesc.Width != texDesc.Width || bufDesc.Height != texDesc.Height || bufDesc.Format != format)
{
_buffer->Release();
_buffer = nullptr;
}
else
return true;
}
LOG_DEBUG("[{0}] Start!", _name);
LOG_INFO("Texture Format: {}", (UINT)texDesc.Format);
D3D12_HEAP_PROPERTIES heapProperties;
D3D12_HEAP_FLAGS heapFlags;
HRESULT hr = InSource->GetHeapProperties(&heapProperties, &heapFlags);
if (hr != S_OK)
{
LOG_ERROR("[{0}] GetHeapProperties result: {1:x}", _name.c_str(), hr);
return false;
}
texDesc.Format = format;
texDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS;
hr = InDevice->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &texDesc, InState, nullptr, IID_PPV_ARGS(&_buffer));
if (hr != S_OK)
{
LOG_ERROR("[{0}] CreateCommittedResource result: {1:x}", _name, hr);
return false;
}
_buffer->SetName(L"HUDless_Buffer");
_bufferState = InState;
return true;
}
void FT_Dx12::SetBufferState(ID3D12GraphicsCommandList* InCommandList, D3D12_RESOURCE_STATES InState)
{
if (_bufferState == InState)
return;
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = _buffer;
barrier.Transition.StateBefore = _bufferState;
barrier.Transition.StateAfter = InState;
barrier.Transition.Subresource = 0;
InCommandList->ResourceBarrier(1, &barrier);
_bufferState = InState;
}
bool FT_Dx12::Dispatch(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* InResource, ID3D12Resource* OutResource)
{
if (!_init || InDevice == nullptr || InCmdList == nullptr || InResource == nullptr || OutResource == nullptr)
return false;
LOG_DEBUG("[{0}] Start!", _name);
_counter++;
_counter = _counter % 2;
if (_cpuSrvHandle[_counter].ptr == NULL)
_cpuSrvHandle[_counter] = _srvHeap[_counter]->GetCPUDescriptorHandleForHeapStart();
if (_cpuUavHandle[_counter].ptr == NULL)
{
_cpuUavHandle[_counter] = _cpuSrvHandle[_counter];
_cpuUavHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
if (_gpuSrvHandle[_counter].ptr == NULL)
_gpuSrvHandle[_counter] = _srvHeap[_counter]->GetGPUDescriptorHandleForHeapStart();
if (_gpuUavHandle[_counter].ptr == NULL)
{
_gpuUavHandle[_counter] = _gpuSrvHandle[_counter];
_gpuUavHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
auto inDesc = InResource->GetDesc();
auto outDesc = OutResource->GetDesc();
// Create SRV for Input Texture
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = TranslateTypelessFormats(inDesc.Format);
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
InDevice->CreateShaderResourceView(InResource, &srvDesc, _cpuSrvHandle[_counter]);
// Create UAV for Output Texture
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
uavDesc.Format = DXGI_FORMAT_R32_UINT;
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
uavDesc.Texture2D.MipSlice = 0;
InDevice->CreateUnorderedAccessView(OutResource, nullptr, &uavDesc, _cpuUavHandle[_counter]);
ID3D12DescriptorHeap* heaps[] = { _srvHeap[_counter] };
InCmdList->SetDescriptorHeaps(_countof(heaps), heaps);
InCmdList->SetComputeRootSignature(_rootSignature);
InCmdList->SetPipelineState(_pipelineState);
InCmdList->SetComputeRootDescriptorTable(0, _gpuSrvHandle[_counter]);
InCmdList->SetComputeRootDescriptorTable(1, _gpuUavHandle[_counter]);
UINT dispatchWidth = 0;
UINT dispatchHeight = 0;
dispatchWidth = static_cast<UINT>((Config::Instance()->CurrentFeature->DisplayWidth() + InNumThreadsX - 1) / InNumThreadsX);
dispatchHeight = (Config::Instance()->CurrentFeature->DisplayHeight() + InNumThreadsY - 1) / InNumThreadsY;
InCmdList->Dispatch(dispatchWidth, dispatchHeight, 1);
return true;
}
FT_Dx12::FT_Dx12(std::string InName, ID3D12Device* InDevice, DXGI_FORMAT InFormat) : _name(InName), _device(InDevice), format(InFormat)
{
if (InDevice == nullptr)
{
LOG_ERROR("InDevice is nullptr!");
return;
}
LOG_DEBUG("{0} start!", _name);
// 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))
{
LOG_ERROR("[{0}] D3D12SerializeRootSignature error {1:x}", _name, hr);
break;
}
hr = InDevice->CreateRootSignature(0, signatureBlob->GetBufferPointer(), signatureBlob->GetBufferSize(), IID_PPV_ARGS(&_rootSignature));
if (FAILED(hr))
{
LOG_ERROR("[{0}] CreateRootSignature error {1:x}", _name, hr);
break;
}
} while (false);
if (errorBlob != nullptr)
{
errorBlob->Release();
errorBlob = nullptr;
}
if (signatureBlob != nullptr)
{
signatureBlob->Release();
signatureBlob = nullptr;
}
if (_rootSignature == nullptr)
{
LOG_ERROR("[{0}] _rootSignature is null!", _name);
return;
}
// Compile shader blobs
ID3DBlob* _recEncodeShader = nullptr;
if (InFormat == DXGI_FORMAT_R10G10B10A2_UNORM)
{
_recEncodeShader = FT_CompileShader(ftR10G10B10A2Code.c_str(), "CSMain", "cs_5_0");
}
else if (InFormat == DXGI_FORMAT_R8G8B8A8_UNORM)
{
_recEncodeShader = FT_CompileShader(ftR8G8B8A8Code.c_str(), "CSMain", "cs_5_0");
}
else if (InFormat == DXGI_FORMAT_B8G8R8A8_UNORM)
{
_recEncodeShader = FT_CompileShader(ftB8G8R8A8Code.c_str(), "CSMain", "cs_5_0");
}
else
{
LOG_ERROR("[{0}] texture format is not found!", _name);
return;
}
if (_recEncodeShader == nullptr)
{
LOG_ERROR("[{0}] CompileShader error!", _name);
return;
}
// create pso objects
if (!CreateComputeShader(InDevice, _rootSignature, &_pipelineState, _recEncodeShader))
{
LOG_ERROR("[{0}] CreateComputeShader error!", _name);
return;
}
if (_recEncodeShader != nullptr)
{
_recEncodeShader->Release();
_recEncodeShader = nullptr;
}
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
heapDesc.NumDescriptors = 2; // SRV + 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[0]));
if (FAILED(hr))
{
LOG_ERROR("[{0}] CreateDescriptorHeap[0] error {1:x}", _name, hr);
return;
}
hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_srvHeap[1]));
if (FAILED(hr))
{
LOG_ERROR("[{0}] CreateDescriptorHeap[1] error {1:x}", _name, hr);
return;
}
hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_srvHeap[2]));
if (FAILED(hr))
{
LOG_ERROR("[{0}] CreateDescriptorHeap[2] error {1:x}", _name, hr);
return;
}
_init = _srvHeap[2] != nullptr;
}
FT_Dx12::~FT_Dx12()
{
if (!_init)
return;
ID3D12Fence* d3d12Fence = nullptr;
do
{
if (_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3d12Fence)) != S_OK)
break;
d3d12Fence->Signal(999);
HANDLE fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (fenceEvent != NULL && d3d12Fence->SetEventOnCompletion(999, fenceEvent) == S_OK)
{
WaitForSingleObject(fenceEvent, INFINITE);
CloseHandle(fenceEvent);
}
} while (false);
if (d3d12Fence != nullptr)
{
d3d12Fence->Release();
d3d12Fence = nullptr;
}
if (_pipelineState != nullptr)
{
_pipelineState->Release();
_pipelineState = nullptr;
}
if (_rootSignature != nullptr)
{
_rootSignature->Release();
_rootSignature = nullptr;
}
if (_srvHeap[0] != nullptr)
{
_srvHeap[0]->Release();
_srvHeap[0] = nullptr;
}
if (_srvHeap[1] != nullptr)
{
_srvHeap[1]->Release();
_srvHeap[1] = nullptr;
}
if (_srvHeap[2] != nullptr)
{
_srvHeap[2]->Release();
_srvHeap[2] = nullptr;
}
if (_buffer != nullptr)
{
_buffer->Release();
_buffer = nullptr;
}
}
+45
View File
@@ -0,0 +1,45 @@
#pragma once
#include "../pch.h"
#include "FT_Common.h"
#include <d3d12.h>
#include "../d3dx/d3dx12.h"
class FT_Dx12
{
private:
std::string _name = "";
bool _init = false;
ID3D12RootSignature* _rootSignature = nullptr;
ID3D12PipelineState* _pipelineState = nullptr;
ID3D12DescriptorHeap* _srvHeap[3] = { nullptr, nullptr, nullptr };
D3D12_CPU_DESCRIPTOR_HANDLE _cpuSrvHandle[2]{ { NULL }, { NULL } };
D3D12_CPU_DESCRIPTOR_HANDLE _cpuUavHandle[2]{ { NULL }, { NULL } };
D3D12_GPU_DESCRIPTOR_HANDLE _gpuSrvHandle[2]{ { NULL }, { NULL } };
D3D12_GPU_DESCRIPTOR_HANDLE _gpuUavHandle[2]{ { NULL }, { NULL } };
int _counter = 0;
uint32_t InNumThreadsX = 512;
uint32_t InNumThreadsY = 1;
ID3D12Device* _device = nullptr;
ID3D12Resource* _buffer = nullptr;
D3D12_RESOURCE_STATES _bufferState = D3D12_RESOURCE_STATE_COMMON;
DXGI_FORMAT format;
public:
bool CreateBufferResource(ID3D12Device* InDevice, ID3D12Resource* InSource, D3D12_RESOURCE_STATES InState);
void SetBufferState(ID3D12GraphicsCommandList* InCommandList, D3D12_RESOURCE_STATES InState);
bool Dispatch(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* InResource, ID3D12Resource* OutResource);
ID3D12Resource* Buffer() { return _buffer; }
bool IsInit() const { return _init; }
bool CanRender() const { return _init && _buffer != nullptr; }
DXGI_FORMAT Format() const { return format; }
FT_Dx12(std::string InName, ID3D12Device* InDevice, DXGI_FORMAT InFormat);
~FT_Dx12();
};
+6 -6
View File
@@ -925,15 +925,15 @@ void ImGuiCommon::RenderMenu()
Config::Instance()->FGHUDLimit = hudFixLimit;
}
ImGui::PopItemWidth();
ShowHelpMarker("Delay HUDless capture, high values might cause crash!");
//ImGui::SameLine(0.0f, 16.0f);
ImGui::SameLine(0.0f, 16.0f);
auto hudExtended = Config::Instance()->FGHUDFixExtended.value_or(false);
if (ImGui::Checkbox("Extended", &hudExtended))
Config::Instance()->FGHUDFixExtended = hudExtended;
ShowHelpMarker("Extended HUDless checks, might cause crash and slowdowns!");
//auto hudExtended = Config::Instance()->FGHUDPrevious.value_or(false);
//if (ImGui::Checkbox("Extended", &hudExtended))
// Config::Instance()->FGHUDPrevious = hudExtended;
//ShowHelpMarker("Extended HUDless checks, might cause crash and slowdowns!");
ImGui::PopItemWidth();
ImGui::EndDisabled();
+59 -32
View File
@@ -189,6 +189,7 @@ static std::shared_mutex counterMutex[ImGuiOverlayDx::FG_BUFFER_SIZE];
// found hudless info
static ID3D12Resource* fgCopySource[ImGuiOverlayDx::FG_BUFFER_SIZE] = { nullptr, nullptr, nullptr, nullptr };
static ID3D12Resource* fgHudless[ImGuiOverlayDx::FG_BUFFER_SIZE] = { nullptr, nullptr, nullptr, nullptr };
static ID3D12Resource* fgHudlessBuffer[ImGuiOverlayDx::FG_BUFFER_SIZE] = { nullptr, nullptr, nullptr, nullptr };
static UINT fgFrameIndex = 0;
@@ -477,7 +478,7 @@ static void FillResourceInfo(ID3D12Resource* resource, ResourceInfo* info)
info->format = desc.Format;
}
static void GetHudless(ID3D12GraphicsCommandList* This) //, D3D12_RESOURCE_STATES State)
static void GetHudless(ID3D12GraphicsCommandList* This, bool SkipCopy) //, D3D12_RESOURCE_STATES State)
{
auto fIndex = fgFrameIndex;
if (This != g_pd3dCommandList && fgCopySource[fIndex] != nullptr && Config::Instance()->CurrentFeature != nullptr &&
@@ -504,11 +505,14 @@ static void GetHudless(ID3D12GraphicsCommandList* This) //, D3D12_RESOURCE_STATE
This->ResourceBarrier(1, &barrier);
#endif
// Take hudless copy
if (CreateBufferResource(g_pd3dDeviceParam, fgCopySource[fIndex], D3D12_RESOURCE_STATE_COPY_DEST, &fgHudless[fIndex]))
This->CopyResource(fgHudless[fIndex], fgCopySource[fIndex]);
else
return;
if (!SkipCopy)
{
// Take hudless copy
if (CreateBufferResource(g_pd3dDeviceParam, fgCopySource[fIndex], D3D12_RESOURCE_STATE_COPY_DEST, &fgHudless[fIndex]))
This->CopyResource(fgHudless[fIndex], fgCopySource[fIndex]);
else
return;
}
#ifdef USE_RESOURCE_BARRIRER
// Not sure about source state, skipping for now
@@ -561,6 +565,7 @@ static void GetHudless(ID3D12GraphicsCommandList* This) //, D3D12_RESOURCE_STATE
result = ImGuiOverlayDx::fgCopyCommandList->Reset(allocator, nullptr);
LOG_WARN("Callback without hudless!");
params->reset = true;
}
if (Config::Instance()->CurrentFeature != nullptr)
@@ -702,13 +707,13 @@ static bool CheckCapture()
LOG_DEBUG_ONLY("lockcounterMutex[{}])", fIndex);
std::unique_lock<std::shared_mutex> lock(counterMutex[fIndex]);
ImGuiOverlayDx::fgHUDlessCaptureCounter[fIndex]++;
LOG_DEBUG("frameCounter: {}, fgHUDlessCaptureCounter: {}, Limit: {}", frameCounter, ImGuiOverlayDx::fgHUDlessCaptureCounter[fIndex], Config::Instance()->FGHUDLimit.value_or(1));
if (ImGuiOverlayDx::fgHUDlessCaptureCounter[fIndex] != Config::Instance()->FGHUDLimit.value_or(1))
return false;
}
LOG_DEBUG("frameCounter: {}, fgHUDlessCaptureCounter: {}, Limit: {}", frameCounter, ImGuiOverlayDx::fgHUDlessCaptureCounter[fIndex], Config::Instance()->FGHUDLimit.value_or(1));
if (ImGuiOverlayDx::fgHUDlessCaptureCounter[fIndex] != Config::Instance()->FGHUDLimit.value_or(1))
return false;
return true;
}
@@ -716,9 +721,36 @@ static void CaptureHudless(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* r
{
auto fIndex = fgFrameIndex;
ImGuiOverlayDx::upscaleRan = false;
fgCopySource[fIndex] = resource;
GetHudless(cmdList);
fgUpscaledFound = false;
fgCopySource[fIndex] = resource;
auto resInfo = resource->GetDesc();
if (resInfo.Format != ImGuiOverlayDx::swapchainFormat && Config::Instance()->FGHUDFixExtended.value_or(false) && ImGuiOverlayDx::fgFormatTransfer != nullptr &&
(resInfo.Format == DXGI_FORMAT_R16G16B16A16_FLOAT || resInfo.Format == DXGI_FORMAT_R11G11B10_FLOAT || resInfo.Format == DXGI_FORMAT_R32G32B32A32_FLOAT || resInfo.Format == DXGI_FORMAT_R32G32B32_FLOAT) &&
(ImGuiOverlayDx::swapchainFormat == DXGI_FORMAT_R8G8B8A8_UNORM || ImGuiOverlayDx::swapchainFormat == DXGI_FORMAT_B8G8R8A8_UNORM || ImGuiOverlayDx::swapchainFormat == DXGI_FORMAT_R10G10B10A2_UNORM))
{
if (ImGuiOverlayDx::fgFormatTransfer->CreateBufferResource(g_pd3dDeviceParam, resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS) &&
CreateBufferResource(g_pd3dDeviceParam, resource, D3D12_RESOURCE_STATE_COPY_SOURCE, &fgHudlessBuffer[fIndex]))
{
ResourceBarrier(cmdList, fgHudlessBuffer[fIndex], D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST);
cmdList->CopyResource(fgHudlessBuffer[fIndex], resource);
ResourceBarrier(cmdList, fgHudlessBuffer[fIndex], D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
ImGuiOverlayDx::fgFormatTransfer->SetBufferState(ImGuiOverlayDx::fgCopyCommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
ImGuiOverlayDx::fgFormatTransfer->Dispatch(g_pd3dDeviceParam, ImGuiOverlayDx::fgCopyCommandList, fgHudlessBuffer[fIndex], ImGuiOverlayDx::fgFormatTransfer->Buffer());
ImGuiOverlayDx::fgFormatTransfer->SetBufferState(ImGuiOverlayDx::fgCopyCommandList, D3D12_RESOURCE_STATE_COPY_SOURCE);
LOG_DEBUG_ONLY("Using fgFormatTransfer->Buffer()");
fgHudless[fIndex] = ImGuiOverlayDx::fgFormatTransfer->Buffer();
}
}
else
{
if (CreateBufferResource(g_pd3dDeviceParam, resource, D3D12_RESOURCE_STATE_COPY_DEST, &fgHudless[fIndex]))
cmdList->CopyResource(fgHudless[fIndex], resource);
}
GetHudless(cmdList, true);
}
static bool CheckForHudless(ResourceInfo* resource, bool checkFormat = true)
@@ -739,8 +771,10 @@ static bool CheckForHudless(ResourceInfo* resource, bool checkFormat = true)
Config::Instance()->SCChanged = false;
}
if (resource->height == fgScDesc.BufferDesc.Height && resource->width == fgScDesc.BufferDesc.Width &&
(!checkFormat || resource->format == fgScDesc.BufferDesc.Format))
if (resource->height == fgScDesc.BufferDesc.Height && resource->width == fgScDesc.BufferDesc.Width && (!checkFormat || resource->format == fgScDesc.BufferDesc.Format ||
(Config::Instance()->FGHUDFixExtended.value_or(false) && ImGuiOverlayDx::fgFormatTransfer != nullptr &&
(resource->format == DXGI_FORMAT_R16G16B16A16_FLOAT || resource->format == DXGI_FORMAT_R11G11B10_FLOAT || resource->format == DXGI_FORMAT_R32G32B32A32_FLOAT || resource->format == DXGI_FORMAT_R32G32B32_FLOAT) &&
(fgScDesc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM || fgScDesc.BufferDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM || fgScDesc.BufferDesc.Format == DXGI_FORMAT_R10G10B10A2_UNORM))))
{
LOG_DEBUG_ONLY("Width: {}/{}, Height: {}/{}, Format: {}/{}, checkFormat: {} -> TRUE",
resource->width, fgScDesc.BufferDesc.Width, resource->height, fgScDesc.BufferDesc.Height, (UINT)resource->format, (UINT)fgScDesc.BufferDesc.Format, checkFormat);
@@ -748,6 +782,9 @@ static bool CheckForHudless(ResourceInfo* resource, bool checkFormat = true)
return true;
}
LOG_DEBUG_ONLY("Width: {}/{}, Height: {}/{}, Format: {}/{}, checkFormat: {} -> FALSE",
resource->width, fgScDesc.BufferDesc.Width, resource->height, fgScDesc.BufferDesc.Height, (UINT)resource->format, (UINT)fgScDesc.BufferDesc.Format, checkFormat);
return false;
}
@@ -911,7 +948,7 @@ static void hkCopyTextureRegion(ID3D12GraphicsCommandList* This, D3D12_TEXTURE_C
auto fIndex = fgFrameIndex;
if (This == g_pd3dCommandList || ImGuiOverlayDx::fgCopyCommandList == This /* || fgPresentRunning */ || ImGuiOverlayDx::fgSkipHudlessChecks || Config::Instance()->CurrentFeature == nullptr || !ImGuiOverlayDx::upscaleRan)
if (This == g_pd3dCommandList || ImGuiOverlayDx::fgCopyCommandList == This || ImGuiOverlayDx::fgSkipHudlessChecks || Config::Instance()->CurrentFeature == nullptr || !ImGuiOverlayDx::upscaleRan)
return;
if (!Config::Instance()->FGEnabled.value_or(false) || !Config::Instance()->FGHUDFix.value_or(false) || ImGuiOverlayDx::fgContext == nullptr ||
@@ -1317,7 +1354,7 @@ static void hkDrawIndexedInstanced(ID3D12GraphicsCommandList* This, UINT IndexCo
do
{
std::shared_lock<std::shared_mutex> lock2(hudlessMutex[fIndex]);
auto val0 = fgPossibleHudless[fIndex][This];
auto& val0 = fgPossibleHudless[fIndex][This];
// if this command list does not have entries skip
if (val0.size() == 0)
@@ -1377,7 +1414,7 @@ static void hkDispatch(ID3D12GraphicsCommandList* This, UINT ThreadGroupCountX,
do
{
std::shared_lock<std::shared_mutex> lock2(hudlessMutex[fIndex]);
auto val0 = fgPossibleHudless[fIndex][This];
auto& val0 = fgPossibleHudless[fIndex][This];
// if this command list does not have entries skip
if (val0.size() == 0)
@@ -3218,29 +3255,19 @@ void ImGuiOverlayDx::NewFrame()
auto newIndex = (fIndex + 2) % FG_BUFFER_SIZE;
//{
// // LOG_DEBUG_ONLY("lockframeResourceMutex[{}])", newIndex);
// std::unique_lock<std::shared_mutex> lock(frameResourceMutex[newIndex]);
// fgFrameResourcesByCpuHandle[newIndex].clear();
// fgFrameResourcesByGpuHandle[newIndex].clear();
//}
{
// LOG_DEBUG_ONLY("locksourceMutex[{}])", newIndex);
//std::unique_lock<std::shared_mutex> lock(sourceMutex[newIndex]);
//fgSources[newIndex].clear();
fgCopySource[newIndex] = nullptr;
}
{
// LOG_DEBUG_ONLY("lockshaderMutex[{}])", newIndex);
std::unique_lock<std::shared_mutex> lock(hudlessMutex[newIndex]);
//fgShaderInputs[newIndex].clear();
fgPossibleHudless[newIndex].clear();
}
std::unique_lock<std::shared_mutex> lock(counterMutex[newIndex]);
ImGuiOverlayDx::fgHUDlessCaptureCounter[newIndex] = 0;
{
std::unique_lock<std::shared_mutex> lock(counterMutex[newIndex]);
ImGuiOverlayDx::fgHUDlessCaptureCounter[newIndex] = 0;
}
}
void ImGuiOverlayDx::UnHookDx()
+3 -1
View File
@@ -8,6 +8,7 @@
#include <ffx_api.h>
#include <dx12/ffx_api_dx12.h>
#include <ffx_framegeneration.h>
#include "../format_transfer/FT_Dx12.h"
namespace ImGuiOverlayDx
{
@@ -48,7 +49,8 @@ namespace ImGuiOverlayDx
inline ID3D12GraphicsCommandList* fgCopyCommandList = nullptr;
inline ID3D12CommandAllocator* fgCopyCommandAllocators[FG_BUFFER_SIZE] = { };
inline UINT64 fgTarget = 10;
inline ID3D12Resource* fgUpscaledImage[FG_BUFFER_SIZE] = { nullptr, nullptr,nullptr, nullptr };
inline ID3D12Resource* fgUpscaledImage[FG_BUFFER_SIZE] = { nullptr, nullptr, nullptr, nullptr };
inline FT_Dx12* fgFormatTransfer = nullptr;
void UnHookDx();
void HookDx();
+1 -1
View File
@@ -21,7 +21,7 @@
#define VER_MAJOR_VERSION 0
#define VER_MINOR_VERSION 7
#define VER_HOTFIX_VERSION 0
#define VER_BUILD_NUMBER 21
#define VER_BUILD_NUMBER 22
#define VER_PRE_RELEASE