From 96ca8705863aaf779f6662284b3ec0b597188875 Mon Sep 17 00:00:00 2001 From: mrq Date: Thu, 4 Aug 2022 23:27:00 -0500 Subject: [PATCH] Commit for 2022.08.04 23-27-32.7z --- bin/data/config.json | 14 +- bin/data/entities/model.json | 4 +- bin/data/scenes/scene.json | 15 - .../scenes/sourceengine/gm_construct.json | 2 +- bin/data/scenes/sourceengine/scene.json | 18 +- .../scenes/sourceengine/sh2_mcdonalds.json | 2 +- .../scenes/sourceengine/sourceengine.json | 4 +- bin/data/shaders/common/functions.h | 6 + bin/data/shaders/common/structs.h | 4 +- bin/data/shaders/display/deferred/comp/comp.h | 8 +- .../shaders/display/depth-pyramid/comp.glsl | 30 ++ bin/data/shaders/graph/baking/frag.glsl | 209 +--------- bin/data/shaders/graph/baking/frag.h | 196 ++++++++++ bin/data/shaders/graph/baking/rt.frag.glsl | 5 + bin/data/shaders/graph/cull/comp.glsl | 246 ++++++++---- bin/data/shaders/graph/occlusion/comp.glsl | 52 --- client/client/ext.cpp | 4 - client/main.cpp | 8 +- .../inc/uf/engine/object/behaviors/render.h | 14 - engine/inc/uf/ext/ncurses/ncurses.h | 55 --- engine/inc/uf/ext/vulkan/buffer.h | 1 + engine/inc/uf/ext/vulkan/shader.h | 4 + engine/inc/uf/ext/vulkan/texture.h | 10 +- engine/inc/uf/utils/math/vector.h | 2 + engine/inc/uf/utils/math/vector/pod.inl | 14 +- engine/inc/uf/utils/mesh/mesh.h | 2 +- engine/src/engine/entity/entity.cpp | 4 +- engine/src/engine/graph/graph.cpp | 118 +++--- engine/src/engine/object/behaviors/graph.cpp | 149 +------ engine/src/engine/object/behaviors/render.cpp | 131 ------- engine/src/engine/scene/scene.cpp | 28 +- engine/src/ext/opengl/rendermode.cpp | 4 +- engine/src/ext/opengl/texture.cpp | 2 +- engine/src/ext/vulkan/graphic.cpp | 95 ++--- engine/src/ext/vulkan/rendermode.cpp | 4 +- .../src/ext/vulkan/rendermodes/deferred.cpp | 369 +++++++++++++----- .../ext/vulkan/rendermodes/rendertarget.cpp | 90 +++-- .../src/ext/vulkan/rendermodes/transition.inl | 2 + engine/src/ext/vulkan/rendertarget.cpp | 2 +- engine/src/ext/vulkan/shader.cpp | 22 +- engine/src/ext/vulkan/texture.cpp | 19 +- engine/src/ext/vulkan/vulkan.cpp | 123 +++--- engine/src/utils/image/image.cpp | 2 +- engine/src/utils/thread/thread.cpp | 2 +- ext/behaviors/baking/behavior.cpp | 7 +- ext/behaviors/light/behavior.cpp | 9 +- ext/behaviors/raytrace/behavior.cpp | 19 +- ext/behaviors/scene/behavior.cpp | 9 +- ext/behaviors/voxelizer/behavior.cpp | 2 +- 49 files changed, 1038 insertions(+), 1103 deletions(-) create mode 100644 bin/data/shaders/display/depth-pyramid/comp.glsl create mode 100644 bin/data/shaders/graph/baking/frag.h create mode 100644 bin/data/shaders/graph/baking/rt.frag.glsl delete mode 100644 bin/data/shaders/graph/occlusion/comp.glsl delete mode 100644 engine/inc/uf/engine/object/behaviors/render.h delete mode 100644 engine/inc/uf/ext/ncurses/ncurses.h delete mode 100644 engine/src/engine/object/behaviors/render.cpp diff --git a/bin/data/config.json b/bin/data/config.json index 520d8c28..e7245a01 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -100,20 +100,20 @@ }, "gpu": 1, "experimental": { - "batch queue submissions": false, "rebuild on tick begin": false, - "dedicated thread": false + "batch queue submissions": true, + "dedicated thread": true }, "invariant": {}, "pipelines": { "deferred": true, - "vsync": false, - "hdr": false, + "vsync": true, + "hdr": true, "vxgi": true, - "culling": true, + "culling": false, "bloom": true, "rt": true, - "postProcess": false, + "postProcess": true, "fsr": true }, "formats": { @@ -221,7 +221,7 @@ "fsr": { "enabled": true, "sharpness": 1, - "jitter scale": 0.0125, + "jitter scale": 0.0625, "preset": "ultra" // native (1x), quality (1.5x), balanced (1.7x), performance (2.0x), ultra (3.0x) }, "reactphysics": { diff --git a/bin/data/entities/model.json b/bin/data/entities/model.json index 3c299bf5..18e81d5d 100644 --- a/bin/data/entities/model.json +++ b/bin/data/entities/model.json @@ -46,9 +46,9 @@ "output": "./lightmap.%i.png", "settings": { "useInputMeshUvs": true, - "maxIterations": 1, + "maxIterations": 4, // "maxChartSize": 0, - "padding": 4, + "padding": 2, // "texelsPerUnit": 0, "bilinear": true, "blockAlign": true, diff --git a/bin/data/scenes/scene.json b/bin/data/scenes/scene.json index ee7170f3..708fc6af 100644 --- a/bin/data/scenes/scene.json +++ b/bin/data/scenes/scene.json @@ -49,21 +49,6 @@ "sigma": 1.0, "samples": 4 }, - "fog": { - // "color": [ 0.1, 0.1, 0.1 ], - // "color": [ 0.2, 0.2, 0.2 ], - "color": [ 0.3, 0.3, 0.3 ], - "range": [ 64, 256 ], - "step scale": 4, - "absorbtion": 0.0125, - "density": { - "threshold": 0.35, - "multiplier": 2.0, - "scale": 25.0, - "offset": [0.2, 0, 1], - "timescale": 32 - } - }, "shadows": { "enabled": true } diff --git a/bin/data/scenes/sourceengine/gm_construct.json b/bin/data/scenes/sourceengine/gm_construct.json index c9e7ef46..4fc60b26 100644 --- a/bin/data/scenes/sourceengine/gm_construct.json +++ b/bin/data/scenes/sourceengine/gm_construct.json @@ -13,7 +13,7 @@ // exact matches // "worldspawn_skybox": { "ignore": true }, "worldspawn_skybox": { - "grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true }, + "grid": { "size": [5,1,5], "epsilon": 1.0, "cleanup": true, "print": true }, "unwrap mesh": true, "optimize mesh": { "simplify": 0 } }, diff --git a/bin/data/scenes/sourceengine/scene.json b/bin/data/scenes/sourceengine/scene.json index 4a809ea6..67186921 100644 --- a/bin/data/scenes/sourceengine/scene.json +++ b/bin/data/scenes/sourceengine/scene.json @@ -13,7 +13,7 @@ // "ambient": [ 0.8, 0.8, 0.8 ], // "ambient": [ 0.1, 0.1, 0.2 ], - "exposure": 1, // 0.125, + "exposure": 0.125, "gamma": 2.2, // 2.2, "bloom": { @@ -22,6 +22,22 @@ "strength": 1, "sigma": 1.0, "samples": 4 + }, + + "fog": { + // "color": [ 0.1, 0.1, 0.1 ], + // "color": [ 0.2, 0.2, 0.2 ], + "color": [ 0.3, 0.3, 0.3 ], + "range": [ 64, 256 ], + "step scale": 4, + "absorbtion": 0.0125, + "density": { + "threshold": 0.35, + "multiplier": 2.0, + "scale": 25.0, + "offset": [0.2, 0, 1], + "timescale": 32 + } } } } diff --git a/bin/data/scenes/sourceengine/sh2_mcdonalds.json b/bin/data/scenes/sourceengine/sh2_mcdonalds.json index 55e39fc6..5024a7ba 100644 --- a/bin/data/scenes/sourceengine/sh2_mcdonalds.json +++ b/bin/data/scenes/sourceengine/sh2_mcdonalds.json @@ -7,7 +7,7 @@ "metadata": { "graph": { "lights": { - "lightmap": false +// "lightmap": false }, "assets": [ "./audio/soundscape/sh2_ambience.ogg" diff --git a/bin/data/scenes/sourceengine/sourceengine.json b/bin/data/scenes/sourceengine/sourceengine.json index beb54dda..2f1ce5e4 100644 --- a/bin/data/scenes/sourceengine/sourceengine.json +++ b/bin/data/scenes/sourceengine/sourceengine.json @@ -1,6 +1,6 @@ { // "import": "./rp_downtown_v2.json" - "import": "./ss2_medsci1.json" -// "import": "./sh2_mcdonalds.json" +// "import": "./ss2_medsci1.json" + "import": "./sh2_mcdonalds.json" // "import": "./gm_construct.json" } \ No newline at end of file diff --git a/bin/data/shaders/common/functions.h b/bin/data/shaders/common/functions.h index 77d168a8..da30758a 100644 --- a/bin/data/shaders/common/functions.h +++ b/bin/data/shaders/common/functions.h @@ -10,6 +10,12 @@ float mipLevel( in vec2 dx_vtc, in vec2 dy_vtc ) { // return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc))); } +float mipLevels( vec2 size ) { + return floor(log2(max(size.x, size.y))); +} +float mipLevels( ivec2 size ) { + return floor(log2(max(size.x, size.y))); +} // void toneMap( inout vec3 color, float exposure ) { color.rgb = vec3(1.0) - exp(-color.rgb * exposure); diff --git a/bin/data/shaders/common/structs.h b/bin/data/shaders/common/structs.h index 3882fa97..c8e35fb5 100644 --- a/bin/data/shaders/common/structs.h +++ b/bin/data/shaders/common/structs.h @@ -87,8 +87,8 @@ struct DrawCommand { int vertexID; // starting vertex position uint instanceID; // starting instance position - uint auxID; // - uint materialID; // material to use for this draw call + float padding1; // + float padding2; // material to use for this draw call uint vertices; // number of vertices used }; diff --git a/bin/data/shaders/display/deferred/comp/comp.h b/bin/data/shaders/display/deferred/comp/comp.h index 7bf2cb8a..6522aca1 100644 --- a/bin/data/shaders/display/deferred/comp/comp.h +++ b/bin/data/shaders/display/deferred/comp/comp.h @@ -15,6 +15,8 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #define PBR 1 #define BUFFER_REFERENCE 1 #define UINT64_ENABLED 1 +#define FOG 1 +#define FOG_RAY_MARCH 1 #include "../../../common/macros.h" @@ -222,12 +224,6 @@ 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/depth-pyramid/comp.glsl b/bin/data/shaders/display/depth-pyramid/comp.glsl new file mode 100644 index 00000000..d58feb89 --- /dev/null +++ b/bin/data/shaders/display/depth-pyramid/comp.glsl @@ -0,0 +1,30 @@ +#version 450 +#pragma shader_stage(compute) + +//#extension GL_EXT_nonuniform_qualifier : enable + +layout (constant_id = 0) const uint MIPS = 6; +layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#define COMPUTE 1 + +#include "../../common/macros.h" +#include "../../common/structs.h" + +layout( push_constant ) uniform PushBlock { + uint _; + uint pass; +} PushConstant; + +layout (binding = 3) uniform sampler2D inImage[MIPS]; +layout (binding = 4, r32f) uniform volatile coherent image2D outImage[MIPS]; + +void main() { + vec2 imageSize = imageSize(outImage[PushConstant.pass]); + uvec2 pos = gl_GlobalInvocationID.xy; + if ( pos.x >= imageSize.x || pos.y >= imageSize.y ) return; + + float depth = texture(inImage[PushConstant.pass], (vec2(pos) + vec2(0.5)) / imageSize).x; + + imageStore(outImage[PushConstant.pass], ivec2(pos), vec4(depth)); +} \ 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 8cac8644..076049f2 100644 --- a/bin/data/shaders/graph/baking/frag.glsl +++ b/bin/data/shaders/graph/baking/frag.glsl @@ -1,210 +1,5 @@ #version 450 #pragma shader_stage(fragment) -//#extension GL_EXT_nonuniform_qualifier : enable - -layout (constant_id = 0) const uint TEXTURES = 512; -layout (constant_id = 1) const uint CUBEMAPS = 128; -layout (constant_id = 2) const uint LAYERS = 32; - -layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES]; -layout (binding = 6) uniform samplerCube samplerCubemaps[CUBEMAPS]; - -#define SHADOW_SAMPLES 16 -#define FRAGMENT 1 -#define BAKING 1 - -#include "../../common/macros.h" -#include "../../common/structs.h" - -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 = 10) readonly buffer Instances { - Instance instances[]; -}; -layout (std140, binding = 11) readonly buffer InstanceAddresseses { - InstanceAddresses instanceAddresses[]; -}; -layout (std140, binding = 12) readonly buffer Materials { - Material materials[]; -}; -layout (std140, binding = 13) readonly buffer Textures { - Texture textures[]; -}; -layout (std140, binding = 14) readonly buffer Lights { - Light lights[]; -}; - -layout (binding = 15, rgba8) uniform volatile coherent image3D outAlbedos; - -#include "../../common/functions.h" -#include "../../common/shadows.h" - -#define PBR 1 - -layout (location = 0) flat in uvec4 inId; -layout (location = 1) flat in vec4 inPOS0; -layout (location = 2) in vec4 inPOS1; -layout (location = 3) in vec3 inPosition; -layout (location = 4) in vec2 inUv; -layout (location = 5) in vec4 inColor; -layout (location = 6) in vec2 inSt; -layout (location = 7) in vec3 inNormal; -layout (location = 8) in vec3 inTangent; - -layout (location = 0) out vec4 outAlbedo; - -void main() { - const uint triangleID = uint(inId.x); // gl_PrimitiveID - const uint drawID = uint(inId.y); - const uint instanceID = uint(inId.z); - - 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); - vec3 B = cross(T, N); - mat3 TBN = mat3(T, B, N); -// mat3 TBN = mat3(N, B, T); - if ( T != vec3(0) && validTextureIndex( material.indexNormal ) ) { - surface.normal.world = TBN * normalize( sampleTexture( material.indexNormal ).xyz * 2.0 - 1.0 ); - } 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 < 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) ); - const vec3 normal = surface.normal.world; - // const vec3 normal = vec3( mat * vec4(surface.normal.world, 0.0) ); - - if ( light.power <= LIGHT_POWER_CUTOFF ) continue; - const vec3 Lp = light.position; - const vec3 Liu = light.position - surface.position.world; - const float La = 1.0 / (PI * pow(length(Liu), 2.0)); - const float Ls = shadowFactor( light, 0.0 ); - if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue; - - const vec3 Lo = normalize( -position ); - 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; - // const float cosLi = max(0.0, dot(normal, Li)); - const float cosLi = abs(dot(normal, Li)); - #if LAMBERT - const vec3 diffuse = surface.material.albedo.rgb; - const vec3 specular = vec3(0); - #elif PBR - const vec3 Lh = normalize(Li + Lo); - // const float cosLh = max(0.0, dot(normal, Lh)); - const float cosLh = abs(dot(normal, Lh)); - - const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) ); - const float D = 1; // ndfGGX( cosLh, surface.material.roughness ); - const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness); - const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb; - const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo); - #endif - - surface.light.rgb += (diffuse + specular) * Lr * cosLi; - surface.light.a += light.power * La * Ls; - } - } -#else - { - // corrections - surface.material.roughness *= 4.0; - const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic); - const vec3 Lo = normalize( surface.position.world ); - const float cosLo = max(0.0, dot(surface.normal.world, Lo)); - for ( uint i = 0; i < lights.length(); ++i ) { - const Light light = lights[i]; - if ( light.power <= LIGHT_POWER_CUTOFF ) continue; - if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) continue; - const vec3 Lp = light.position; - 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)); - if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue; - - const float cosLi = max(0.0, dot(surface.normal.world, Li)); - const vec3 Lr = light.color.rgb * light.power * La * Ls; - #if LAMBERT - const vec3 diffuse = surface.material.albedo.rgb; - const vec3 specular = vec3(0); - #elif PBR - const vec3 Lh = normalize(Li + Lo); - const float cosLh = max(0.0, dot(surface.normal.world, Lh)); - - const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) ); - const float D = ndfGGX( cosLh, surface.material.roughness ); - const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness); - const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb; - const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo); - #endif - - surface.light.rgb += (diffuse + specular) * Lr * cosLi; - surface.light.a += light.power * La * Ls; - } - } -#endif -#endif -#define EXPOSURE 0 -#define GAMMA 0 - -// surface.light.rgb = vec3(1.0) - exp(-surface.light.rgb * EXPOSURE); -// surface.light.rgb = pow(surface.light.rgb, vec3(1.0 / GAMMA)); - - outAlbedo = vec4(surface.light.rgb, 1); - - { - const vec2 st = inSt.xy * imageSize(outAlbedos).xy; - 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 +#define RT 0 +#include "./frag.h" diff --git a/bin/data/shaders/graph/baking/frag.h b/bin/data/shaders/graph/baking/frag.h new file mode 100644 index 00000000..8e995076 --- /dev/null +++ b/bin/data/shaders/graph/baking/frag.h @@ -0,0 +1,196 @@ +//#extension GL_EXT_nonuniform_qualifier : enable +#if RT + #extension GL_EXT_ray_tracing : enable + #extension GL_EXT_ray_query : enable +#endif + +layout (constant_id = 0) const uint TEXTURES = 512; +layout (constant_id = 1) const uint CUBEMAPS = 128; +layout (constant_id = 2) const uint LAYERS = 32; + +layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES]; +layout (binding = 6) uniform samplerCube samplerCubemaps[CUBEMAPS]; + +#define SHADOW_SAMPLES 16 +#define FRAGMENT 1 +#define BAKING 1 + +#include "../../common/macros.h" +#include "../../common/structs.h" + +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 = 10) readonly buffer Instances { + Instance instances[]; +}; +layout (std140, binding = 11) readonly buffer InstanceAddresseses { + InstanceAddresses instanceAddresses[]; +}; +layout (std140, binding = 12) readonly buffer Materials { + Material materials[]; +}; +layout (std140, binding = 13) readonly buffer Textures { + Texture textures[]; +}; +layout (std140, binding = 14) readonly buffer Lights { + Light lights[]; +}; + +layout (binding = 15, rgba8) uniform volatile coherent image3D outAlbedos; + +#if RT + layout (binding = 16) uniform accelerationStructureEXT tlas; +#endif + +#include "../../common/functions.h" +#if RT +float shadowFactor( const Light light, float def ) { + Ray ray; + ray.origin = surface.position.world; + ray.direction = light.position - ray.origin; + + float tMin = 0.001; + float tMax = length(ray.direction) + tMin; + + 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; +} +#else + #include "../../common/shadows.h" +#endif + +#define PBR 1 + +layout (location = 0) flat in uvec4 inId; +layout (location = 1) flat in vec4 inPOS0; +layout (location = 2) in vec4 inPOS1; +layout (location = 3) in vec3 inPosition; +layout (location = 4) in vec2 inUv; +layout (location = 5) in vec4 inColor; +layout (location = 6) in vec2 inSt; +layout (location = 7) in vec3 inNormal; +layout (location = 8) in vec3 inTangent; + +layout (location = 0) out vec4 outAlbedo; + +void main() { + const uint triangleID = uint(inId.x); // gl_PrimitiveID + const uint drawID = uint(inId.y); + const uint instanceID = uint(inId.z); + + 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); + vec3 B = cross(T, N); + mat3 TBN = mat3(T, B, N); +// mat3 TBN = mat3(N, B, T); + if ( T != vec3(0) && validTextureIndex( material.indexNormal ) ) { + surface.normal.world = TBN * normalize( sampleTexture( material.indexNormal ).xyz * 2.0 - 1.0 ); + } else { + surface.normal.world = N; + } +#endif + + surface.light = material.colorEmissive; + surface.material.albedo = vec4(1); + { + const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic); + 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) ); + const vec3 normal = surface.normal.world; + // const vec3 normal = vec3( mat * vec4(surface.normal.world, 0.0) ); + + if ( light.power <= LIGHT_POWER_CUTOFF ) continue; + const vec3 Lp = light.position; + const vec3 Liu = light.position - surface.position.world; + const float La = 1.0 / (1 + PI * pow(length(Liu), 2.0)); + const float Ls = shadowFactor( light, 0.0 ); + if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue; + + const vec3 Lo = normalize( -position ); + 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; + // const float cosLi = max(0.0, dot(normal, Li)); + const float cosLi = abs(dot(normal, Li)); + #if LAMBERT + const vec3 diffuse = surface.material.albedo.rgb; + const vec3 specular = vec3(0); + #elif PBR + const vec3 Lh = normalize(Li + Lo); + // const float cosLh = max(0.0, dot(normal, Lh)); + const float cosLh = abs(dot(normal, Lh)); + + const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) ); + const float D = 1; // ndfGGX( cosLh, surface.material.roughness ); + const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness); + const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb; + const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo); + #endif + + surface.light.rgb += (diffuse + specular) * Lr * cosLi; + surface.light.a += light.power * La * Ls; + } + } +#define EXPOSURE 0 +#define GAMMA 0 + +// surface.light.rgb = vec3(1.0) - exp(-surface.light.rgb * EXPOSURE); +// surface.light.rgb = pow(surface.light.rgb, vec3(1.0 / GAMMA)); + + outAlbedo = vec4(surface.light.rgb, 1); + + { + const vec2 st = inSt.xy * imageSize(outAlbedos).xy; + 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/rt.frag.glsl b/bin/data/shaders/graph/baking/rt.frag.glsl new file mode 100644 index 00000000..a7eca538 --- /dev/null +++ b/bin/data/shaders/graph/baking/rt.frag.glsl @@ -0,0 +1,5 @@ +#version 460 +#pragma shader_stage(fragment) + +#define RT 1 +#include "./frag.h" diff --git a/bin/data/shaders/graph/cull/comp.glsl b/bin/data/shaders/graph/cull/comp.glsl index 1053f4c7..efb2bfd6 100644 --- a/bin/data/shaders/graph/cull/comp.glsl +++ b/bin/data/shaders/graph/cull/comp.glsl @@ -2,15 +2,54 @@ #pragma shader_stage(compute) //#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_samplerless_texture_functions : enable layout (constant_id = 0) const uint PASSES = 6; layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; #define COMPUTE 1 +#define QUERY_MIPMAPS 1 +#define DEPTH_BIAS 0.00005 #include "../../common/macros.h" #include "../../common/structs.h" +float mipLevels( vec2 size ) { + return floor(log2(max(size.x, size.y))); +} +float mipLevels( ivec2 size ) { + return floor(log2(max(size.x, size.y))); +} + +vec4 aabbToSphere( Bounds bounds ) { + vec4 sphere; + sphere.xyz = (bounds.max + bounds.min) * 0.5; + sphere.w = length((bounds.max - bounds.min) * 0.5); + return sphere; +} + +// 2D Polyhedral Bounds of a Clipped, Perspective-Projected 3D Sphere. Michael Mara, Morgan McGuire. 2013 +bool projectSphere(vec3 C, float r, float znear, float P00, float P11, out vec4 aabb) +{ + if (C.z < r + znear) + return false; + + vec2 cx = -C.xz; + vec2 vx = vec2(sqrt(dot(cx, cx) - r * r), r); + vec2 minx = mat2(vx.x, vx.y, -vx.y, vx.x) * cx; + vec2 maxx = mat2(vx.x, -vx.y, vx.y, vx.x) * cx; + + vec2 cy = -C.yz; + vec2 vy = vec2(sqrt(dot(cy, cy) - r * r), r); + vec2 miny = mat2(vy.x, vy.y, -vy.y, vy.x) * cy; + vec2 maxy = mat2(vy.x, -vy.y, vy.y, vy.x) * cy; + + aabb = vec4(minx.x / minx.y * P00, miny.x / miny.y * P11, maxx.x / maxx.y * P00, maxy.x / maxy.y * P11); + aabb = aabb.xwzy * vec4(0.5f, -0.5f, 0.5f, -0.5f) + vec4(0.5f); // clip space -> uv space + + return true; +} + layout( push_constant ) uniform PushBlock { uint pass; uint passes; @@ -28,6 +67,8 @@ layout (std140, binding = 2) buffer Instances { Instance instances[]; }; +layout (binding = 3) uniform sampler2D samplerDepth; + struct Frustum { vec4 planes[6]; }; @@ -44,72 +85,12 @@ bool frustumCull( uint id ) { bool visible = false; for ( uint pass = 0; pass < PushConstant.passes; ++pass ) { - // return if our camera position is inside the AABB -// vec3 camPos = vec3( inverse(camera.viewport[pass].view)[3] ); -// if ( instance.bounds.min.x <= camPos.x && camPos.x <= instance.bounds.max.x && instance.bounds.min.y <= camPos.y && camPos.y <= instance.bounds.max.y && instance.bounds.min.z <= camPos.z && camPos.z <= instance.bounds.max.z ) return true; - // sphere based one, source of this block uses reverse infinite Z, but would be nice if it used AABB - // doesn't work - #if 0 - vec3 min = vec3(camera.viewport[pass].view * instance.model * vec4(instance.bounds.min, 1)); - vec3 max = vec3(camera.viewport[pass].view * instance.model * vec4(instance.bounds.max, 1)); - - vec3 center = (max + min) * 0.5; - vec3 extent = (max - min) * 0.5; - float radius = length(extent); - - mat4 projectionT = transpose(camera.viewport[pass].projection); - vec4 frustumX = normalizePlane(projectionT[3] + projectionT[0]); // x + w < 0 - vec4 frustumY = normalizePlane(projectionT[3] + projectionT[1]); // y + w < 0 - vec4 frustum = vec4( frustumX.x, frustumX.z, frustumY.y, frustumY.z ); - - visible = visible && center.z * frustum[1] - abs(center.x) * frustum[0] > -radius; - visible = visible && center.z * frustum[3] - abs(center.y) * frustum[2] > -radius; - // optimized version of the below blocks - // doesn't work - #elif 0 - mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model; - vec3 min = vec3(mat * vec4(instance.bounds.min, 1)); - vec3 max = vec3(mat * vec4(instance.bounds.max, 1)); - vec3 center = (max + min) * 0.5; - vec3 extent = (max - min) * 0.5; - - vec4 planes[6]; { - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 2; ++j) { - planes[i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]); - planes[i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]); - planes[i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]); - planes[i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]); - planes[i*2+j] = normalizePlane( planes[i*2+j] ); - } - } - for ( uint p = 0; p < 6; ++p ) { - if ( dot(center + extent * sign(planes[p].xyz), planes[p].xyz ) > -planes[p].w ) return true; - } - // transforms each corner into clip space - // an AABB is not visible if a plane has all 8 corners outside of it - // doesn't work - #elif 0 - mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model; - vec4 corners[8] = { - vec4( instance.bounds.min.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ), - vec4( instance.bounds.max.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ), - vec4( instance.bounds.max.x, instance.bounds.max.y, instance.bounds.min.z, 1.0 ), - vec4( instance.bounds.min.x, instance.bounds.max.y, instance.bounds.min.z, 1.0 ), - - vec4( instance.bounds.min.x, instance.bounds.min.y, instance.bounds.max.z, 1.0 ), - vec4( instance.bounds.max.x, instance.bounds.min.y, instance.bounds.max.z, 1.0 ), - vec4( instance.bounds.max.x, instance.bounds.max.y, instance.bounds.max.z, 1.0 ), - vec4( instance.bounds.min.x, instance.bounds.max.y, instance.bounds.max.z, 1.0 ), - }; - for ( uint p = 0; p < 8; ++p ) { - vec4 t = mat * corners[p]; - if ( -t.w <= t.x && t.x <= t.w && -t.w <= t.y && t.y <= t.w && -t.w <= t.z && t.z <= t.w ) return true; - } - // "optimized" version of the next block, compares bounds to each plane - // an AABB is not visible if a plane has all 8 corners outside of it - #elif 1 +#if 0 + vec4 sphere = aabbToSphere( instance.bounds ); + vec3 center = vec3( camera.viewport[pass].view * instance.model * vec4( ) ); +#else mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model; + #if 1 vec4 planes[6]; { for (int i = 0; i < 3; ++i) for (int j = 0; j < 2; ++j) { @@ -127,7 +108,6 @@ bool frustumCull( uint id ) { if ( d > -planes[p].w ) return true; } #else - mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model; vec4 corners[8] = { vec4( instance.bounds.min.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ), vec4( instance.bounds.max.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ), @@ -161,6 +141,134 @@ bool frustumCull( uint id ) { } return false; } + #endif +#endif + } + return visible; +} + +bool occlusionCull( uint id ) { + if ( PushConstant.passes == 0 ) return true; + + const DrawCommand drawCommand = drawCommands[id]; + const Instance instance = instances[drawCommand.instanceID]; + + bool visible = true; + for ( uint pass = 0; pass < PushConstant.passes; ++pass ) { +#if 1 + vec4 aabb; + vec4 sphere = aabbToSphere( instance.bounds ); + vec3 center = (camera.viewport[pass].view * instance.model * vec4(sphere.xyz, 1)).xyz; + float radius = (instance.model * vec4(sphere.w, 0, 0, 0)).x; + // center.y *= -1; + mat4 proj = camera.viewport[pass].projection; + float znear = proj[3][2]; + float P00 = proj[0][0]; + float P11 = proj[1][1]; + if (projectSphere(center, radius, znear, P00, P11, aabb)) { + ivec2 pyramidSize = textureSize( samplerDepth, 0 ); + float mips = mipLevels( pyramidSize ); + + float width = (aabb.z - aabb.x) * pyramidSize.x; + float height = (aabb.w - aabb.y) * pyramidSize.y; + + //find the mipmap level that will match the screen size of the sphere + float level = floor(log2(max(width, height))); + // if ( level == mips ) + --level; + level = clamp( level, 0, mips ); + + //sample the depth pyramid at that specific level + float depth = textureLod(samplerDepth, (aabb.xy + aabb.zw) * 0.5, level).x; + + float depthSphere = znear / (center.z - radius); + + instances[drawCommand.instanceID].bounds.padding1 = depth; + instances[drawCommand.instanceID].bounds.padding2 = proj[3][2]; + + //if the depth of the sphere is in front of the depth pyramid value, then the object is visible + visible = visible && depthSphere >= depth - DEPTH_BIAS; + } + +#else + mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model; + vec3 boundsSize = instance.bounds.max - instance.bounds.min; + vec3 points[8] = { + instance.bounds.min.xyz, + instance.bounds.min.xyz + vec3(boundsSize.x,0,0), + instance.bounds.min.xyz + vec3(0, boundsSize.y,0), + instance.bounds.min.xyz + vec3(0, 0, boundsSize.z), + instance.bounds.min.xyz + vec3(boundsSize.xy,0), + instance.bounds.min.xyz + vec3(0, boundsSize.yz), + instance.bounds.min.xyz + vec3(boundsSize.x, 0, boundsSize.z), + instance.bounds.min.xyz + boundsSize.xyz, + }; + vec2 minXY = vec2(1); + vec2 maxXY = vec2(0); + + float minZ = 1; + float maxZ = 0; + + #pragma unroll 8 + for ( uint i = 0; i < 8; ++i ) { + vec4 clip = mat * vec4( points[i], 1 ); + clip.xyz /= clip.w; + clip.xy = clip.xy * 0.5 + 0.5; + + minXY.x = min(minXY.x, clip.x); + minXY.y = min(minXY.y, clip.y); + + maxXY.x = max(maxXY.x, clip.x); + maxXY.y = max(maxXY.y, clip.y); + + #if INVERSE + clip.z = 1.0 - clip.z; + maxZ = max(maxZ, clip.z); + #else + minZ = min(minZ, clip.z); + #endif + } + + if ( maxXY.x <= 0 || maxXY.y <= 0 ) return false; + if ( minXY.x >= 1 || minXY.y >= 1 ) return false; + + ivec2 depthSize = textureSize( samplerDepth, 0 ); + float mips = mipLevels( depthSize ); + + vec4 uv = vec4(minXY, maxXY); + + ivec2 clipSize = ivec2(maxXY - minXY) * depthSize; + float mip = mipLevels( clipSize ); + mip = clamp( mip, 0, mips ); + if ( mip == 0 ) { + mip = 1; + } else { + float lower = max(mip - 1, 0); + float scale = exp2(-lower); + vec2 a = floor(uv.xy * scale); + vec2 b = ceil(uv.zw * scale); + vec2 dims = b - a; + + // Use the lower level if we only touch <= 2 texels in both dimensions + if (dims.x <= 2 && dims.y <= 2) mip = lower; + } + + float depths[4] = { + textureLod( samplerDepth, uv.xy, mip ).r, + textureLod( samplerDepth, uv.zy, mip ).r, + textureLod( samplerDepth, uv.xw, mip ).r, + textureLod( samplerDepth, uv.zw, mip ).r, + }; + #if INVERSE + float minDepth = 1.0 - min(min(min(depths[0], depths[1]), depths[2]), depths[3]); + #else + float maxDepth = max(max(max(depths[0], depths[1]), depths[2]), depths[3]); + #endif + + instances[drawCommand.instanceID].bounds.padding1 = minZ; + instances[drawCommand.instanceID].bounds.padding2 = maxDepth; + + return minZ <= maxDepth; #endif } return visible; @@ -169,7 +277,11 @@ bool frustumCull( uint id ) { void main() { const uint gID = gl_GlobalInvocationID.x; if ( !(0 <= gID && gID < drawCommands.length()) ) return; - drawCommands[gID].instances = frustumCull( gID ) ? 1 : 0; + + bool visible = frustumCull( gID ); + if ( visible ) visible = occlusionCull( gID ); +// bool visible = occlusionCull( gID ); + drawCommands[gID].instances = visible ? 1 : 0; } diff --git a/bin/data/shaders/graph/occlusion/comp.glsl b/bin/data/shaders/graph/occlusion/comp.glsl deleted file mode 100644 index 9c7a35d9..00000000 --- a/bin/data/shaders/graph/occlusion/comp.glsl +++ /dev/null @@ -1,52 +0,0 @@ -#version 450 -#pragma shader_stage(compute) - -//#extension GL_EXT_nonuniform_qualifier : enable - -layout (constant_id = 0) const uint PASSES = 6; -layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; - -#define COMPUTE 1 - -#include "../../common/macros.h" -#include "../../common/structs.h" - -layout( push_constant ) uniform PushBlock { - uint pass; - uint passes; -} PushConstant; - -layout (binding = 0) uniform Camera { - Viewport viewport[PASSES]; -} camera; - -layout (std140, binding = 1) buffer DrawCommands { - DrawCommand drawCommands[]; -}; - -layout (std140, binding = 2) buffer Instances { - Instance instances[]; -}; - -layout (binding = 3) uniform sampler2D samplerID; -layout (binding = 4) uniform sampler2D samplerDepth; - -bool frustumCull( uint id ) { - if ( PushConstant.passes == 0 ) return true; - - const DrawCommand drawCommand = drawCommands[id]; - const Instance instance = instances[drawCommand.instanceID]; - - bool visible = true; - for ( uint pass = 0; pass < PushConstant.passes; ++pass ) { - mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model; - } - return visible; -} - -void main() { - const uint gID = gl_GlobalInvocationID.x; - if ( !(0 <= gID && gID < drawCommands.length()) ) return; - if ( drawCommands[gID].instances == 0 ) return; -// drawCommands[gID].instances = frustumCull( gID ) ? 1 : 0; -} \ No newline at end of file diff --git a/client/client/ext.cpp b/client/client/ext.cpp index 6cf5c260..e1ff9aae 100644 --- a/client/client/ext.cpp +++ b/client/client/ext.cpp @@ -168,9 +168,5 @@ void client::render() { } void client::terminate() { - /* Close Threads */ { - uf::thread::terminate(); - } - client::window.terminate(); } \ No newline at end of file diff --git a/client/main.cpp b/client/main.cpp index d20ab961..c727fc2f 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -77,7 +77,8 @@ int main(int argc, char** argv){ try { #endif if ( uf::renderer::settings::experimental::dedicatedThread /*&& !uf::renderer::states::rebuild*/ ) { - auto& thread = uf::thread::fetchWorker(); + // auto& thread = uf::thread::fetchWorker(); + auto& thread = uf::thread::get("Render"); uf::thread::queue(thread, [&]{ ext::render(); client::render(); @@ -88,14 +89,11 @@ int main(int argc, char** argv){ uf::thread::wait( thread ); } else { - // UF_TIMER_MULTITRACE_START("Frame Start"); client::tick(); ext::tick(); - // UF_TIMER_MULTITRACE("Ticked"); + ext::render(); client::render(); - // UF_TIMER_MULTITRACE("Rendered"); - // UF_TIMER_MULTITRACE_END("Frame End"); } #if UF_EXCEPTIONS } catch ( std::runtime_error& e ) { diff --git a/engine/inc/uf/engine/object/behaviors/render.h b/engine/inc/uf/engine/object/behaviors/render.h deleted file mode 100644 index aff0e282..00000000 --- a/engine/inc/uf/engine/object/behaviors/render.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace uf { - namespace RenderBehavior { - UF_BEHAVIOR_DEFINE_TYPE(); - UF_BEHAVIOR_DEFINE_TRAITS(); - UF_BEHAVIOR_DEFINE_FUNCTIONS(); - UF_BEHAVIOR_DEFINE_METADATA(); - } -} \ No newline at end of file diff --git a/engine/inc/uf/ext/ncurses/ncurses.h b/engine/inc/uf/ext/ncurses/ncurses.h deleted file mode 100644 index 86d210af..00000000 --- a/engine/inc/uf/ext/ncurses/ncurses.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include - -#if !UF_USE_NCURSES -#include - -namespace ext { - class UF_API Ncurses { - protected: - bool m_initialized; - bool m_initializeOnCtor = false; - void* m_window; - int m_timeout; - public: - // C-tor/D-tor - UF_API_CALL Ncurses(); - ~Ncurses(); - // On-demand C-tor/D-tor - void UF_API_CALL initialize(); - bool UF_API_CALL initialized(); - void UF_API_CALL terminate(); - // API (original named) - - void UF_API_CALL getYX(int& row, int& column); - void UF_API_CALL getMaxYX(int& row, int& column); - void UF_API_CALL move(int row, int column); - void UF_API_CALL move(int toRow, int toColumn, int& row, int& column); - - void UF_API_CALL refresh(); - void UF_API_CALL clrToEol(); - void UF_API_CALL clrToBot(); - - int UF_API_CALL getCh(); - void UF_API_CALL delCh(); - void UF_API_CALL addCh( char c ); - void UF_API_CALL addStr(const char* c_str); - void UF_API_CALL addStr(const uf::stl::string str); - - void UF_API_CALL attrOn(int att); - void UF_API_CALL attrOff(int att); - bool UF_API_CALL hasColors(); - bool UF_API_CALL startColor(); - void UF_API_CALL initPair( short id, short fore, short back ); - - // API (different named) - inline void UF_API_CALL clear(bool toBottom = true) { toBottom ? this->clrToBot() : this->clrToEol(); } - inline int UF_API_CALL getChar() { return this->getCh(); } - inline void UF_API_CALL delChar() { this->delCh(); } - inline void UF_API_CALL addChar( char c ) { this->addCh( c ); } - inline void UF_API_CALL addString( const uf::stl::string& str ) { this->addStr( str.c_str() ); } - inline void UF_API_CALL attribute(int att, bool on = true) { on ? this->attrOn(att) : this->attrOff(att); } - }; - extern UF_API ext::Ncurses ncurses; -} -#endif \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/buffer.h b/engine/inc/uf/ext/vulkan/buffer.h index bf650ab2..de906adf 100644 --- a/engine/inc/uf/ext/vulkan/buffer.h +++ b/engine/inc/uf/ext/vulkan/buffer.h @@ -76,6 +76,7 @@ namespace ext { Buffer buffer{}; size_t instanceID{}; + bool aliased = false; }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/shader.h b/engine/inc/uf/ext/vulkan/shader.h index 06d5e608..cca12b17 100644 --- a/engine/inc/uf/ext/vulkan/shader.h +++ b/engine/inc/uf/ext/vulkan/shader.h @@ -160,6 +160,10 @@ namespace ext { return updateStorage(name, (const void*) userdata, userdata.size() ); } + void setSpecializationConstants( const uf::stl::unordered_map& values ); + void setDescriptorCounts( const uf::stl::unordered_map& values ); + + /* uf::Serializer getUniformJson( const uf::stl::string& name, bool cache = true ); bool updateUniform( const uf::stl::string& name, const ext::json::Value& payload ); diff --git a/engine/inc/uf/ext/vulkan/texture.h b/engine/inc/uf/ext/vulkan/texture.h index c3cc7e80..e17a5f47 100644 --- a/engine/inc/uf/ext/vulkan/texture.h +++ b/engine/inc/uf/ext/vulkan/texture.h @@ -19,10 +19,10 @@ namespace ext { } filter; struct { VkSamplerAddressMode u = VK_SAMPLER_ADDRESS_MODE_REPEAT, v = VK_SAMPLER_ADDRESS_MODE_REPEAT, w = VK_SAMPLER_ADDRESS_MODE_REPEAT; - VkBool32 unnormalizedCoordinates = VK_FALSE; + bool unnormalizedCoordinates = VK_FALSE; } addressMode; struct { - VkBool32 compareEnable = VK_FALSE; + bool compareEnable = VK_FALSE; VkCompareOp compareOp = VK_COMPARE_OP_ALWAYS; VkSamplerMipmapMode mode = VK_SAMPLER_MIPMAP_MODE_LINEAR; float lodBias = 0.0f; @@ -30,9 +30,13 @@ namespace ext { float max = 0.0f; } mip; struct { - VkBool32 enabled = VK_TRUE; + bool enabled = VK_TRUE; float max = 16.0f; } anisotropy; + struct { + bool enabled = false; + VkSamplerReductionMode mode = {}; + } reduction; VkDescriptorImageInfo info; } descriptor = {}; diff --git a/engine/inc/uf/utils/math/vector.h b/engine/inc/uf/utils/math/vector.h index 8215edf2..a11e5af3 100644 --- a/engine/inc/uf/utils/math/vector.h +++ b/engine/inc/uf/utils/math/vector.h @@ -163,6 +163,8 @@ namespace uf { template pod::Vector& decode( const ext::json::Value& v, pod::Vector& ); // Parses a JSON value into a vector template pod::Vector decode( const ext::json::Value& v, const pod::Vector& = {} ); // Parses a JSON value into a vector + + template typename T::type_t /*UF_API*/ mips( const T& size ); // Calculate amount of mips to use given a size } } diff --git a/engine/inc/uf/utils/math/vector/pod.inl b/engine/inc/uf/utils/math/vector/pod.inl index 191ec6ba..7fdf6c10 100644 --- a/engine/inc/uf/utils/math/vector/pod.inl +++ b/engine/inc/uf/utils/math/vector/pod.inl @@ -463,13 +463,12 @@ T /*UF_API*/ uf::vector::cross( const T& a, const T& b ) { } template // Normalizes a vector uf::stl::string /*UF_API*/ uf::vector::toString( const T& v ) { - uint_fast8_t size = T::size; uf::stl::stringstream ss; ss << "Vector("; #pragma unroll // GCC unroll T::size - for ( auto i = 0; i < size; ++i ) { + for ( auto i = 0; i < T::size; ++i ) { ss << v[i]; - if ( i + 1 < size ) ss << ", "; + if ( i + 1 < T::size ) ss << ", "; } ss << ")"; return ss.str(); @@ -521,6 +520,15 @@ pod::Vector /*UF_API*/ uf::vector::decode( const ext::json::Value& json, co } return v; } + +template +typename T::type_t /*UF_API*/ uf::vector::mips( const T& size ) { + typename T::type_t max = 0; + #pragma unroll // GCC unroll T::size + for ( auto i = 0; i < T::size; ++i ) max = std::max(max, size[i]); + return static_cast(std::floor(std::log2(max))) + 1; +} + #if !__clang__ && __GNUC__ #pragma GCC pop_options #endif \ No newline at end of file diff --git a/engine/inc/uf/utils/mesh/mesh.h b/engine/inc/uf/utils/mesh/mesh.h index 5478b61c..ffe49bee 100644 --- a/engine/inc/uf/utils/mesh/mesh.h +++ b/engine/inc/uf/utils/mesh/mesh.h @@ -296,7 +296,7 @@ namespace ext { uint32_t renderTarget = 0; uint32_t subpass = 0; - + uint32_t aux = 0; struct { size_t width = 1; diff --git a/engine/src/engine/entity/entity.cpp b/engine/src/engine/entity/entity.cpp index 32a92286..852dd512 100644 --- a/engine/src/engine/entity/entity.cpp +++ b/engine/src/engine/entity/entity.cpp @@ -133,7 +133,7 @@ uf::Entity* uf::Entity::globalFindByUid( size_t uid ) { } { auto& scene = uf::scene::getCurrentScene(); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); for ( uf::Entity* entity : graph ) { if ( entity->getUid() == uid ) return entity; } @@ -148,7 +148,7 @@ uf::Entity* uf::Entity::globalFindByName( const uf::stl::string& name ) { } { auto& scene = uf::scene::getCurrentScene(); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); for ( uf::Entity* entity : graph ) { if ( entity->getName() == name ) return entity; } diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index 4aa0defa..a76aa0e6 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -195,11 +195,9 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() ); #if UF_USE_VULKAN uint32_t maxPasses = 6; - uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; - for ( auto pair : shader.metadata.definitions.specializationConstants ) { - auto& sc = pair.second; - if ( sc.name == "PASSES" ) sc.value.ui = (specializationConstants[sc.index] = maxPasses); - } + shader.setSpecializationConstants({ + { "PASSES", maxPasses } + }); #endif } { @@ -214,19 +212,12 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M #if UF_USE_VULKAN uint32_t maxTextures = graph.textures.size(); // texture2Ds; - - 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] = maxTextures); - } - 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 = maxTextures; - } - } + shader.setSpecializationConstants({ + { "TEXTURES", maxTextures }, + }); + shader.setDescriptorCounts({ + { "samplerTextures", maxTextures }, + }); #endif } #if UF_USE_VULKAN @@ -253,7 +244,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M shader.buffers.emplace_back( indirect->alias() ); shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); - shader.aliasAttachment("depth"); + shader.aliasAttachment("depthPyramid"); } } if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) { @@ -268,21 +259,15 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "depth"); graphic.material.metadata.autoInitializeUniformBuffers = true; { - uint32_t maxTextures = graph.textures.size(); // texture2Ds; - auto& shader = graphic.material.getShader("fragment", "depth"); - 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] = maxTextures); - } - 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 = maxTextures; - } - } + + uint32_t maxTextures = graph.textures.size(); // texture2Ds; + shader.setSpecializationConstants({ + { "TEXTURES", maxTextures }, + }); + shader.setDescriptorCounts({ + { "samplerTextures", maxTextures }, + }); shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); @@ -320,23 +305,17 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M uint32_t maxCascades = texture3Ds / voxelTypes; auto& shader = graphic.material.getShader("fragment", uf::renderer::settings::pipelines::names::vxgi); - 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] = maxTextures); - 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 = maxTextures; - 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; - } - } + shader.setSpecializationConstants({ + { "TEXTURES", maxTextures }, + { "CASCADES", maxCascades }, + }); + shader.setDescriptorCounts({ + { "samplerTextures", maxTextures }, + { "voxelId", maxCascades }, + { "voxelUv", maxCascades }, + { "voxelNormal", maxCascades }, + { "voxelRadiance", maxCascades }, + }); shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); @@ -353,6 +332,11 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M uf::stl::string vertexShaderFilename = uf::io::resolveURI("/graph/baking/vert.spv"); uf::stl::string geometryShaderFilename = uf::io::resolveURI("/graph/baking/geom.spv"); uf::stl::string fragmentShaderFilename = uf::io::resolveURI("/graph/baking/frag.spv"); + std::pair settings[] = { + { uf::renderer::settings::pipelines::rt, "rt.frag" }, + }; + FOR_ARRAY(settings) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second ); + graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "baking"); // graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking"); graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "baking"); @@ -362,11 +346,9 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M uint32_t maxPasses = 6; auto& shader = graphic.material.getShader("vertex", "baking"); - uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; - for ( auto pair : shader.metadata.definitions.specializationConstants ) { - auto& sc = pair.second; - if ( sc.name == "PASSES" ) sc.value.ui = (specializationConstants[sc.index] = maxPasses); - } + shader.setSpecializationConstants({ + { "PASSES", maxPasses }, + }); // shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() ); // shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); @@ -383,20 +365,14 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as(128); auto& shader = graphic.material.getShader("fragment", "baking"); - 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] = maxTextures); - else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxCubemaps); - } - 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 = maxTextures; - else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxCubemaps; - } - } + shader.setSpecializationConstants({ + { "TEXTURES", maxTextures }, + { "CUBEMAPS", maxCubemaps }, + }); + shader.setDescriptorCounts({ + { "samplerTextures", maxTextures }, + { "samplerCubemaps", maxCubemaps }, + }); shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() ); @@ -457,9 +433,6 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M } #endif -// uf::instantiator::bind( "GraphBehavior", entity ); -// uf::instantiator::unbind( "RenderBehavior", entity ); - graphic.process = true; } @@ -1167,7 +1140,6 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) } } if ( (graph.metadata["renderer"]["separate"].as()) && graph.metadata["renderer"]["render"].as() ) { - // uf::instantiator::bind("RenderBehavior", entity); uf::graph::initializeGraphics( graph, entity, mesh ); } diff --git a/engine/src/engine/object/behaviors/graph.cpp b/engine/src/engine/object/behaviors/graph.cpp index 8efd8ea2..61bda47d 100644 --- a/engine/src/engine/object/behaviors/graph.cpp +++ b/engine/src/engine/object/behaviors/graph.cpp @@ -50,153 +50,8 @@ void uf::GraphBehavior::initialize( uf::Object& self ) { }); } void uf::GraphBehavior::destroy( uf::Object& self ) {} -void uf::GraphBehavior::tick( uf::Object& self ) { -#if 0 - if ( this->hasComponent() ) { - auto& graph = this->getComponent(); - uf::graph::update( graph ); - } - /* Update animations */ if ( this->hasComponent() ) { - auto& graph = this->getComponent(); - // if ( graph.metadata["renderer"]["skinned"].as() ) uf::graph::update( graph ); - } - - if ( !this->hasComponent() ) return; - - const auto& scene = uf::scene::getCurrentScene(); - const auto& metadata = this->getComponent(); - const auto& graphic = this->getComponent(); - const auto& controller = scene.getController(); - const auto& camera = controller.getComponent(); - const auto& transform = this->getComponent>(); - - if ( !graphic.initialized ) return; - - const auto* objectWithGraph = this; - while ( objectWithGraph != &scene ) { - if ( objectWithGraph->hasComponent() ) break; - objectWithGraph = &objectWithGraph->getParent().as(); - } - if ( !objectWithGraph->hasComponent() ) return; - auto& graph = objectWithGraph->getComponent(); - -#if UF_USE_OPENGL - if ( graphic.material.hasShader("vertex") ) { - auto& shader = graphic.material.getShader("vertex"); - auto& mesh = this->getComponent(); - - if ( !(graph.metadata["renderer"]["separate"].as()) ) { - uf::stl::vector instances( graph.nodes.size() ); - for ( size_t i = 0; i < graph.nodes.size(); ++i ) { - auto& node = graph.nodes[i]; - instances[i] = uf::transform::model( node.entity ? node.entity->getComponent>() : node.transform ); - } - shader.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance ); - shader.execute( graphic, mesh.attributes.vertex.pointer ); - } else if ( graph.metadata["renderer"]["skinned"].as() ) { - shader.execute( graphic, mesh.attributes.vertex.pointer ); - } - } -#elif UF_USE_VULKAN - if ( graphic.material.hasShader("vertex") ) { - auto& shader = graphic.material.getShader("vertex"); - - if ( !(graph.metadata["renderer"]["separate"].as()) ) { - uf::stl::vector instances( graph.nodes.size() ); - for ( size_t i = 0; i < graph.nodes.size(); ++i ) { - auto& node = graph.nodes[i]; - instances[i] = uf::transform::model( node.entity ? node.entity->getComponent>() : node.transform ); - } - shader.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance /*storageBuffer*/ ); - } else { - struct UniformDescriptor { - pod::Matrix4f model; - }; - #if UF_UNIFORMS_REUSE - auto& uniform = shader.getUniform("UBO"); - auto& uniforms = uniform.get(); - uniforms = { - .model = uf::transform::model( transform ); - // .color = uf::vector::decode( metadata["color"], pod::Vector4f{1,1,1,1} ), - }; - shader.updateUniform( "UBO", uniform ); - #else - UniformDescriptor uniforms = { - .model = uf::transform::model( transform ), - // .color = uf::vector::decode( metadata["color"], pod::Vector4f{1,1,1,1} ), - }; - shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") ); - #endif - } - } -#if 0 - if ( graphic.material.hasShader("vertex") && !(graph.metadata["renderer"]["separate"].as()) ) { - auto& shader = graphic.material.getShader("vertex"); - uf::stl::vector instances( graph.nodes.size() ); - for ( size_t i = 0; i < graph.nodes.size(); ++i ) { - auto& node = graph.nodes[i]; - instances[i] = node.entity ? uf::transform::model( node.entity->getComponent>() ) : uf::transform::model( node.transform ); - } - auto& storageBuffer = *graphic.getStorageBuffer("Models"); - shader.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance /*storageBuffer*/ ); - } -#endif -#endif -#endif -} -void uf::GraphBehavior::render( uf::Object& self ) { -#if 0 - /* Update uniforms */ - if ( !this->hasComponent() ) return; - - const auto& scene = uf::scene::getCurrentScene(); - const auto& metadata = this->getComponent(); - const auto& graphic = this->getComponent(); - const auto& controller = scene.getController(); - const auto& camera = controller.getComponent(); - const auto& transform = this->getComponent>(); - - if ( !graphic.initialized ) return; - -#if UF_USE_OPENGL - const auto* objectWithGraph = this; - while ( objectWithGraph != &scene ) { - if ( objectWithGraph->hasComponent() ) break; - objectWithGraph = &objectWithGraph->getParent().as(); - } - if ( !objectWithGraph->hasComponent() ) return; - auto& graph = objectWithGraph->getComponent(); -#if UF_UNIFORMS_REUSE - auto uniforms = graphic.getUniform(); - pod::Uniform& uniform = *((pod::Uniform*) graphic.device->getBuffer(uniforms.buffer)); - uniform = { - .modelView = !(graph.metadata["renderer"]["separate"].as()) ? camera.getView() : camera.getView() * uf::transform::model( transform ), - .projection = camera.getProjection(); - }; - graphic.updateUniform( (const void*) &uniform, sizeof(uniform) ); -#else - pod::Uniform uniform = { - .modelView = !(graph.metadata["renderer"]["separate"].as()) ? camera.getView() : camera.getView() * uf::transform::model( transform ), - .projection = camera.getProjection(), - }; - graphic.updateUniform( (const void*) &uniform, sizeof(uniform) ); -#endif -#elif UF_USE_VULKAN - if ( graphic.material.hasShader("vertex") ) { - auto& shader = graphic.material.getShader("vertex"); - #if UF_UNIFORMS_REUSE - auto& uniform = shader.getUniform("Camera"); - auto& uniforms = uniform.get(); - uniforms = camera.data().viewport; - shader.updateUniform("Camera", uniform); - #else - pod::Camera::Viewports uniforms = camera.data().viewport; - shader.updateBuffer( uniforms, shader.getUniformBuffer("Camera") ); - #endif - } -#endif -#endif -} +void uf::GraphBehavior::tick( uf::Object& self ) {} +void uf::GraphBehavior::render( uf::Object& self ) {} void uf::GraphBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {} void uf::GraphBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) {} #undef this \ No newline at end of file diff --git a/engine/src/engine/object/behaviors/render.cpp b/engine/src/engine/object/behaviors/render.cpp deleted file mode 100644 index 1be1f05f..00000000 --- a/engine/src/engine/object/behaviors/render.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define UF_UNIFORMS_UPDATE_WITH_JSON 0 - -UF_BEHAVIOR_REGISTER_CPP(uf::RenderBehavior) -UF_BEHAVIOR_TRAITS_CPP(uf::RenderBehavior, ticks = false, renders = false, multithread = false) -#define this (&self) -void uf::RenderBehavior::initialize( uf::Object& self ) {} -void uf::RenderBehavior::tick( uf::Object& self ) { -#if 0 - if ( !this->hasComponent() ) return; - const auto& metadata = this->getComponent(); - const auto& scene = uf::scene::getCurrentScene(); - const auto& graphic = this->getComponent(); - const auto& transform = this->getComponent>(); - const auto& controller = scene.getController(); - const auto& camera = controller.getComponent(); - - if ( !graphic.initialized ) return; -#if UF_USE_OPENGL -/* - auto uniformBuffer = graphic.getUniform(); - pod::Uniform& uniform = *((pod::Uniform*) uf::renderer::device.getBuffer(uniformBuffer.buffer)); - uniform.projection = camera.getProjection(); - uniform.modelView = camera.getView(); // * uf::transform::model( transform ); - graphic.updateUniform( &uniform, sizeof(uniform) ); -*/ -#elif UF_USE_VULKAN - if ( graphic.material.hasShader("vertex") ) { - auto& shader = graphic.material.getShader("vertex"); - auto& uniform = shader.getUniform("UBO"); - - #if UF_UNIFORMS_UPDATE_WITH_JSON - // auto uniforms = shader.getUniformJson("UBO"); - ext::json::Value uniforms; - uniforms["model"] = uf::matrix::encode( uf::transform::model( transform ) ); - // uniforms["colors"] = metadata["color"]; - shader.updateUniform("UBO", uniforms ); - #else - struct UniformDescriptor { - pod::Matrix4f model; - }; - #if UF_UNIFORMS_REUSE - auto& uniforms = uniform.get(); - uniforms = { - .model = uf::transform::model( transform ); - // .color = uf::vector::decode( metadata["color"], pod::Vector4f{ 1, 1, 1, 1 } ), - }; - shader.updateUniform( "UBO", uniform ); - #else - UniformDescriptor uniforms = { - .model = uf::transform::model( transform ), - // .color = uf::vector::decode( metadata["color"], pod::Vector4f{ 1, 1, 1, 1 } ), - }; - shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") ); - #endif - #endif - } -#endif -#endif -} -void uf::RenderBehavior::render( uf::Object& self ) { -#if 0 - if ( !this->hasComponent() ) return; - const auto& metadata = this->getComponent(); - const auto& scene = uf::scene::getCurrentScene(); - const auto& graphic = this->getComponent(); - const auto& transform = this->getComponent>(); - const auto& controller = scene.getController(); - const auto& camera = controller.getComponent(); - - if ( !graphic.initialized ) return; -#if UF_USE_OPENGL -#if UF_UNIFORMS_REUSE - auto uniforms = graphic.getUniform(); - pod::Uniform& uniform = *((pod::Uniform*) uf::renderer::device.getBuffer(uniforms.buffer)); - uniform = { - .modelView = camera.getView() * uf::transform::model( transform ), - .projection = camera.getProjection(), - }; - graphic.updateUniform( &uniform, sizeof(uniform) ); -#else - pod::Uniform uniform = { - .modelView = camera.getView() * uf::transform::model( transform ), - .projection = camera.getProjection(), - }; - graphic.updateUniform( &uniform, sizeof(uniform) ); -#endif -#elif UF_USE_VULKAN - if ( graphic.material.hasShader("vertex") ) { - auto& shader = graphic.material.getShader("vertex"); - auto& uniform = shader.getUniform("Camera"); - - #if UF_UNIFORMS_UPDATE_WITH_JSON - // auto uniforms = shader.getUniformJson("Camera"); - ext::json::Value uniforms; - ext::json::reserve( uniforms["viewport"], uf::camera::maxViews ); - for ( uint_fast8_t i = 0; i < uf::camera::maxViews; ++i ) { - uniforms["viewport"][i]["view"] = uf::matrix::encode( camera.getView( i ) ); - uniforms["viewport"][i]["projection"] = uf::matrix::encode( camera.getProjection( i ) ); - } - shader.updateUniform("Camera", uniforms); - #else - #if UF_UNIFORMS_REUSE - auto& uniforms = uniform.get(); - uniforms = camera.data().viewport; - shader.updateUniform("Camera", uniform); - #else - pod::Camera::Viewports uniforms = camera.data().viewport; - shader.updateBuffer( uniforms, shader.getUniformBuffer("Camera") ); - #endif - #endif - } -#endif -#endif -} -void uf::RenderBehavior::destroy( uf::Object& self ) {} -void uf::RenderBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {} -void uf::RenderBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) {} -#undef this \ No newline at end of file diff --git a/engine/src/engine/scene/scene.cpp b/engine/src/engine/scene/scene.cpp index 934e52ae..5e1dc759 100644 --- a/engine/src/engine/scene/scene.cpp +++ b/engine/src/engine/scene/scene.cpp @@ -15,6 +15,7 @@ uf::Scene::Scene() UF_BEHAVIOR_ENTITY_CPP_ATTACH(uf::Scene) #define UF_SCENE_GLOBAL_GRAPH 1 #define UF_TICK_MULTITHREAD_OVERRIDE 0 #define UF_TICK_FROM_TASKS 1 +#define UF_SCENE_INVALIDATE_IMMEDIATE 1 #if UF_SCENE_GLOBAL_GRAPH namespace { @@ -61,20 +62,27 @@ void uf::Scene::invalidateGraph() { auto& metadata = this->getComponent(); #endif metadata.invalidationQueued = true; +/* metadata.cache.clear(); metadata.tasks.serial.clear(); metadata.tasks.parallel.clear(); + + metadata.graph.clear(); +*/ } const uf::stl::vector& uf::Scene::getGraph() { #if !UF_SCENE_GLOBAL_GRAPH auto& metadata = this->getComponent(); #endif +#if UF_SCENE_INVALIDATE_IMMEDIATE if ( metadata.invalidationQueued ) { metadata.invalidationQueued = false; + metadata.cache.clear(); metadata.graph.clear(); metadata.tasks.serial.clear(); metadata.tasks.parallel.clear(); } +#endif if ( !metadata.graph.empty() ) return metadata.graph; metadata.tasks.serial = uf::thread::schedule(false); @@ -89,7 +97,7 @@ const uf::stl::vector& uf::Scene::getGraph() { #if UF_TICK_FROM_TASKS auto* self = (uf::Object*) entity; - auto& behaviorGraph = entity->getGraph(); + auto/*&*/ behaviorGraph = entity->getGraph(); #if 1 #if UF_TICK_MULTITHREAD_OVERRIDE for ( auto fun : behaviorGraph.tick.serial ) metadata.tasks.parallel.queue([=]{ fun(*self); }); @@ -124,7 +132,7 @@ const uf::stl::vector& uf::Scene::getGraph() { return metadata.graph; } uf::stl::vector uf::Scene::getGraph( bool reverse ) { - auto graph = this->getGraph(); + auto/*&*/ graph = this->getGraph(); if ( reverse ) std::reverse( graph.begin(), graph.end() ); return graph; } @@ -160,7 +168,7 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::Serializ void uf::scene::unloadScene() { uf::Scene* current = uf::scene::scenes.back(); // current->destroy(); - auto graph = current->getGraph(true); + auto/*&*/ graph = current->getGraph(true); for ( auto entity : graph ) entity->destroy(); uf::scene::scenes.pop_back(); } @@ -176,11 +184,20 @@ void uf::scene::invalidateGraphs() { void uf::scene::tick() { if ( scenes.empty() ) return; +#if !UF_SCENE_INVALIDATE_IMMEDIATE + if ( metadata.invalidationQueued ) { + metadata.invalidationQueued = false; + metadata.graph.clear(); + metadata.tasks.serial.clear(); + metadata.tasks.parallel.clear(); + } +#endif + auto& scene = uf::scene::getCurrentScene(); #if !UF_SCENE_GLOBAL_GRAPH auto& metadata = scene.getComponent(); #endif - auto graph = scene.getGraph(true); + auto/*&*/ graph = scene.getGraph(true); #if UF_TICK_FROM_TASKS // copy because executing from the tasks erases them all auto tasks = metadata.tasks; @@ -194,7 +211,8 @@ void uf::scene::tick() { } void uf::scene::render() { if ( scenes.empty() ) return; - auto graph = uf::scene::getCurrentScene().getGraph(true); + auto& scene = uf::scene::getCurrentScene(); + auto/*&*/ graph = scene.getGraph(true); for ( auto entity : graph ) entity->render(); } void uf::scene::destroy() { diff --git a/engine/src/ext/opengl/rendermode.cpp b/engine/src/ext/opengl/rendermode.cpp index 62a5bf2d..51fa8494 100644 --- a/engine/src/ext/opengl/rendermode.cpp +++ b/engine/src/ext/opengl/rendermode.cpp @@ -59,7 +59,7 @@ void ext::opengl::RenderMode::createCommandBuffers() { uf::stl::vector graphics; auto& scene = uf::scene::getCurrentScene(); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; ext::opengl::Graphic& graphic = entity->getComponent(); @@ -89,7 +89,7 @@ void ext::opengl::RenderMode::bindPipelines() { uf::stl::vector graphics; auto& scene = uf::scene::getCurrentScene(); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; ext::opengl::Graphic& graphic = entity->getComponent(); diff --git a/engine/src/ext/opengl/texture.cpp b/engine/src/ext/opengl/texture.cpp index 48bcc535..dceb3df1 100644 --- a/engine/src/ext/opengl/texture.cpp +++ b/engine/src/ext/opengl/texture.cpp @@ -220,7 +220,7 @@ void ext::opengl::Texture::fromBuffers( if ( this->mips == 0 ) { this->mips = 1; } else if ( this->depth == 1 ) { - this->mips = static_cast(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1; + this->mips = uf::vector::mips( pod::Vector2ui{ texWidth, texHeight, texDepth } ); } if ( this->mips > 1 ) { diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index eefe1b41..c889eb06 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -458,10 +458,16 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescrip for ( auto* shader : shaders ) { if ( shader->descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue; auto& localSize = shader->metadata.definitions.localSize; + auto dispatch = pod::Vector3ui{ + std::ceil( (float) width / localSize.x ), + std::ceil( (float) height / localSize.y ), + std::ceil( (float) depth / localSize.z ), + }; + vkCmdDispatch(commandBuffer, - 1 < localSize.x ? ((width / localSize.x) + 1) : 1, - 1 < localSize.y ? ((height / localSize.y) + 1) : 1, - 1 < localSize.z ? ((depth / localSize.z) + 1) : 1 + dispatch.x, + dispatch.y, + dispatch.z ); } } @@ -480,6 +486,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip auto shaders = getShaders( graphic.material.shaders ); uf::stl::vector writeDescriptorSets; + uf::stl::vector tlases; struct Infos { uf::stl::vector uniform; @@ -646,14 +653,25 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip } if ( !graphic.accelerationStructures.tops.empty() ) { - infos.accelerationStructure.emplace_back(graphic.accelerationStructures.tops[0].buffer.descriptor); + auto tlas = graphic.accelerationStructures.tops.front(); + if ( tlas.handle != VK_NULL_HANDLE ) tlases.emplace_back(tlas); } - for ( auto& info : infos.accelerationStructure ) { + if ( infos.accelerationStructure.empty() ) { + uf::stl::string renderModeName = uf::renderer::hasRenderMode("Compute:RT", true) ? "Compute:RT" : ""; + auto& blitter = *(uf::renderer::getRenderMode(renderModeName, true).getBlitter()); + if ( !blitter.accelerationStructures.tops.empty() ) { + tlases.emplace_back(blitter.accelerationStructures.tops.front()); + } + } + + for ( auto& tlas : tlases ) { + infos.accelerationStructure.emplace_back(tlas.buffer.descriptor); + auto& descriptorAccelerationStructureInfo = infos.accelerationStructureInfos.emplace_back(); descriptorAccelerationStructureInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; descriptorAccelerationStructureInfo.accelerationStructureCount = 1; - descriptorAccelerationStructureInfo.pAccelerationStructures = &graphic.accelerationStructures.tops[infos.accelerationStructureInfos.size()-1].handle; + descriptorAccelerationStructureInfo.pAccelerationStructures = &tlas.handle; } auto uniformBufferInfo = infos.uniform.begin(); @@ -1958,11 +1976,13 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD void ext::vulkan::Graphic::destroy() { if ( device ) { for ( auto& as : accelerationStructures.bottoms ) { + if ( as.aliased ) continue; uf::renderer::vkDestroyAccelerationStructureKHR(*device, as.handle, nullptr); } accelerationStructures.bottoms.clear(); for ( auto& as : accelerationStructures.tops ) { + if ( as.aliased ) continue; uf::renderer::vkDestroyAccelerationStructureKHR(*device, as.handle, nullptr); } accelerationStructures.tops.clear(); @@ -1996,69 +2016,8 @@ void ext::vulkan::GraphicDescriptor::parse( ext::json::Value& metadata ) { } ext::vulkan::GraphicDescriptor::hash_t ext::vulkan::GraphicDescriptor::hash() const { size_t seed{}; -#if 0 - for ( auto i = 0; i < inputs.vertex.attributes.size(); ++i ) { - uf::hash( inputs.vertex.attributes[i].descriptor.format ); - uf::hash( inputs.vertex.attributes[i].descriptor.offset ); - } - for ( auto i = 0; i < inputs.index.attributes.size(); ++i ) { - uf::hash( inputs.index.attributes[i].descriptor.format ); - uf::hash( inputs.index.attributes[i].descriptor.offset ); - } - for ( auto i = 0; i < inputs.instance.attributes.size(); ++i ) { - uf::hash( inputs.instance.attributes[i].descriptor.format ); - uf::hash( inputs.instance.attributes[i].descriptor.offset ); - } - for ( auto i = 0; i < inputs.indirect.attributes.size(); ++i ) { - uf::hash( inputs.indirect.attributes[i].descriptor.format ); - uf::hash( inputs.indirect.attributes[i].descriptor.offset ); - } -#endif - uf::hash( seed, subpass, renderMode, renderTarget, pipeline, topology, cullMode, fill, lineWidth, frontFace, depth.test, depth.write, depth.operation, depth.bias.enable, depth.bias.constant, depth.bias.slope, depth.bias.clamp ); + uf::hash( seed, aux, subpass, renderMode, renderTarget, pipeline, topology, cullMode, fill, lineWidth, frontFace, depth.test, depth.write, depth.operation, depth.bias.enable, depth.bias.constant, depth.bias.slope, depth.bias.clamp ); return seed; -#if 0 - - hash += std::hash{}(subpass); - if ( settings::invariant::individualPipelines ) - hash += std::hash{}(renderMode); - - hash += std::hash{}(renderTarget); - hash += std::hash{}(pipeline); - - for ( auto i = 0; i < inputs.vertex.attributes.size(); ++i ) { - hash += std::hash{}(inputs.vertex.attributes[i].descriptor.format); - hash += std::hash{}(inputs.vertex.attributes[i].descriptor.offset); - } - for ( auto i = 0; i < inputs.index.attributes.size(); ++i ) { - hash += std::hash{}(inputs.index.attributes[i].descriptor.format); - hash += std::hash{}(inputs.index.attributes[i].descriptor.offset); - } - for ( auto i = 0; i < inputs.instance.attributes.size(); ++i ) { - hash += std::hash{}(inputs.instance.attributes[i].descriptor.format); - hash += std::hash{}(inputs.instance.attributes[i].descriptor.offset); - } -/* - for ( auto i = 0; i < inputs.indirect.attributes.size(); ++i ) { - hash += std::hash{}(inputs.indirect.attributes[i].descriptor.format); - hash += std::hash{}(inputs.indirect.attributes[i].descriptor.offset); - } -*/ - - hash += std::hash{}(topology); - hash += std::hash{}(cullMode); - hash += std::hash{}(fill); - hash += std::hash{}(lineWidth); - hash += std::hash{}(frontFace); - hash += std::hash{}(depth.test); - hash += std::hash{}(depth.write); - hash += std::hash{}(depth.operation); - hash += std::hash{}(depth.bias.enable); - hash += std::hash{}(depth.bias.constant); - hash += std::hash{}(depth.bias.slope); - hash += std::hash{}(depth.bias.clamp); - - return hash; -#endif } #endif \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index e577c742..bc08ec2f 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -211,7 +211,7 @@ void ext::vulkan::RenderMode::createCommandBuffers() { uf::stl::vector graphics; auto& scene = uf::scene::getCurrentScene(); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; ext::vulkan::Graphic& graphic = entity->getComponent(); @@ -284,7 +284,7 @@ void ext::vulkan::RenderMode::bindPipelines() { uf::stl::vector graphics; auto& scene = uf::scene::getCurrentScene(); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; ext::vulkan::Graphic& graphic = entity->getComponent(); diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index df6c3d47..bba82d90 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -23,6 +23,8 @@ namespace { const uf::stl::string DEFERRED_MODE = "compute"; + ext::vulkan::Texture depthPyramid; + uf::stl::vector depthPyramidViews; } #include "./transition.inl" @@ -50,10 +52,10 @@ void ext::vulkan::DeferredRenderMode::initialize( 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; + size_t depthPyramid; } attachments = {}; bool blend = true; // !ext::vulkan::settings::invariant::deferredSampling; @@ -99,6 +101,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { /*.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, + //*.mips = */1, }); // output buffers attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{ @@ -130,6 +133,14 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { /*.blend = */false, /*.samples = */1, }); + attachments.depthPyramid = renderTarget.attach(RenderTarget::Attachment::Descriptor{ + /*.format = */VK_FORMAT_R32_SFLOAT, + /*.layout = */ VK_IMAGE_LAYOUT_GENERAL, + /*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + /*.blend = */false, + /*.samples = */1, + /*.mips = */1 + }); metadata.attachments["id"] = attachments.id; @@ -143,6 +154,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { #endif metadata.attachments["depth"] = attachments.depth; + metadata.attachments["depthPyramid"] = attachments.depthPyramid; metadata.attachments["color"] = attachments.color; metadata.attachments["bright"] = attachments.bright; metadata.attachments["scratch"] = attachments.scratch; @@ -224,22 +236,13 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { {uf::io::resolveURI(vertexShaderFilename), uf::renderer::enums::Shader::VERTEX}, {uf::io::resolveURI(fragmentShaderFilename), uf::renderer::enums::Shader::FRAGMENT} }); - } - if ( blitter.material.hasShader("fragment") ) { auto& shader = blitter.material.getShader("fragment"); 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"; { @@ -267,19 +270,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { blitter.material.attachShader(uf::io::resolveURI(fragmentShaderFilename), uf::renderer::enums::Shader::FRAGMENT, "deferred"); UF_MSG_DEBUG("Using deferred shader: {}", fragmentShaderFilename); } - } - - if ( settings::pipelines::bloom ) { - uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/bloom/comp.spv"); - blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "bloom"); - auto& shader = blitter.material.getShader("compute", "bloom"); - shader.aliasAttachment("color", this, VK_IMAGE_LAYOUT_GENERAL); - shader.aliasAttachment("bright", this, VK_IMAGE_LAYOUT_GENERAL); - shader.aliasAttachment("scratch", this, VK_IMAGE_LAYOUT_GENERAL); - } - - if ( settings::pipelines::deferred ) { auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred"); size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(512); @@ -288,6 +279,20 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as(128); size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(16); + shader.setSpecializationConstants({ + { "TEXTURES", maxTextures2D }, + { "CUBEMAPS", maxTexturesCube }, + { "CASCADES", maxCascades }, + }); + shader.setDescriptorCounts({ + { "samplerTextures", maxTextures2D }, + { "samplerCubemaps", maxTexturesCube }, + { "voxelId", maxCascades }, + { "voxelUv", maxCascades }, + { "voxelNormal", maxCascades }, + { "voxelRadiance", maxCascades }, + }); + // shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() ); // shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() ); shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); @@ -297,46 +302,6 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); - if ( ext::vulkan::settings::pipelines::vxgi ) { - 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; - } - } - } else { - 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); - } - 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; - } - } - } - } - - if ( settings::pipelines::deferred && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) { - auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred"); shader.aliasAttachment("id", this); #if BARYCENTRIC #if !BARYCENTRIC_CALCULATE @@ -352,7 +317,78 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { shader.aliasAttachment("bright", this, VK_IMAGE_LAYOUT_GENERAL); shader.aliasAttachment("motion", this, VK_IMAGE_LAYOUT_GENERAL); } + + if ( settings::pipelines::bloom ) { + uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/bloom/comp.spv"); + blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "bloom"); + auto& shader = blitter.material.getShader("compute", "bloom"); + shader.aliasAttachment("color", this, VK_IMAGE_LAYOUT_GENERAL); + shader.aliasAttachment("bright", this, VK_IMAGE_LAYOUT_GENERAL); + shader.aliasAttachment("scratch", this, VK_IMAGE_LAYOUT_GENERAL); + } + + if ( settings::pipelines::culling ) { + uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/depth-pyramid/comp.spv"); + blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "depth-pyramid"); + + auto& shader = blitter.material.getShader("compute", "depth-pyramid"); + auto attachment = this->getAttachment("depth"); + auto mips = uf::vector::mips( pod::Vector2ui{ width, height } ); + shader.setSpecializationConstants({ + { "MIPS", mips - 1 }, + }); + shader.setDescriptorCounts({ + { "inImage", mips - 1 }, + { "outImage", mips - 1 }, + }); + + shader.aliasAttachment("depth", this); + + ext::vulkan::Texture2D source; source.aliasAttachment( this->getAttachment("depthPyramid") ); + source.sampler.descriptor.reduction.enabled = true; + source.sampler.descriptor.reduction.mode = VK_SAMPLER_REDUCTION_MODE_MIN; + + for ( auto& view : ::depthPyramidViews ) { + vkDestroyImageView(device.logicalDevice, view, nullptr); + } + ::depthPyramidViews.clear(); + ::depthPyramidViews.resize(mips-1); + shader.textures.clear(); + + for ( auto i = 1; i < mips; ++i ) { + auto& view = ::depthPyramidViews[i-1]; + VkImageViewCreateInfo viewCreateInfo = {}; + viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewCreateInfo.pNext = NULL; + viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; + viewCreateInfo.subresourceRange.baseMipLevel = i; + viewCreateInfo.subresourceRange.layerCount = 1; + viewCreateInfo.subresourceRange.levelCount = 1; + viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewCreateInfo.viewType = source.viewType; + viewCreateInfo.format = source.format; + viewCreateInfo.image = source.image; + VK_CHECK_RESULT(vkCreateImageView(device.logicalDevice, &viewCreateInfo, nullptr, &view)); + + if ( i + 1 < mips ) { + auto& texture = shader.textures.emplace_back(); + texture.aliasTexture( source ); + texture.view = view; + texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + texture.updateDescriptors(); + } + } + for ( auto i = 1; i < mips; ++i ) { + auto& view = ::depthPyramidViews[i-1]; + auto& texture = shader.textures.emplace_back(); + texture.aliasTexture( source ); + texture.view = view; + texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + texture.updateDescriptors(); + } + } + if ( !blitter.hasPipeline( blitter.descriptor ) ){ blitter.initializePipeline( blitter.descriptor ); } @@ -386,6 +422,16 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { blitter.initializePipeline( descriptor ); } } + + if ( settings::pipelines::culling ) { + descriptor.aux = uf::vector::mips( pod::Vector2ui{ width, height } ); + descriptor.pipeline = "depth-pyramid"; + descriptor.subpass = 0; + descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE; + if ( !blitter.hasPipeline( descriptor ) ) { + blitter.initializePipeline( descriptor ); + } + } } } } @@ -395,22 +441,78 @@ 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; + 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; rebuild = true; renderTarget.initialize( *renderTarget.device ); + + if ( settings::pipelines::culling ) { + auto& shader = blitter.material.getShader("compute", "depth-pyramid"); + auto attachment = this->getAttachment("depth"); + auto mips = uf::vector::mips( pod::Vector2ui{ width, height } ); + shader.setSpecializationConstants({ + { "MIPS", mips - 1 }, + }); + shader.setDescriptorCounts({ + { "inImage", mips - 1 }, + { "outImage", mips - 1 }, + }); + + ext::vulkan::Texture2D source; source.aliasAttachment( this->getAttachment("depthPyramid") ); + source.sampler.descriptor.reduction.enabled = true; + source.sampler.descriptor.reduction.mode = VK_SAMPLER_REDUCTION_MODE_MIN; + + for ( auto& view : ::depthPyramidViews ) { + vkDestroyImageView(device->logicalDevice, view, nullptr); + } + ::depthPyramidViews.clear(); + ::depthPyramidViews.resize(mips-1); + shader.textures.clear(); + + for ( auto i = 1; i < mips; ++i ) { + auto& view = ::depthPyramidViews[i-1]; + VkImageViewCreateInfo viewCreateInfo = {}; + viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewCreateInfo.pNext = NULL; + viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; + viewCreateInfo.subresourceRange.baseMipLevel = i; + viewCreateInfo.subresourceRange.layerCount = 1; + viewCreateInfo.subresourceRange.levelCount = 1; + viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewCreateInfo.viewType = source.viewType; + viewCreateInfo.format = source.format; + viewCreateInfo.image = source.image; + VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view)); + + if ( i + 1 < mips ) { + auto& texture = shader.textures.emplace_back(); + texture.aliasTexture( source ); + texture.view = view; + texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + texture.updateDescriptors(); + } + } + for ( auto i = 1; i < mips; ++i ) { + auto& view = ::depthPyramidViews[i-1]; + auto& texture = shader.textures.emplace_back(); + texture.aliasTexture( source ); + texture.view = view; + texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + texture.updateDescriptors(); + } + } } // 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 ); + } else { + blitter.initializePipeline( blitter.descriptor ); } + { ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; descriptor.renderMode = ""; @@ -429,6 +531,8 @@ void ext::vulkan::DeferredRenderMode::tick() { } if ( blitter.hasPipeline( descriptor ) ) { blitter.getPipeline( descriptor ).update( blitter, descriptor ); + } else { + blitter.initializePipeline( descriptor ); } } @@ -438,6 +542,20 @@ void ext::vulkan::DeferredRenderMode::tick() { descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE; if ( blitter.hasPipeline( descriptor ) ) { blitter.getPipeline( descriptor ).update( blitter, descriptor ); + } else { + blitter.initializePipeline( descriptor ); + } + } + + if ( settings::pipelines::culling ) { + descriptor.aux = uf::vector::mips( pod::Vector2ui{ width, height } ); + descriptor.pipeline = "depth-pyramid"; + descriptor.subpass = 0; + descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE; + if ( blitter.hasPipeline( descriptor ) ) { + blitter.getPipeline( descriptor ).update( blitter, descriptor ); + } else { + blitter.initializePipeline( descriptor ); } } } @@ -543,7 +661,8 @@ 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)); + auto commandBuffer = commands[i]; + VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo)); // Fill GBuffer { VkRenderPassBeginInfo renderPassBeginInfo = {}; @@ -576,7 +695,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto // transition layers for read for ( auto layer : layers ) { - layer->pipelineBarrier( commands[i], 0 ); + layer->pipelineBarrier( commandBuffer, 0 ); } for ( auto& pipeline : metadata.pipelines ) { @@ -585,16 +704,22 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto if ( graphic->descriptor.renderMode != this->getName() ) continue; ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass); descriptor.pipeline = pipeline; - graphic->record( commands[i], descriptor, 0, metadata.eyes ); + if ( pipeline == uf::renderer::settings::pipelines::names::culling ) { + descriptor.bind.width = graphic->descriptor.inputs.indirect.count; + descriptor.bind.height = 1; + descriptor.bind.depth = 1; + descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE; + } + graphic->record( commandBuffer, descriptor, 0, metadata.eyes ); } } // pre-renderpass commands - if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commands[i], i ); + if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commandBuffer, i ); - vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(commands[i], 0, 1, &viewport); - vkCmdSetScissor(commands[i], 0, 1, &scissor); + vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + vkCmdSetScissor(commandBuffer, 0, 1, &scissor); // render to geometry buffers for ( size_t eye = 0; eye < metadata.eyes; ++eye ) { size_t currentPass = 0; @@ -603,10 +728,10 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto // only draw graphics that are assigned to this type of render mode if ( graphic->descriptor.renderMode != this->getName() ) continue; ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass); - graphic->record( commands[i], descriptor, eye, currentDraw++ ); + graphic->record( commandBuffer, descriptor, eye, currentDraw++ ); } if ( eye + 1 < metadata.eyes ) { - vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass; + vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass; } } // skip deferred pass if RT is enabled, we still process geometry for a depth buffer @@ -619,13 +744,13 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto descriptor.pipeline = "deferred"; descriptor.subpass = currentSubpass; descriptor.bind.point = VK_PIPELINE_BIND_POINT_GRAPHICS; - blitter.record(commands[i], descriptor, eye, currentDraw++); + blitter.record(commandBuffer, descriptor, eye, currentDraw++); } if ( eye + 1 < metadata.eyes ) { - vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass; + vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass; } } - vkCmdEndRenderPass(commands[i]); + vkCmdEndRenderPass(commandBuffer); if ( settings::pipelines::deferred && DEFERRED_MODE == "compute" && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) { auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred"); @@ -639,13 +764,13 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto descriptor.subpass = 0; // transition attachments to general attachments for imageStore - ::transitionAttachmentsTo( this, shader, commands[i] ); + ::transitionAttachmentsTo( this, shader, commandBuffer ); // dispatch compute shader - blitter.record(commands[i], descriptor, 0, 0); + blitter.record(commandBuffer, descriptor, 0, 0); // transition attachments back to shader read layouts - ::transitionAttachmentsFrom( this, shader, commands[i] ); + ::transitionAttachmentsFrom( this, shader, commandBuffer ); } if ( settings::pipelines::bloom && blitter.material.hasShader("compute", "bloom") ) { @@ -660,25 +785,77 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto descriptor.subpass = 0; // transition attachments to general attachments for imageStore - ::transitionAttachmentsTo( this, shader, commands[i] ); + ::transitionAttachmentsTo( this, shader, commandBuffer ); // dispatch compute shader VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER}; memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - blitter.record(commands[i], descriptor, 0, 1); - vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 1, &memoryBarrier, 0, NULL, 0, NULL ); - blitter.record(commands[i], descriptor, 0, 2); - vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 1, &memoryBarrier, 0, NULL, 0, NULL ); - blitter.record(commands[i], descriptor, 0, 3); + vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 1, &memoryBarrier, 0, NULL, 0, NULL ); + blitter.record(commandBuffer, descriptor, 0, 1); + vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 1, &memoryBarrier, 0, NULL, 0, NULL ); + blitter.record(commandBuffer, descriptor, 0, 2); + vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 1, &memoryBarrier, 0, NULL, 0, NULL ); + blitter.record(commandBuffer, descriptor, 0, 3); // transition attachments back to shader read layouts - ::transitionAttachmentsFrom( this, shader, commands[i] ); + ::transitionAttachmentsFrom( this, shader, commandBuffer ); + } + + // construct depth-pyramid + if ( settings::pipelines::culling && blitter.material.hasShader("compute", "depth-pyramid") ) { + auto& shader = blitter.material.getShader("compute", "depth-pyramid"); + // auto mips = attachment.descriptor.mips; // uf::vector::mips( pod::Vector2ui{ renderTarget.width, renderTarget.height } ); + auto mips = uf::vector::mips( pod::Vector2ui{ width, height } ); + + ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; + descriptor.renderMode = ""; + descriptor.aux = uf::vector::mips( pod::Vector2ui{ width, height } ); + descriptor.pipeline = "depth-pyramid"; + descriptor.bind.width = width; + descriptor.bind.height = height; + descriptor.bind.depth = metadata.eyes; + descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE; + descriptor.subpass = 0; + + /* + // transition attachments to general attachments for imageStore + VkImageSubresourceRange subresourceRange; + subresourceRange.baseMipLevel = 0; + subresourceRange.levelCount = 1; + subresourceRange.baseArrayLayer = 0; + subresourceRange.layerCount = mips; + subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + subresourceRange.layerCount = this->metadata.eyes; + + auto& attachment = this->getAttachment("depth"); + uf::renderer::Texture::setImageLayout( commandBuffer, attachment.image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, subresourceRange ); + */ + + // dispatch compute shader + VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER}; + memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + for ( auto i = 0; i < mips - 1; ++i ) { + descriptor.bind.width = width >> i; + descriptor.bind.height = height >> i; + if ( descriptor.bind.width < 1 ) descriptor.bind.width = 1; + if ( descriptor.bind.height < 1 ) descriptor.bind.height = 1; + + blitter.record(commandBuffer, descriptor, 0, i); + vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 1, &memoryBarrier, 0, NULL, 0, NULL ); + } + + /* + // transition attachments to general attachments for imageStore + uf::renderer::Texture::setImageLayout( commandBuffer, attachment.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, subresourceRange ); + */ } // post-renderpass commands - if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i], i ); + if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commandBuffer, i ); #if 0 if ( this->hasAttachment("depth") ) { @@ -693,16 +870,16 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto #if 1 imageMemoryBarrier.subresourceRange.layerCount = metadata.eyes; imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - uf::renderer::Texture::setImageLayout( commands[i], attachment.image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageMemoryBarrier.subresourceRange ); + uf::renderer::Texture::setImageLayout( commandBuffer, attachment.image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageMemoryBarrier.subresourceRange ); #endif for ( size_t eye = 0; eye < metadata.eyes; ++eye ) { - texture.generateMipmaps(commands[i], eye); + texture.generateMipmaps(commandBuffer, eye); } #if 1 - uf::renderer::Texture::setImageLayout( commands[i], attachment.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, imageMemoryBarrier.subresourceRange ); + uf::renderer::Texture::setImageLayout( commandBuffer, attachment.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, imageMemoryBarrier.subresourceRange ); imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageMemoryBarrier.subresourceRange.layerCount = 1; #endif @@ -710,11 +887,11 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto #endif for ( auto layer : layers ) { - layer->pipelineBarrier( commands[i], 1 ); + layer->pipelineBarrier( commandBuffer, 1 ); } } - VK_CHECK_RESULT(vkEndCommandBuffer(commands[i])); + VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer)); } } diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index 00daaf63..3ff829db 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -333,15 +333,30 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { } if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) { auto& scene = uf::scene::getCurrentScene(); - auto& sceneMetadataJson = scene.getComponent(); + + auto& shader = blitter.material.getShader("compute"); + 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& shader = blitter.material.getShader("compute"); + shader.setSpecializationConstants({ + { "TEXTURES", maxTextures2D }, + { "CUBEMAPS", maxTexturesCube }, + { "CASCADES", maxCascades }, + }); + shader.setDescriptorCounts({ + { "samplerTextures", maxTextures2D }, + { "samplerCubemaps", maxTexturesCube }, + { "voxelId", maxCascades }, + { "voxelUv", maxCascades }, + { "voxelNormal", maxCascades }, + { "voxelRadiance", maxCascades }, + }); + // shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() ); // shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() ); shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() ); @@ -350,26 +365,6 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { 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; - } - } } else if ( metadata.type == uf::renderer::settings::pipelines::names::rt ) { #if 0 auto& shader = blitter.material.getShader("fragment"); @@ -490,7 +485,8 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v auto& commands = getCommands(); for (size_t i = 0; i < commands.size(); ++i) { - VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); + auto& commandBuffer = commands[i]; + VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo)); { VkRenderPassBeginInfo renderPassBeginInfo = {}; @@ -522,15 +518,16 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v size_t subpasses = renderTarget.passes.size(); size_t currentPass = 0; // pre-renderpass commands - if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commands[i], i ); + if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commandBuffer, i ); if ( this->getName() == "Compute" ) { for ( auto graphic : graphics ) { if ( graphic->descriptor.renderMode != this->getTarget() ) continue; if ( graphic->descriptor.pipeline != uf::renderer::settings::pipelines::names::rt ) continue; - graphic->record( commands[i] ); + graphic->record( commandBuffer ); } } else { + #if 0 for ( auto& pipeline : metadata.pipelines ) { if ( pipeline == metadata.pipeline ) continue; for ( auto graphic : graphics ) { @@ -538,31 +535,54 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass); descriptor.pipeline = pipeline; if ( pipeline == "rt" ) descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; - graphic->record( commands[i], descriptor, 0, metadata.type == uf::renderer::settings::pipelines::names::vxgi ? 0 : MIN(subpasses,6) ); + graphic->record( commandBuffer, descriptor, 0, metadata.type == uf::renderer::settings::pipelines::names::vxgi ? 0 : MIN(subpasses,6) ); + } + } + #endif + for ( auto& pipeline : metadata.pipelines ) { + if ( pipeline == metadata.pipeline ) continue; + for ( auto graphic : graphics ) { + if ( graphic->descriptor.renderMode != this->getTarget() ) continue; + ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass); + descriptor.pipeline = pipeline; + if ( pipeline == uf::renderer::settings::pipelines::names::culling ) { + descriptor.bind.width = graphic->descriptor.inputs.indirect.count; + descriptor.bind.height = 1; + descriptor.bind.depth = 1; + descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE; + } else if ( pipeline == uf::renderer::settings::pipelines::names::rt ) { + descriptor.bind.width = width; + descriptor.bind.height = height; + descriptor.bind.depth = 1; + descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; + } else { + UF_MSG_DEBUG("Aux pipeline: {}", pipeline); + } + graphic->record( commandBuffer, descriptor, 0, metadata.type == uf::renderer::settings::pipelines::names::vxgi ? 0 : MIN(subpasses,6) ); } } - vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(commands[i], 0, 1, &viewport); - vkCmdSetScissor(commands[i], 0, 1, &scissor); + vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + vkCmdSetScissor(commandBuffer, 0, 1, &scissor); for ( ; currentPass < subpasses; ++currentPass ) { size_t currentDraw = 0; for ( auto graphic : graphics ) { if ( graphic->descriptor.renderMode != this->getTarget() ) continue; ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass); - graphic->record( commands[i], descriptor, currentPass, currentDraw++ ); + graphic->record( commandBuffer, descriptor, currentPass, currentDraw++ ); } - if ( commandBufferCallbacks.count( currentPass ) > 0 ) commandBufferCallbacks[currentPass]( commands[i], i ); - if ( currentPass + 1 < subpasses ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); + if ( commandBufferCallbacks.count( currentPass ) > 0 ) commandBufferCallbacks[currentPass]( commandBuffer, i ); + if ( currentPass + 1 < subpasses ) vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); } - vkCmdEndRenderPass(commands[i]); + vkCmdEndRenderPass(commandBuffer); } // post-renderpass commands - if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i], i ); + if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commandBuffer, i ); } - VK_CHECK_RESULT(vkEndCommandBuffer(commands[i])); + VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer)); } } diff --git a/engine/src/ext/vulkan/rendermodes/transition.inl b/engine/src/ext/vulkan/rendermodes/transition.inl index 139008e2..a2ebbc14 100644 --- a/engine/src/ext/vulkan/rendermodes/transition.inl +++ b/engine/src/ext/vulkan/rendermodes/transition.inl @@ -25,6 +25,7 @@ namespace { image = self->getAttachment(descriptor.name).image; } if ( image == VK_NULL_HANDLE ) continue; + subresourceRange.aspectMask = descriptor.name == "depth" ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; uf::renderer::Texture::setImageLayout( commandBuffer, image, layout, descriptor.layout, subresourceRange ); } } @@ -54,6 +55,7 @@ namespace { image = self->getAttachment(descriptor.name).image; } if ( image == VK_NULL_HANDLE ) continue; + subresourceRange.aspectMask = descriptor.name == "depth" ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; uf::renderer::Texture::setImageLayout( commandBuffer, image, descriptor.layout, layout, subresourceRange ); } } diff --git a/engine/src/ext/vulkan/rendertarget.cpp b/engine/src/ext/vulkan/rendertarget.cpp index cde8f9aa..6b392d6c 100644 --- a/engine/src/ext/vulkan/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendertarget.cpp @@ -64,7 +64,7 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript if ( attachment->descriptor.mips == 0 ) { attachment->descriptor.mips = 1; } else { - attachment->descriptor.mips = static_cast(std::floor(std::log2(std::max(width, height)))) + 1; + attachment->descriptor.mips = uf::vector::mips( pod::Vector2ui{ width, height } ); } attachment->views.resize(this->views * attachment->descriptor.mips); diff --git a/engine/src/ext/vulkan/shader.cpp b/engine/src/ext/vulkan/shader.cpp index c58ca578..cae59f45 100644 --- a/engine/src/ext/vulkan/shader.cpp +++ b/engine/src/ext/vulkan/shader.cpp @@ -728,7 +728,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl size_t size = 4; uint8_t buffer[size]; - memset( &buffer[0], size, 0 ); + memset( &buffer[0], 0, size ); auto& definition = metadata.definitions.specializationConstants[name]; definition.name = name; @@ -936,6 +936,26 @@ bool ext::vulkan::Shader::updateStorage( const uf::stl::string& name, const void updateBuffer( data, size, getStorageBuffer(name) ); return true; } + +void ext::vulkan::Shader::setSpecializationConstants( const uf::stl::unordered_map& values ) { + uint32_t* specializationConstants = (uint32_t*) (void*) this->specializationConstants; + for ( auto pair : this->metadata.definitions.specializationConstants ) { + auto& sc = pair.second; + if ( values.count(sc.name) == 0 ) continue; + sc.value.ui = (specializationConstants[sc.index] = values.at(sc.name)); + } +} +void ext::vulkan::Shader::setDescriptorCounts( const uf::stl::unordered_map& values ) { + for ( auto pair : this->metadata.definitions.textures ) { + auto& tx = pair.second; + if ( values.count(tx.name) == 0 ) continue; + for ( auto& layout : this->descriptorSetLayoutBindings ) { + if ( layout.binding != tx.binding ) continue; + layout.descriptorCount = values.at(tx.name); + } + } +} + // JSON shit #if 0 && UF_SHADER_PARSE_AS_JSON uf::Serializer ext::vulkan::Shader::getUniformJson( const uf::stl::string& name, bool cache ) { diff --git a/engine/src/ext/vulkan/texture.cpp b/engine/src/ext/vulkan/texture.cpp index a3f53059..8df95718 100644 --- a/engine/src/ext/vulkan/texture.cpp +++ b/engine/src/ext/vulkan/texture.cpp @@ -112,6 +112,14 @@ void ext::vulkan::Sampler::initialize( Device& device ) { samplerCreateInfo.anisotropyEnable = descriptor.anisotropy.enabled; samplerCreateInfo.maxAnisotropy = descriptor.anisotropy.max; + + VkSamplerReductionModeCreateInfoEXT createInfoReduction{}; + if ( descriptor.reduction.enabled ) { + createInfoReduction.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT; + createInfoReduction.reductionMode = descriptor.reduction.mode; + samplerCreateInfo.pNext = &createInfoReduction; + } + VK_CHECK_RESULT(vkCreateSampler(device.logicalDevice, &samplerCreateInfo, nullptr, &sampler)); } { @@ -493,7 +501,7 @@ void ext::vulkan::Texture::fromBuffers( // } else if ( this->depth == 1 ) { } else { // this->mips = static_cast(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1; - this->mips = static_cast(std::floor(std::log2(std::max(std::max(texWidth, texHeight),texDepth)))) + 1; + this->mips = uf::vector::mips( pod::Vector3ui{ texWidth, texHeight, texDepth } ); VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(device.physicalDevice, format, &formatProperties); if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) { @@ -834,6 +842,15 @@ void ext::vulkan::Texture::generateMipmaps( VkCommandBuffer commandBuffer, uint3 } bool isDepth = formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + switch ( format ) { + case ext::vulkan::enums::Format::D16_UNORM: + case ext::vulkan::enums::Format::D32_SFLOAT: + case ext::vulkan::enums::Format::D16_UNORM_S8_UINT: + case ext::vulkan::enums::Format::D24_UNORM_S8_UINT: + case ext::vulkan::enums::Format::D32_SFLOAT_S8_UINT: + isDepth = true; + break; + } auto aspectMask = isDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; auto filter = isDepth ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index 15d1b883..21988e21 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -15,8 +15,10 @@ #include namespace { - uf::stl::vector auxFencesGraphics; - uf::stl::vector auxFencesCompute; + struct { + uf::stl::vector graphics; + uf::stl::vector compute; + } auxFences; } uint32_t ext::vulkan::settings::width = 1280; @@ -335,15 +337,15 @@ void ext::vulkan::initialize() { } { - ::auxFencesGraphics.resize( swapchain.buffers ); - ::auxFencesCompute.resize( swapchain.buffers ); + ::auxFences.graphics.resize( swapchain.buffers ); + ::auxFences.compute.resize( swapchain.buffers ); VkFenceCreateInfo fenceCreateInfo = {}; fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - for ( auto& fence : ::auxFencesGraphics ) VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); - for ( auto& fence : ::auxFencesCompute ) VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); + for ( auto& fence : ::auxFences.graphics ) VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); + for ( auto& fence : ::auxFences.compute ) VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); } uf::graph::initialize(); @@ -356,11 +358,8 @@ void ext::vulkan::initialize() { auto tasks = uf::thread::schedule( settings::invariant::multithreadedRecording ); for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; tasks.queue([&]{ - // auto guard = renderMode->guardMutex(); - // renderMode->lockMutex(); if ( settings::invariant::individualPipelines ) renderMode->bindPipelines(); renderMode->createCommandBuffers(); - // renderMode->unlockMutex(); }); } uf::thread::execute( tasks ); @@ -381,7 +380,7 @@ void ext::vulkan::tick() { #if 0 { auto& scene = uf::scene::getCurrentScene(); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); auto tasks = uf::thread::schedule(settings::experimental::dedicatedThread); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; @@ -397,7 +396,7 @@ void ext::vulkan::tick() { #else { auto& scene = uf::scene::getCurrentScene(); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; ext::vulkan::Graphic& graphic = entity->getComponent(); @@ -442,11 +441,8 @@ void ext::vulkan::tick() { auto tasks = uf::thread::schedule( settings::invariant::multithreadedRecording ); for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; if ( ext::vulkan::states::rebuild || renderMode->rebuild ) tasks.queue([&]{ - // auto guard = renderMode->guardMutex(); - // renderMode->lockMutex(); if ( settings::invariant::individualPipelines ) renderMode->bindPipelines(); renderMode->createCommandBuffers(); - // renderMode->unlockMutex(); }); } uf::thread::execute( tasks ); @@ -458,13 +454,14 @@ 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(); // cleanup in-flight commands - for ( auto& pair : device.transient.commandBuffers ) { + auto transient = std::move(device.transient); + for ( auto& pair : /*device.*/transient.commandBuffers ) { auto queueType = pair.first; auto& commandBuffers = pair.second; @@ -495,63 +492,54 @@ void ext::vulkan::render() { #endif if ( settings::experimental::batchQueueSubmissions ) { + uf::stl::vector fences = { ::auxFences.compute[states::currentBuffer], ::auxFences.graphics[states::currentBuffer] }; uf::stl::vector auxRenderModes; auxRenderModes.reserve( renderModes.size() ); uf::stl::vector specialRenderModes; specialRenderModes.reserve( renderModes.size() ); for ( auto renderMode : renderModes ) { if ( !renderMode || !renderMode->execute || !renderMode->metadata.limiter.execute ) continue; - // renderMode->lockMutex( renderMode->mostRecentCommandPoolId ); if ( renderMode->commandBufferCallbacks.count(RenderMode::EXECUTE_BEGIN) > 0 ) renderMode->commandBufferCallbacks[RenderMode::EXECUTE_BEGIN]( VkCommandBuffer{}, 0 ); - if ( renderMode->getName() == "Gui" || renderMode->getName() == "" || renderMode->getName() == "Swapchain" ) - specialRenderModes.emplace_back(renderMode); - else - auxRenderModes.emplace_back(renderMode); + if ( renderMode->getName() == "" || renderMode->getName() == "Swapchain" ) specialRenderModes.emplace_back(renderMode); + else auxRenderModes.emplace_back(renderMode); } + + uf::stl::vector submitsGraphics; submitsGraphics.reserve( auxRenderModes.size() ); + uf::stl::vector submitsCompute; submitsCompute.reserve( auxRenderModes.size() ); // stuff we can batch - { - // Get next image in the swap chain (back/front buffer) - uf::stl::vector submitsGraphics; submitsGraphics.reserve( auxRenderModes.size() ); - uf::stl::vector submitsCompute; submitsCompute.reserve( auxRenderModes.size() ); - for ( auto renderMode : auxRenderModes ) { - auto submitInfo = renderMode->queue(); - if ( submitInfo.sType != VK_STRUCTURE_TYPE_SUBMIT_INFO ) continue; + // auto tasks = uf::thread::schedule( settings::invariant::multithreadedRecording ); + for ( auto renderMode : auxRenderModes ) { + auto submitInfo = renderMode->queue(); + if ( submitInfo.sType != VK_STRUCTURE_TYPE_SUBMIT_INFO ) continue; + if ( renderMode->metadata.compute ) submitsCompute.emplace_back(submitInfo); + else submitsGraphics.emplace_back(submitInfo); + renderMode->executed = true; + // tasks.queue([&]{ ext::vulkan::setCurrentRenderMode(renderMode); uf::graph::render(); uf::scene::render(); - - if ( renderMode->metadata.compute ) { - submitsCompute.emplace_back(submitInfo); - } else { - submitsGraphics.emplace_back(submitInfo); - } - renderMode->executed = true; ext::vulkan::setCurrentRenderMode(NULL); - } - - if ( !submitsCompute.empty() ) { - VK_CHECK_RESULT(vkWaitForFences(device, 1, &::auxFencesCompute[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT)); - VK_CHECK_RESULT(vkResetFences(device, 1, &::auxFencesCompute[states::currentBuffer])); - VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( QueueEnum::COMPUTE ), submitsCompute.size(), submitsCompute.data(), ::auxFencesCompute[states::currentBuffer])); - } - if ( !submitsGraphics.empty() ) { - VK_CHECK_RESULT(vkWaitForFences(device, 1, &::auxFencesGraphics[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT)); - VK_CHECK_RESULT(vkResetFences(device, 1, &::auxFencesGraphics[states::currentBuffer])); - VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( QueueEnum::GRAPHICS ), submitsGraphics.size(), submitsGraphics.data(), ::auxFencesGraphics[states::currentBuffer])); - } + // }); } + // uf::thread::execute( tasks ); + + VK_CHECK_RESULT(vkWaitForFences(device, fences.size(), fences.data(), VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT)); + VK_CHECK_RESULT(vkResetFences(device, fences.size(), fences.data())); + + VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( QueueEnum::COMPUTE ), submitsCompute.size(), submitsCompute.data(), ::auxFences.compute[states::currentBuffer])); + VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( QueueEnum::GRAPHICS ), submitsGraphics.size(), submitsGraphics.data(), ::auxFences.graphics[states::currentBuffer])); + // stuff we can't batch - { - for ( auto renderMode : specialRenderModes ) { - ext::vulkan::setCurrentRenderMode(renderMode); - uf::graph::render(); - uf::scene::render(); - renderMode->render(); - ext::vulkan::setCurrentRenderMode(NULL); - } + for ( auto renderMode : specialRenderModes ) { + ext::vulkan::setCurrentRenderMode(renderMode); + uf::graph::render(); + uf::scene::render(); + renderMode->render(); + ext::vulkan::setCurrentRenderMode(NULL); } + #if UF_USE_FFX_FSR if ( settings::pipelines::fsr ) { ext::fsr::render(); @@ -560,40 +548,29 @@ void ext::vulkan::render() { for ( auto renderMode : renderModes ) { if ( renderMode->commandBufferCallbacks.count(RenderMode::EXECUTE_END) > 0 ) renderMode->commandBufferCallbacks[RenderMode::EXECUTE_END]( VkCommandBuffer{}, 0 ); - // renderMode->cleanupCommands( renderMode->mostRecentCommandPoolId ); - // renderMode->unlockMutex( renderMode->mostRecentCommandPoolId ); } } else { 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 - } + #if UF_USE_FFX_FSR + if ( renderMode->getName() == "Swapchain" && settings::pipelines::fsr ) ext::fsr::render(); + #endif - // renderMode->lockMutex( renderMode->mostRecentCommandPoolId ); - // auto guard = renderMode->guardMutex( renderMode->mostRecentCommandPoolId ); ext::vulkan::setCurrentRenderMode(renderMode); uf::graph::render(); uf::scene::render(); renderMode->render(); ext::vulkan::setCurrentRenderMode(NULL); - // renderMode->unlockMutex( renderMode->mostRecentCommandPoolId ); } - // for ( auto& renderMode : renderModes ) renderMode->cleanupCommands( renderMode->mostRecentCommandPoolId ); } - if ( ext::vulkan::settings::invariant::waitOnRenderEnd ) synchronize(); // if ( ext::openvr::context ) ext::openvr::postSubmit(); // cleanup in-flight buffers - for ( auto& buffer : device.transient.buffers ) buffer.destroy(false); - device.transient.buffers.clear(); + for ( auto& buffer : transient.buffers ) buffer.destroy(false); + transient.buffers.clear(); ext::vulkan::mutex.unlock(); } @@ -619,8 +596,8 @@ void ext::vulkan::destroy() { TextureCube::empty.destroy(); for ( auto& s : ext::vulkan::Sampler::samplers ) s.destroy(); - for ( auto& fence : ::auxFencesGraphics ) vkDestroyFence( device, fence, nullptr); - for ( auto& fence : ::auxFencesCompute ) vkDestroyFence( device, fence, nullptr); + for ( auto& fence : ::auxFences.graphics ) vkDestroyFence( device, fence, nullptr); + for ( auto& fence : ::auxFences.compute ) vkDestroyFence( device, fence, nullptr); ext::vulkan::scratchBuffer.destroy(); diff --git a/engine/src/utils/image/image.cpp b/engine/src/utils/image/image.cpp index d47b2cea..0319ba76 100644 --- a/engine/src/utils/image/image.cpp +++ b/engine/src/utils/image/image.cpp @@ -391,7 +391,7 @@ uf::Image uf::Image::replace(const Image::pixel_t& from, const Image::pixel_t& t uf::Image uf::Image::subImage( const Image::vec2_t& start, const Image::vec2_t& end) const { return *this; /* - uf::Vector2ui size = parameter; + pod::Vector2ui size = parameter; if ( mode == uf::Image::CropMode::START_SPAN_SIZE ) size = parameter; if ( mode == uf::Image::CropMode::START_TO_END ) size = parameter - start; if ( size > this->size ) return uf::Image(*this); diff --git a/engine/src/utils/thread/thread.cpp b/engine/src/utils/thread/thread.cpp index a515127a..eac1de26 100644 --- a/engine/src/utils/thread/thread.cpp +++ b/engine/src/utils/thread/thread.cpp @@ -38,7 +38,7 @@ void UF_API uf::thread::tick( pod::Thread& thread ) { while ( thread.running ) { std::unique_lock lock(*thread.mutex); thread.conditions.queued.wait(lock, [&]{ - return !thread.queue.empty() || !thread.running; + return (!thread.container.empty() || !thread.queue.empty()) || !thread.running; }); uf::thread::process( thread ); diff --git a/ext/behaviors/baking/behavior.cpp b/ext/behaviors/baking/behavior.cpp index 7798cc58..c7625308 100644 --- a/ext/behaviors/baking/behavior.cpp +++ b/ext/behaviors/baking/behavior.cpp @@ -106,13 +106,12 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { shader.buffers.insert( shader.buffers.begin(), metadata.buffers.uniforms.alias() ); }); - // uf::thread::queue([&]{ - uf::renderer::addRenderMode( &renderMode, metadata.renderModeName ); - // }); + uf::renderer::addRenderMode( &renderMode, metadata.renderModeName ); + uf::renderer::states::rebuild = true; UF_MSG_DEBUG("Finished initialiation."); }); - this->queueHook( "entity:PostInitialization.%UID%", 1.0f ); + this->queueHook( "entity:PostInitialization.%UID%", 2.0f ); #endif } void ext::BakingBehavior::tick( uf::Object& self ) { diff --git a/ext/behaviors/light/behavior.cpp b/ext/behaviors/light/behavior.cpp index 0fe65a12..3fc3ad32 100644 --- a/ext/behaviors/light/behavior.cpp +++ b/ext/behaviors/light/behavior.cpp @@ -32,10 +32,10 @@ void ext::LightBehavior::initialize( uf::Object& self ) { auto& camera = this->getComponent(); auto& scene = uf::scene::getCurrentScene(); auto& controller = scene.getController(); - auto& sceneMetadata = scene.getComponent(); + auto& sceneMetadataJson = scene.getComponent(); - if ( !sceneMetadata["system"]["lights"]["round robin hook bound"].as() ) { - sceneMetadata["system"]["lights"]["round robin hook bound"] = true; + if ( !sceneMetadataJson["system"]["lights"]["round robin hook bound"].as() ) { + sceneMetadataJson["system"]["lights"]["round robin hook bound"] = true; scene.addHook("game:Frame.Start", [&]( ext::json::Value& payload ){ if ( ++::roundRobin.current >= ::roundRobin.lights.size() ) ::roundRobin.current = 0; }); @@ -56,8 +56,9 @@ void ext::LightBehavior::initialize( uf::Object& self ) { #if UF_USE_OPENGL metadataJson["light"]["shadows"] = false; #endif - if ( !sceneMetadata["light"]["shadows"]["enabled"].as(true) ) + if ( !sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["shadows"]["enabled"].as(true) ) { metadataJson["light"]["shadows"] = false; + } if ( metadataJson["light"]["shadows"].as() ) { auto& cameraTransform = camera.getTransform(); cameraTransform.reference = &transform; diff --git a/ext/behaviors/raytrace/behavior.cpp b/ext/behaviors/raytrace/behavior.cpp index 4c01a2b0..3023bdf9 100644 --- a/ext/behaviors/raytrace/behavior.cpp +++ b/ext/behaviors/raytrace/behavior.cpp @@ -93,7 +93,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { static uf::stl::vector previousGraphics; uf::stl::vector graphics; auto& scene = uf::scene::getCurrentScene(); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; auto& graphic = entity->getComponent(); @@ -182,6 +182,21 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() ); shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() ); + shader.setSpecializationConstants({ + { "TEXTURES", maxTextures2D }, + { "CUBEMAPS", maxTexturesCube }, + { "CASCADES", maxCascades }, + }); + shader.setDescriptorCounts({ + { "samplerTextures", maxTextures2D }, + { "samplerCubemaps", maxTexturesCube }, + { "voxelId", maxCascades }, + { "voxelUv", maxCascades }, + { "voxelNormal", maxCascades }, + { "voxelRadiance", maxCascades }, + }); + + /* uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants; for ( auto pair : shader.metadata.definitions.specializationConstants ) { auto& sc = pair.second; @@ -201,7 +216,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades; } } - + */ } } } diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 4acc6aba..86462c9b 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -44,6 +44,7 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) { auto& metadataJson = this->getComponent(); this->addHook( "system:Quit.%UID%", [&](ext::json::Value& payload){ + uf::renderer::settings::experimental::dedicatedThread = false; ext::ready = false; }); @@ -355,7 +356,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { #endif #if UF_USE_OPENGL if ( metadata.light.enabled ) { - auto& graph = this->getGraph(); + auto/*&*/ graph = this->getGraph(); auto& controller = this->getController(); auto& camera = controller.getComponent(); auto& controllerMetadata = controller.getComponent(); @@ -420,7 +421,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { } #elif UF_USE_VULKAN { - auto& graph = this->getGraph(); + auto/*&*/ graph = this->getGraph(); auto& controller = this->getController(); auto& camera = controller.getComponent(); auto& controllerMetadata = controller.getComponent(); @@ -720,7 +721,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; +// 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); @@ -816,7 +817,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string bindBuffers( self, *blitters.front(), shaderType, shaderPipeline ); } void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic& graphic, const uf::stl::string& shaderType, const uf::stl::string& shaderPipeline ) { - auto& graph = this->getGraph(); + auto/*&*/ graph = this->getGraph(); auto& controller = this->getController(); auto& camera = controller.getComponent(); auto& controllerMetadata = controller.getComponent(); diff --git a/ext/behaviors/voxelizer/behavior.cpp b/ext/behaviors/voxelizer/behavior.cpp index 56aff042..83d139e5 100644 --- a/ext/behaviors/voxelizer/behavior.cpp +++ b/ext/behaviors/voxelizer/behavior.cpp @@ -201,7 +201,7 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) { metadata.extents.matrix = uf::matrix::orthographic( min.x, max.x, min.y, max.y, min.z, max.z ); - auto& graph = scene.getGraph(); + auto/*&*/ graph = scene.getGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; auto& graphic = entity->getComponent();