added frame-gen via FFX-SDK (naively)

This commit is contained in:
ecker 2026-04-24 00:18:59 -05:00
parent a6c74572c6
commit 8803034a60
13 changed files with 586 additions and 183 deletions

View File

@ -66,9 +66,9 @@
"vulkan": {
"version": 1.3,
"validation": {
"enabled": true,
"messages": true,
"checkpoints": true,
"enabled": false,
"messages": false,
"checkpoints": false,
"filters": [
// "0xe5d1743c" // VUID-vkCmdDispatch-None-02699 (problem when using VXGI) (seems to be fixed?)
// ,"0x6714bd0c" // VUID-vkCmdDispatch-format-07753 (for some dumb shit) (seems to be fixed?)
@ -110,17 +110,17 @@
"default stage buffers": true,
"default defer buffer destroy": true,
"default command buffer immediate": false,
"multithreaded recording": false
"multithreaded recording": true
},
"pipelines": {
"deferred": true,
"gui": true,
"vsync": true, // vsync on vulkan side rather than engine-side
"hdr": true,
"vxgi": false,
"culling": false,
"bloom": false,
"dof": false,
"vxgi": true,
"culling": true,
"bloom": true,
"dof": true,
"rt": false,
"fsr": true,
"postProcess": false // "postProcess.chromab" // false
@ -302,6 +302,8 @@
},
"fsr": {
"enabled": true,
"upscale": true,
"interpolation": false, // it works but it's naively using the interpolated frame
"sharpness": 0,
"jitter scale": 0.0625,
"preset": "native" // native (1x), quality (1.5x), balanced (1.7x), performance (2.0x), ultra (3.0x)

View File

@ -16,6 +16,8 @@ layout (binding = 1) uniform UBO {
uint padding;
} ubo;
layout(constant_id = 0) const int FORCE_OPAQUE = 0;
#define TONE_MAP 1
#define GAMMA_CORRECT 1
#define TEXTURES 1
@ -26,6 +28,7 @@ layout (binding = 1) uniform UBO {
void main() {
outColor = texture( samplerColor, inUv );
if ( FORCE_OPAQUE == 1 ) outColor.a = 1;
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif

View File

@ -10,6 +10,8 @@ layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#define COMPUTE 1
#define QUERY_MIPMAPS 1
#define DEPTH_BIAS 0.00005
#define FRUSTUM_CULLING 1
#define OCCLUSION_CULLING 0 // currently whack
#include "../../common/macros.h"
#include "../../common/structs.h"
@ -76,97 +78,102 @@ layout (binding = 4) uniform sampler2D samplerDepth;
shared vec4 sharedPlanes[PASSES][6];
vec4 normalizePlane( vec4 p ) {
return p / length(p.xyz);
return p / length(p.xyz);
}
void main() {
const uint gID = gl_GlobalInvocationID.x;
const uint lID = gl_LocalInvocationIndex;
const uint gID = gl_GlobalInvocationID.x;
const uint lID = gl_LocalInvocationIndex;
if ( lID == 0 ) {
for (uint pass = 0; pass < PushConstant.passes; ++pass) {
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 2; ++j) {
sharedPlanes[pass][i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
sharedPlanes[pass][i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
sharedPlanes[pass][i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
sharedPlanes[pass][i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
sharedPlanes[pass][i*2+j] = normalizePlane( sharedPlanes[pass][i*2+j] );
}
}
if ( lID == 0 ) {
for (uint pass = 0; pass < PushConstant.passes; ++pass) {
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 2; ++j) {
sharedPlanes[pass][i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
sharedPlanes[pass][i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
sharedPlanes[pass][i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
sharedPlanes[pass][i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
sharedPlanes[pass][i*2+j] = normalizePlane( sharedPlanes[pass][i*2+j] );
}
}
barrier();
}
barrier();
if ( gID >= drawCommands.length() ) return;
if ( gID >= drawCommands.length() ) return;
const DrawCommand drawCommand = drawCommands[gID];
if ( drawCommand.indices == 0 || drawCommand.vertices == 0 ) return;
const DrawCommand drawCommand = drawCommands[gID];
if ( drawCommand.indices == 0 || drawCommand.vertices == 0 ) return;
const Instance instance = instances[drawCommand.instanceID];
const Object object = objects[instance.objectID];
const Instance instance = instances[drawCommand.instanceID];
const Object object = objects[instance.objectID];
vec4 sphere = aabbToSphere( instance.bounds );
vec3 worldCenter = (object.model * vec4(sphere.xyz, 1.0)).xyz;
vec4 sphere = aabbToSphere( instance.bounds );
vec3 worldCenter = (object.model * vec4(sphere.xyz, 1.0)).xyz;
float scaleX = length(object.model[0].xyz);
float scaleY = length(object.model[1].xyz);
float scaleZ = length(object.model[2].xyz);
float maxScale = max(max(scaleX, scaleY), scaleZ);
float worldRadius = sphere.w * maxScale;
float scaleX = length(object.model[0].xyz);
float scaleY = length(object.model[1].xyz);
float scaleZ = length(object.model[2].xyz);
float maxScale = max(max(scaleX, scaleY), scaleZ);
float worldRadius = sphere.w * maxScale;
bool isVisible = false;
bool isVisible = false;
#if FRUSTUM_CULLING
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
bool insideFrustum = true;
for ( int p = 0; p < 6; ++p ) {
if ( dot(sharedPlanes[pass][p].xyz, worldCenter) + sharedPlanes[pass][p].w < -worldRadius ) {
insideFrustum = false;
break;
}
}
if ( insideFrustum ) {
isVisible = true;
break;
}
}
#else
isVisible = true;
#endif
#if OCCLUSION_CULLING
if ( isVisible ) {
isVisible = false;
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
bool insideFrustum = true;
for ( int p = 0; p < 6; ++p ) {
if ( dot(sharedPlanes[pass][p].xyz, worldCenter) + sharedPlanes[pass][p].w < -worldRadius ) {
insideFrustum = false;
break;
}
}
if ( insideFrustum ) {
isVisible = true;
break;
vec4 aabb;
vec3 viewCenter = ( camera.viewport[pass].view * vec4(worldCenter, 1.0) ).xyz;
mat4 proj = camera.viewport[pass].projection;
float znear = proj[3][2];
float P00 = proj[0][0];
float P11 = proj[1][1];
if ( projectSphere(viewCenter, worldRadius, znear, P00, P11, aabb) ) {
vec2 pyramidSize = vec2(textureSize( samplerDepth, 0 ));
float width = (aabb.z - aabb.x) * pyramidSize.x;
float height = (aabb.w - aabb.y) * pyramidSize.y;
float level = floor(log2(max(width, height)));
level = max(0.0, level);
float d1 = textureLod(samplerDepth, vec2(aabb.x, aabb.y), level).x;
float d2 = textureLod(samplerDepth, vec2(aabb.z, aabb.y), level).x;
float d3 = textureLod(samplerDepth, vec2(aabb.x, aabb.w), level).x;
float d4 = textureLod(samplerDepth, vec2(aabb.z, aabb.w), level).x;
float depth = min(min(d1, d2), min(d3, d4));
float depthSphere = znear / (viewCenter.z - worldRadius);
if ( depthSphere >= depth - DEPTH_BIAS ) {
isVisible = true;
break;
}
} else {
isVisible = true;
break;
}
}
}
#endif
if ( isVisible ) {
isVisible = false;
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
vec4 aabb;
vec3 viewCenter = ( camera.viewport[pass].view * vec4(worldCenter, 1.0) ).xyz;
mat4 proj = camera.viewport[pass].projection;
float znear = proj[3][2];
float P00 = proj[0][0];
float P11 = proj[1][1];
if ( projectSphere(viewCenter, worldRadius, znear, P00, P11, aabb) ) {
vec2 pyramidSize = vec2(textureSize( samplerDepth, 0 ));
float width = (aabb.z - aabb.x) * pyramidSize.x;
float height = (aabb.w - aabb.y) * pyramidSize.y;
float level = floor(log2(max(width, height)));
level = max(0.0, level);
float d1 = textureLod(samplerDepth, vec2(aabb.x, aabb.y), level).x;
float d2 = textureLod(samplerDepth, vec2(aabb.z, aabb.y), level).x;
float d3 = textureLod(samplerDepth, vec2(aabb.x, aabb.w), level).x;
float d4 = textureLod(samplerDepth, vec2(aabb.z, aabb.w), level).x;
float depth = min(min(d1, d2), min(d3, d4));
float depthSphere = znear / (viewCenter.z - worldRadius);
if ( depthSphere >= depth - DEPTH_BIAS ) {
isVisible = true;
break;
}
} else {
isVisible = true;
break;
}
}
}
drawCommands[gID].instances = isVisible ? 1 : 0;
drawCommands[gID].instances = isVisible ? 1 : 0;
}

View File

@ -9,6 +9,8 @@
namespace ext {
namespace fsr {
extern bool UF_API initialized;
extern bool UF_API frameUpscale;
extern bool UF_API frameInterpolation;
extern uf::stl::string UF_API preset;

View File

@ -62,6 +62,7 @@ namespace ext {
VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
VkDescriptorImageInfo descriptor = {};
VkFormat format = enums::Format::R8G8B8A8_UNORM;
VkComponentMapping viewComponentMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
bool srgb = false;
Sampler sampler = {};

View File

@ -452,6 +452,20 @@ namespace ext {
float clamp = 0;
} bias;
} depth;
// to-do: port the rest
struct {
bool enabled = true;
#if UF_USE_VULKAN
VkBlendFactor srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
VkBlendFactor dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
VkBlendOp colorBlendOp = VK_BLEND_OP_ADD;
VkBlendFactor srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
VkBlendFactor dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
VkBlendOp alphaBlendOp = VK_BLEND_OP_ADD;
VkColorComponentFlags colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
#endif
} blend;
bool invalidated = false;

View File

@ -283,6 +283,9 @@ void UF_API uf::load( ext::json::Value& json ) {
ext::fsr::preset = json["engine"]["ext"]["fsr"]["preset"].as(ext::fsr::preset);
ext::fsr::jitterScale = json["engine"]["ext"]["fsr"]["jitter scale"].as(ext::fsr::jitterScale);
ext::fsr::sharpness = json["engine"]["ext"]["fsr"]["sharpness"].as(ext::fsr::sharpness);
ext::fsr::frameUpscale = json["engine"]["ext"]["fsr"]["upscale"].as(ext::fsr::frameUpscale);
ext::fsr::frameInterpolation = json["engine"]["ext"]["fsr"]["interpolation"].as(ext::fsr::frameInterpolation);
#endif
if ( uf::renderer::hasRenderMode("", true) ) {

View File

@ -87,7 +87,7 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
renderMode.metadata.type = uf::renderer::settings::pipelines::names::vxgi;
renderMode.metadata.pipeline = uf::renderer::settings::pipelines::names::vxgi;
if ( uf::renderer::settings::pipelines::culling ) {
renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::culling);
// renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::culling);
}
renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::vxgi);
renderMode.metadata.samples = 1;

View File

@ -5,12 +5,24 @@
#include <uf/ext/ffx/fsr.h>
#include <uf/engine/graph/graph.h>
#define FFX_FSR_BLOCK_SIZE 8
#define FFX_FSR_MAX_WIDTH 3840
#define FFX_FSR_MAX_HEIGHT 2160
#if UF_USE_FFX_SDK
#include <FidelityFX/host/backends/vk/ffx_vk.h>
#define UF_USE_FFX_SDK 3
#define FFX_SDK_2 2
#define FFX_SDK_3 3
#define FFX_SDK_3_1 31
#if UF_USE_FFX_SDK == 2
#define UF_USE_FFX_SDK FFX_SDK_3_1
#define UF_USE_FFX_SDR_FRAME_INTERP 1
#if UF_USE_FFX_SDK == FFX_SDK_2
#warning "Using FFX-FSR2"
#include <FidelityFX/host/ffx_fsr2.h>
#define FfxContext FfxFsr2Context
#define FfxContextDescription FfxFsr2ContextDescription
#define FfxGenerateReactiveDescription FfxFsr2GenerateReactiveDescription
@ -45,8 +57,53 @@
#define FSR_InputExposure L"FSR2_InputExposure"
#define FSR_InputReactiveMap L"FSR2_InputReactiveMap"
#define FSR_TransparencyAndCompositionMap L"FSR2_TransparencyAndCompositionMap"
#elif UF_USE_FFX_SDK == 3
#elif UF_USE_FFX_SDK == FFX_SDK_3
#warning "Using FFX-FSR3"
#include <FidelityFX/host/ffx_fsr3.h>
#define FfxContext FfxFsr3Context
#define FfxContextDescription FfxFsr3ContextDescription
#define FfxGenerateReactiveDescription FfxFsr3GenerateReactiveDescription
#define FfxDispatchDescription FfxFsr3DispatchUpscaleDescription
#define ffxContextGenerateReactiveMask ffxFsr3ContextGenerateReactiveMask
#define ffxContextDispatch ffxFsr3ContextDispatchUpscale
#define ffxContextCreate ffxFsr3ContextCreate
#define ffxContextDestroy ffxFsr3ContextDestroy
#define ffxGetJitterPhaseCount ffxFsr3GetJitterPhaseCount
#define ffxGetJitterOffset ffxFsr3GetJitterOffset
#define FFX_FSR_AUTOREACTIVEFLAGS_APPLY_TONEMAP FFX_FSR3_AUTOREACTIVEFLAGS_APPLY_TONEMAP
#define FFX_FSR_AUTOREACTIVEFLAGS_APPLY_INVERSETONEMAP FFX_FSR3_AUTOREACTIVEFLAGS_APPLY_INVERSETONEMAP
#define FFX_FSR_AUTOREACTIVEFLAGS_APPLY_THRESHOLD FFX_FSR3_AUTOREACTIVEFLAGS_APPLY_THRESHOLD
#define FFX_FSR_AUTOREACTIVEFLAGS_USE_COMPONENTS_MAX FFX_FSR3_AUTOREACTIVEFLAGS_USE_COMPONENTS_MAX
#define FFX_FSR_ENABLE_AUTO_EXPOSURE FFX_FSR3_ENABLE_AUTO_EXPOSURE
#define FFX_FSR_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION FFX_FSR3_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION
#define FFX_FSR_ENABLE_HIGH_DYNAMIC_RANGE FFX_FSR3_ENABLE_HIGH_DYNAMIC_RANGE
#define FFX_FSR_ENABLE_DEPTH_INVERTED FFX_FSR3_ENABLE_DEPTH_INVERTED
#define FFX_FSR_ENABLE_DEPTH_INFINITE FFX_FSR3_ENABLE_DEPTH_INFINITE
#define FSR_InputColor L"FSR3_InputColor"
#define FSR_InputDepth L"FSR3_InputDepth"
#define FSR_InputMotionVectors L"FSR3_InputMotionVectors"
#define FSR_OutputUpscaledColor L"FSR3_OutputUpscaledColor"
#define FSR_OutputUpscaledColor L"FSR3_OutputUpscaledColor"
#define FSR_InputColor L"FSR3_InputColor"
#define FSR_InputDepth L"FSR3_InputDepth"
#define FSR_InputMotionVectors L"FSR3_InputMotionVectors"
#define FSR_OutputUpscaledColor L"FSR3_OutputUpscaledColor"
#define FSR_InputExposure L"FSR3_InputExposure"
#define FSR_InputReactiveMap L"FSR3_InputReactiveMap"
#define FSR_TransparencyAndCompositionMap L"FSR3_TransparencyAndCompositionMap"
#define FSR_DilatedMotionVectors L"FSR_DilatedMotionVectors"
#define FSR_DilatedDepth L"FSR_DilatedDepth"
#define FSR_ReconstructedPrevNearestDepth L"FSR_ReconstructedPrevNearestDepth"
#elif UF_USE_FFX_SDK == FFX_SDK_3_1
#warning "Using FFX-FSR3.1"
#include <FidelityFX/host/ffx_fsr3upscaler.h>
#include <FidelityFX/host/ffx_frameinterpolation.h>
#include <FidelityFX/host/ffx_opticalflow.h>
#define FfxContext FfxFsr3UpscalerContext
#define FfxContextDescription FfxFsr3UpscalerContextDescription
#define FfxGenerateReactiveDescription FfxFsr3UpscalerGenerateReactiveDescription
@ -132,19 +189,33 @@ namespace {
FfxContext context;
FfxContextDescription contextDescription;
#if UF_USE_FFX_SDR_FRAME_INTERP && UF_USE_FFX_SDK == FFX_SDK_3_1
uf::stl::vector<uint8_t> scratchBufferFG;
uf::stl::vector<uint8_t> scratchBufferOF;
FfxFrameInterpolationContext contextFG;
FfxFrameInterpolationContextDescription contextDescriptionFG;
FfxOpticalflowContext contextOF;
FfxOpticalflowContextDescription contextDescriptionOF;
#endif
struct {
uf::renderer::Texture empty;
uf::renderer::Texture output;
#if UF_USE_FFX_SDK == 3
#if UF_USE_FFX_SDK == FFX_SDK_3_1
uf::renderer::Texture outputFG;
uf::renderer::Texture dilatedMotionVectors;
uf::renderer::Texture dilatedDepth;
uf::renderer::Texture reconstructedPrevNearestDepth;
uf::renderer::Texture opticalFlowVector;
uf::renderer::Texture opticalFlowSceneChangeDetection;
#endif
} resources;
void initializeResource( uf::renderer::Texture& resource, uint32_t width = 0, uint32_t height = 0 ) {
void initializeResource( uf::renderer::Texture& resource, uint32_t width = 0, uint32_t height = 0, VkImageUsageFlags usage = 0, VkImageLayout layout = VK_IMAGE_LAYOUT_GENERAL ) {
if ( width == 0 ) width = uf::renderer::settings::width;
if ( height == 0 ) height = uf::renderer::settings::height;
resource.mips = 0;
resource.destroy();
resource.fromBuffers(
NULL,
@ -153,8 +224,8 @@ namespace {
width, height,
1,
1,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_LAYOUT_GENERAL
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | usage,
layout
);
}
@ -193,6 +264,7 @@ namespace {
desc.format = ffxGetSurfaceFormatVK(texture.format);
desc.flags = FFX_RESOURCE_FLAGS_NONE;
if ( texture.usage & VK_IMAGE_USAGE_STORAGE_BIT ) desc.usage = FFX_RESOURCE_USAGE_UAV;
if ( texture.layout == VK_IMAGE_LAYOUT_GENERAL ) state = FFX_RESOURCE_STATE_UNORDERED_ACCESS;
return ffxGetResourceVK(texture.image, desc, (wchar_t*) name, state);
};
@ -203,7 +275,31 @@ namespace {
}
#endif
void draw(VkCommandBuffer commandBuffer, size_t swapchainIndex) {
void barrier( VkCommandBuffer commandBuffer, VkImage image ) {
VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; // FFX expects GENERAL
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
vkCmdPipelineBarrier(
commandBuffer,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
0, 0, nullptr, 0, nullptr, 1, &barrier
);
}
void upscale( VkCommandBuffer commandBuffer ) {
FfxDispatchDescription dispatchParameters = {};
dispatchParameters.commandList = ffxGetCommandListVK(commandBuffer);
@ -238,13 +334,17 @@ namespace {
dispatchParameters.reactive = createFfxResource(::resources.empty, FSR_InputReactiveMap);
dispatchParameters.transparencyAndComposition = createFfxResource(::resources.empty, FSR_TransparencyAndCompositionMap);
#if UF_USE_FFX_SDK == 3
dispatchParameters.dilatedMotionVectors = createFfxResource(::resources.dilatedMotionVectors, FSR_DilatedMotionVectors, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
dispatchParameters.dilatedDepth = createFfxResource(::resources.dilatedDepth, FSR_DilatedDepth, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
dispatchParameters.reconstructedPrevNearestDepth = createFfxResource(::resources.reconstructedPrevNearestDepth, FSR_ReconstructedPrevNearestDepth, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
#endif
#if UF_USE_FFX_SDK == FFX_SDK_3_1
dispatchParameters.dilatedMotionVectors = createFfxResource(::resources.dilatedMotionVectors, FSR_DilatedMotionVectors);
dispatchParameters.dilatedDepth = createFfxResource(::resources.dilatedDepth, FSR_DilatedDepth);
dispatchParameters.reconstructedPrevNearestDepth = createFfxResource(::resources.reconstructedPrevNearestDepth, FSR_ReconstructedPrevNearestDepth);
#endif
dispatchParameters.output = createFfxResource(::resources.output, FSR_OutputUpscaledColor, FFX_RESOURCE_STATE_UNORDERED_ACCESS );
#if UF_USE_FFX_SDK == FFX_SDK_3
dispatchParameters.upscaleOutput = createFfxResource(::resources.output, FSR_OutputUpscaledColor );
#else
dispatchParameters.output = createFfxResource(::resources.output, FSR_OutputUpscaledColor );
#endif
#else
dispatchParameters.color = ffxGetTextureResourceVK(&::context, attachmentColor.image, attachmentColor.view, renderSize.x, renderSize.y, attachmentColor.descriptor.format, FSR_InputColor );
dispatchParameters.depth = ffxGetTextureResourceVK(&::context, attachmentDepth.image, attachmentDepth.view, renderSize.x, renderSize.y, attachmentDepth.descriptor.format, FSR_InputDepth );
@ -254,7 +354,7 @@ namespace {
dispatchParameters.reactive = ffxGetTextureResourceVK(&::context, nullptr, nullptr, 1, 1, VK_FORMAT_UNDEFINED, FSR_InputReactiveMap );
dispatchParameters.transparencyAndComposition = ffxGetTextureResourceVK(&::context, nullptr, nullptr, 1, 1, VK_FORMAT_UNDEFINED, FSR_TransparencyAndCompositionMap );
dispatchParameters.output = ffxGetTextureResourceVK(&::context, ::resources.output.image, ::resources.output.view, ::resources.output.width, ::resources.output.height, ::resources.output.format, FSR_OutputUpscaledColor, FFX_RESOURCE_STATE_UNORDERED_ACCESS );
dispatchParameters.output = ffxGetTextureResourceVK(&::context, ::resources.output.image, ::resources.output.view, ::resources.output.width, ::resources.output.height, ::resources.output.format, FSR_OutputUpscaledColor );
#endif
auto& controller = scene.getController();
@ -274,7 +374,119 @@ namespace {
dispatchParameters.cameraFovAngleVertical = 2.0f * std::atan(1.0f / fabs(projection(1,1)));
FFX_ERROR_CHECK(ffxContextDispatch(&::context, &dispatchParameters));
barrier(commandBuffer, ::resources.output.image);
}
// finish filling out
#if UF_USE_FFX_SDR_FRAME_INTERP
void framegen( VkCommandBuffer commandBuffer ) {
if ( !uf::renderer::hasRenderMode("", true) ) return;
if ( !uf::renderer::hasRenderMode("Swapchain", true) ) return;
auto& swapchainRenderMode = uf::renderer::getRenderMode("Swapchain", true);
auto& renderMode = uf::renderer::getRenderMode("", true);
pod::Vector2ui renderSize = {
renderMode.width > 0 ? renderMode.width : (uf::renderer::settings::width * renderMode.scale),
renderMode.height > 0 ? renderMode.height : (uf::renderer::settings::height * renderMode.scale),
};
pod::Vector2ui displaySize = {
swapchainRenderMode.width > 0 ? swapchainRenderMode.width : uf::renderer::settings::width,
swapchainRenderMode.height > 0 ? swapchainRenderMode.height : uf::renderer::settings::height,
};
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
auto& projection = camera.getProjection();
#if UF_USE_FFX_SDK == FFX_SDK_3
FfxFsr3DispatchFrameGenerationPrepareDescription dispatchParameters = {};
dispatchParameters.commandList = ffxGetCommandListVK(commandBuffer);
// ...
FFX_ERROR_CHECK(ffxFsr3ContextDispatchFrameGenerationPrepare(&::context, &dispatchParameters));
#elif UF_USE_FFX_SDK == FFX_SDK_3_1
FfxFrameInterpolationDispatchDescription dispatchParameters = {};
dispatchParameters.commandList = ffxGetCommandListVK(commandBuffer);
dispatchParameters.displaySize.width = displaySize.x;
dispatchParameters.displaySize.height = displaySize.y;
dispatchParameters.renderSize.width = displaySize.x;
dispatchParameters.renderSize.height = displaySize.y;
// use output from rendermode
if ( ext::fsr::frameUpscale ) {
if ( !renderMode.hasAttachment("output") && !renderMode.hasAttachment("color") ) return;
auto& attachmentColor = renderMode.hasAttachment("output") ? renderMode.getAttachment("output") : renderMode.getAttachment("color");
dispatchParameters.currentBackBuffer = createFfxResource(attachmentColor, L"FSR3_InterpolationSource");
} else {
dispatchParameters.currentBackBuffer = createFfxResource(::resources.output, L"FSR3_InterpolationSource");
}
dispatchParameters.output = createFfxResource(::resources.outputFG, L"FSR3_InterpolatedOutput");
dispatchParameters.cameraNear = projection(2,3);
dispatchParameters.cameraFar = FLT_MAX;
dispatchParameters.cameraFovAngleVertical = 2.0f * std::atan(1.0f / fabs(projection(1,1)));
dispatchParameters.viewSpaceToMetersFactor = 1.0f;
dispatchParameters.frameTimeDelta = uf::time::delta * 1000.0f;
dispatchParameters.reset = uf::renderer::states::frameAccumulateReset;
static uint64_t frameID = 0;
dispatchParameters.frameID = frameID++;
dispatchParameters.backBufferTransferFunction = uf::renderer::settings::pipelines::hdr ? FFX_BACKBUFFER_TRANSFER_FUNCTION_PQ : FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB;
dispatchParameters.minMaxLuminance[0] = 0.0f;
dispatchParameters.minMaxLuminance[1] = 1000.0f;
dispatchParameters.dilatedDepth = createFfxResource(::resources.dilatedDepth, FSR_DilatedDepth);
dispatchParameters.dilatedMotionVectors = createFfxResource(::resources.dilatedMotionVectors, FSR_DilatedMotionVectors);
dispatchParameters.reconstructedPrevDepth = createFfxResource(::resources.reconstructedPrevNearestDepth, FSR_ReconstructedPrevNearestDepth);
dispatchParameters.opticalFlowVector = createFfxResource(::resources.opticalFlowVector, L"OF_Vector");
dispatchParameters.opticalFlowSceneChangeDetection = createFfxResource(::resources.opticalFlowSceneChangeDetection, L"OF_SCD");
dispatchParameters.opticalFlowScale.x = 1.0f;
dispatchParameters.opticalFlowScale.y = 1.0f;
dispatchParameters.opticalFlowBlockSize = FFX_FSR_BLOCK_SIZE;
FFX_ERROR_CHECK(ffxFrameInterpolationDispatch(&::contextFG, &dispatchParameters));
barrier(commandBuffer, ::resources.outputFG.image);
#endif
}
#endif
#if UF_USE_FFX_SDK == FFX_SDK_3_1
void computeOpticalFlow( VkCommandBuffer commandBuffer ) {
FfxOpticalflowDispatchDescription dispatchParameters = {};
dispatchParameters.commandList = ffxGetCommandListVK(commandBuffer);
// use output from rendermode
if ( !ext::fsr::frameUpscale ) {
if ( !uf::renderer::hasRenderMode("", true) ) return;
auto& renderMode = uf::renderer::getRenderMode("", true);
if ( !renderMode.hasAttachment("output") && !renderMode.hasAttachment("color") ) return;
auto& attachmentColor = renderMode.hasAttachment("output") ? renderMode.getAttachment("output") : renderMode.getAttachment("color");
dispatchParameters.color = createFfxResource(attachmentColor, L"OF_InputColor");
} else {
dispatchParameters.color = createFfxResource(::resources.output, L"OF_InputColor");
}
dispatchParameters.reset = uf::renderer::states::frameAccumulateReset;
dispatchParameters.backbufferTransferFunction = uf::renderer::settings::pipelines::hdr ? FFX_BACKBUFFER_TRANSFER_FUNCTION_PQ : FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB;
dispatchParameters.minMaxLuminance.x = 0.0f;
dispatchParameters.minMaxLuminance.y = 1000.0f;
dispatchParameters.opticalFlowVector = createFfxResource(::resources.opticalFlowVector, L"OF_Vector");
dispatchParameters.opticalFlowSCD = createFfxResource(::resources.opticalFlowSceneChangeDetection, L"OF_SCD");
FFX_ERROR_CHECK(ffxOpticalflowContextDispatch(&::contextOF, &dispatchParameters));
barrier(commandBuffer, ::resources.opticalFlowVector.image);
barrier(commandBuffer, ::resources.opticalFlowSceneChangeDetection.image);
}
#endif
}
uf::stl::string ext::fsr::preset = "native";
@ -282,28 +494,48 @@ pod::Vector2f ext::fsr::jitter = {};
float ext::fsr::sharpness = 1.0f;
float ext::fsr::jitterScale = 2.0f;
bool ext::fsr::initialized = false;
uf::renderer::Texture& ext::fsr::getRenderTarget() {
return ::resources.output;
}
bool ext::fsr::frameUpscale = true;
bool ext::fsr::frameInterpolation = true;
void ext::fsr::initialize() {
auto scratchSize = ffxGetScratchMemorySizeVK(uf::renderer::device.physicalDevice, MAX(uf::renderer::device.extensions.properties.device.size(), 1) );
::scratchBuffer.resize(scratchSize);
// setup scratch buffer
{
auto scratchSize = ffxGetScratchMemorySizeVK(uf::renderer::device.physicalDevice, MAX(uf::renderer::device.extensions.properties.device.size(), 1) );
if ( ext::fsr::frameUpscale ) {
::scratchBuffer.resize(scratchSize);
}
if ( ext::fsr::frameInterpolation ) {
#if UF_USE_FFX_SDR_FRAME_INTERP
::scratchBufferFG.resize(scratchSize);
#endif
#if UF_USE_FFX_SDK == FFX_SDK_3_1
::scratchBufferOF.resize(scratchSize);
#endif
}
}
::contextDescription.maxRenderSize.width = 3840;
::contextDescription.maxRenderSize.height = 2160;
#if UF_USE_FFX_SDK == 3
::contextDescription.maxUpscaleSize.width = uf::renderer::settings::width;
::contextDescription.maxUpscaleSize.height = uf::renderer::settings::height;
#else
::contextDescription.displaySize.width = uf::renderer::settings::width;
::contextDescription.displaySize.height = uf::renderer::settings::height;
#endif
::contextDescription.flags = FFX_FSR_ENABLE_AUTO_EXPOSURE | FFX_FSR_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION;
// setup context description
if ( ext::fsr::frameUpscale ) {
::contextDescription.maxRenderSize.width = FFX_FSR_MAX_WIDTH;
::contextDescription.maxRenderSize.height = FFX_FSR_MAX_HEIGHT;
#if UF_USE_FFX_SDK >= FFX_SDK_3
::contextDescription.maxUpscaleSize.width = uf::renderer::settings::width;
::contextDescription.maxUpscaleSize.height = uf::renderer::settings::height;
#else
::contextDescription.displaySize.width = uf::renderer::settings::width;
::contextDescription.displaySize.height = uf::renderer::settings::height;
#endif
// to-do: validate if motion vectors are rendered with jitter
//::contextDescription.flags = FFX_FSR_ENABLE_AUTO_EXPOSURE | FFX_FSR_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION;
#if UF_USE_FFX_SDK == FFX_SDK_3
if ( !ext::fsr::frameInterpolation ) ::contextDescription.flags |= FFX_FSR3_ENABLE_UPSCALING_ONLY;
::contextDescription.backBufferFormat = ffxGetSurfaceFormatVK(ext::vulkan::settings::formats::color);
#endif
if ( uf::renderer::settings::pipelines::hdr ) ::contextDescription.flags |= FFX_FSR_ENABLE_HIGH_DYNAMIC_RANGE;
if ( uf::matrix::reverseInfiniteProjection ) ::contextDescription.flags |= FFX_FSR_ENABLE_DEPTH_INVERTED | FFX_FSR_ENABLE_DEPTH_INFINITE;
if ( uf::renderer::settings::pipelines::hdr ) ::contextDescription.flags |= FFX_FSR_ENABLE_HIGH_DYNAMIC_RANGE;
if ( uf::matrix::reverseInfiniteProjection ) ::contextDescription.flags |= FFX_FSR_ENABLE_DEPTH_INVERTED | FFX_FSR_ENABLE_DEPTH_INFINITE;
}
#if UF_USE_FFX_SDK
VkDeviceContext deviceContextVK = {};
@ -311,23 +543,78 @@ void ext::fsr::initialize() {
deviceContextVK.vkPhysicalDevice = uf::renderer::device.physicalDevice;
deviceContextVK.vkDeviceProcAddr = vkGetDeviceProcAddr;
FfxDevice ffxDevice = ffxGetDeviceVK(&deviceContextVK);
FFX_ERROR_CHECK(ffxGetInterfaceVK( &::contextDescription.backendInterface, ffxDevice, ::scratchBuffer.data(), ::scratchBuffer.size(), 1 ));
#else
FFX_ERROR_CHECK(ffxGetInterfaceVK( &::contextDescription.callbacks, ::scratchBuffer.data(), ::scratchBuffer.size(), uf::renderer::device.physicalDevice, &vkGetDeviceProcAddr ));
#endif
FFX_ERROR_CHECK(ffxContextCreate( &::context, &::contextDescription ));
::resources.output.format = uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR;
::initializeResource( ::resources.output );
#if UF_USE_FFX_SDK == 3
::resources.dilatedMotionVectors.format = uf::renderer::enums::Format::R16G16_SFLOAT;
::resources.dilatedDepth.format = uf::renderer::enums::Format::R32_SFLOAT;
::resources.reconstructedPrevNearestDepth.format = uf::renderer::enums::Format::R32_UINT;
// setup context
if ( ext::fsr::frameUpscale ) {
#if UF_USE_FFX_SDK == FFX_SDK_3
FFX_ERROR_CHECK(ffxGetInterfaceVK( &::contextDescription.backendInterfaceUpscaling, ffxDevice, ::scratchBuffer.data(), ::scratchBuffer.size(), 1 ));
FFX_ERROR_CHECK(ffxGetInterfaceVK( &::contextDescription.backendInterfaceSharedResources, ffxDevice, ::scratchBuffer.data(), ::scratchBuffer.size(), 1 ));
FFX_ERROR_CHECK(ffxGetInterfaceVK( &::contextDescription.backendInterfaceFrameInterpolation, ffxDevice, ::scratchBuffer.data(), ::scratchBuffer.size(), 1 ));
#elif UF_USE_FFX_SDK
FFX_ERROR_CHECK(ffxGetInterfaceVK( &::contextDescription.backendInterface, ffxDevice, ::scratchBuffer.data(), ::scratchBuffer.size(), 1 ));
#else
FFX_ERROR_CHECK(ffxGetInterfaceVK( &::contextDescription.callbacks, ::scratchBuffer.data(), ::scratchBuffer.size(), uf::renderer::device.physicalDevice, &vkGetDeviceProcAddr ));
#endif
FFX_ERROR_CHECK(ffxContextCreate( &::context, &::contextDescription ));
}
::initializeResource( ::resources.dilatedMotionVectors );
::initializeResource( ::resources.dilatedDepth );
::initializeResource( ::resources.reconstructedPrevNearestDepth );
#endif
#if UF_USE_FFX_SDR_FRAME_INTERP && UF_USE_FFX_SDK == FFX_SDK_3_1
// setup frame interpolation context
if ( ext::fsr::frameInterpolation ) {
::contextDescriptionFG.maxRenderSize.width = FFX_FSR_MAX_WIDTH;
::contextDescriptionFG.maxRenderSize.height = FFX_FSR_MAX_HEIGHT;
::contextDescriptionFG.displaySize.width = uf::renderer::settings::width;
::contextDescriptionFG.displaySize.height = uf::renderer::settings::height;
::contextDescriptionFG.previousInterpolationSourceFormat = ffxGetSurfaceFormatVK( uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR );
::contextDescriptionFG.backBufferFormat = ::contextDescriptionFG.previousInterpolationSourceFormat;
// ::contextDescriptionFG.backBufferFormat = ffxGetSurfaceFormatVK( ext::vulkan::settings::formats::color );
// to-do: validate if motion vectors are rendered with jitter
// ::contextDescriptionFG.flags = FFX_FRAMEINTERPOLATION_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS;
if ( uf::renderer::settings::pipelines::hdr ) ::contextDescriptionFG.flags |= FFX_FRAMEINTERPOLATION_ENABLE_HDR_COLOR_INPUT;
if ( uf::matrix::reverseInfiniteProjection ) ::contextDescriptionFG.flags |= FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED | FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INFINITE;
FFX_ERROR_CHECK(ffxGetInterfaceVK( &::contextDescriptionFG.backendInterface, ffxDevice, ::scratchBufferFG.data(), ::scratchBufferFG.size(), 1 ));
FFX_ERROR_CHECK(ffxFrameInterpolationContextCreate( &::contextFG, &::contextDescriptionFG ));
}
// setup optical flow context
if ( ext::fsr::frameInterpolation ) {
::contextDescriptionOF.resolution.width = uf::renderer::settings::width;
::contextDescriptionOF.resolution.height = uf::renderer::settings::height;
FFX_ERROR_CHECK(ffxGetInterfaceVK( &::contextDescriptionOF.backendInterface, ffxDevice, ::scratchBufferOF.data(), ::scratchBufferOF.size(), 1 ));
FFX_ERROR_CHECK(ffxOpticalflowContextCreate( &::contextOF, &::contextDescriptionOF ));
}
#endif
// setup resources
{
::resources.output.format = uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR;
::initializeResource( ::resources.output );
#if UF_USE_FFX_SDK == FFX_SDK_3_1
::resources.outputFG.viewComponentMapping.a = VK_COMPONENT_SWIZZLE_ONE; // for some reason framegen has the alpha set to 1 (or never writes it)
::resources.outputFG.format = uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR;
::resources.dilatedMotionVectors.format = uf::renderer::enums::Format::R16G16_SFLOAT;
::resources.dilatedDepth.format = uf::renderer::enums::Format::R32_SFLOAT;
::resources.reconstructedPrevNearestDepth.format = uf::renderer::enums::Format::R32_UINT;
::resources.opticalFlowVector.format = uf::renderer::enums::Format::R16G16_SINT;
::resources.opticalFlowSceneChangeDetection.format = uf::renderer::enums::Format::R32_UINT;
uint32_t block_size = FFX_FSR_BLOCK_SIZE;
uint32_t ofWidth = (uf::renderer::settings::width + block_size) / block_size;
uint32_t ofHeight = (uf::renderer::settings::height + block_size) / block_size;
::initializeResource( ::resources.outputFG );
::initializeResource( ::resources.dilatedMotionVectors );
::initializeResource( ::resources.dilatedDepth );
::initializeResource( ::resources.reconstructedPrevNearestDepth );
::initializeResource( ::resources.opticalFlowVector, ofWidth, ofHeight );
::initializeResource( ::resources.opticalFlowSceneChangeDetection, ofWidth, ofHeight );
#endif
}
ext::fsr::initialized = true;
}
@ -338,67 +625,148 @@ void ext::fsr::tick() {
pod::Vector2ui displaySize = {};
if ( !uf::renderer::hasRenderMode("", true) ) return;
if ( !uf::renderer::hasRenderMode("Swapchain", true) ) return;
auto& renderMode = uf::renderer::getRenderMode("", true);
renderSize = {
renderMode.width > 0 ? renderMode.width : (uf::renderer::settings::width * renderMode.scale),
renderMode.height > 0 ? renderMode.height : (uf::renderer::settings::height * renderMode.scale),
};
auto& swapchainRenderMode = uf::renderer::getRenderMode("Swapchain", true);
// update sizes
{
if ( !uf::renderer::hasRenderMode("Swapchain", true) ) return;
auto& swapchainRenderMode = uf::renderer::getRenderMode("Swapchain", true);
renderSize = {
renderMode.width > 0 ? renderMode.width : (uf::renderer::settings::width * renderMode.scale),
renderMode.height > 0 ? renderMode.height : (uf::renderer::settings::height * renderMode.scale),
};
displaySize = {
swapchainRenderMode.width > 0 ? swapchainRenderMode.width : uf::renderer::settings::width,
swapchainRenderMode.height > 0 ? swapchainRenderMode.height : uf::renderer::settings::height,
};
}
if ( uf::renderer::states::resized ) {
#if UF_USE_FFX_SDK == 3
::contextDescription.maxUpscaleSize.width = uf::renderer::settings::width;
::contextDescription.maxUpscaleSize.height = uf::renderer::settings::height;
#else
::contextDescription.displaySize.width = displaySize.x;
::contextDescription.displaySize.height = displaySize.y;
#endif
FFX_ERROR_CHECK(ffxContextDestroy( &::context ));
FFX_ERROR_CHECK(ffxContextCreate( &::context, &::contextDescription ));
if ( uf::renderer::states::resized || ::resources.output.width != displaySize.x || ::resources.output.height != displaySize.y ) {
// recreate context
// uf::renderer::states::rebuild = true;
if ( ext::fsr::frameUpscale ) {
#if UF_USE_FFX_SDK >= FFX_SDK_3
::contextDescription.maxUpscaleSize.width = displaySize.x;
::contextDescription.maxUpscaleSize.height = displaySize.y;
#else
::contextDescription.displaySize.width = displaySize.x;
::contextDescription.displaySize.height = displaySize.y;
#endif
FFX_ERROR_CHECK(ffxContextDestroy( &::context ));
FFX_ERROR_CHECK(ffxContextCreate( &::context, &::contextDescription ));
}
::initializeResource( ::resources.output, displaySize.x, displaySize.y );
#if UF_USE_FFX_SDK == 3
::initializeResource( ::resources.dilatedMotionVectors, displaySize.x, displaySize.y );
::initializeResource( ::resources.dilatedDepth, displaySize.x, displaySize.y );
::initializeResource( ::resources.reconstructedPrevNearestDepth, displaySize.x, displaySize.y );
#endif
#if UF_USE_FFX_SDR_FRAME_INTERP && UF_USE_FFX_SDK == FFX_SDK_3_1
// recreate frame interpolation context
if ( ext::fsr::frameInterpolation ) {
::contextDescriptionFG.displaySize.width = displaySize.x;
::contextDescriptionFG.displaySize.height = displaySize.y;
FFX_ERROR_CHECK(ffxFrameInterpolationContextDestroy( &::contextFG ));
FFX_ERROR_CHECK(ffxFrameInterpolationContextCreate( &::contextFG, &::contextDescriptionFG ));
}
// recreate optical flow context
if ( ext::fsr::frameInterpolation ) {
::contextDescriptionOF.resolution.width = displaySize.x;
::contextDescriptionOF.resolution.height = displaySize.y;
FFX_ERROR_CHECK(ffxOpticalflowContextDestroy( &::contextOF ));
FFX_ERROR_CHECK(ffxOpticalflowContextCreate( &::contextOF, &::contextDescriptionOF ));
}
#endif
// recreate resources
{
::initializeResource( ::resources.output, displaySize.x, displaySize.y );
#if UF_USE_FFX_SDK == FFX_SDK_3_1
uint32_t block_size = FFX_FSR_BLOCK_SIZE;
uint32_t ofWidth = (displaySize.x + block_size) / block_size;
uint32_t ofHeight = (displaySize.y + block_size) / block_size;
::initializeResource( ::resources.outputFG, displaySize.x, displaySize.y );
::initializeResource( ::resources.dilatedMotionVectors, displaySize.x, displaySize.y );
::initializeResource( ::resources.dilatedDepth, displaySize.x, displaySize.y );
::initializeResource( ::resources.reconstructedPrevNearestDepth, displaySize.x, displaySize.y );
::initializeResource( ::resources.opticalFlowVector, ofWidth, ofHeight );
::initializeResource( ::resources.opticalFlowSceneChangeDetection, ofWidth, ofHeight );
#endif
}
}
const int32_t jitterPhaseCount = ffxGetJitterPhaseCount(renderSize.x, displaySize.x);
static uint32_t index = 0;
index = (index + 1) % jitterPhaseCount;
// update jitter
{
const int32_t jitterPhaseCount = ffxGetJitterPhaseCount(renderSize.x, displaySize.x);
static uint32_t index = 0;
index = (index + 1) % jitterPhaseCount;
ffxGetJitterOffset(&ext::fsr::jitter.x, &ext::fsr::jitter.y, index, jitterPhaseCount);
ffxGetJitterOffset(&ext::fsr::jitter.x, &ext::fsr::jitter.y, index, jitterPhaseCount);
pod::Vector2f jitter = {};
pod::Vector2f jitter = {};
jitter.x = ext::fsr::jitterScale * ext::fsr::jitter.x / (float) renderSize.x;
jitter.y = ext::fsr::jitterScale * ext::fsr::jitter.y / (float) renderSize.y;
jitter.x = ext::fsr::jitterScale * ext::fsr::jitter.x / (float) renderSize.x;
jitter.y = ext::fsr::jitterScale * ext::fsr::jitter.y / (float) renderSize.y;
ext::fsr::jitter = jitter;
::jitterMatrix = uf::matrix::translate( uf::matrix::identity(), pod::Vector3f{ jitter.x, jitter.y, 0 } );
ext::fsr::jitter = jitter;
::jitterMatrix = uf::matrix::translate( uf::matrix::identity(), pod::Vector3f{ jitter.x, jitter.y, 0 } );
}
}
void ext::fsr::render() {
if ( !ext::fsr::initialized ) return;
auto commandBuffer = uf::renderer::device.fetchCommandBuffer(uf::renderer::QueueEnum::GRAPHICS, true); // immediately flush
draw(commandBuffer, uf::renderer::states::currentBuffer);
if ( ext::fsr::frameUpscale ) {
upscale( commandBuffer );
}
if ( ext::fsr::frameInterpolation ) {
#if UF_USE_FFX_SDK == FFX_SDK_3_1
computeOpticalFlow( commandBuffer );
#endif
#if UF_USE_FFX_SDR_FRAME_INTERP
framegen( commandBuffer );
#endif
}
uf::renderer::device.flushCommandBuffer(commandBuffer);
}
void ext::fsr::terminate() {
if ( !ext::fsr::initialized ) return;
FFX_ERROR_CHECK(ffxContextDestroy( &::context ));
// destroy context
if ( ext::fsr::frameUpscale ) {
FFX_ERROR_CHECK(ffxContextDestroy( &::context ));
}
// destroy framegen context
#if UF_USE_FFX_SDR_FRAME_INTERP && UF_USE_FFX_SDK == FFX_SDK_3_1
if ( ext::fsr::frameInterpolation ) {
FFX_ERROR_CHECK(ffxFrameInterpolationContextDestroy( &::contextFG ));
}
#endif
// destroy resources
{
::resources.output.destroy();
#if UF_USE_FFX_SDK == FFX_SDK_3_1
::resources.outputFG.destroy();
::resources.dilatedMotionVectors.destroy();
::resources.dilatedDepth.destroy();
::resources.reconstructedPrevNearestDepth.destroy();
::resources.opticalFlowVector.destroy();
::resources.opticalFlowSceneChangeDetection.destroy();
#endif
}
}
pod::Matrix4f ext::fsr::getJitterMatrix() {
return ::jitterMatrix;
}
uf::renderer::Texture& ext::fsr::getRenderTarget() {
#if UF_USE_FFX_SDR_FRAME_INTERP
if ( ext::fsr::frameInterpolation ) return ::resources.outputFG;
#endif
return ::resources.output;
}
// to-do: add functions to get framegen swapchain functions
#endif

View File

@ -259,20 +259,19 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
}
} else {
subpass = 0;
VkBool32 blendEnabled = VK_TRUE;
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
writeMask,
blendEnabled
descriptor.blend.colorWriteMask,
descriptor.blend.enabled ? VK_TRUE : VK_FALSE
);
if ( blendEnabled == VK_TRUE ) {
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
if ( descriptor.blend.enabled ) {
blendAttachmentState.srcColorBlendFactor = descriptor.blend.srcColorBlendFactor;
blendAttachmentState.dstColorBlendFactor = descriptor.blend.dstColorBlendFactor;
blendAttachmentState.colorBlendOp = descriptor.blend.colorBlendOp;
blendAttachmentState.srcAlphaBlendFactor = descriptor.blend.srcAlphaBlendFactor;
blendAttachmentState.dstAlphaBlendFactor = descriptor.blend.dstAlphaBlendFactor;
blendAttachmentState.alphaBlendOp = descriptor.blend.alphaBlendOp;
}
blendAttachmentStates.emplace_back(blendAttachmentState);
}

View File

@ -257,6 +257,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
blitter.descriptor.subpass = 0;
blitter.descriptor.depth.test = false;
blitter.descriptor.depth.write = false;
blitter.descriptor.blend.enabled = false;
blitter.initialize( "Swapchain" );
blitter.initializeMesh( mesh );

View File

@ -577,12 +577,13 @@ void ext::vulkan::Texture::fromBuffers(
viewCreateInfo.pNext = NULL;
viewCreateInfo.viewType = viewType;
viewCreateInfo.format = format;
viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
viewCreateInfo.components = viewComponentMapping;
viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewCreateInfo.subresourceRange.baseMipLevel = 0;
viewCreateInfo.subresourceRange.layerCount = this->layers;
viewCreateInfo.subresourceRange.levelCount = this->mips;
viewCreateInfo.image = image;
VK_CHECK_RESULT(vkCreateImageView(device.logicalDevice, &viewCreateInfo, nullptr, &view));
VK_REGISTER_HANDLE( view );
@ -683,7 +684,7 @@ void ext::vulkan::Texture::asRenderTarget( Device& device, uint32_t width, uint3
VkImageViewCreateInfo viewCreateInfo = ext::vulkan::initializers::imageViewCreateInfo();
viewCreateInfo.viewType = viewType;
viewCreateInfo.format = format;
viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
viewCreateInfo.components = viewComponentMapping;
viewCreateInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
viewCreateInfo.image = image;
VK_CHECK_RESULT(vkCreateImageView(device, &viewCreateInfo, nullptr, &view));

View File

@ -499,6 +499,8 @@ void ext::vulkan::tick() {
ext::vulkan::states::rebuild = true;
::skip = true;
}
ext::fsr::tick();
auto renderModes = ::fetchRenderModes();
for ( auto& renderMode : renderModes ) {
@ -618,7 +620,7 @@ void ext::vulkan::render() {
}
#if UF_USE_FFX_FSR || UF_USE_FFX_SDK
if ( renderMode->getType() == "Swapchain" && settings::pipelines::fsr && ext::fsr::initialized ) {
ext::fsr::tick();
//ext::fsr::tick();
ext::fsr::render();
}
#endif
@ -636,7 +638,7 @@ void ext::vulkan::render() {
#if UF_USE_FFX_FSR || UF_USE_FFX_SDK
if ( renderMode->getType() == "Swapchain" && settings::pipelines::fsr && ext::fsr::initialized ) {
ext::fsr::tick();
//ext::fsr::tick();
ext::fsr::render();
}
#endif