diff --git a/bin/data/config.json b/bin/data/config.json index 9e794a8c..520d8c28 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -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", diff --git a/bin/data/entities/light.json b/bin/data/entities/light.json index 061654ef..02f31a93 100644 --- a/bin/data/entities/light.json +++ b/bin/data/entities/light.json @@ -31,7 +31,7 @@ "radius": [0.1, 0], "resolution": 512, "shadows": true, - "static": false + "dynamic": true } } } \ No newline at end of file diff --git a/bin/data/entities/model.json b/bin/data/entities/model.json index 6f163190..3c299bf5 100644 --- a/bin/data/entities/model.json +++ b/bin/data/entities/model.json @@ -38,7 +38,7 @@ }, "baking": { "enabled": true, - "resolution": 2048, + "resolution": 4096, "shadows": 1024, "layers": 1, "trigger": { "mode": "rendered", "quit": true }, diff --git a/bin/data/entities/playerLight.json b/bin/data/entities/playerLight.json index ad807d00..6f83eba5 100644 --- a/bin/data/entities/playerLight.json +++ b/bin/data/entities/playerLight.json @@ -26,7 +26,7 @@ "radius": [0.001, 0], "resolution": 512, "shadows": false, - "static": false + "dynamic": true } } } \ No newline at end of file diff --git a/bin/data/entities/scripts/player.lua b/bin/data/entities/scripts/player.lua index c82ce54c..180c0714 100644 --- a/bin/data/entities/scripts/player.lua +++ b/bin/data/entities/scripts/player.lua @@ -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 diff --git a/bin/data/scenes/sm64/sm64.json b/bin/data/scenes/sm64/sm64.json index 4140f707..24cbf693 100644 --- a/bin/data/scenes/sm64/sm64.json +++ b/bin/data/scenes/sm64/sm64.json @@ -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" }, diff --git a/bin/data/scenes/sourceengine/base_sourceengine.json b/bin/data/scenes/sourceengine/base_sourceengine.json index ab8bfe1a..5aa2d17f 100644 --- a/bin/data/scenes/sourceengine/base_sourceengine.json +++ b/bin/data/scenes/sourceengine/base_sourceengine.json @@ -3,7 +3,7 @@ "metadata": { "graph": { // "renderer": { "separate": true }, - "baking": { "enabled": false }, + "baking": { "enabled": true }, "tags": { // exact matches "worldspawn": { diff --git a/bin/data/scenes/sourceengine/scene.json b/bin/data/scenes/sourceengine/scene.json index 0a76433d..4a809ea6 100644 --- a/bin/data/scenes/sourceengine/scene.json +++ b/bin/data/scenes/sourceengine/scene.json @@ -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, diff --git a/bin/data/scenes/sourceengine/sh2_mcdonalds.json b/bin/data/scenes/sourceengine/sh2_mcdonalds.json index 9e7d6b55..55e39fc6 100644 --- a/bin/data/scenes/sourceengine/sh2_mcdonalds.json +++ b/bin/data/scenes/sourceengine/sh2_mcdonalds.json @@ -6,6 +6,9 @@ ], "metadata": { "graph": { + "lights": { + "lightmap": false + }, "assets": [ "./audio/soundscape/sh2_ambience.ogg" ], diff --git a/bin/data/shaders/common/functions.h b/bin/data/shaders/common/functions.h index d5d526a3..77d168a8 100644 --- a/bin/data/shaders/common/functions.h +++ b/bin/data/shaders/common/functions.h @@ -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); diff --git a/bin/data/shaders/common/light.h b/bin/data/shaders/common/light.h index f708b70d..0dbfe75c 100644 --- a/bin/data/shaders/common/light.h +++ b/bin/data/shaders/common/light.h @@ -1,3 +1,5 @@ +float shadowFactor( const Light light, float def ); + #if PBR #include "../common/pbr.h" #endif diff --git a/bin/data/shaders/common/pbr.h b/bin/data/shaders/common/pbr.h index d9007698..29c5fbef 100644 --- a/bin/data/shaders/common/pbr.h +++ b/bin/data/shaders/common/pbr.h @@ -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)); diff --git a/bin/data/shaders/common/shadows.h b/bin/data/shaders/common/shadows.h index e2e1bfaf..f6d42ca3 100644 --- a/bin/data/shaders/common/shadows.h +++ b/bin/data/shaders/common/shadows.h @@ -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) ) diff --git a/bin/data/shaders/common/structs.h b/bin/data/shaders/common/structs.h index c3518b76..3882fa97 100644 --- a/bin/data/shaders/common/structs.h +++ b/bin/data/shaders/common/structs.h @@ -200,9 +200,9 @@ struct SettingsMode { }; struct SettingsLighting { vec3 ambient; - float padding1; - uint indexSkybox; + + uint maxShadows; uint shadowSamples; uint useLightmaps; }; diff --git a/bin/data/shaders/common/vxgi.h b/bin/data/shaders/common/vxgi.h index 1863e545..a67042ee 100644 --- a/bin/data/shaders/common/vxgi.h +++ b/bin/data/shaders/common/vxgi.h @@ -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 diff --git a/bin/data/shaders/display/deferred/comp/comp.h b/bin/data/shaders/display/deferred/comp/comp.h index d8973f5d..7bf2cb8a 100644 --- a/bin/data/shaders/display/deferred/comp/comp.h +++ b/bin/data/shaders/display/deferred/comp/comp.h @@ -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 diff --git a/bin/data/shaders/display/deferred/comp/rt.comp.glsl b/bin/data/shaders/display/deferred/comp/rt.comp.glsl index 3f95c10f..bdc07694 100644 --- a/bin/data/shaders/display/deferred/comp/rt.comp.glsl +++ b/bin/data/shaders/display/deferred/comp/rt.comp.glsl @@ -1,4 +1,4 @@ -#version 450 +#version 460 #pragma shader_stage(compute) #define RT 1 diff --git a/bin/data/shaders/display/deferred/comp/rt.msaa.comp.glsl b/bin/data/shaders/display/deferred/comp/rt.msaa.comp.glsl index 9197eee9..1388e20b 100644 --- a/bin/data/shaders/display/deferred/comp/rt.msaa.comp.glsl +++ b/bin/data/shaders/display/deferred/comp/rt.msaa.comp.glsl @@ -1,4 +1,4 @@ -#version 450 +#version 460 #pragma shader_stage(compute) #define RT 1 diff --git a/bin/data/shaders/display/deferred/comp/rt.vxgi.comp.glsl b/bin/data/shaders/display/deferred/comp/rt.vxgi.comp.glsl new file mode 100644 index 00000000..18e067a1 --- /dev/null +++ b/bin/data/shaders/display/deferred/comp/rt.vxgi.comp.glsl @@ -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(); +} \ No newline at end of file diff --git a/bin/data/shaders/display/deferred/comp/rt.vxgi.msaa.comp.glsl b/bin/data/shaders/display/deferred/comp/rt.vxgi.msaa.comp.glsl index 45c3953d..87394afc 100644 --- a/bin/data/shaders/display/deferred/comp/rt.vxgi.msaa.comp.glsl +++ b/bin/data/shaders/display/deferred/comp/rt.vxgi.msaa.comp.glsl @@ -1,4 +1,4 @@ -#version 450 +#version 460 #pragma shader_stage(compute) #define RT 1 diff --git a/bin/data/shaders/display/renderTarget/frag.glsl b/bin/data/shaders/display/renderTarget/frag.glsl index 3a61a822..8758b85d 100644 --- a/bin/data/shaders/display/renderTarget/frag.glsl +++ b/bin/data/shaders/display/renderTarget/frag.glsl @@ -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 } \ No newline at end of file diff --git a/bin/data/shaders/display/renderTarget/postProcess.frag.glsl b/bin/data/shaders/display/renderTarget/postProcess.frag.glsl index 8feb4b31..a753bcec 100644 --- a/bin/data/shaders/display/renderTarget/postProcess.frag.glsl +++ b/bin/data/shaders/display/renderTarget/postProcess.frag.glsl @@ -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 \ No newline at end of file diff --git a/bin/data/shaders/display/vxgi/comp.glsl b/bin/data/shaders/display/vxgi/comp.glsl index 856c7af2..5c94f4c9 100644 --- a/bin/data/shaders/display/vxgi/comp.glsl +++ b/bin/data/shaders/display/vxgi/comp.glsl @@ -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)); } } \ No newline at end of file diff --git a/bin/data/shaders/graph/baking/frag.glsl b/bin/data/shaders/graph/baking/frag.glsl index 0dee8917..8cac8644 100644 --- a/bin/data/shaders/graph/baking/frag.glsl +++ b/bin/data/shaders/graph/baking/frag.glsl @@ -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) ); } } \ No newline at end of file diff --git a/bin/data/shaders/graph/baking/vert.glsl b/bin/data/shaders/graph/baking/vert.glsl index e3fb2d59..1f20a625 100644 --- a/bin/data/shaders/graph/baking/vert.glsl +++ b/bin/data/shaders/graph/baking/vert.glsl @@ -4,6 +4,5 @@ #define INSTANCED 1 #define SKINNED 0 #define BAKING 1 -#define LAYERED 1 #include "../base/vert.h" diff --git a/bin/data/shaders/graph/base/vert.h b/bin/data/shaders/graph/base/vert.h index 1dc686e6..5aad74bf 100644 --- a/bin/data/shaders/graph/base/vert.h +++ b/bin/data/shaders/graph/base/vert.h @@ -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" diff --git a/bin/data/shaders/raytrace/shader.ray-gen.glsl b/bin/data/shaders/raytrace/shader.ray-gen.glsl index 96fcad8c..40eca388 100644 --- a/bin/data/shaders/raytrace/shader.ray-gen.glsl +++ b/bin/data/shaders/raytrace/shader.ray-gen.glsl @@ -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 } { diff --git a/client/client/ext.cpp b/client/client/ext.cpp index 87d30eeb..6cf5c260 100644 --- a/client/client/ext.cpp +++ b/client/client/ext.cpp @@ -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() { diff --git a/engine/inc/uf/ext/ffx/fsr.h b/engine/inc/uf/ext/ffx/fsr.h index a0f3eae0..8a7e7a07 100644 --- a/engine/inc/uf/ext/ffx/fsr.h +++ b/engine/inc/uf/ext/ffx/fsr.h @@ -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(); diff --git a/engine/inc/uf/ext/vulkan/enums.h b/engine/inc/uf/ext/vulkan/enums.h index e3c17a6f..a0a210c8 100644 --- a/engine/inc/uf/ext/vulkan/enums.h +++ b/engine/inc/uf/ext/vulkan/enums.h @@ -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; diff --git a/engine/inc/uf/ext/vulkan/rendermode.h b/engine/inc/uf/ext/vulkan/rendermode.h index df53be6c..a52291b4 100644 --- a/engine/inc/uf/ext/vulkan/rendermode.h +++ b/engine/inc/uf/ext/vulkan/rendermode.h @@ -18,6 +18,7 @@ namespace ext { uint32_t width = 0; uint32_t height = 0; + float scale = 0; struct { uf::Serializer json; diff --git a/engine/inc/uf/ext/vulkan/rendertarget.h b/engine/inc/uf/ext/vulkan/rendertarget.h index 8a23e5de..91218e7e 100644 --- a/engine/inc/uf/ext/vulkan/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/rendertarget.h @@ -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(); diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index ca386c10..4aa0defa 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -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() && !graph.metadata["lights"]["lightmap"].as() ) { + graph.metadata["baking"]["enabled"] = false; + } if ( !sceneMetadataJson["light"]["useLightmaps"].as(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() ) 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() ) { + 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() ) { + 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() && graph.metadata["lights"]["disable if lightmapped"].as(true) ) if ( graph.lights.count(node.name) > 0 ) ignore = true; +/* + if ( graph.metadata["lights"]["lightmap"].as() && graph.metadata["lights"]["disable if lightmapped"].as(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(false) && !tag["bake"].as(true) ) ignore = true; if ( tag["ignore"].as() ) ignore = true; } + bool isLight = graph.lights.count(node.name) > 0; +/* + if ( graph.metadata["lights"]["lightmap"].as() ) + if ( ext::json::isObject( tag ) ) { + if ( !tag["light"]["dynamic"].as() && !tag["light"]["shadows"].as() ) { + 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(); + 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() ) { + if ( !graph.metadata["lights"]["lightmap"].as() ) { should = true; } else if ( metadataLight["shadows"].as() || metadataLight["dynamic"].as() ) { should = true; } - if ( should ) { - auto& metadataJson = entity.getComponent(); - 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() == "point" ) { - auto& transform = entity.getComponent>(); - transform.orientation = uf::quaternion::identity(); - } - */ - } - #endif + */ + auto& metadataJson = entity.getComponent(); + entity.load("/light.json"); + // copy + ext::json::forEach( metadataLight, [&]( const uf::stl::string& key, ext::json::Value& value ) { + metadataJson["light"][key] = value; + }); } } diff --git a/engine/src/engine/scene/scene.cpp b/engine/src/engine/scene/scene.cpp index 16201d05..934e52ae 100644 --- a/engine/src/engine/scene/scene.cpp +++ b/engine/src/engine/scene/scene.cpp @@ -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; } diff --git a/engine/src/ext/ffx/fsr.cpp b/engine/src/ext/ffx/fsr.cpp index 98f1dc6c..c0339d8d 100644 --- a/engine/src/ext/ffx/fsr.cpp +++ b/engine/src/ext/ffx/fsr.cpp @@ -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; diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index f646e52a..cb79a9e1 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -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); diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 46e77ed0..eefe1b41 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -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; diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index e0b5fced..e577c742 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -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 diff --git a/engine/src/ext/vulkan/rendermodes/base.cpp b/engine/src/ext/vulkan/rendermodes/base.cpp index 0d1e2dae..7ada0194 100644 --- a/engine/src/ext/vulkan/rendermodes/base.cpp +++ b/engine/src/ext/vulkan/rendermodes/base.cpp @@ -40,10 +40,12 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vector layers = ext::vulkan::getRenderModes(uf::stl::vector{"RenderTarget", "Compute:RT", "Deferred"}, false); - if ( !settings::pipelines::rt ) { + uf::stl::vector layers = ext::vulkan::getRenderModes(uf::stl::vector{"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(); @@ -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 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; diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index 1e03f418..df6c3d47 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -41,14 +41,16 @@ uf::stl::vector 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 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 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& 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() ) || !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 = ""; diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index 51140cc6..00daaf63 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -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& 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; diff --git a/engine/src/ext/vulkan/rendertarget.cpp b/engine/src/ext/vulkan/rendertarget.cpp index 76d8f12e..cde8f9aa 100644 --- a/engine/src/ext/vulkan/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendertarget.cpp @@ -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 ) { diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index 9672631d..15d1b883 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -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 ext::vulkan::settings::validationFilters; uf::stl::vector ext::vulkan::settings::requestedDeviceFeatures; @@ -229,11 +229,22 @@ uf::stl::vector ext::vulkan::getRenderModes( const uf: } uf::stl::vector ext::vulkan::getRenderModes( const uf::stl::vector& names, bool isName ) { uf::stl::vector 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); diff --git a/ext/behaviors/baking/behavior.cpp b/ext/behaviors/baking/behavior.cpp index 7032cc65..7798cc58 100644 --- a/ext/behaviors/baking/behavior.cpp +++ b/ext/behaviors/baking/behavior.cpp @@ -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(), metadataJson["baking"]["root"].as() ); 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() ) return; auto& graphic = entity->getComponent(); + 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(); + #if UF_USE_VULKAN if ( !this->hasComponent() ) return; auto& metadata = this->getComponent(); auto& renderMode = this->getComponent(); 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(); - sceneMetadata.light.max = metadata.previous.lights; sceneMetadata.shadow.max = metadata.previous.shadows; sceneMetadata.shadow.update = metadata.previous.update; diff --git a/ext/behaviors/baking/behavior.h b/ext/behaviors/baking/behavior.h index 6a228fab..08a6d31f 100644 --- a/ext/behaviors/baking/behavior.h +++ b/ext/behaviors/baking/behavior.h @@ -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; diff --git a/ext/behaviors/light/behavior.cpp b/ext/behaviors/light/behavior.cpp index 330897d3..0fe65a12 100644 --- a/ext/behaviors/light/behavior.cpp +++ b/ext/behaviors/light/behavior.cpp @@ -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(/*this->*/renderer.limiter); - if ( serializer["light"]["type"].is() ) { + if ( serializer["light"]["type"].is() ) { /*this->*/type = serializer["light"]["type"].as(/*this->*/type); - if ( serializer["light"]["dynamic"].as() ) /*this->*/type = -/*this->*/type; - } else if ( serializer["light"]["type"].is() ) { - uf::stl::string lightType = serializer["light"]["type"].as(); if ( lightType == "point" ) /*this->*/type = 1; else if ( lightType == "spot" ) /*this->*/type = 2; - if ( serializer["light"]["dynamic"].as() ) /*this->*/type = -/*this->*/type; } + if ( serializer["light"]["dynamic"].as() ) /*this->*/type = -/*this->*/type; } #undef this \ No newline at end of file diff --git a/ext/behaviors/raytrace/behavior.cpp b/ext/behaviors/raytrace/behavior.cpp index e9a5db27..4c01a2b0 100644 --- a/ext/behaviors/raytrace/behavior.cpp +++ b/ext/behaviors/raytrace/behavior.cpp @@ -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(); auto& metadataJson = this->getComponent(); - - 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 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 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 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 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(); @@ -97,9 +103,12 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { if ( graphics.empty() ) return; bool update = false; - auto& graphic = this->getComponent(); + auto& renderMode = uf::renderer::getRenderMode("", true); + auto& graphic = metadata.renderer.full ? this->getComponent() : *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(); 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(); + size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(512); + size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as(512); + size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as(128); + size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as(1); + size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(16); - // - auto& scene = uf::scene::getCurrentScene(); - auto& sceneMetadataJson = scene.getComponent(); - size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(512); - size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as(512); - size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as(128); - size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as(1); - size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(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(); - auto& graphic = this->getComponent(); + if ( !metadata.renderer.full ) return; + auto& graphic = this->getComponent(); 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() ) { /*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); diff --git a/ext/behaviors/raytrace/behavior.h b/ext/behaviors/raytrace/behavior.h index b3d98fb7..b7c0bff1 100644 --- a/ext/behaviors/raytrace/behavior.h +++ b/ext/behaviors/raytrace/behavior.h @@ -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 { diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index c55e6f23..4acc6aba 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -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 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 diff --git a/ext/behaviors/voxelizer/behavior.cpp b/ext/behaviors/voxelizer/behavior.cpp index abf98203..56aff042 100644 --- a/ext/behaviors/voxelizer/behavior.cpp +++ b/ext/behaviors/voxelizer/behavior.cpp @@ -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(256); - const float DEFAULT_VOXELIZE_LIMITER = ext::config["engine"]["scenes"]["vxgi"]["limiter"].as(0); - const uint32_t DEFAULT_DISPATCH_SIZE = ext::config["engine"]["scenes"]["vxgi"]["dispatch"].as(8); - const uint32_t DEFAULT_CASCADES = ext::config["engine"]["scenes"]["vxgi"]["cascades"].as(8); - const float DEFAULT_CASCADE_POWER = ext::config["engine"]["scenes"]["vxgi"]["cascadePower"].as(1.5); - const float DEFAULT_GRANULARITY = ext::config["engine"]["scenes"]["vxgi"]["granularity"].as(2.0); - const float DEFAULT_SHADOWS = ext::config["engine"]["scenes"]["vxgi"]["shadows"].as(8); - const float DEFAULT_PIXEL_SCALE = ext::config["engine"]["scenes"]["vxgi"]["voxelizeScale"].as(1); - const float DEFAULT_OCCLUSION_FALLOFF = ext::config["engine"]["scenes"]["vxgi"]["occlusionFalloff"].as(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 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(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); diff --git a/ext/gui/manager/behavior.cpp b/ext/gui/manager/behavior.cpp index eb6f77de..d82b1396 100644 --- a/ext/gui/manager/behavior.cpp +++ b/ext/gui/manager/behavior.cpp @@ -54,6 +54,7 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) { if ( !uf::renderer::hasRenderMode( "Gui", true ) ) { auto& renderMode = this->getComponent(); 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() ) { + renderModePointer = this->getComponentPointer(); + } 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() ) { + renderModePointer = this->getComponentPointer(); + } 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(); -#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>().position ); - auto rotation = uf::quaternion::matrix( controller.getComponent>().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(); #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>().position ); + auto rotation = uf::quaternion::matrix( controller.getComponent>().orientation ); - if ( metadata.overlay.cursor.enabled ) { - uniforms.cursor.position = metadata.overlay.cursor.position * 0.5f + 0.5f; - uniforms.cursor.radius = uf::matrix::multiply( 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( 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 } diff --git a/ext/main.cpp b/ext/main.cpp index 2645a038..ed84404c 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -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 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() ) {\ @@ -491,6 +498,7 @@ void EXT_API ext::initialize() { /* Initialize Vulkan */ { // setup render mode + /* if ( ::json["engine"]["render modes"]["gui"].as(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(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() ) { 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