mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 19:09:25 +02:00
Ordering them before the imports in the same file was not enough: a project header on line 1 can import a module several levels down whose global module fragment already pulled in the same standard header, and that include guard does not cross the module boundary. Putting them first means the guard is set before anything can import. Skips vendored single-header libraries and anything inside an #if.
205 lines
7.7 KiB
C++
205 lines
7.7 KiB
C++
#include <queue>
|
|
#include "fsr.h"
|
|
|
|
#if LIBMANUL_WITH_D3D12
|
|
#include <ffx-fsr2-api/dx12/ffx_fsr2_dx12.h>
|
|
|
|
#include "nvrenderer_d3d12.h"
|
|
#endif
|
|
|
|
#if LIBMANUL_WITH_VULKAN
|
|
#include <ffx-fsr2-api/vk/ffx_fsr2_vk.h>
|
|
#include <nvrhi/vulkan.h>
|
|
|
|
#include "nvrenderer_vulkan.h"
|
|
#endif
|
|
|
|
#include "utilities/Globals_macros.h"
|
|
#include "gbuffer.h"
|
|
#include "gbufferblitpass.h"
|
|
|
|
import eu07.utilities.globals;
|
|
import eu07.glm;
|
|
NvFSR::NvFSR(NvRenderer* renderer)
|
|
: m_backend(renderer->m_backend.get()),
|
|
m_inputpass(renderer->m_gbuffer_blit.get()),
|
|
m_gbuffer(renderer->m_gbuffer.get()) {}
|
|
|
|
void OnFsrMessage(FfxFsr2MsgType type, const wchar_t* msg) {
|
|
//__debugbreak();
|
|
}
|
|
|
|
void NvFSR::Init() {
|
|
m_width = m_backend->GetCurrentFramebuffer()->getFramebufferInfo().width;
|
|
m_height = m_backend->GetCurrentFramebuffer()->getFramebufferInfo().height;
|
|
m_input_width = m_gbuffer->m_framebuffer->getFramebufferInfo().width;
|
|
m_input_height = m_gbuffer->m_framebuffer->getFramebufferInfo().height;
|
|
|
|
m_color = m_inputpass->m_output;
|
|
m_depth = m_gbuffer->m_gbuffer_depth;
|
|
m_motion = m_gbuffer->m_gbuffer_motion;
|
|
|
|
m_output = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setFormat(nvrhi::Format::RGBA16_FLOAT)
|
|
.setWidth(m_width)
|
|
.setHeight(m_height)
|
|
.setIsUAV(true)
|
|
.setDebugName("FSR Output")
|
|
.setInitialState(nvrhi::ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true));
|
|
m_auto_exposure_buffer = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setFormat(nvrhi::Format::RG32_FLOAT)
|
|
.setWidth(1)
|
|
.setHeight(1)
|
|
.setIsUAV(true)
|
|
.setDebugName("FSR Auto Exposure Buffer")
|
|
.setInitialState(nvrhi::ResourceStates::UnorderedAccess)
|
|
.setKeepInitialState(true));
|
|
auto device = m_backend->GetDevice();
|
|
FfxFsr2ContextDescription context_description{};
|
|
switch (device->getGraphicsAPI()) {
|
|
#if LIBMANUL_WITH_D3D12
|
|
case nvrhi::GraphicsAPI::D3D12:
|
|
m_scratch_buffer.resize(ffxFsr2GetScratchMemorySizeDX12());
|
|
ffxFsr2GetInterfaceDX12(&m_fsr2_interface,
|
|
m_backend->GetDevice()->getNativeObject(
|
|
nvrhi::ObjectTypes::D3D12_Device),
|
|
m_scratch_buffer.data(), m_scratch_buffer.size());
|
|
context_description.device = m_backend->GetDevice()->getNativeObject(
|
|
nvrhi::ObjectTypes::D3D12_Device);
|
|
break;
|
|
#endif
|
|
#if LIBMANUL_WITH_VULKAN
|
|
case nvrhi::GraphicsAPI::VULKAN:
|
|
m_scratch_buffer.resize(
|
|
ffxFsr2GetScratchMemorySizeVK(m_backend->GetDevice()->getNativeObject(
|
|
nvrhi::ObjectTypes::VK_PhysicalDevice)));
|
|
ffxFsr2GetInterfaceVK(&m_fsr2_interface, m_scratch_buffer.data(),
|
|
m_scratch_buffer.size(),
|
|
m_backend->GetDevice()->getNativeObject(
|
|
nvrhi::ObjectTypes::VK_PhysicalDevice),
|
|
dynamic_cast<NvRendererBackend_Vulkan*>(m_backend)
|
|
->GetDeviceProcAddr());
|
|
context_description.device =
|
|
ffxGetDeviceVK(m_backend->GetDevice()->getNativeObject(
|
|
nvrhi::ObjectTypes::VK_Device));
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
context_description.callbacks = m_fsr2_interface;
|
|
context_description.displaySize.width = m_width;
|
|
context_description.displaySize.height = m_height;
|
|
context_description.maxRenderSize.width = 3440;
|
|
context_description.maxRenderSize.height = 1440;
|
|
context_description.flags = // FFX_FSR2_ENABLE_DEBUG_CHECKING |
|
|
FFX_FSR2_ENABLE_AUTO_EXPOSURE | FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE |
|
|
FFX_FSR2_ENABLE_DEPTH_INVERTED;
|
|
context_description.fpMessage = &OnFsrMessage;
|
|
ffxFsr2ContextCreate(&m_fsr2_context, &context_description);
|
|
}
|
|
|
|
void NvFSR::Render(nvrhi::ICommandList* command_list, double far_plane,
|
|
double near_plane, double fov) {
|
|
FfxFsr2DispatchDescription dispatch_description{};
|
|
switch (m_backend->GetDevice()->getGraphicsAPI()) {
|
|
#if LIBMANUL_WITH_D3D12
|
|
case nvrhi::GraphicsAPI::D3D12:
|
|
dispatch_description.commandList =
|
|
ffxGetCommandListDX12(command_list->getNativeObject(
|
|
nvrhi::ObjectTypes::D3D12_GraphicsCommandList));
|
|
break;
|
|
#endif
|
|
#if LIBMANUL_WITH_VULKAN
|
|
case nvrhi::GraphicsAPI::VULKAN:
|
|
dispatch_description.commandList = ffxGetCommandListVK(
|
|
command_list->getNativeObject(nvrhi::ObjectTypes::VK_CommandBuffer));
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
dispatch_description.color = GetFfxResource(m_color, L"FSR2 Input Color");
|
|
dispatch_description.depth = GetFfxResource(m_depth, L"FSR2 Input Depth");
|
|
dispatch_description.motionVectors =
|
|
GetFfxResource(m_motion, L"FSR2 Input Motion");
|
|
dispatch_description.exposure =
|
|
GetFfxResource(nullptr, L"FSR2 Empty Auto Exposure");
|
|
dispatch_description.reactive =
|
|
GetFfxResource(nullptr, L"FSR2 Empty Input Reactive Map");
|
|
dispatch_description.transparencyAndComposition =
|
|
GetFfxResource(nullptr, L"FSR2 Empty Transparency And Composition Map");
|
|
dispatch_description.output = GetFfxResource(
|
|
m_output, L"FSR2 Output", FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
|
|
|
dispatch_description.jitterOffset.x = m_current_jitter.x;
|
|
dispatch_description.jitterOffset.y = m_current_jitter.y;
|
|
dispatch_description.motionVectorScale.x = static_cast<float>(m_input_width);
|
|
dispatch_description.motionVectorScale.y = static_cast<float>(m_input_height);
|
|
dispatch_description.reset = false;
|
|
dispatch_description.enableSharpening = true;
|
|
dispatch_description.sharpness = .4;
|
|
dispatch_description.frameTimeDelta = 10.f;
|
|
dispatch_description.preExposure = 1.0f;
|
|
dispatch_description.renderSize.width = m_input_width;
|
|
dispatch_description.renderSize.height = m_input_height;
|
|
dispatch_description.cameraFar = far_plane;
|
|
dispatch_description.cameraNear = near_plane;
|
|
dispatch_description.cameraFovAngleVertical = fov;
|
|
|
|
ffxFsr2ContextDispatch(&m_fsr2_context, &dispatch_description);
|
|
command_list->clearState();
|
|
}
|
|
|
|
FfxResource NvFSR::GetFfxResource(nvrhi::ITexture* texture, wchar_t const* name,
|
|
FfxResourceStates state) {
|
|
switch (m_backend->GetDevice()->getGraphicsAPI()) {
|
|
#if LIBMANUL_WITH_D3D12
|
|
case nvrhi::GraphicsAPI::D3D12:
|
|
if (!texture) {
|
|
return ffxGetResourceDX12(&m_fsr2_context, nullptr, name, state);
|
|
}
|
|
return ffxGetResourceDX12(
|
|
&m_fsr2_context,
|
|
texture->getNativeObject(nvrhi::ObjectTypes::D3D12_Resource), name,
|
|
state);
|
|
#endif
|
|
#if LIBMANUL_WITH_VULKAN
|
|
case nvrhi::GraphicsAPI::VULKAN: {
|
|
if (!texture) {
|
|
return ffxGetTextureResourceVK(&m_fsr2_context, nullptr, nullptr, 1, 1,
|
|
VK_FORMAT_UNDEFINED, name, state);
|
|
}
|
|
const auto& desc = texture->getDesc();
|
|
return ffxGetTextureResourceVK(
|
|
&m_fsr2_context,
|
|
texture->getNativeObject(nvrhi::ObjectTypes::VK_Image),
|
|
texture->getNativeView(nvrhi::ObjectTypes::VK_ImageView), desc.width,
|
|
desc.height, nvrhi::vulkan::convertFormat(desc.format), name, state);
|
|
}
|
|
#endif
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
|
|
void NvFSR::BeginFrame() {
|
|
++m_current_frame;
|
|
ComputeJitter();
|
|
}
|
|
|
|
glm::dmat4 NvFSR::GetJitterMatrix() const {
|
|
return glm::translate(glm::dvec3(2. * m_current_jitter.x / m_input_width,
|
|
-2. * m_current_jitter.y / m_input_height,
|
|
0.));
|
|
}
|
|
|
|
void NvFSR::ComputeJitter() {
|
|
int phase_count = ffxFsr2GetJitterPhaseCount(m_input_width, m_width);
|
|
ffxFsr2GetJitterOffset(&m_current_jitter.x, &m_current_jitter.y,
|
|
m_current_frame % phase_count, phase_count);
|
|
}
|