Commit for 2022.07.31 22-17-30.7z

This commit is contained in:
mrq 2022-07-31 22:17:00 -05:00
parent 212347ee9c
commit cfdb877ed3
52 changed files with 1087 additions and 712 deletions

View File

@ -5,13 +5,13 @@
"matrix": { "reverseInfinite": true },
"meshes": { "interleaved": false },
"lights": { "enabled": true,
"useLightmaps": false,
"max": 48,
"useLightmaps": true,
"max": 16,
"shadows": {
"enabled": true,
"update": 4,
"max": 24,
"samples": 16
"update": 2,
"max": 4,
"samples": 1
},
"bloom": {
"scale": 1.0,
@ -30,6 +30,7 @@
},
"vxgi": {
"limiter": 0.5,
// "limiter": 0.125,
"size": 128,
"dispatch": 8,
"cascades": 3,
@ -37,15 +38,16 @@
"granularity": 12,
"voxelizeScale": 1,
"occlusionFalloff": 2,
"traceStartOffsetFactor": 2.5,
"traceStartOffsetFactor": 1,
"shadows": 0,
"extents": {
"min": [ -8, -4, -8 ],
"max": [ 8, 4, 8 ]
"min": [ -16, -4, -16 ],
"max": [ 16, 4, 16 ]
}
},
"rt": {
// "size": [ 1280, 720 ],
"full": false,
"filter": "nearest",
"defaultRayBounds": [ 0.5, 256.0 ],
"alphaTestOffset": 0.01,
@ -90,10 +92,7 @@
},
"framebuffer": {
"msaa": 1,
// "size": 0.25
// "size": 0.50
// "size": 0.75
"size": 1
"size": 1 // 0.5
// "size": [ 640, 480, "NEAREST" ]
// "size": [ 1280, 720 ]
// "size": [ 960, 540 ]
@ -101,7 +100,7 @@
},
"gpu": 1,
"experimental": {
"batch queue submissions": true,
"batch queue submissions": false,
"rebuild on tick begin": false,
"dedicated thread": false
},
@ -110,12 +109,12 @@
"deferred": true,
"vsync": false,
"hdr": false,
"vxgi": false,
"vxgi": true,
"culling": true,
"bloom": true,
"rt": false,
"rt": true,
"postProcess": false,
"fsr": false
"fsr": true
},
"formats": {
"depth": "D32_SFLOAT",
@ -137,6 +136,8 @@
"fragmentStoresAndAtomics",
"geometryShader",
"multiViewport",
"shaderInt16",
"shaderFloat16",
"shaderInt64",
"shaderFloat64",
"shaderSubgroupClock",
@ -174,6 +175,7 @@
"VK_KHR_shader_float_controls",
"VK_KHR_shader_clock",
"VK_KHR_ray_query",
"VK_EXT_subgroup_size_control",
"VK_AMD_shader_explicit_vertex_parameter" // "VK_KHR_fragment_shader_barycentric"
]
}
@ -217,7 +219,10 @@
"enabled": false
},
"fsr": {
"enabled": true
"enabled": true,
"sharpness": 1,
"jitter scale": 0.0125,
"preset": "ultra" // native (1x), quality (1.5x), balanced (1.7x), performance (2.0x), ultra (3.0x)
},
"reactphysics": {
"timescale": 0.01666666666,
@ -321,8 +326,8 @@
"mode" : "windowed", // fullscreen, borderless, windowed
"icon" : "./data/textures/icon.png",
// "size" : [ 1920, 1080 ],
// "size" : [ 1280, 720 ],
"size" : [ 960, 540 ],
"size" : [ 1280, 720 ],
// "size" : [ 960, 540 ],
// "size" : [ 640, 480 ],
// "size" : [ 256, 224 ],
"title" : "Grimgram",

View File

@ -31,7 +31,7 @@
"radius": [0.1, 0],
"resolution": 512,
"shadows": true,
"static": false
"dynamic": true
}
}
}

View File

@ -38,7 +38,7 @@
},
"baking": {
"enabled": true,
"resolution": 2048,
"resolution": 4096,
"shadows": 1024,
"layers": 1,
"trigger": { "mode": "rendered", "quit": true },

View File

@ -26,7 +26,7 @@
"radius": [0.001, 0],
"resolution": 512,
"shadows": false,
"static": false
"dynamic": true
}
}
}

View File

@ -79,7 +79,7 @@ ent:bind( "tick", function(self)
local center = flattenedTransform.position
local direction = flattenedTransform.forward * 4
local offset = 0.05
local offset = 0.25
local _, depth = physicsState:rayCast( center, direction )
if depth >= 0.5 then
depth = 0.5

View File

@ -1,8 +1,8 @@
{
"import": "/model.json",
"assets": [
// { "filename": "./models/sm64_bbb.glb" }
{ "filename": "./models/sm64_bbb/graph.json" }
{ "filename": "./models/sm64_bbb.glb" }
// { "filename": "./models/sm64_bbb/graph.json" }
],
"metadata": {
"graph": {
@ -20,8 +20,8 @@
"tags": {
"/^worldspawn/": {
"physics": { "type": "mesh", "static": true },
"grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true },
// "optimize mesh": { "simplify": 0 },
// "grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true },
"optimize mesh": { "simplify": 0 },
"unwrap mesh": true
},
"info_player_spawn": { "action": "attach", "filename": "./player.json" },

View File

@ -3,7 +3,7 @@
"metadata": {
"graph": {
// "renderer": { "separate": true },
"baking": { "enabled": false },
"baking": { "enabled": true },
"tags": {
// exact matches
"worldspawn": {

View File

@ -13,8 +13,8 @@
// "ambient": [ 0.8, 0.8, 0.8 ],
// "ambient": [ 0.1, 0.1, 0.2 ],
"exposure": 0.125,
"gamma": 2.2,
"exposure": 1, // 0.125,
"gamma": 2.2, // 2.2,
"bloom": {
"threshold": 1.2,

View File

@ -6,6 +6,9 @@
],
"metadata": {
"graph": {
"lights": {
"lightmap": false
},
"assets": [
"./audio/soundscape/sh2_ambience.ogg"
],

View File

@ -3,6 +3,23 @@ float random(vec3 seed, int i){ return fract(sin(dot(vec4(seed,i), vec4(12.9898,
float rand2(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453); }
float rand3(vec3 co){ return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453); }
//
float mipLevel( in vec2 dx_vtc, in vec2 dy_vtc ) {
const float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
return 0.5 * log2(delta_max_sqr);
// return max(0.0, 0.5 * log2(delta_max_sqr) - 1.0);
// return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
//
void toneMap( inout vec3 color, float exposure ) {
color.rgb = vec3(1.0) - exp(-color.rgb * exposure);
}
void gammaCorrect( inout vec3 color, float gamma ) {
color.rgb = pow(color.rgb, vec3(1.0 / gamma));
}
void toneMap( inout vec4 color, float exposure ) { toneMap(color.rgb, exposure); }
void gammaCorrect( inout vec4 color, float gamma ) { gammaCorrect(color.rgb, gamma); }
//
uint tea(uint val0, uint val1) {
uint v0 = val0;
uint v1 = val1;
@ -27,7 +44,6 @@ float rnd(inout uint prev) { return (float(lcg(prev)) / float(0x01000000)); }
uint prngSeed;
float rnd() { return rnd(prngSeed); }
//
float shadowFactor( const Light light, float def );
float ndfGGX(float cosLh, float roughness) {
const float alpha = roughness * roughness;
const float alphaSq = alpha * alpha;
@ -119,7 +135,7 @@ bool validCubemapIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < MAX_CUBEMAPS;
}
#endif
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE)
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE || RT)
bool validTextureIndex( uint id ) {
return 0 <= id && id < MAX_TEXTURES;
}
@ -160,7 +176,7 @@ float cascadePower( uint x ) {
// return max( 1, x * ubo.settings.vxgi.cascadePower );
}
#endif
#if !COMPUTE
#if FRAGMENT
void whitenoise(inout vec3 color, const vec4 parameters) {
const float flicker = parameters.x;
const float pieces = parameters.y;
@ -171,13 +187,6 @@ void whitenoise(inout vec3 color, const vec4 parameters) {
const float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
color = mix( color, vec3(whiteNoise), blend );
}
float mipLevel( in vec2 dx_vtc, in vec2 dy_vtc ) {
const float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
return 0.5 * log2(delta_max_sqr);
// return max(0.0, 0.5 * log2(delta_max_sqr) - 1.0);
// return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
vec4 resolve( subpassInputMS t, const uint samples ) {
vec4 resolved = vec4(0);
for ( int i = 0; i < samples; ++i ) resolved += subpassLoad(t, i);

View File

@ -1,3 +1,5 @@
float shadowFactor( const Light light, float def );
#if PBR
#include "../common/pbr.h"
#endif

View File

@ -1,20 +1,24 @@
// PBR
void pbr() {
if ( surface.material.lightmapped ) return;
// if ( surface.material.lightmapped ) return;
const float Rs = 4.0; // specular lighting looks gross without this
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
const vec3 Lo = normalize( -surface.position.eye );
const float cosLo = max(0.0, dot(surface.normal.eye, Lo));
uint shadows = 0;
for ( uint i = 0; i < ubo.settings.lengths.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
if ( surface.material.lightmapped && light.type >= 0 ) continue;
const vec3 Liu = vec3(ubo.eyes[surface.pass].view * vec4(light.position, 1)) - surface.position.eye;
const vec3 Li = normalize(Liu);
const bool reverseZ = light.projection[2][2] < 0.00001;
const float Ls = shadowFactor( light, 0.0 );
const float La = 1.0 / (PI * pow(length(Liu), 2.0));
const float Ls = ( shadows++ < ubo.settings.lighting.maxShadows ) ? shadowFactor( light, 0.0 ) : 1;
// const float La = 1.0 / (PI * pow(length(Liu), 2.0));
const float La = 1.0 / (1 + (PI * pow(length(Liu), 2.0)));
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.eye, Li));

View File

@ -102,7 +102,33 @@ float omniShadowMap( const Light light, float def ) {
return eyeDepth < sampled - bias ? 0.0 : factor;
}
#endif
#if RT
float shadowFactorRT( const Light light, float def ) {
Ray ray;
ray.origin = surface.position.world;
ray.direction = light.position - ray.origin;
float tMin = ubo.settings.rt.defaultRayBounds.x;
float tMax = length(ray.direction) - 0.0001;
ray.direction = normalize(ray.direction);
uint rayFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsSkipClosestHitShaderEXT;
uint cullMask = 0xFF;
rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, tlas, rayFlags, cullMask, ray.origin, tMin, ray.direction, tMax);
while(rayQueryProceedEXT(rayQuery)) {
}
return rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT ? 1.0 : 0.0;
}
#endif
float shadowFactor( const Light light, float def ) {
#if RT
return shadowFactorRT( light, def );
#endif
if ( light.typeMap != 0 ) return omniShadowMap( light, def );
if ( !validTextureIndex(light.indexMap) )

View File

@ -200,9 +200,9 @@ struct SettingsMode {
};
struct SettingsLighting {
vec3 ambient;
float padding1;
uint indexSkybox;
uint maxShadows;
uint shadowSamples;
uint useLightmaps;
};

View File

@ -165,7 +165,16 @@ void indirectLighting() {
// outFragColor.rgb = indirectSpecular.rgb; return;
}
surface.material.indirect = indirectDiffuse * DIFFUSE_INDIRECT_FACTOR + indirectSpecular * SPECULAR_INDIRECT_FACTOR;
/*
if ( true ) {
gammaCorrect(indirectDiffuse.rgb, 1.0 / ubo.settings.bloom.gamma);
}
*/
indirectDiffuse *= DIFFUSE_INDIRECT_FACTOR;
indirectSpecular *= SPECULAR_INDIRECT_FACTOR;
surface.material.indirect = indirectDiffuse + indirectSpecular;
// outFragColor.rgb = surface.material.indirect.rgb; return;
// deferred sampling doesn't have a blended albedo buffer

View File

@ -2,7 +2,8 @@
#extension GL_EXT_nonuniform_qualifier : enable
#if RT
#extension GL_EXT_ray_query : require
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_ray_query : enable
#endif
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
@ -129,18 +130,8 @@ void postProcess() {
float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
vec4 outFragBright = brightness > ubo.settings.bloom.threshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
vec2 outFragMotion = surface.motion;
#if FOG
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
#endif
#if TONE_MAP
surface.fragment.rgb = vec3(1.0) - exp(-surface.fragment.rgb * ubo.settings.bloom.exposure);
#endif
#if GAMMA_CORRECT
surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / ubo.settings.bloom.gamma));
#endif
#if WHITENOISE
if ( enabled(ubo.settings.mode.type, 1) ) whitenoise(surface.fragment.rgb, ubo.settings.mode.parameters);
#endif
vec4 outFragColor = vec4(surface.fragment.rgb, 1.0);
@ -151,7 +142,7 @@ void postProcess() {
void populateSurface() {
uvec2 renderSize = imageSize(imageColor);
if ( gl_GlobalInvocationID.x >= renderSize.x|| gl_GlobalInvocationID.y >= renderSize.y ) return;
if ( gl_GlobalInvocationID.x >= renderSize.x || gl_GlobalInvocationID.y >= renderSize.y || gl_GlobalInvocationID.z > PushConstant.pass ) return;
surface.fragment = vec4(0);
surface.pass = PushConstant.pass;
@ -231,6 +222,12 @@ void populateSurface() {
}
void directLighting() {
#if RT && COMPUTE && !VXGI
{
}
#endif
surface.light.rgb += surface.material.albedo.rgb * ubo.settings.lighting.ambient.rgb * surface.material.occlusion; // add ambient lighting
surface.light.rgb += surface.material.indirect.rgb; // add indirect lighting
#if PBR

View File

@ -1,4 +1,4 @@
#version 450
#version 460
#pragma shader_stage(compute)
#define RT 1

View File

@ -1,4 +1,4 @@
#version 450
#version 460
#pragma shader_stage(compute)
#define RT 1

View File

@ -0,0 +1,14 @@
#version 460
#pragma shader_stage(compute)
#define RT 1
#define VXGI 1
#define MULTISAMPLING 0
#include "./comp.h"
void main() {
populateSurface();
indirectLighting();
directLighting();
postProcess();
}

View File

@ -1,4 +1,4 @@
#version 450
#version 460
#pragma shader_stage(compute)
#define RT 1

View File

@ -5,10 +5,31 @@
layout (location = 0) in vec2 inUv;
layout (location = 1) flat in uint inPass;
layout (location = 0) out vec4 outAlbedo;
layout (location = 0) out vec4 outColor;
layout (binding = 0) uniform sampler2D samplerAlbedo;
layout (binding = 0) uniform sampler2D samplerColor;
layout (binding = 1) uniform UBO {
float curTime;
float gamma;
float exposure;
uint padding;
} ubo;
#define TONE_MAP 1
#define GAMMA_CORRECT 1
#define TEXTURES 1
#include "../../common/macros.h"
#include "../../common/structs.h"
#include "../../common/functions.h"
void main() {
outAlbedo = texture( samplerAlbedo, inUv );
outColor = texture( samplerColor, inUv );
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}

View File

@ -5,15 +5,26 @@
layout (location = 0) in vec2 inUv;
layout (location = 1) flat in uint inPass;
layout (location = 0) out vec4 fragColor;
layout (location = 0) out vec4 outColor;
layout (binding = 0) uniform sampler2D samplerAlbedo;
layout (binding = 0) uniform sampler2D samplerColor;
layout (binding = 1) uniform UBO {
float curTime;
float gamma;
float exposure;
uint padding;
} ubo;
#define PI 3.14159265358
#define TONE_MAP 1
#define GAMMA_CORRECT 1
#define TEXTURES 1
#include "../../common/macros.h"
#include "../../common/structs.h"
#include "../../common/functions.h"
#if 0
float iTime = 0;
float noise(vec2 p) {
@ -45,7 +56,7 @@ vec4 getVideo(vec2 uv) {
float vShift = 0.4*onOff(2.,3.,.9)*(sin(iTime)*sin(iTime*20.) +
(0.5 + 0.1*sin(iTime*200.)*cos(iTime)));
look.y = mod(look.y + vShift, 1.);
return texture(samplerAlbedo,look);
return texture(samplerColor,look);
}
vec2 screenDistort(vec2 uv) {
@ -69,52 +80,65 @@ void main() {
video.rgb *= vignette;
video.rgb *= (12.+mod(uv.y*30.+iTime,1.))/13.;
fragColor = video;
outColor = video;
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#endif
#if 1
vec2 curveRemapUV(vec2 uv, vec2 curvature) {
uv = uv * 2.0 - 1.0;
uv = uv * 2.0 - 1.0;
vec2 offset = abs(uv.yx) / vec2(curvature.x, curvature.y);
uv = uv + uv * offset * offset;
uv = uv * 0.5 + 0.5;
return uv;
return uv;
}
vec4 scanLineIntensity(float uv, float resolution, float opacity) {
float intensity = sin(uv * resolution * PI * 2.0);
intensity = ((0.5 * intensity) + 0.5) * 0.9 + 0.1;
return vec4(vec3(pow(intensity, opacity)), 1.0);
float intensity = sin(uv * resolution * PI * 2.0);
intensity = ((0.5 * intensity) + 0.5) * 0.9 + 0.1;
return vec4(vec3(pow(intensity, opacity)), 1.0);
}
vec4 vignetteIntensity(vec2 uv, vec2 resolution, float opacity, float roundness) {
float intensity = uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y);
return vec4(vec3(clamp(pow((resolution.x / roundness) * intensity, opacity), 0.0, 1.0)), 1.0);
float intensity = uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y);
return vec4(vec3(clamp(pow((resolution.x / roundness) * intensity, opacity), 0.0, 1.0)), 1.0);
}
void main(void) {
const vec2 screenResolution = textureSize( samplerAlbedo, 0 );
const vec2 screenResolution = textureSize( samplerColor, 0 );
const vec2 scanLineOpacity = vec2(0.5);
const float brightness = 2;
const float vignetteOpacity = 0.5;
const float vignetteRoundness = 0.5;
const vec2 curvature = vec2(8);
const vec2 remappedUV = curveRemapUV(vec2(inUv.x, inUv.y), curvature);
vec4 baseColor = texture(samplerAlbedo, remappedUV);
const vec2 remappedUV = curveRemapUV(vec2(inUv.x, inUv.y), curvature);
vec4 baseColor = texture(samplerColor, remappedUV);
baseColor *= vignetteIntensity(remappedUV, screenResolution, vignetteOpacity, vignetteRoundness);
baseColor *= vignetteIntensity(remappedUV, screenResolution, vignetteOpacity, vignetteRoundness);
baseColor *= scanLineIntensity(remappedUV.x, screenResolution.y, scanLineOpacity.x);
baseColor *= scanLineIntensity(remappedUV.y, screenResolution.x, scanLineOpacity.y);
baseColor *= scanLineIntensity(remappedUV.x, screenResolution.y, scanLineOpacity.x);
baseColor *= scanLineIntensity(remappedUV.y, screenResolution.x, scanLineOpacity.y);
baseColor *= vec4(vec3(brightness), 1.0);
baseColor *= vec4(vec3(brightness), 1.0);
if (remappedUV.x < 0.0 || remappedUV.y < 0.0 || remappedUV.x > 1.0 || remappedUV.y > 1.0){
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
} else {
fragColor = baseColor;
}
if (remappedUV.x < 0.0 || remappedUV.y < 0.0 || remappedUV.x > 1.0 || remappedUV.y > 1.0){
outColor = vec4(0.0, 0.0, 0.0, 1.0);
} else {
outColor = baseColor;
}
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#endif
#if 0
@ -123,15 +147,15 @@ vec2 iResolution = vec2(640,480);
// Emulated input resolution.
#if 0
// Fix resolution to set amount.
#define res (vec2(320.0/1.0,160.0/1.0))
// Fix resolution to set amount.
#define res (vec2(320.0/1.0,160.0/1.0))
#else
// Optimize for resize.
#define res (iResolution.xy/6.0)
// Optimize for resize.
#define res (iResolution.xy/6.0)
#endif
// Hardness of scanline.
// -8.0 = soft
// -8.0 = soft
// -16.0 = medium
float hardScan=-8.0;
@ -164,92 +188,98 @@ vec3 ToSrgb(vec3 c){return vec3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}
// Nearest emulated sample given floating point position and texel offset.
// Also zero's off screen.
vec3 Fetch(vec2 pos,vec2 off){
pos=floor(pos*res+off)/res;
if(max(abs(pos.x-0.5),abs(pos.y-0.5))>0.5)return vec3(0.0,0.0,0.0);
return ToLinear(texture(samplerAlbedo,pos.xy,-16.0).rgb);}
pos=floor(pos*res+off)/res;
if(max(abs(pos.x-0.5),abs(pos.y-0.5))>0.5)return vec3(0.0,0.0,0.0);
return ToLinear(texture(samplerColor,pos.xy,-16.0).rgb);}
// Distance in emulated pixels to nearest texel.
vec2 Dist(vec2 pos){pos=pos*res;return -((pos-floor(pos))-vec2(0.5));}
// 1D Gaussian.
float Gaus(float pos,float scale){return exp2(scale*pos*pos);}
// 3-tap Gaussian filter along horz line.
vec3 Horz3(vec2 pos,float off){
vec3 b=Fetch(pos,vec2(-1.0,off));
vec3 c=Fetch(pos,vec2( 0.0,off));
vec3 d=Fetch(pos,vec2( 1.0,off));
float dst=Dist(pos).x;
// Convert distance to weight.
float scale=hardPix;
float wb=Gaus(dst-1.0,scale);
float wc=Gaus(dst+0.0,scale);
float wd=Gaus(dst+1.0,scale);
// Return filtered sample.
return (b*wb+c*wc+d*wd)/(wb+wc+wd);}
vec3 b=Fetch(pos,vec2(-1.0,off));
vec3 c=Fetch(pos,vec2( 0.0,off));
vec3 d=Fetch(pos,vec2( 1.0,off));
float dst=Dist(pos).x;
// Convert distance to weight.
float scale=hardPix;
float wb=Gaus(dst-1.0,scale);
float wc=Gaus(dst+0.0,scale);
float wd=Gaus(dst+1.0,scale);
// Return filtered sample.
return (b*wb+c*wc+d*wd)/(wb+wc+wd);}
// 5-tap Gaussian filter along horz line.
vec3 Horz5(vec2 pos,float off){
vec3 a=Fetch(pos,vec2(-2.0,off));
vec3 b=Fetch(pos,vec2(-1.0,off));
vec3 c=Fetch(pos,vec2( 0.0,off));
vec3 d=Fetch(pos,vec2( 1.0,off));
vec3 e=Fetch(pos,vec2( 2.0,off));
float dst=Dist(pos).x;
// Convert distance to weight.
float scale=hardPix;
float wa=Gaus(dst-2.0,scale);
float wb=Gaus(dst-1.0,scale);
float wc=Gaus(dst+0.0,scale);
float wd=Gaus(dst+1.0,scale);
float we=Gaus(dst+2.0,scale);
// Return filtered sample.
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}
vec3 a=Fetch(pos,vec2(-2.0,off));
vec3 b=Fetch(pos,vec2(-1.0,off));
vec3 c=Fetch(pos,vec2( 0.0,off));
vec3 d=Fetch(pos,vec2( 1.0,off));
vec3 e=Fetch(pos,vec2( 2.0,off));
float dst=Dist(pos).x;
// Convert distance to weight.
float scale=hardPix;
float wa=Gaus(dst-2.0,scale);
float wb=Gaus(dst-1.0,scale);
float wc=Gaus(dst+0.0,scale);
float wd=Gaus(dst+1.0,scale);
float we=Gaus(dst+2.0,scale);
// Return filtered sample.
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}
// Return scanline weight.
float Scan(vec2 pos,float off){
float dst=Dist(pos).y;
return Gaus(dst+off,hardScan);}
float dst=Dist(pos).y;
return Gaus(dst+off,hardScan);}
// Allow nearest three lines to effect pixel.
vec3 Tri(vec2 pos){
vec3 a=Horz3(pos,-1.0);
vec3 b=Horz5(pos, 0.0);
vec3 c=Horz3(pos, 1.0);
float wa=Scan(pos,-1.0);
float wb=Scan(pos, 0.0);
float wc=Scan(pos, 1.0);
return a*wa+b*wb+c*wc;}
vec3 a=Horz3(pos,-1.0);
vec3 b=Horz5(pos, 0.0);
vec3 c=Horz3(pos, 1.0);
float wa=Scan(pos,-1.0);
float wb=Scan(pos, 0.0);
float wc=Scan(pos, 1.0);
return a*wa+b*wb+c*wc;}
// Distortion of scanlines, and end of screen alpha.
vec2 Warp(vec2 pos){
pos=pos*2.0-1.0;
pos*=vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y);
return pos*0.5+0.5;}
pos=pos*2.0-1.0;
pos*=vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y);
return pos*0.5+0.5;}
// Shadow mask.
vec3 Mask(vec2 pos){
pos.x+=pos.y*3.0;
vec3 mask=vec3(maskDark,maskDark,maskDark);
pos.x=fract(pos.x/6.0);
if(pos.x<0.333)mask.r=maskLight;
else if(pos.x<0.666)mask.g=maskLight;
else mask.b=maskLight;
return mask;}
pos.x+=pos.y*3.0;
vec3 mask=vec3(maskDark,maskDark,maskDark);
pos.x=fract(pos.x/6.0);
if(pos.x<0.333)mask.r=maskLight;
else if(pos.x<0.666)mask.g=maskLight;
else mask.b=maskLight;
return mask;}
void main() {
iResolution = textureSize( samplerAlbedo, 0 );
iResolution = textureSize( samplerColor, 0 );
fragCoord = inUv * iResolution;
vec2 pos = Warp(fragCoord.xy / iResolution.xy);
hardScan = -12.0;
maskDark = maskLight = 1.0;
hardScan = -12.0;
maskDark = maskLight = 1.0;
fragColor.rgb = Tri(pos) * Mask(fragCoord.xy);
fragColor.rgb = ToSrgb(fragColor.rgb);
fragColor.a = 1.0;
outColor.rgb = Tri(pos) * Mask(fragCoord.xy);
outColor.rgb = ToSrgb(outColor.rgb);
outColor.a = 1.0;
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#endif
#if 0
@ -257,8 +287,11 @@ void main() {
const vec2 uv = 0.025 * sin( ubo.curTime ) * inUv.xy;
const float mdf = 0.5;
const float noise = (fract(sin(dot(uv, vec2(12.9898,78.233)*2.0)) * 43758.5453));
const vec4 sampled = texture( samplerAlbedo, inUv );
fragColor = sampled - noise * mdf;
const vec4 sampled = texture( samplerColor, inUv );
outColor = sampled - noise * mdf;
toneMap(outColor, ubo.exposure);
gammaCorrect(outColor, ubo.gamma);
}
#endif

View File

@ -10,6 +10,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
#define VXGI 1
#define MAX_CUBEMAPS CUBEMAPS
#define GAMMA_CORRECT 1
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
@ -104,7 +105,7 @@ void main() {
const vec3 Liu = light.position - surface.position.world;
const vec3 Li = normalize(Liu);
const float Ls = shadowFactor( light, 0.0 );
const float La = 1.0 / (PI * pow(length(Liu), 2.0));
const float La = 1.0 / (1 + (PI * pow(length(Liu), 2.0)));
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.world, Li));
@ -130,6 +131,13 @@ void main() {
surface.fragment.rgb += surface.light.rgb;
#if TONE_MAP
toneMap(surface.fragment.rgb, ubo.settings.bloom.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(surface.fragment.rgb, 1.0 / ubo.settings.bloom.gamma);
#endif
imageStore(voxelRadiance[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, surface.material.albedo.a));
}
}

View File

@ -17,26 +17,37 @@ layout (binding = 6) uniform samplerCube samplerCubemaps[CUBEMAPS];
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (std140, binding = 7) readonly buffer DrawCommands {
layout (binding = 7) uniform Camera {
Viewport viewport[6];
} camera;
layout (binding = 8) uniform UBO {
uint lights;
uint currentID;
uint padding1;
uint padding2;
} ubo;
layout (std140, binding = 9) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 8) readonly buffer Instances {
layout (std140, binding = 10) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 9) readonly buffer InstanceAddresseses {
layout (std140, binding = 11) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 10) readonly buffer Materials {
layout (std140, binding = 12) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 11) readonly buffer Textures {
layout (std140, binding = 13) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 12) readonly buffer Lights {
layout (std140, binding = 14) readonly buffer Lights {
Light lights[];
};
layout (binding = 13, rgba8) uniform volatile coherent image3D outAlbedos;
layout (binding = 15, rgba8) uniform volatile coherent image3D outAlbedos;
#include "../../common/functions.h"
#include "../../common/shadows.h"
@ -60,19 +71,26 @@ void main() {
const uint drawID = uint(inId.y);
const uint instanceID = uint(inId.z);
const DrawCommand drawCommand = drawCommands[drawID];
const Instance instance = instances[instanceID];
if ( instanceID != ubo.currentID ) discard;
surface.uv.xy = wrap(inUv.xy);
surface.uv.z = mipLevel(dFdx(inUv), dFdy(inUv));
surface.position.world = inPosition;
surface.normal.world = inNormal;
const DrawCommand drawCommand = drawCommands[drawID];
const Instance instance = instances[instanceID];
const Material material = materials[instance.materialID];
const uint mapID = instance.auxID;
vec4 A = material.colorBase;
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = 1.0f - material.factorOcclusion;
#if 0
vec3 N = inNormal;
vec3 T = inTangent;
T = normalize(T - dot(T, N) * N);
@ -84,14 +102,19 @@ void main() {
} else {
surface.normal.world = N;
}
#endif
surface.light = material.colorEmissive;
surface.material.albedo = vec4(1);
#if 1
#if 1
{
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
for ( uint i = 0; i < lights.length(); ++i ) {
for ( uint i = 0; i < min(ubo.lights, lights.length()); ++i ) {
const Light light = lights[i];
if ( light.type <= 0 ) continue;
const mat4 mat = light.view; // inverse(light.view);
const vec3 position = surface.position.world;
// const vec3 position = vec3( mat * vec4(surface.position.world, 1.0) );
@ -106,7 +129,7 @@ void main() {
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Lo = normalize( -position );
const float cosLo = max(0.0, dot(normal, Lo));
const float cosLo = max(0.0, abs(dot(normal, Lo)));
const vec3 Li = normalize(Liu);
const vec3 Lr = light.color.rgb * light.power * La * Ls;
@ -168,8 +191,8 @@ void main() {
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += light.power * La * Ls;
}
}
}
#endif
#endif
#define EXPOSURE 0
#define GAMMA 0
@ -181,7 +204,7 @@ void main() {
{
const vec2 st = inSt.xy * imageSize(outAlbedos).xy;
const ivec3 uvw = ivec3(int(st.x), int(st.y), int(drawCommand.auxID));
const ivec3 uvw = ivec3(int(st.x), int(st.y), int(mapID));
imageStore(outAlbedos, uvw, vec4(surface.light.rgb, 1) );
}
}

View File

@ -4,6 +4,5 @@
#define INSTANCED 1
#define SKINNED 0
#define BAKING 1
#define LAYERED 1
#include "../base/vert.h"

View File

@ -1,8 +1,5 @@
layout (constant_id = 0) const uint PASSES = 6;
#extension GL_ARB_shader_draw_parameters : enable
#if LAYERED
#extension GL_ARB_shader_viewport_layer_array : enable
#endif
#include "../../common/macros.h"
#include "../../common/structs.h"

View File

@ -11,7 +11,6 @@ layout (constant_id = 3) const uint CASCADES = 1;
// shader type settings
#define RT 1
#define COMPUTE 1
#define DEFERRED_SAMPLING 1
#define BUFFER_REFERENCE 1
#define UINT64_ENABLED 1
@ -379,20 +378,11 @@ void main() {
#if BLOOM
float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
vec4 outFragBright = brightness > ubo.threshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), outFragBright);
// imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), outFragBright);
#endif
#if FOG
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
#endif
#if TONE_MAP
surface.fragment.rgb = vec3(1.0) - exp(-surface.fragment.rgb * ubo.settings.bloom.exposure);
#endif
#if GAMMA_CORRECT
surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / ubo.settings.bloom.gamma));
#endif
#if WHITENOISE
if ( enabled(ubo.settings.mode.type, 1) ) whitenoise(surface.fragment.rgb, ubo.settings.mode.parameters);
#endif
}
{

View File

@ -109,10 +109,8 @@ void client::initialize() {
#endif
if ( !ext::json::isArray( configRenderJson["framebuffer"]["size"] ) ) {
float scale = configRenderJson["framebuffer"]["size"].as(1.0f);
uf::renderer::settings::width = payload.window.size.x * scale;
uf::renderer::settings::height = payload.window.size.y * scale;
uf::renderer::settings::width = payload.window.size.x;
uf::renderer::settings::height = payload.window.size.y;
}
uf::renderer::states::resized = true;
} );
@ -126,9 +124,6 @@ void client::initialize() {
#if UF_ENV_DREAMCAST
client::window.pollEvents();
#endif
{
}
}
void client::tick() {

View File

@ -7,9 +7,13 @@
#if UF_USE_FFX_FSR
namespace ext {
namespace fsr {
extern pod::Vector2f UF_API jitter;
extern float UF_API sharpness;
extern bool UF_API initialized;
extern uf::stl::string UF_API preset;
extern float UF_API sharpness;
extern pod::Vector2f UF_API jitter;
extern float UF_API jitterScale;
void UF_API initialize();
void UF_API tick();

View File

@ -19,6 +19,9 @@ namespace ext {
namespace Format {
typedef decltype(VK_FORMAT_R32G32_SFLOAT) type_t;
#include "enums/format.inl"
static const type_t HDR = R32G32B32A32_SFLOAT;
static const type_t SDR = R16G16B16A16_SFLOAT;
}
namespace Face {
typedef decltype(VK_FRONT_FACE_CLOCKWISE) type_t;

View File

@ -18,6 +18,7 @@ namespace ext {
uint32_t width = 0;
uint32_t height = 0;
float scale = 0;
struct {
uf::Serializer json;

View File

@ -47,6 +47,7 @@ namespace ext {
uint32_t width = 0;
uint32_t height = 0;
uint8_t views = 1;
float scale = 0;
// RAII
void initialize( Device& device );
void destroy();

View File

@ -354,7 +354,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
uf::stl::string geometryShaderFilename = uf::io::resolveURI("/graph/baking/geom.spv");
uf::stl::string fragmentShaderFilename = uf::io::resolveURI("/graph/baking/frag.spv");
graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "baking");
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking");
// graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking");
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "baking");
graphic.material.metadata.autoInitializeUniformBuffers = true;
}
@ -539,6 +539,9 @@ void uf::graph::process( pod::Graph& graph ) {
}
}
if ( graph.metadata["lights"]["lightmap"].is<bool>() && !graph.metadata["lights"]["lightmap"].as<bool>() ) {
graph.metadata["baking"]["enabled"] = false;
}
if ( !sceneMetadataJson["light"]["useLightmaps"].as<bool>(true) ) {
graph.metadata["lights"]["lightmap"] = false;
graph.metadata["baking"]["enabled"] = false;
@ -564,31 +567,38 @@ void uf::graph::process( pod::Graph& graph ) {
graph.metadata["baking"]["layers"] = lightmapCount;
if ( graph.metadata["lights"]["lightmap"].as<bool>() ) for ( auto& pair : filenames ) {
auto i = pair.first;
auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) );
if ( !uf::io::exists( f ) ) {
UF_MSG_ERROR( "lightmap does not exist: {} {}", i, f )
continue;
if ( graph.metadata["lights"]["lightmap"].as<bool>() ) {
for ( auto& pair : filenames ) {
auto i = pair.first;
auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) );
if ( !uf::io::exists( f ) ) {
graph.metadata["lights"]["lightmap"] = false;
UF_MSG_ERROR( "lightmap does not exist: {} {}, disabling lightmaps", i, f )
break;
}
}
}
if ( graph.metadata["lights"]["lightmap"].as<bool>() ) {
for ( auto& pair : filenames ) {
auto i = pair.first;
auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) );
auto textureID = graph.textures.size();
auto imageID = graph.images.size();
auto textureID = graph.textures.size();
auto imageID = graph.images.size();
auto& texture = /*graph.storage*/uf::graph::storage.textures[graph.textures.emplace_back(f)];
auto& image = /*graph.storage*/uf::graph::storage.images[graph.images.emplace_back(f)];
image.open( f, false );
auto& texture = /*graph.storage*/uf::graph::storage.textures[graph.textures.emplace_back(f)];
auto& image = /*graph.storage*/uf::graph::storage.images[graph.images.emplace_back(f)];
image.open( f, false );
texture.index = imageID;
texture.index = imageID;
lightmapIDs[i] = textureID;
lightmapIDs[i] = textureID;
graph.metadata["lights"]["lightmaps"][i] = f;
graph.metadata["baking"]["enabled"] = false;
graph.metadata["lights"]["lightmaps"][i] = f;
graph.metadata["baking"]["enabled"] = false;
isSrgb[f] = false;
isSrgb[f] = false;
}
}
for ( auto& name : graph.instances ) {
@ -960,7 +970,11 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
// ignore pesky light_Orientation nodes
if ( uf::string::split( node.name, "_" ).back() == "Orientation" ) ignore = true;
// for dreamcast, ignore lights if we're baked
if ( graph.metadata["lights"]["lightmapped"].as<bool>() && graph.metadata["lights"]["disable if lightmapped"].as<bool>(true) ) if ( graph.lights.count(node.name) > 0 ) ignore = true;
/*
if ( graph.metadata["lights"]["lightmap"].as<bool>() && graph.metadata["lights"]["disable if lightmapped"].as<bool>(true) ) {
if ( graph.lights.count(node.name) > 0 ) ignore = true;
}
*/
// on systems where frametime is very, very important, we can set all static nodes to not tick
@ -969,6 +983,19 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
if ( graph.metadata["baking"]["enabled"].as<bool>(false) && !tag["bake"].as<bool>(true) ) ignore = true;
if ( tag["ignore"].as<bool>() ) ignore = true;
}
bool isLight = graph.lights.count(node.name) > 0;
/*
if ( graph.metadata["lights"]["lightmap"].as<bool>() )
if ( ext::json::isObject( tag ) ) {
if ( !tag["light"]["dynamic"].as<bool>() && !tag["light"]["shadows"].as<bool>() ) {
ignore = true;
UF_MSG_DEBUG("IGNORING {}", node.name);
}
} else {
ignore = true;
}
}
*/
if ( ignore ) return;
// create child
@ -1017,7 +1044,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
// create as light
{
if ( graph.lights.count(node.name) > 0 ) {
if ( isLight ) {
auto& l = graph.lights[node.name];
#if UF_USE_OPENGL
@ -1034,8 +1061,9 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
metadataLight["color"][1] = l.color.y;
metadataLight["color"][2] = l.color.z;
metadataLight["shadows"] = graph.metadata["lights"]["shadows"].as<bool>();
metadataLight["dynamic"] = false;
if ( uf::string::matched( node.name, "/\\bspot\\b/" ) ) {
if ( uf::string::matched( node.name, R"(/\bspot\b/)" ) ) {
metadataLight["type"] = "spot";
}
@ -1050,28 +1078,20 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
if ( key == "transform" ) return;
metadataLight[key] = value;
});
#if !UF_USE_OPENGL
/*
bool should = false;
if ( !graph.metadata["lights"]["lightmapped"].as<bool>() ) {
if ( !graph.metadata["lights"]["lightmap"].as<bool>() ) {
should = true;
} else if ( metadataLight["shadows"].as<bool>() || metadataLight["dynamic"].as<bool>() ) {
should = true;
}
if ( should ) {
auto& metadataJson = entity.getComponent<uf::Serializer>();
entity.load("/light.json");
// copy
ext::json::forEach( metadataLight, [&]( const uf::stl::string& key, ext::json::Value& value ) {
metadataJson["light"][key] = value;
});
/*
if ( metadataJson["light"]["type"].as<uf::stl::string>() == "point" ) {
auto& transform = entity.getComponent<pod::Transform<>>();
transform.orientation = uf::quaternion::identity();
}
*/
}
#endif
*/
auto& metadataJson = entity.getComponent<uf::Serializer>();
entity.load("/light.json");
// copy
ext::json::forEach( metadataLight, [&]( const uf::stl::string& key, ext::json::Value& value ) {
metadataJson["light"][key] = value;
});
}
}

View File

@ -143,8 +143,8 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::stl::str
const uf::stl::string filename = _filename != "" ? _filename : (uf::stl::string("/") + uf::string::lowercase(name) + "/scene.json");
#endif
scene->load(filename);
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
if ( uf::renderer::settings::pipelines::rt ) uf::instantiator::bind( "RayTraceSceneBehavior", *scene );
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
scene->initialize();
return *scene;
}
@ -152,8 +152,8 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::Serializ
uf::Scene* scene = uf::instantiator::objects->has( name ) ? (uf::Scene*) &uf::instantiator::instantiate( name ) : new uf::Scene;
uf::scene::scenes.emplace_back( scene );
if ( data != "" ) scene->load(data);
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
if ( uf::renderer::settings::pipelines::rt ) uf::instantiator::bind( "RayTraceSceneBehavior", *scene );
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
scene->initialize();
return *scene;
}

View File

@ -17,6 +17,8 @@ namespace {
FfxFsr2Context context;
FfxFsr2ContextDescription contextDescription;
uf::renderer::Texture fsrTarget;
uf::stl::string FFX_ERROR_TO_STRING( FfxErrorCode code ) {
switch ( code ) {
case FFX_OK: return "OK"; break;
@ -66,55 +68,14 @@ namespace {
#if 1
FfxFsr2DispatchDescription dispatchParameters = {};
dispatchParameters.commandList = ffxGetCommandListVK(commandBuffer);
if ( uf::renderer::settings::pipelines::rt ) {
if ( !uf::renderer::hasRenderMode("Compute:RT", true) ) return;
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
pod::Vector2ui renderSize = {
renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width,
renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height,
};
dispatchParameters.renderSize.width = renderSize.x;
dispatchParameters.renderSize.height = renderSize.y;
auto& attachmentColor = renderMode.hasAttachment("output") ? renderMode.getAttachment("output") : renderMode.getAttachment("color");
auto& attachmentDepth = renderMode.getAttachment("depth");
auto& attachmentMotion = renderMode.getAttachment("motion");
dispatchParameters.color = ffxGetTextureResourceVK(&::context,
attachmentColor.image,
attachmentColor.view,
renderSize.x,
renderSize.y,
attachmentColor.descriptor.format,
L"FSR2_InputColor"
);
dispatchParameters.depth = ffxGetTextureResourceVK(&::context,
attachmentDepth.image,
attachmentDepth.view,
renderSize.x,
renderSize.y,
attachmentDepth.descriptor.format,
L"FSR2_InputDepth"
);
dispatchParameters.motionVectors = ffxGetTextureResourceVK(&::context,
attachmentMotion.image,
attachmentMotion.view,
renderSize.x,
renderSize.y,
attachmentMotion.descriptor.format,
L"FSR2_InputMotionVectors"
);
dispatchParameters.motionVectorScale.x = renderSize.x;
dispatchParameters.motionVectorScale.y = renderSize.y;
} else {
{
if ( !uf::renderer::hasRenderMode("", true) ) return;
auto& renderMode = uf::renderer::getRenderMode("", true);
pod::Vector2ui renderSize = {
renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width,
renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height,
renderMode.width > 0 ? renderMode.width : (uf::renderer::settings::width * renderMode.scale),
renderMode.height > 0 ? renderMode.height : (uf::renderer::settings::height * renderMode.scale),
};
dispatchParameters.renderSize.width = renderSize.x;
dispatchParameters.renderSize.height = renderSize.y;
@ -151,15 +112,16 @@ namespace {
dispatchParameters.motionVectorScale.y = renderSize.y;
}
{
/*
if ( !uf::renderer::hasRenderMode("Swapchain", true) ) return;
auto& swapchainRenderMode = uf::renderer::getRenderMode("Swapchain", true);
auto& attachmentOutput = swapchainRenderMode.getAttachment("color["+std::to_string(swapchainIndex)+"]");
// auto& attachmentOutput = swapchainRenderMode.getAttachment("color["+std::to_string(swapchainIndex)+"]");
pod::Vector2ui displaySize = {
swapchainRenderMode.width, // uf::renderer::settings::width
swapchainRenderMode.height, // uf::renderer::settings::height
};
auto& attachmentOutput = swapchainRenderMode.getAttachment("fsr");
dispatchParameters.output = ffxGetTextureResourceVK(&::context,
attachmentOutput.image,
attachmentOutput.view,
@ -168,6 +130,15 @@ namespace {
attachmentOutput.descriptor.format,
L"FSR2_OutputUpscaledColor", FFX_RESOURCE_STATE_UNORDERED_ACCESS
);
*/
dispatchParameters.output = ffxGetTextureResourceVK(&::context,
fsrTarget.image,
fsrTarget.view,
fsrTarget.width,
fsrTarget.height,
fsrTarget.format,
L"FSR2_OutputUpscaledColor", FFX_RESOURCE_STATE_UNORDERED_ACCESS
);
}
dispatchParameters.exposure = ffxGetTextureResourceVK(&::context,
@ -202,7 +173,7 @@ namespace {
dispatchParameters.jitterOffset.x = ext::fsr::jitter.x; // m_JitterX;
dispatchParameters.jitterOffset.y = ext::fsr::jitter.y; // m_JitterY;
dispatchParameters.reset = false; // uf::renderer::states::frameAccumulateReset; // pState->bReset;
dispatchParameters.reset = uf::renderer::states::frameAccumulateReset; // pState->bReset;
dispatchParameters.enableSharpening = ext::fsr::sharpness > 0.0f; // pState->bUseRcas;
dispatchParameters.sharpness = ext::fsr::sharpness; //1.0f; // pState->sharpening;
dispatchParameters.frameTimeDelta = uf::time::delta;
@ -216,8 +187,10 @@ namespace {
}
}
uf::stl::string ext::fsr::preset = "native";
pod::Vector2f ext::fsr::jitter = {};
float ext::fsr::sharpness = 1.0f;
float ext::fsr::jitterScale = 2.0f;
bool ext::fsr::initialized = false;
void UF_API ext::fsr::initialize() {
@ -230,7 +203,7 @@ void UF_API ext::fsr::initialize() {
::contextDescription.maxRenderSize.height = 2160; // uf::renderer::settings::height;
::contextDescription.displaySize.width = uf::renderer::settings::width;
::contextDescription.displaySize.height = uf::renderer::settings::height;
::contextDescription.flags = FFX_FSR2_ENABLE_AUTO_EXPOSURE | FFX_FSR2_ENABLE_DYNAMIC_RESOLUTION; // | FFX_FSR2_ENABLE_TEXTURE1D_USAGE;
::contextDescription.flags = FFX_FSR2_ENABLE_AUTO_EXPOSURE | FFX_FSR2_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION ; // | FFX_FSR2_ENABLE_DYNAMIC_RESOLUTION; // | FFX_FSR2_ENABLE_TEXTURE1D_USAGE;
if ( uf::renderer::settings::pipelines::hdr ) ::contextDescription.flags |= FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE;
if ( uf::matrix::reverseInfiniteProjection ) ::contextDescription.flags |= FFX_FSR2_ENABLE_DEPTH_INVERTED | FFX_FSR2_ENABLE_DEPTH_INFINITE;
@ -242,30 +215,56 @@ void UF_API ext::fsr::initialize() {
#if 0
swapchainRenderMode.bindCallback( swapchainRenderMode.CALLBACK_BEGIN, draw);
#endif
{
fsrTarget.destroy();
fsrTarget.fromBuffers(
NULL, 0,
uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR,
uf::renderer::settings::width, uf::renderer::settings::height, 1, 1,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
);
auto& renderMode = uf::renderer::getRenderMode("", true);
auto& blitter = *renderMode.getBlitter();
auto& shader = blitter.material.getShader("fragment");
shader.textures.clear();
shader.textures.emplace_back().aliasTexture( fsrTarget );
}
}
void UF_API ext::fsr::tick() {
if ( !ext::fsr::initialized ) return;
pod::Vector2ui renderSize = {};
pod::Vector2ui displaySize = {};
if ( uf::renderer::settings::pipelines::rt ) {
if ( !uf::renderer::hasRenderMode("Compute:RT", true) ) return;
if ( uf::renderer::states::resized ) {
::contextDescription.displaySize.width = uf::renderer::settings::width;
::contextDescription.displaySize.height = uf::renderer::settings::height;
FFX_ERROR_CHECK(ffxFsr2ContextDestroy( &::context ));
FFX_ERROR_CHECK(ffxFsr2ContextCreate( &::context, &::contextDescription ));
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
auto& blitter = *renderMode.getBlitter(); if ( !blitter.material.hasShader("fragment") ) return;
auto& shader = blitter.material.getShader("fragment"); if ( shader.textures.empty() ) return;
fsrTarget.destroy();
fsrTarget.fromBuffers(
NULL, 0,
uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR,
::contextDescription.displaySize.width, ::contextDescription.displaySize.height, 1, 1,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
);
auto& attachmentColor = shader.textures.front();
renderSize = {
attachmentColor.width > 0 ? attachmentColor.width : uf::renderer::settings::width,
attachmentColor.height > 0 ? attachmentColor.height : uf::renderer::settings::height,
};
} else {
auto& renderMode = uf::renderer::getRenderMode("", true);
auto& blitter = *renderMode.getBlitter();
auto& shader = blitter.material.getShader("fragment");
shader.textures.clear();
shader.textures.emplace_back().aliasTexture( fsrTarget );
}
{
if ( !uf::renderer::hasRenderMode("", true) ) return;
auto& renderMode = uf::renderer::getRenderMode("", true);
renderSize = {
renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width,
renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height,
renderMode.width > 0 ? renderMode.width : (uf::renderer::settings::width * renderMode.scale),
renderMode.height > 0 ? renderMode.height : (uf::renderer::settings::height * renderMode.scale),
};
}
@ -281,13 +280,17 @@ void UF_API ext::fsr::tick() {
const int32_t jitterPhaseCount = ffxFsr2GetJitterPhaseCount(renderSize.x, displaySize.x);
static uint32_t index = 0;
if ( ++index > jitterPhaseCount ) index = 0;
if ( index++ > jitterPhaseCount ) index = 0;
ffxFsr2GetJitterOffset(&ext::fsr::jitter.x, &ext::fsr::jitter.x, index, jitterPhaseCount);
ffxFsr2GetJitterOffset(&ext::fsr::jitter.x, &ext::fsr::jitter.y, index, jitterPhaseCount);
pod::Vector2f jitter = {};
jitter.x = 2.0f * jitter.x / (float) renderSize.x;
jitter.y = 2.0f * 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;
// UF_MSG_DEBUG("{}, {} x {} ({} {})", ext::fsr::jitterScale, jitter.x, jitter.y, index, jitterPhaseCount);
::jitterMatrix = uf::matrix::translate( uf::matrix::identity(), pod::Vector3f{ jitter.x, jitter.y, 0 } );
}
void UF_API ext::fsr::render() {
@ -295,7 +298,6 @@ void UF_API ext::fsr::render() {
auto commandBuffer = uf::renderer::device.fetchCommandBuffer(uf::renderer::QueueEnum::GRAPHICS, true);
draw(commandBuffer, uf::renderer::states::currentBuffer);
uf::renderer::device.flushCommandBuffer(commandBuffer);
}
void UF_API ext::fsr::terminate() {
if ( !ext::fsr::initialized ) return;

View File

@ -1058,6 +1058,7 @@ void ext::vulkan::Device::initialize() {
VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures{};
VkPhysicalDeviceShaderClockFeaturesKHR shaderClockFeatures{};
VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR fragmentShaderBarycentricFeatures{};
VkPhysicalDeviceSubgroupSizeControlFeatures subgroupSizeControlFeatures{};
VkPhysicalDeviceVulkan12Features enabledPhysicalDeviceVulkan12Features{};
VkPhysicalDeviceFeatures2 enabledDeviceFeatures2{}; {
@ -1121,6 +1122,10 @@ void ext::vulkan::Device::initialize() {
fragmentShaderBarycentricFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR;
fragmentShaderBarycentricFeatures.fragmentShaderBarycentric = VK_TRUE;
}
{
subgroupSizeControlFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES;
subgroupSizeControlFeatures.subgroupSizeControl = true;
}
deviceCreateInfo.pNext = &physicalDeviceFeatures2;
physicalDeviceFeatures2.pNext = &physicalDeviceVulkan12Features;
@ -1133,6 +1138,7 @@ void ext::vulkan::Device::initialize() {
rayQueryFeatures.pNext = &accelerationStructureFeatures;
accelerationStructureFeatures.pNext = &shaderClockFeatures;
shaderClockFeatures.pNext = &fragmentShaderBarycentricFeatures;
fragmentShaderBarycentricFeatures.pNext = &subgroupSizeControlFeatures;
if ( settings::experimental::enableMultiGPU ) {
UF_MSG_DEBUG("Multiple devices supported, using {} devices...", groupDeviceCreateInfo.physicalDeviceCount);

View File

@ -459,9 +459,9 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescrip
if ( shader->descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
auto& localSize = shader->metadata.definitions.localSize;
vkCmdDispatch(commandBuffer,
localSize.x ? ((width / localSize.x) + 1) : 1,
localSize.y ? ((height / localSize.y) + 1) : 1,
localSize.z ? ((depth / localSize.z) + 1) : 1
1 < localSize.x ? ((width / localSize.x) + 1) : 1,
1 < localSize.y ? ((height / localSize.y) + 1) : 1,
1 < localSize.z ? ((depth / localSize.z) + 1) : 1
);
}
}
@ -566,7 +566,6 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
}
if ( attachment ) {
// subscript on name will grab the view # from attachment->views
if ( 0 <= view ) {
texture.aliasAttachment( *attachment, (size_t) view );
@ -578,6 +577,10 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
if ( descriptor.layout != VK_IMAGE_LAYOUT_UNDEFINED ) {
texture.imageLayout = descriptor.layout;
texture.descriptor.imageLayout = descriptor.layout;
} else {
texture.imageLayout = ext::vulkan::Texture::remapRenderpassLayout( texture.imageLayout );
texture.descriptor.imageLayout = ext::vulkan::Texture::remapRenderpassLayout( texture.imageLayout );
}
INSERT_IMAGE(texture);
@ -1038,14 +1041,6 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
// ensure our descriptors are proper
mesh.updateDescriptor();
#if 0
// it makes my life 10000x easier if we interleave a mesh while also requesting RT pipelines
if ( !mesh.isInterleaved() && uf::renderer::settings::pipelines::rt ) {
auto interleaved = mesh.interleave();
return initializeMesh(interleaved);
}
#endif
// copy descriptors
descriptor.inputs.vertex = mesh.vertex;
descriptor.inputs.index = mesh.index;
@ -1584,6 +1579,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
} else UF_EXCEPTION("Buffers not found: {}", "tlasInstance");
rebuild = rebuild || this->updateBuffer( (const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR), instanceIndex, false );
}
size_t instanceBufferAddress = this->buffers[instanceIndex].getAddress();
// have a front-and-back TLAS (buffer)
@ -1784,7 +1780,6 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
// uf::renderer::states::rebuild = true;
}
// build SBT
if ( !this->material.hasShader("ray:gen", uf::renderer::settings::pipelines::names::rt) ) {
{
@ -1802,7 +1797,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
auto& shader = this->material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
shader.buffers.emplace_back( this->buffers[tlasBufferIndex].alias() );
}
}
}
}
bool ext::vulkan::Graphic::hasPipeline( const GraphicDescriptor& descriptor ) const {
return pipelines.count( descriptor ) > 0;

View File

@ -343,9 +343,12 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
// this->width = 0; //ext::vulkan::width;
// this->height = 0; //ext::vulkan::height;
if ( this->scale == 0 ) this->scale = 1;
{
if ( this->width > 0 ) renderTarget.width = this->width;
if ( this->height > 0 ) renderTarget.height = this->height;
if ( this->scale > 0 ) renderTarget.scale = this->scale;
}
// Set sync objects

View File

@ -40,10 +40,12 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ex
imageMemoryBarrier.subresourceRange.layerCount = 1;
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
uf::stl::vector<RenderMode*> layers = ext::vulkan::getRenderModes(uf::stl::vector<uf::stl::string>{"RenderTarget", "Compute:RT", "Deferred"}, false);
if ( !settings::pipelines::rt ) {
uf::stl::vector<RenderMode*> layers = ext::vulkan::getRenderModes(uf::stl::vector<uf::stl::string>{"Deferred", "Compute:RT", "RenderTarget"}, false);
#if 0
if ( settings::pipelines::rt ) {
std::reverse( layers.begin(), layers.end() );
}
#endif
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
@ -214,6 +216,7 @@ void ext::vulkan::BaseRenderMode::tick() {
}
}
void ext::vulkan::BaseRenderMode::render() {
// if ( ext::vulkan::states::frameSkip ) return;
// if ( ext::vulkan::renderModes.size() > 1 ) return;
// if ( ext::vulkan::renderModes.back() != this ) return;
@ -273,13 +276,13 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
// create image views for swapchain images
renderTarget.attachments.clear();
renderTarget.attachments.resize( ext::vulkan::swapchain.buffers + 1 );
renderTarget.attachments.resize( ext::vulkan::swapchain.buffers );
// uint32_t width = windowSize.x; //this->width > 0 ? this->width : windowSize.x;
// uint32_t height = windowSize.y; //this->height > 0 ? this->height : windowSize.y;
size_t attachmentIndex = 0;
for ( size_t i = 0; i < images.size(); ++i ) {
for ( size_t i = 0; i < ext::vulkan::swapchain.buffers; ++i ) {
VkImageViewCreateInfo colorAttachmentView = {};
colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
colorAttachmentView.pNext = NULL;
@ -310,10 +313,11 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
metadata.attachments["color["+std::to_string((int) i)+"]"] = attachmentIndex++;
}
// Create depth
auto& depthAttachment = renderTarget.attachments.back();
metadata.attachments["depth"] = attachmentIndex++;
{
// Create depth
auto& attachment = renderTarget.attachments.emplace_back();
metadata.attachments["depth"] = attachmentIndex++;
// Create an optimal image used as the depth stencil attachment
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@ -330,25 +334,9 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &depthAttachment.image, &depthAttachment.allocation, &depthAttachment.allocationInfo));
depthAttachment.mem = depthAttachment.allocationInfo.deviceMemory;
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &attachment.image, &attachment.allocation, &attachment.allocationInfo));
attachment.mem = attachment.allocationInfo.deviceMemory;
/*
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &depthAttachment.image));
// Allocate memory for the image (device local) and bind it to our image
VkMemoryAllocateInfo memAlloc = {};
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements(device, depthAttachment.image, &memReqs);
memAlloc.allocationSize = memReqs.size;
memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthAttachment.mem));
VK_CHECK_RESULT(vkBindImageMemory(device, depthAttachment.image, depthAttachment.mem, 0));
*/
// Create a view for the depth stencil image
// Images aren't directly accessed in Vulkan, but rather through views described by a subresource range
// This allows for multiple views of one image with differing ranges (e.g. for different layers)
VkImageViewCreateInfo depthStencilView = {};
depthStencilView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
@ -359,11 +347,49 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
depthStencilView.subresourceRange.levelCount = 1;
depthStencilView.subresourceRange.baseArrayLayer = 0;
depthStencilView.subresourceRange.layerCount = 1;
depthStencilView.image = depthAttachment.image;
depthStencilView.image = attachment.image;
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthAttachment.view));
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &attachment.view));
}
// Create FSR dump
/*
if ( settings::pipelines::fsr ) {
auto& attachment = renderTarget.attachments.emplace_back();
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR;
imageCreateInfo.extent = { width, height, 1 };
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &attachment.image, &attachment.allocation, &attachment.allocationInfo));
attachment.mem = attachment.allocationInfo.deviceMemory;
VkImageViewCreateInfo imageViewCreateInfo = {};
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCreateInfo.format = ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR;
imageViewCreateInfo.subresourceRange = {};
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
imageViewCreateInfo.subresourceRange.levelCount = 1;
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
imageViewCreateInfo.subresourceRange.layerCount = 1;
imageViewCreateInfo.image = attachment.image;
VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCreateInfo, nullptr, &attachment.view));
metadata.attachments["fsr"] = attachmentIndex++;
}
*/
// Create renderpass
if ( !renderTarget.renderPass ) {// Create render pass
// This example will use a single render pass with one subpass
@ -459,8 +485,8 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
for (size_t i = 0; i < renderTarget.framebuffers.size(); i++)
{
std::array<VkImageView, 2> attachments;
attachments[0] = renderTarget.attachments[i].view; // Color attachment is the view of the swapchain image
attachments[1] = depthAttachment.view; // Depth/Stencil attachment is the same for all frame buffers
attachments[0] = renderTarget.attachments[i].view; // Color attachment is the view of the swapchain image
attachments[1] = renderTarget.attachments[metadata.attachments["depth"]].view; // Depth/Stencil attachment is the same for all frame buffers
VkFramebufferCreateInfo frameBufferCreateInfo = {};
frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;

View File

@ -41,14 +41,16 @@ uf::stl::vector<ext::vulkan::Graphic*> ext::vulkan::DeferredRenderMode::getBlitt
}
void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
auto HDR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
auto SDR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
ext::vulkan::RenderMode::initialize( device );
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
renderTarget.device = &device;
renderTarget.views = metadata.eyes;
size_t msaa = ext::vulkan::settings::msaa;
struct {
size_t id, bary, depth, uv, normal;
size_t color, bright, motion, scratch, output;
@ -100,21 +102,21 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
});
// output buffers
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.bright = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
@ -213,7 +215,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/renderTarget/frag.spv";
{
std::pair<bool, uf::stl::string> settings[] = {
{ !settings::pipelines::rt && settings::pipelines::postProcess, "postProcess.frag" },
{ settings::pipelines::postProcess /*&& !settings::pipelines::rt*/, "postProcess.frag" },
// { msaa > 1, "msaa.frag" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
@ -226,15 +228,25 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
shader.aliasAttachment("output", this);
if ( !settings::pipelines::fsr ) {
shader.aliasAttachment("output", this);
}
/*
if ( settings::pipelines::fsr ) {
auto& renderMode = ext::vulkan::getRenderMode("Swapchain", true);
shader.aliasAttachment("fsr", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
} else {
shader.aliasAttachment("output", this);
}
*/
}
if ( settings::pipelines::deferred ) {
if ( DEFERRED_MODE == "compute" ) {
uf::stl::string computeShaderFilename = "comp.spv"; {
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::pipelines::vxgi, "vxgi.comp" },
{ msaa > 1, "msaa.comp" },
{ uf::renderer::settings::pipelines::rt, "rt.comp" },
{ uf::renderer::settings::pipelines::vxgi, "vxgi.comp" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", settings[i].second );
}
@ -383,18 +395,6 @@ void ext::vulkan::DeferredRenderMode::tick() {
bool resized = (this->width == 0 && this->height == 0 && ext::vulkan::states::resized) || this->resized;
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
// update post processing
if ( blitter.material.hasShader("fragment") && !settings::pipelines::rt && settings::pipelines::postProcess ) {
auto& shader = blitter.material.getShader("fragment");
struct {
float curTime = 0;
} uniforms;
uniforms.curTime = uf::time::current;
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
}
if ( resized ) {
this->resized = false;
@ -403,6 +403,11 @@ void ext::vulkan::DeferredRenderMode::tick() {
}
// update blitter descriptor set
if ( rebuild && blitter.initialized ) {
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
// UF_MSG_DEBUG("{} x {} ({:3f}%)", width, height, this->scale*100.0f);
if ( blitter.hasPipeline( blitter.descriptor ) ){
blitter.getPipeline( blitter.descriptor ).update( blitter, blitter.descriptor );
}
@ -457,6 +462,8 @@ VkSubmitInfo ext::vulkan::DeferredRenderMode::queue() {
return submitInfo;
}
void ext::vulkan::DeferredRenderMode::render() {
// if ( ext::vulkan::states::frameSkip ) return;
if ( commandBufferCallbacks.count(EXECUTE_BEGIN) > 0 ) commandBufferCallbacks[EXECUTE_BEGIN]( VkCommandBuffer{}, 0 );
//lockMutex( this->mostRecentCommandPoolId );
@ -494,8 +501,8 @@ ext::vulkan::GraphicDescriptor ext::vulkan::DeferredRenderMode::bindGraphicDescr
return descriptor;
}
void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
float width = this->width > 0 ? this->width : ext::vulkan::settings::width;
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@ -534,12 +541,11 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
}
}
}
bool shouldRecord = true; // ( settings::pipelines::rt && !sceneMetadataJson["system"]["config"]["engine"]["scenes"]["rt"]["full"].as<bool>() ) || !settings::pipelines::rt;
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
// Fill GBuffer
if ( !settings::pipelines::rt ) {
{
VkRenderPassBeginInfo renderPassBeginInfo = {};
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBeginInfo.pNext = nullptr;
@ -604,7 +610,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
}
}
// skip deferred pass if RT is enabled, we still process geometry for a depth buffer
if ( !settings::pipelines::rt ) for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
if ( DEFERRED_MODE == "fragment" ) for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
size_t currentPass = 0;
size_t currentDraw = 0;
{
@ -621,7 +627,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
}
vkCmdEndRenderPass(commands[i]);
if ( !settings::pipelines::rt && settings::pipelines::deferred && DEFERRED_MODE == "compute" && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
if ( settings::pipelines::deferred && DEFERRED_MODE == "compute" && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred");
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.renderMode = "";

View File

@ -56,6 +56,9 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicD
}
void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
ext::vulkan::RenderMode::initialize( device );
this->setTarget( this->getName() );
@ -101,9 +104,6 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
size_t depth, color, bright, motion, scratch, output;
} attachments = {};
auto HDR_FORMAT = uf::renderer::enums::Format::R32G32B32A32_SFLOAT;
auto SDR_FORMAT = uf::renderer::enums::Format::R16G16B16A16_SFLOAT; // uf::renderer::enums::Format::R8G8B8A8_UNORM
bool blend = true;
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
@ -113,21 +113,21 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
/*.samples = */1,
});
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.bright = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
@ -160,6 +160,71 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
metadata.attachments["output"] = attachments.color;
#endif
} else if ( metadata.type == "full" ) {
#if 0
struct {
size_t id, position, normal, depth, color;
} attachments = {};
// input g-buffers
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R32G32_UINT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.position = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.normal = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
// output buffers
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
metadata.attachments["id"] = attachments.id;
metadata.attachments["position"] = attachments.position;
metadata.attachments["normal"] = attachments.normal;
metadata.attachments["depth"] = attachments.depth;
metadata.attachments["color"] = attachments.color;
metadata.attachments["output"] = attachments.color;
// First pass: fill the G-Buffer
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
/*.colors =*/ { attachments.id, attachments.uv, attachments.normal },
/*.inputs =*/ {},
/*.resolve =*/{},
/*.depth = */ attachments.depth,
/*.layer = */eye,
/*.autoBuildPipeline =*/ true
);
}
#endif
} else {
for ( size_t currentPass = 0; currentPass < metadata.subpasses; ++currentPass ) {
struct {
@ -331,8 +396,8 @@ void ext::vulkan::RenderTargetRenderMode::tick() {
bool resized = this->width == 0 && this->height == 0 && (ext::vulkan::states::resized || this->resized);
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
if ( resized ) {
this->resized = false;
@ -397,8 +462,8 @@ void ext::vulkan::RenderTargetRenderMode::pipelineBarrier( VkCommandBuffer comma
}
void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
// destroy if exists
float width = this->width > 0 ? this->width : ext::vulkan::settings::width;
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;

View File

@ -25,8 +25,8 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
if ( this->views == 0 ) this->views = 1;
size_t index = attachments.size();
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
if ( attachment ) {
for ( auto& view : attachment->views ) vkDestroyImageView(*device, view, nullptr);
@ -149,8 +149,8 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
void ext::vulkan::RenderTarget::initialize( Device& device ) {
// Bind
this->device = &device;
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
// resize attachments if necessary
if ( initialized ) {

View File

@ -31,7 +31,7 @@ size_t ext::vulkan::settings::viewCount = 2;
size_t ext::vulkan::settings::gpuID = -1;
size_t ext::vulkan::settings::scratchBufferAlignment = 256;
size_t ext::vulkan::settings::scratchBufferInitialSize = 1024 * 1024;
size_t ext::vulkan::settings::defaultTimeout = 100000000000;
size_t ext::vulkan::settings::defaultTimeout = UINT64_MAX; // 100000000000;
uf::stl::vector<uf::stl::string> ext::vulkan::settings::validationFilters;
uf::stl::vector<uf::stl::string> ext::vulkan::settings::requestedDeviceFeatures;
@ -229,11 +229,22 @@ uf::stl::vector<ext::vulkan::RenderMode*> ext::vulkan::getRenderModes( const uf:
}
uf::stl::vector<ext::vulkan::RenderMode*> ext::vulkan::getRenderModes( const uf::stl::vector<uf::stl::string>& names, bool isName ) {
uf::stl::vector<RenderMode*> targets;
#if 1
// this way keeps the render mode ordered as requested
for ( auto& name : names ) {
for ( auto& renderMode: renderModes ) {
if ( (isName && renderMode->getName() == name) || (!isName && renderMode->getType() == name) ) {
targets.emplace_back( renderMode );
}
}
}
#else
for ( auto& renderMode: renderModes ) {
if ( ( isName && std::find(names.begin(), names.end(), renderMode->getName()) != names.end() ) || std::find(names.begin(), names.end(), renderMode->getType()) != names.end() ) {
targets.push_back(renderMode);
}
}
#endif
return targets;
}
void ext::vulkan::removeRenderMode( ext::vulkan::RenderMode* mode, bool free ) {
@ -447,7 +458,7 @@ void ext::vulkan::tick() {
}
void ext::vulkan::render() {
if ( ext::vulkan::states::frameSkip ) {
ext::vulkan::states::frameSkip = false;
// ext::vulkan::states::frameSkip = false;
return;
}
ext::vulkan::mutex.lock();
@ -543,7 +554,7 @@ void ext::vulkan::render() {
}
#if UF_USE_FFX_FSR
if ( settings::pipelines::fsr ) {
ext::fsr::tick();
ext::fsr::render();
}
#endif
@ -556,6 +567,14 @@ void ext::vulkan::render() {
for ( auto& renderMode : renderModes ) {
if ( !renderMode || !renderMode->execute || !renderMode->metadata.limiter.execute ) continue;
if ( renderMode->getName() == "Swapchain" ) {
#if UF_USE_FFX_FSR
if ( settings::pipelines::fsr ) {
ext::fsr::render();
}
#endif
}
// renderMode->lockMutex( renderMode->mostRecentCommandPoolId );
// auto guard = renderMode->guardMutex( renderMode->mostRecentCommandPoolId );
ext::vulkan::setCurrentRenderMode(renderMode);

View File

@ -17,8 +17,14 @@
#define UF_BAKER_SAVE_MULTITHREAD 0
namespace {
bool accumulated = false;
size_t frames = 0;
size_t totalIDs = 0;
}
UF_BEHAVIOR_REGISTER_CPP(ext::BakingBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::BakingBehavior, ticks = true, renders = false, multithread = true)
UF_BEHAVIOR_TRAITS_CPP(ext::BakingBehavior, ticks = true, renders = false, multithread = false)
#define this (&self)
void ext::BakingBehavior::initialize( uf::Object& self ) {
#if UF_USE_VULKAN
@ -37,6 +43,12 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
sceneMetadata.shadow.update = metadata.max.shadows;
UF_MSG_DEBUG("Temporarily altering shadow limits...");
{
metadata.uniforms.lights = metadata.max.shadows;
metadata.uniforms.currentID = 0;
metadata.buffers.uniforms.initialize( (const void*) &metadata.uniforms, sizeof(metadata.uniforms), uf::renderer::enums::Buffer::UNIFORM );
}
this->addHook( "entity:PostInitialization.%UID%", [&](){
metadata.output = this->resolveURI( metadataJson["baking"]["output"].as<uf::stl::string>(), metadataJson["baking"]["root"].as<uf::stl::string>() );
metadata.renderModeName = "B:" + std::to_string((int) this->getUid());
@ -76,17 +88,23 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
for ( auto& texture : uf::graph::storage.shadow2Ds ) textures2D.emplace_back().aliasTexture(texture);
for ( auto& texture : uf::graph::storage.shadowCubes ) texturesCube.emplace_back().aliasTexture(texture);
::totalIDs = uf::graph::storage.instances.keys.size();
metadata.buffers.baked.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, metadata.size.x, metadata.size.y, metadata.max.layers, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
scene.process([&]( uf::Entity* entity ) {
if ( !entity->hasComponent<uf::Graphic>() ) return;
auto& graphic = entity->getComponent<uf::Graphic>();
if ( !graphic.material.hasShader("fragment", "baking") ) return;
auto& shader = graphic.material.getShader("fragment", "baking");
for ( auto& t : textures2D ) shader.textures.emplace_back().aliasTexture( t );
for ( auto& t : texturesCube ) shader.textures.emplace_back().aliasTexture( t );
shader.textures.emplace_back().aliasTexture( metadata.buffers.baked );
shader.buffers.insert( shader.buffers.begin(), metadata.buffers.uniforms.alias() );
});
// uf::thread::queue([&]{
uf::renderer::addRenderMode( &renderMode, metadata.renderModeName );
@ -98,13 +116,30 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
#endif
}
void ext::BakingBehavior::tick( uf::Object& self ) {
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadata = scene.getComponent<ext::ExtSceneBehavior::Metadata>();
#if UF_USE_VULKAN
if ( !this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) return;
auto& metadata = this->getComponent<ext::BakingBehavior::Metadata>();
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
if ( renderMode.executed && !metadata.initialized.renderMode ) goto PREPARE;
else if ( renderMode.executed && !metadata.initialized.map ) {
TIMER(1.0, (metadata.trigger.mode == "rendered" || (metadata.trigger.mode == "key" && uf::Window::isKeyPressed(metadata.trigger.value))) ) {
sceneMetadata.shadow.update = metadata.previous.update;
{
if ( metadata.uniforms.currentID == ::totalIDs ) {
if ( !accumulated ) {
accumulated = true;
renderMode.execute = false;
UF_MSG_DEBUG("Finished accumulating lightmaps");
}
} else {
UF_MSG_DEBUG("Baking instance ID {} / {}", metadata.uniforms.currentID, ::totalIDs);
metadata.buffers.uniforms.update( (const void*) &metadata.uniforms, sizeof(metadata.uniforms) );
++metadata.uniforms.currentID;
}
}
TIMER(1.0, accumulated && (metadata.trigger.mode == "rendered" || (metadata.trigger.mode == "key" && uf::Window::isKeyPressed(metadata.trigger.value))) ) {
goto SAVE;
}
}
@ -142,11 +177,9 @@ SAVE: {
uf::thread::execute( tasks );
UF_MSG_DEBUG("Baked.");
// ext::vulkan::states::frameSkip = false;
metadata.initialized.map = true;
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadata = scene.getComponent<ext::ExtSceneBehavior::Metadata>();
sceneMetadata.light.max = metadata.previous.lights;
sceneMetadata.shadow.max = metadata.previous.shadows;
sceneMetadata.shadow.update = metadata.previous.update;

View File

@ -25,7 +25,14 @@ namespace ext {
size_t light = 0;
uf::renderer::Texture3D baked;
uf::renderer::Buffer uniforms;
} buffers;
struct UBO {
alignas(4) uint32_t lights = 0;
alignas(4) uint32_t currentID = 0;
alignas(4) uint32_t totalIDs = 0;
alignas(4) uint32_t padding2 = 0;
} uniforms;
struct {
size_t textures2D = 1024;
size_t texturesCube = 512;

View File

@ -251,11 +251,14 @@ void ext::LightBehavior::Metadata::serialize( uf::Object& self, uf::Serializer&
serializer["system"]["renderer"]["mode"] = /*this->*/renderer.mode;
serializer["light"]["external update"] = /*this->*/renderer.external;
// serializer["system"]["renderer"]["timer"] = /*this->*/renderer.limiter;
switch ( /*this->*/type ) {
switch ( abs(/*this->*/type) ) {
case 0: serializer["light"]["type"] = "point"; break;
case 1: serializer["light"]["type"] = "point"; break;
case 2: serializer["light"]["type"] = "spot"; break;
}
if ( type < 0 ) {
serializer["light"]["dynamic"] = true;
}
}
void ext::LightBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){
/*this->*/color = uf::vector::decode( serializer["light"]["color"], /*this->*/color );
@ -268,16 +271,13 @@ void ext::LightBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer
/*this->*/renderer.external = serializer["light"]["external update"].as(/*this->*/renderer.external);
// /*this->*/renderer.limiter = serializer["system"]["renderer"]["timer"].as<float>(/*this->*/renderer.limiter);
if ( serializer["light"]["type"].is<size_t>() ) {
if ( serializer["light"]["type"].is<int32_t>() ) {
/*this->*/type = serializer["light"]["type"].as(/*this->*/type);
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
} else if ( serializer["light"]["type"].is<uf::stl::string>() ) {
uf::stl::string lightType = serializer["light"]["type"].as<uf::stl::string>();
if ( lightType == "point" ) /*this->*/type = 1;
else if ( lightType == "spot" ) /*this->*/type = 2;
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
}
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
}
#undef this

View File

@ -28,54 +28,60 @@ UF_BEHAVIOR_TRAITS_CPP(ext::RayTraceSceneBehavior, ticks = true, renders = false
void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
if ( !uf::renderer::hasRenderMode("Compute:RT", true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
renderMode->setTarget("Compute:RT");
{
uf::stl::string vertexShaderFilename = "/shaders/display/renderTarget/vert.spv";
uf::stl::string fragmentShaderFilename = "/shaders/display/renderTarget/frag.spv";
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::pipelines::postProcess, "postProcess.frag" },
// { msaa > 1, "msaa.frag" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
renderMode->metadata.json["shaders"]["vertex"] = vertexShaderFilename;
renderMode->metadata.json["shaders"]["fragment"] = fragmentShaderFilename;
}
renderMode->blitter.descriptor.renderMode = "Swapchain";
renderMode->blitter.descriptor.subpass = 0;
renderMode->metadata.type = uf::renderer::settings::pipelines::names::rt;
renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::rt);
renderMode->execute = false;
renderMode->metadata.limiter.execute = false;
// renderMode->blitter.process = false;
uf::renderer::addRenderMode( renderMode, "Compute:RT" );
}
#if !UF_USE_EXTERNAL_IMAGE
#else
{
uf::stl::vector<uint8_t> pixels = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
::emptyTexture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
::emptyTexture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
::emptyTexture.fromBuffers( (void*) &pixels[0], pixels.size(), ext::vulkan::enums::Format::R8G8B8A8_UNORM, 2, 2, ext::vulkan::device, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
auto& blitter = *renderMode.getBlitter();
blitter.material.textures.emplace_back().aliasTexture( ::emptyTexture );
}
#endif
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
if ( metadata.renderer.full ) {
if ( !uf::renderer::hasRenderMode("Compute:RT", true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
renderMode->setTarget("Compute:RT");
{
uf::stl::string vertexShaderFilename = "/shaders/display/renderTarget/vert.spv";
uf::stl::string fragmentShaderFilename = "/shaders/display/renderTarget/frag.spv";
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::pipelines::postProcess, "postProcess.frag" },
// { msaa > 1, "msaa.frag" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
renderMode->metadata.json["shaders"]["vertex"] = vertexShaderFilename;
renderMode->metadata.json["shaders"]["fragment"] = fragmentShaderFilename;
}
renderMode->blitter.descriptor.renderMode = "Swapchain";
renderMode->blitter.descriptor.subpass = 0;
renderMode->metadata.type = uf::renderer::settings::pipelines::names::rt;
renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::rt);
renderMode->execute = false;
renderMode->metadata.limiter.execute = false;
// renderMode->blitter.process = false;
uf::renderer::addRenderMode( renderMode, "Compute:RT" );
}
#if UF_USE_EXTERNAL_IMAGE
{
uf::stl::vector<uint8_t> pixels = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
::emptyTexture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
::emptyTexture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
::emptyTexture.fromBuffers(
(void*) &pixels[0],
pixels.size(),
uf::renderer::enums::Format::R8G8B8A8_UNORM,
2, 2,
uf::renderer::device,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
);
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
auto& blitter = *renderMode.getBlitter();
blitter.material.textures.emplace_back().aliasTexture( ::emptyTexture );
}
#endif
}
}
void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
@ -97,9 +103,12 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
if ( graphics.empty() ) return;
bool update = false;
auto& graphic = this->getComponent<uf::renderer::Graphic>();
auto& renderMode = uf::renderer::getRenderMode("", true);
auto& graphic = metadata.renderer.full ? this->getComponent<uf::renderer::Graphic>() : *renderMode.getBlitter();
if ( !metadata.renderer.bound ) {
graphic.initialize("Compute:RT");
if ( metadata.renderer.full ) {
graphic.initialize("Compute:RT");
}
update = true;
} else {
if ( previousInstances.size() != instances.size() ) update = true;
@ -116,6 +125,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
auto& sceneMetadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
sceneMetadata.shader.frameAccumulateReset = true;
uf::renderer::states::frameAccumulateReset = true;
previousInstances = instances;
previousGraphics = graphics;
@ -123,166 +133,156 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
if ( !metadata.renderer.bound ) {
if ( graphic.material.hasShader("ray:gen", uf::renderer::settings::pipelines::names::rt) ) {
#if !UF_USE_EXTERNAL_IMAGE
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
shader.aliasAttachment("color", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
shader.aliasAttachment("bright", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
shader.aliasAttachment("motion", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
metadata.renderer.bound = true;
if ( metadata.renderer.full ) {
graphic.process = false;
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
#if !UF_USE_EXTERNAL_IMAGE
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
shader.aliasAttachment("color", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
shader.aliasAttachment("bright", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
shader.aliasAttachment("motion", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : ext::vulkan::settings::width;
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : ext::vulkan::settings::height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
#else
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
//
pod::Vector2ui size = metadata.renderer.size;
UF_MSG_DEBUG("Size: {}", uf::vector::toString( size ));
if ( size.x == 0 ) size.x = uf::renderer::settings::width; // * metadata.renderer.scale;
if ( size.y == 0 ) size.y = uf::renderer::settings::height; // * metadata.renderer.scale;
UF_MSG_DEBUG("Size: {}", uf::vector::toString( size ));
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width;
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
#else
//
pod::Vector2ui size = metadata.renderer.size;
if ( size.x == 0 ) size.x = uf::renderer::settings::width;
if ( size.y == 0 ) size.y = uf::renderer::settings::height;
auto HDR_FORMAT = uf::renderer::enums::Format::R32G32B32A32_SFLOAT;
auto SDR_FORMAT = uf::renderer::enums::Format::R16G16B16A16_SFLOAT; // uf::renderer::enums::Format::R8G8B8A8_UNORM
auto& image = shader.textures.emplace_back();
image.fromBuffers(
NULL, 0,
uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR,
size.x, size.y, 1, 1,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
);
auto& image = shader.textures.emplace_back();
image.fromBuffers(
NULL, 0,
uf::renderer::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
size.x, size.y, 1, 1,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
);
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
graphic.descriptor.bind.width = image.width;
graphic.descriptor.bind.height = image.height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
#endif
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
graphic.descriptor.bind.width = image.width;
graphic.descriptor.bind.height = image.height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
#endif
//
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(1);
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
//
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(1);
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures2D);
else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxTexturesCube);
else if ( sc.name == "CASCADES" ) sc.value.ui = (specializationConstants[sc.index] = maxCascades);
}
for ( auto pair : shader.metadata.definitions.textures ) {
auto& tx = pair.second;
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != tx.binding ) continue;
if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
else if ( tx.name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelNormal" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
}
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures2D);
else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxTexturesCube);
else if ( sc.name == "CASCADES" ) sc.value.ui = (specializationConstants[sc.index] = maxCascades);
}
for ( auto pair : shader.metadata.definitions.textures ) {
auto& tx = pair.second;
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != tx.binding ) continue;
if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
else if ( tx.name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelNormal" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
}
if ( metadata.renderer.full ) {
/* Update lights */ {
ext::ExtSceneBehavior::bindBuffers( *this, graphic, "ray:gen", uf::renderer::settings::pipelines::names::rt );
}
if ( !metadata.renderer.bound ) return;
#if !UF_USE_EXTERNAL_IMAGE
if ( uf::renderer::states::resized ) {
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width;
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
graphic.getPipeline().update( graphic );
}
#else
{
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& image = shader.textures.front();
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
auto& blitter = *renderMode.getBlitter();
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
if ( shader.textures.empty() || ( !shader.textures.empty() && shader.textures.front().image == ::emptyTexture.image ) ) {
shader.textures.clear();
auto& tex = shader.textures.emplace_back();
tex.aliasTexture( image );
tex.sampler.descriptor.filter.min = metadata.renderer.filter;
tex.sampler.descriptor.filter.mag = metadata.renderer.filter;
renderMode.execute = true;
renderMode.metadata.limiter.execute = true;
blitter.process = true;
graphic.process = true;
}
}
metadata.renderer.bound = true;
if ( uf::renderer::states::resized ) {
pod::Vector2ui size = metadata.renderer.size;
if ( size.x == 0 ) size.x = uf::renderer::settings::width;
if ( size.y == 0 ) size.y = uf::renderer::settings::height;
image.destroy();
image.fromBuffers(
NULL, 0,
uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR,
size.x, size.y, 1, 1,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
);
graphic.descriptor.bind.width = image.width;
graphic.descriptor.bind.height = image.height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic.getPipeline().update( graphic );
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
shader.textures.front().aliasTexture( image );
}
}
}
/*
if ( graphic.material.hasShader("ray:hit:closest", uf::renderer::settings::pipelines::names::rt) ) {
auto& shader = graphic.material.getShader("ray:hit:closest", uf::renderer::settings::pipelines::names::rt);
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
#endif
#if 0
TIMER(1.0, uf::Window::isKeyPressed("R") ) {
UF_MSG_DEBUG("Screenshotting RT scene...");
image.screenshot().save("./data/rt.png");
}
if ( graphic.material.hasShader("ray:hit:any", uf::renderer::settings::pipelines::names::rt) ) {
auto& shader = graphic.material.getShader("ray:hit:any", uf::renderer::settings::pipelines::names::rt);
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
}
*/
graphic.process = false;
#endif
}
/* Update lights */ {
ext::ExtSceneBehavior::bindBuffers( *this, graphic, "ray:gen", uf::renderer::settings::pipelines::names::rt );
}
if ( !metadata.renderer.bound ) return;
#if !UF_USE_EXTERNAL_IMAGE
if ( uf::renderer::states::resized ) {
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : ext::vulkan::settings::width;
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : ext::vulkan::settings::height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
graphic.getPipeline().update( graphic );
}
#else
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& image = shader.textures.front();
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
auto& blitter = *renderMode.getBlitter();
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
if ( shader.textures.empty() || ( !shader.textures.empty() && shader.textures.front().image == ::emptyTexture.image ) ) {
shader.textures.clear();
auto& tex = shader.textures.emplace_back();
tex.aliasTexture( image );
tex.sampler.descriptor.filter.min = metadata.renderer.filter;
tex.sampler.descriptor.filter.mag = metadata.renderer.filter;
renderMode.execute = true;
renderMode.metadata.limiter.execute = true;
blitter.process = true;
graphic.process = true;
}
}
if ( uf::renderer::states::resized ) {
pod::Vector2ui size = metadata.renderer.size;
if ( size.x == 0 ) size.x = uf::renderer::settings::width * metadata.renderer.scale;
if ( size.y == 0 ) size.y = uf::renderer::settings::height * metadata.renderer.scale;
image.destroy();
image.fromBuffers(
NULL, 0,
uf::renderer::enums::Format::R8G8B8A8_UNORM,
size.x, size.y, 1, 1,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
);
graphic.descriptor.bind.width = image.width;
graphic.descriptor.bind.height = image.height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic.getPipeline().update( graphic );
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
shader.textures.front().aliasTexture( image );
}
}
#endif
#if 0
TIMER(1.0, uf::Window::isKeyPressed("R") ) {
UF_MSG_DEBUG("Screenshotting RT scene...");
image.screenshot().save("./data/rt.png");
}
#endif
}
void ext::RayTraceSceneBehavior::render( uf::Object& self ){}
void ext::RayTraceSceneBehavior::destroy( uf::Object& self ){
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
auto& graphic = this->getComponent<uf::renderer::Graphic>();
if ( !metadata.renderer.full ) return;
auto& graphic = this->getComponent<uf::renderer::Graphic>();
graphic.destroy();
}
void ext::RayTraceSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {
@ -312,6 +312,8 @@ void ext::RayTraceSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Se
} else if ( ext::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].is<float>() ) {
/*this->*/renderer.scale = ext::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as(/*this->*/renderer.scale);
}
/*this->*/renderer.full = serializer["rt"]["full"].as(/*this->*/renderer.full);
/*this->*/settings.defaultRayBounds = uf::vector::decode(serializer["rt"]["defaultRayBounds"], settings.defaultRayBounds); // serializer["rt"]["defaultRayBounds"].as(/*this->*/settings.defaultRayBounds);
/*this->*/settings.alphaTestOffset = serializer["rt"]["alphaTestOffset"].as(/*this->*/settings.alphaTestOffset);

View File

@ -19,6 +19,8 @@ namespace ext {
float scale = 1;
pod::Vector2ui size{};
uf::renderer::enums::Filter::type_t filter = uf::renderer::enums::Filter::NEAREST;
bool full = true;
} renderer;
struct {

View File

@ -225,8 +225,8 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
metadata.shader.frameAccumulateReset = false;
}
uf::renderer::states::frameAccumulate = metadata.shader.frameAccumulate;
uf::renderer::states::frameAccumulateReset = metadata.shader.frameAccumulateReset;
// uf::renderer::states::frameAccumulate = metadata.shader.frameAccumulate;
// uf::renderer::states::frameAccumulateReset = metadata.shader.frameAccumulateReset;
/* Print World Tree */ {
TIMER(1, uf::inputs::kbm::states::U ) {
@ -603,6 +603,28 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
ext::ExtSceneBehavior::bindBuffers( *this, "", "fragment", "deferred" );
}
}
/* Update post processing */ {
auto& renderMode = uf::renderer::getRenderMode("", true);
auto& blitter = *renderMode.getBlitter();
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
struct {
float curTime = 0;
float gamma = 1.0;
float exposure = 1.0;
uint32_t padding = 0;
} uniforms = {
.curTime = uf::time::current,
.gamma = metadata.light.gamma,
.exposure = metadata.light.exposure
};
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
}
}
}
void ext::ExtSceneBehavior::render( uf::Object& self ) {}
void ext::ExtSceneBehavior::destroy( uf::Object& self ) {
@ -698,6 +720,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
/*this->*/light.max = serializer["light"]["max"].as(/*this->*/light.max);
/*this->*/light.ambient = uf::vector::decode( serializer["light"]["ambient"], /*this->*/light.ambient);
if ( uf::renderer::settings::pipelines::fsr ) serializer["light"]["exposure"] = 1;
/*this->*/light.exposure = serializer["light"]["exposure"].as(/*this->*/light.exposure);
/*this->*/light.gamma = serializer["light"]["gamma"].as(/*this->*/light.gamma);
/*this->*/light.useLightmaps = serializer["light"]["useLightmaps"].as(/*this->*/light.useLightmaps);
@ -841,9 +864,9 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
struct Lighting {
pod::Vector3f ambient;
alignas(4) float padding1;
alignas(4) uint32_t indexSkybox;
alignas(4) uint32_t maxShadows;
alignas(4) uint32_t shadowSamples;
alignas(4) uint32_t useLightmaps;
} lighting;
@ -941,20 +964,20 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
UniformDescriptor uniforms; {
for ( auto i = 0; i < 2; ++i ) {
#if UF_USE_FFX_FSR
auto jitter = ext::fsr::getJitterMatrix();
auto projection = ext::fsr::getJitterMatrix() * camera.getProjection(i);
#else
auto jitter = uf::matrix::identity();
auto projection = camera.getProjection(i);
#endif
uniforms.matrices[i] = UniformDescriptor::Matrices{
.view = camera.getView(i),
.projection = jitter * camera.getProjection(i),
.projection = projection,
.model = jitter * camera.getProjection(i) * camera.getView(i),
.model = projection * camera.getView(i),
.previous = camera.getPrevious(i),
.iView = uf::matrix::inverse( camera.getView(i) ),
.iProjection = uf::matrix::inverse( jitter * camera.getProjection(i) ),
// .iProjectionView = uf::matrix::inverse( jitter * camera.getProjection(i) * camera.getView(i) ),
.iProjection = uf::matrix::inverse( projection ),
// .iProjectionView = uf::matrix::inverse( projection * camera.getView(i) ),
.eyePos = camera.getEye( i ),
};
@ -976,8 +999,9 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
};
uniforms.settings.lighting = UniformDescriptor::Settings::Lighting{
.ambient = metadata.light.ambient,
.indexSkybox = indexSkybox,
.maxShadows = metadata.shadow.max,
.shadowSamples = std::min( 0, metadata.shadow.samples ),
.useLightmaps = metadata.light.useLightmaps,
};
@ -1017,7 +1041,6 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
.paths = metadataRt.settings.paths, // 1,
.frameAccumulationMinimum = metadataRt.settings.frameAccumulationMinimum, // 0,
};
}
uf::stl::vector<VkImage> previousTextures;
@ -1046,6 +1069,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
bool shouldUpdate2 = !uf::matrix::equals( uniforms.matrices[0].view, previousUniforms.matrices[0].view, 0.0001f );
if ( shouldUpdate || shouldUpdate2 ) {
metadata.shader.frameAccumulateReset = true;
uf::renderer::states::frameAccumulateReset = true;
previousUniforms = uniforms;
}
#endif

View File

@ -33,61 +33,20 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
// initialize voxel map
#if 0
{
const uint32_t DEFAULT_VOXEL_SIZE = ext::config["engine"]["scenes"]["vxgi"]["size"].as<uint32_t>(256);
const float DEFAULT_VOXELIZE_LIMITER = ext::config["engine"]["scenes"]["vxgi"]["limiter"].as<float>(0);
const uint32_t DEFAULT_DISPATCH_SIZE = ext::config["engine"]["scenes"]["vxgi"]["dispatch"].as<uint32_t>(8);
const uint32_t DEFAULT_CASCADES = ext::config["engine"]["scenes"]["vxgi"]["cascades"].as<uint32_t>(8);
const float DEFAULT_CASCADE_POWER = ext::config["engine"]["scenes"]["vxgi"]["cascadePower"].as<float>(1.5);
const float DEFAULT_GRANULARITY = ext::config["engine"]["scenes"]["vxgi"]["granularity"].as<float>(2.0);
const float DEFAULT_SHADOWS = ext::config["engine"]["scenes"]["vxgi"]["shadows"].as<size_t>(8);
const float DEFAULT_PIXEL_SCALE = ext::config["engine"]["scenes"]["vxgi"]["voxelizeScale"].as<float>(1);
const float DEFAULT_OCCLUSION_FALLOFF = ext::config["engine"]["scenes"]["vxgi"]["occlusionFalloff"].as<float>(128.0f);
if ( metadata.voxelSize.x == 0 ) metadata.voxelSize.x = DEFAULT_VOXEL_SIZE;
if ( metadata.voxelSize.y == 0 ) metadata.voxelSize.y = DEFAULT_VOXEL_SIZE;
if ( metadata.voxelSize.z == 0 ) metadata.voxelSize.z = DEFAULT_VOXEL_SIZE;
if ( metadata.limiter.frequency == 0 ) metadata.limiter.frequency = DEFAULT_VOXELIZE_LIMITER;
if ( metadata.dispatchSize.x == 0 ) metadata.dispatchSize.x = DEFAULT_DISPATCH_SIZE;
if ( metadata.dispatchSize.y == 0 ) metadata.dispatchSize.y = DEFAULT_DISPATCH_SIZE;
if ( metadata.dispatchSize.z == 0 ) metadata.dispatchSize.z = DEFAULT_DISPATCH_SIZE;
if ( metadata.cascades == 0 ) metadata.cascades = DEFAULT_CASCADES;
if ( metadata.cascadePower == 0 ) metadata.cascadePower = DEFAULT_CASCADE_POWER;
if ( metadata.granularity == 0 ) metadata.granularity = DEFAULT_GRANULARITY;
if ( metadata.voxelizeScale == 0 ) metadata.voxelizeScale = DEFAULT_PIXEL_SCALE;
if ( metadata.occlusionFalloff == 0 ) metadata.occlusionFalloff = DEFAULT_OCCLUSION_FALLOFF;
if ( metadata.shadows == 0 ) metadata.shadows = DEFAULT_SHADOWS;
metadata.extents.min = uf::vector::decode( ext::config["engine"]["scenes"]["vxgi"]["extents"]["min"], pod::Vector3f{-32, -32, -32} );
metadata.extents.max = uf::vector::decode( ext::config["engine"]["scenes"]["vxgi"]["extents"]["max"], pod::Vector3f{ 32, 32, 32} );
// uf::stl::vector<uint8_t> empty(metadata.voxelSize.x * metadata.voxelSize.y * metadata.voxelSize.z * sizeof(uint8_t) * 4);
}
#endif
for ( size_t i = 0; i < metadata.cascades; ++i ) {
const bool HDR = false;
auto& id = sceneTextures.voxels.id.emplace_back();
// auto& uv = sceneTextures.voxels.uv.emplace_back();
auto& normal = sceneTextures.voxels.normal.emplace_back();
auto& radiance = sceneTextures.voxels.radiance.emplace_back();
// auto& depth = sceneTextures.voxels.depth.emplace_back();
id.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
id.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
auto HDR_FORMAT = uf::renderer::enums::Format::R32G32B32A32_SFLOAT;
auto SDR_FORMAT = uf::renderer::enums::Format::R16G16B16A16_SFLOAT; // uf::renderer::enums::Format::R8G8B8A8_UNORM
id.fromBuffers( NULL, 0, uf::renderer::enums::Format::R16G16_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
// auto& uv = sceneTextures.voxels.uv.emplace_back();
// uv.fromBuffers( NULL, 0, uf::renderer::enums::Format::R16G16_SFLOAT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& normal = sceneTextures.voxels.normal.emplace_back();
normal.fromBuffers( NULL, 0, uf::renderer::enums::Format::R16G16_SFLOAT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
radiance.fromBuffers( NULL, 0, uf::renderer::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& radiance = sceneTextures.voxels.radiance.emplace_back();
radiance.fromBuffers( NULL, 0, uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
// auto& depth = sceneTextures.voxels.depth.emplace_back();
// depth.fromBuffers( (void*) empty.data(), empty.size(), uf::renderer::enums::Format::R16_SFLOAT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
}
// initialize render mode
@ -108,7 +67,7 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
renderMode.metadata.samples = 1;
renderMode.metadata.subpasses = metadata.cascades;
renderMode.blitter.device = &ext::vulkan::device;
renderMode.blitter.device = &uf::renderer::device;
renderMode.width = metadata.fragmentSize.x;
renderMode.height = metadata.fragmentSize.y;
@ -118,9 +77,6 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
if ( renderMode.metadata.samples > 1 ) {
computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", "msaa.comp" );
}
// if ( uf::renderer::settings::invariant::deferredSampling ) {
// computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", "deferredSampling.comp" );
// }
renderMode.metadata.json["shaders"]["compute"] = computeShaderFilename;
renderMode.blitter.descriptor.renderMode = metadata.renderModeName;
renderMode.blitter.descriptor.subpass = -1;
@ -128,13 +84,6 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
renderMode.blitter.descriptor.bind.height = metadata.voxelSize.y;
renderMode.blitter.descriptor.bind.depth = metadata.voxelSize.z;
renderMode.blitter.descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
/*
renderMode.blitter.descriptor.bind.dispatch = {
(metadata.voxelSize.x / metadata.dispatchSize.x),
(metadata.voxelSize.y / metadata.dispatchSize.y),
(metadata.voxelSize.z / metadata.dispatchSize.z),
};
*/
renderMode.blitter.process = true;
size_t maxTextures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
@ -305,6 +254,7 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
}
#endif
}
ext::ExtSceneBehavior::bindBuffers( scene, metadata.renderModeName, "compute", "" );
auto& deferredRenderMode = uf::renderer::getRenderMode("", true);

View File

@ -54,6 +54,7 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
if ( !uf::renderer::hasRenderMode( "Gui", true ) ) {
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
uf::stl::string name = "Gui";
renderMode.blitter.descriptor.renderMode = "Swapchain";
renderMode.blitter.descriptor.subpass = 0;
renderMode.metadata.type = "single";
uf::renderer::addRenderMode( &renderMode, name );
@ -68,6 +69,19 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
this->addHook( "window:Resized", [&](pod::payloads::windowResized& payload){
ext::gui::size.current = payload.window.size;
ext::gui::size.reference = payload.window.size;
/*
uf::renderer::RenderTargetRenderMode* renderModePointer = NULL;
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
renderModePointer = this->getComponentPointer<uf::renderer::RenderTargetRenderMode>();
} else {
renderModePointer = (uf::renderer::RenderTargetRenderMode*) &uf::renderer::getRenderMode( "Gui", true );
}
auto& renderMode = *renderModePointer;
renderMode.width = payload.window.size.x;
renderMode.height = payload.window.size.y;
renderMode.rebuild = true;
*/
} );
this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload){
bool clicked = false;
@ -98,8 +112,36 @@ void ext::GuiManagerBehavior::tick( uf::Object& self ) {
auto& blitter = renderMode.blitter;
if ( !blitter.initialized ) return;
if ( !blitter.material.hasShader("fragment") ) return;
/* Update post processing */ {
uf::renderer::RenderTargetRenderMode* renderModePointer = NULL;
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
renderModePointer = this->getComponentPointer<uf::renderer::RenderTargetRenderMode>();
} else {
renderModePointer = (uf::renderer::RenderTargetRenderMode*) &uf::renderer::getRenderMode( "Gui", true );
}
auto& renderMode = *renderModePointer;
auto& blitter = *renderMode.getBlitter();
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
struct {
float curTime = 0;
float gamma = 1.0;
float exposure = 1.0;
uint32_t padding = 0;
} uniforms = {
.curTime = uf::time::current,
.gamma = 1,
.exposure = 1
};
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
}
}
#if 0
if ( !blitter.material.hasShader("fragment") ) return;
return;
auto& scene = uf::scene::getCurrentScene();
@ -112,56 +154,59 @@ void ext::GuiManagerBehavior::tick( uf::Object& self ) {
#else
// if ( metadata.overlay.cursor.type == "" ) metadata.deserialize( self, metadataJson );
#endif
struct UniformDescriptor {
struct {
/*alignas(16)*/ pod::Matrix4f models[2];
} matrices;
struct {
/*alignas(8)*/ pod::Vector2f position = { 0.5f, 0.5f };
/*alignas(8)*/ pod::Vector2f radius = { 0.1f, 0.1f };
/*alignas(16)*/ pod::Vector4f color = { 1, 1, 1, 1 };
} cursor;
// /*alignas(8)*/ pod::Vector2f alpha;
};
auto& shader = blitter.material.getShader("vertex");
#if UF_UNIFORMS_REUSE
auto& uniform = shader.getUniform("UBO");
auto& uniforms = uniform.get<UniformDescriptor>();
#else
UniformDescriptor uniforms;
#endif
for ( size_t i = 0; i < 2; ++i ) {
#if UF_USE_OPENVR
if ( ext::openvr::enabled && metadata.overlay.enabled ) {
if ( metadata.overlay.floating ) {
pod::Matrix4f model = uf::transform::model( metadata.overlay.transform );
uniforms.matrices.models[i] = camera.getProjection(i) * ext::openvr::hmdEyePositionMatrix( i == 0 ? vr::Eye_Left : vr::Eye_Right ) * model;
} else {
auto translation = uf::matrix::translate( uf::matrix::identity(), camera.getTransform().position + controller.getComponent<pod::Transform<>>().position );
auto rotation = uf::quaternion::matrix( controller.getComponent<pod::Transform<>>().orientation );
pod::Matrix4f model = translation * rotation * uf::transform::model( metadata.overlay.transform );
uniforms.matrices.models[i] = camera.getProjection(i) * camera.getView(i) * model;
}
} else {
{
struct UniformDescriptor {
struct {
/*alignas(16)*/ pod::Matrix4f models[2];
} matrices;
struct {
/*alignas(8)*/ pod::Vector2f position = { 0.5f, 0.5f };
/*alignas(8)*/ pod::Vector2f radius = { 0.1f, 0.1f };
/*alignas(16)*/ pod::Vector4f color = { 1, 1, 1, 1 };
} cursor;
// /*alignas(8)*/ pod::Vector2f alpha;
};
auto& shader = blitter.material.getShader("vertex");
#if UF_UNIFORMS_REUSE
auto& uniform = shader.getUniform("UBO");
auto& uniforms = uniform.get<UniformDescriptor>();
#else
{
UniformDescriptor uniforms;
#endif
pod::Matrix4t<> model = uf::matrix::translate( uf::matrix::identity(), { 0, 0, 1 } );
uniforms.matrices.models[i] = model;
}
for ( size_t i = 0; i < 2; ++i ) {
#if UF_USE_OPENVR
if ( ext::openvr::enabled && metadata.overlay.enabled ) {
if ( metadata.overlay.floating ) {
pod::Matrix4f model = uf::transform::model( metadata.overlay.transform );
uniforms.matrices.models[i] = camera.getProjection(i) * ext::openvr::hmdEyePositionMatrix( i == 0 ? vr::Eye_Left : vr::Eye_Right ) * model;
} else {
auto translation = uf::matrix::translate( uf::matrix::identity(), camera.getTransform().position + controller.getComponent<pod::Transform<>>().position );
auto rotation = uf::quaternion::matrix( controller.getComponent<pod::Transform<>>().orientation );
if ( metadata.overlay.cursor.enabled ) {
uniforms.cursor.position = metadata.overlay.cursor.position * 0.5f + 0.5f;
uniforms.cursor.radius = uf::matrix::multiply<float>( uf::matrix::inverse( uf::matrix::scale( uf::matrix::identity() , metadata.overlay.transform.scale) ), pod::Vector3f{ metadata.overlay.cursor.radius, metadata.overlay.cursor.radius, 0 } );
pod::Matrix4f model = translation * rotation * uf::transform::model( metadata.overlay.transform );
uniforms.matrices.models[i] = camera.getProjection(i) * camera.getView(i) * model;
}
} else {
#else
{
#endif
pod::Matrix4t<> model = uf::matrix::translate( uf::matrix::identity(), { 0, 0, 1 } );
uniforms.matrices.models[i] = model;
}
if ( metadata.overlay.cursor.enabled ) {
uniforms.cursor.position = metadata.overlay.cursor.position * 0.5f + 0.5f;
uniforms.cursor.radius = uf::matrix::multiply<float>( uf::matrix::inverse( uf::matrix::scale( uf::matrix::identity() , metadata.overlay.transform.scale) ), pod::Vector3f{ metadata.overlay.cursor.radius, metadata.overlay.cursor.radius, 0 } );
}
uniforms.cursor.color = metadata.overlay.cursor.color;
}
uniforms.cursor.color = metadata.overlay.cursor.color;
#if UF_UNIFORMS_REUSE
shader.updateUniform( "UBO", uniform );
#else
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
#endif
}
#if UF_UNIFORMS_REUSE
shader.updateUniform( "UBO", uniform );
#else
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
#endif
#endif
}

View File

@ -366,9 +366,9 @@ void EXT_API ext::initialize() {
uf::renderer::settings::defaultCommandBufferWait = configRenderJson["invariant"]["default command buffer wait"].as( uf::renderer::settings::defaultCommandBufferWait );
if ( configRenderJson["framebuffer"]["size"].is<float>() ) {
float scale = configRenderJson["framebuffer"]["size"].as(1.0f);
uf::renderer::settings::width *= scale;
uf::renderer::settings::height *= scale;
// float scale = configRenderJson["framebuffer"]["size"].as(1.0f);
// uf::renderer::settings::width *= scale;
// uf::renderer::settings::height *= scale;
} else if ( ext::json::isArray( configRenderJson["framebuffer"]["size"] ) ) {
uf::renderer::settings::width = configRenderJson["framebuffer"]["size"][0].as(uf::renderer::settings::width);
uf::renderer::settings::height = configRenderJson["framebuffer"]["size"][1].as(uf::renderer::settings::height);
@ -431,10 +431,17 @@ void EXT_API ext::initialize() {
uf::renderer::settings::pipelines::rt = configRenderPipelinesJson["rt"].as( uf::renderer::settings::pipelines::rt );
uf::renderer::settings::pipelines::postProcess = configRenderPipelinesJson["postProcess"].as( uf::renderer::settings::pipelines::postProcess );
uf::renderer::settings::pipelines::fsr = configRenderPipelinesJson["fsr"].as( uf::renderer::settings::pipelines::fsr );
#if UF_USE_FFX_FSR
// ext::fsr::enabled = uf::renderer::settings::pipelines::fsr;
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);
#endif
if ( uf::renderer::settings::pipelines::rt ) {
uf::renderer::settings::pipelines::vxgi = false;
uf::renderer::settings::pipelines::culling = false;
// uf::renderer::settings::pipelines::vxgi = false;
// uf::renderer::settings::pipelines::culling = false;
::json["engine"]["scenes"]["lights"]["shadows"]["enabled"] = false;
}
#define JSON_TO_FORMAT( key ) if ( configRenderJson["formats"][#key].is<uf::stl::string>() ) {\
@ -491,6 +498,7 @@ void EXT_API ext::initialize() {
/* Initialize Vulkan */ {
// setup render mode
/*
if ( ::json["engine"]["render modes"]["gui"].as<bool>(true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
renderMode->blitter.descriptor.renderMode = "Swapchain";
@ -498,11 +506,29 @@ void EXT_API ext::initialize() {
renderMode->metadata.type = "single";
uf::renderer::addRenderMode( renderMode, "Gui" );
}
*/
if ( ::json["engine"]["render modes"]["deferred"].as<bool>(true) ) {
auto* renderMode = new uf::renderer::DeferredRenderMode;
renderMode->blitter.descriptor.renderMode = "Swapchain";
renderMode->blitter.descriptor.subpass = 0;
#if UF_USE_FFX_FSR
if ( uf::renderer::settings::pipelines::fsr ) {
auto mode = uf::string::lowercase( ext::fsr::preset );
if ( mode == "native" ) renderMode->scale = 1;
else if ( mode == "quality" ) renderMode->scale = 1.0f / (1.5f);
else if ( mode == "balanced" ) renderMode->scale = 1.0f / (1.7f);
else if ( mode == "performance" ) renderMode->scale = 1.0f / (2.0f);
else if ( mode == "ultra" ) renderMode->scale = 1.0f / (3.0f);
else {
renderMode->scale = 1;
UF_MSG_WARNING("Invalid FFX FSR preset enum string specified: {}", mode);
}
UF_MSG_DEBUG("Using FFX FSR Preset: {} ({:.3f}% render scale)", mode, (1.0f / renderMode->scale));
} else
#endif
renderMode->scale = ::json["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as(1.0f);
UF_MSG_DEBUG("Geometry render scale: {:.3f}", renderMode->scale);
if ( ::json["engine"]["render modes"]["stereo deferred"].as<bool>() ) {
renderMode->metadata.eyes = 2;
@ -692,7 +718,7 @@ void EXT_API ext::tick() {
spec::controller::tick();
}
#if UF_USE_FFX_FSR
/* OpenVR */ if ( ext::fsr::initialized ) {
/* FFX FSR */ if ( ext::fsr::initialized ) {
ext::fsr::tick();
}
#endif