From 77f24467e9cbfb4918491052b5afe381a55b86d0 Mon Sep 17 00:00:00 2001 From: mrq Date: Thu, 4 Feb 2021 00:00:00 -0600 Subject: [PATCH] Commit for 2021.02.04.7z --- bin/data/shaders/base.colored.vert.glsl | 44 ++++ bin/data/shaders/base.frag.glsl | 22 ++ bin/data/shaders/base.vert.glsl | 1 + .../shaders/display.rendertarget.vert.glsl | 1 + bin/data/shaders/display.subpass.frag.glsl | 173 ++++++++++--- ...rag.glsl => display.subpass.old.frag.glsl} | 30 +-- bin/data/shaders/display.subpass.vert.glsl | 1 + bin/data/shaders/gltf.frag.glsl | 114 ++++++++- bin/data/shaders/gltf.instanced.vert.glsl | 13 +- .../shaders/gltf.skinned.instanced.vert.glsl | 11 +- bin/data/shaders/gltf.skinned.vert.glsl | 9 +- bin/data/shaders/gltf.vert.glsl | 7 +- bin/data/shaders/gui.text.vert.glsl | 1 + bin/data/shaders/gui.vert.glsl | 1 + bin/data/shaders/heightmap.vert.glsl | 1 + bin/data/shaders/line.vert.glsl | 1 + bin/data/shaders/terrain.vert.glsl | 1 + engine/inc/uf/ext/gltf/graph.h | 31 ++- engine/inc/uf/ext/vulkan/graphic.h | 6 +- engine/inc/uf/ext/vulkan/rendertarget.h | 4 +- engine/inc/uf/ext/vulkan/vulkan.h | 1 + engine/src/engine/asset/asset.cpp | 1 + engine/src/engine/object/behaviors/gltf.cpp | 5 +- engine/src/ext/bullet/bullet.cpp | 15 +- engine/src/ext/gltf/gltf.cpp | 43 +++- engine/src/ext/gltf/graph.cpp | 128 ++++++++-- engine/src/ext/vulkan/buffer.cpp | 4 +- engine/src/ext/vulkan/graphic.cpp | 64 ++--- engine/src/ext/vulkan/rendermode.cpp | 3 +- engine/src/ext/vulkan/rendermodes/base.cpp | 4 +- .../src/ext/vulkan/rendermodes/deferred.cpp | 235 ++++++++++++++---- .../ext/vulkan/rendermodes/rendertarget.cpp | 36 ++- .../rendermodes/stereoscopic_deferred.cpp | 4 +- engine/src/ext/vulkan/rendertarget.cpp | 32 ++- engine/src/ext/vulkan/vulkan.cpp | 1 + engine/src/utils/image/atlas.cpp | 4 +- ext/behaviors/scene/behavior.cpp | 83 ++++++- ext/main.cpp | 1 + 38 files changed, 890 insertions(+), 246 deletions(-) create mode 100644 bin/data/shaders/base.colored.vert.glsl create mode 100644 bin/data/shaders/base.frag.glsl rename bin/data/shaders/{display.subpass.stereo.frag.glsl => display.subpass.old.frag.glsl} (93%) diff --git a/bin/data/shaders/base.colored.vert.glsl b/bin/data/shaders/base.colored.vert.glsl new file mode 100644 index 00000000..f2d96b4a --- /dev/null +++ b/bin/data/shaders/base.colored.vert.glsl @@ -0,0 +1,44 @@ +#version 450 + +layout (constant_id = 0) const uint PASSES = 6; +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec2 inUv; +layout (location = 2) in vec3 inNormal; +layout (location = 3) in vec4 inColor; + +layout( push_constant ) uniform PushBlock { + uint pass; + uint draw; +} PushConstant; + +struct Matrices { + mat4 model; + mat4 view[PASSES]; + mat4 projection[PASSES]; +}; + +layout (binding = 0) uniform UBO { + Matrices matrices; + vec4 color; +} ubo; + +layout (location = 0) out vec2 outUv; +layout (location = 1) out vec4 outColor; +layout (location = 2) out vec3 outNormal; +layout (location = 3) out vec3 outPosition; + +out gl_PerVertex { + vec4 gl_Position; +}; + + +void main() { + outUv = inUv; + outColor = inColor.rgba; + + outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0)); + outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0)); + outNormal = normalize(outNormal); + + gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0); +} \ No newline at end of file diff --git a/bin/data/shaders/base.frag.glsl b/bin/data/shaders/base.frag.glsl new file mode 100644 index 00000000..3277d475 --- /dev/null +++ b/bin/data/shaders/base.frag.glsl @@ -0,0 +1,22 @@ +#version 450 + +layout (binding = 1) uniform sampler2D samplerColor; + +layout (location = 0) in vec2 inUv; +layout (location = 1) in vec4 inColor; +layout (location = 2) in vec3 inNormal; +layout (location = 3) in vec3 inPosition; + +layout (location = 0) out vec4 outAlbedoSpecular; +layout (location = 1) out vec4 outNormal; +layout (location = 2) out vec4 outPosition; + +void main() { + outAlbedoSpecular = texture(samplerColor, inUv); + if ( outAlbedoSpecular.a < 0.001 ) discard; + outAlbedoSpecular.rgb *= inColor.rgb; + outAlbedoSpecular.a = 1; + + outNormal = vec4(inNormal,1); + outPosition = vec4(inPosition,1); +} \ No newline at end of file diff --git a/bin/data/shaders/base.vert.glsl b/bin/data/shaders/base.vert.glsl index 2513d942..0c83f290 100644 --- a/bin/data/shaders/base.vert.glsl +++ b/bin/data/shaders/base.vert.glsl @@ -7,6 +7,7 @@ layout (location = 2) in vec3 inNormal; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; struct Matrices { diff --git a/bin/data/shaders/display.rendertarget.vert.glsl b/bin/data/shaders/display.rendertarget.vert.glsl index 1141c455..c90a0fb3 100644 --- a/bin/data/shaders/display.rendertarget.vert.glsl +++ b/bin/data/shaders/display.rendertarget.vert.glsl @@ -15,6 +15,7 @@ layout (location = 2) out flat Cursor outCursor; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; out gl_PerVertex { diff --git a/bin/data/shaders/display.subpass.frag.glsl b/bin/data/shaders/display.subpass.frag.glsl index 705a45d0..d03af0ac 100644 --- a/bin/data/shaders/display.subpass.frag.glsl +++ b/bin/data/shaders/display.subpass.frag.glsl @@ -1,14 +1,70 @@ #version 450 #extension GL_EXT_samplerless_texture_functions : require -layout (constant_id = 0) const uint LIGHTS = 256; +#define UF_DEFERRED_SAMPLING 0 -layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedoMetallic; -layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormalRoughness; -layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerDepth; +layout (constant_id = 0) const uint LIGHTS = 256; +layout (constant_id = 1) const uint TEXTURES = 256; + +struct Material { + vec4 colorBase; + vec4 colorEmissive; + + float factorMetallic; + float factorRoughness; + float factorOcclusion; + float factorAlphaCutoff; + + int indexAlbedo; + int indexNormal; + int indexEmissive; + int indexOcclusion; + + int indexMetallicRoughness; + + int padding1; + int padding2; + int padding3; +}; +struct Texture { + int index; + int samp; + int remap; + float blend; + + vec4 lerp; +}; +struct DrawCall { + int materialIndex; + uint materials; + int textureIndex; + uint textures; +}; + +layout (input_attachment_index = 0, binding = 1) uniform usubpassInput samplerId; +layout (input_attachment_index = 1, binding = 2) uniform subpassInput samplerNormal; + +#if UF_DEFERRED_SAMPLING + layout (input_attachment_index = 2, binding = 3) uniform subpassInput samplerUv; +#else + layout (input_attachment_index = 2, binding = 3) uniform subpassInput samplerAlbedo; +#endif + +layout (input_attachment_index = 3, binding = 4) uniform subpassInput samplerDepth; layout (binding = 5) uniform sampler3D samplerNoise; -layout (binding = 6) uniform sampler2D samplerShadows[LIGHTS]; +layout (binding = 6) uniform sampler2D samplerTextures[TEXTURES]; +layout (binding = 7) uniform sampler2D samplerShadows[LIGHTS]; +layout (std140, binding = 8) readonly buffer Materials { + Material materials[]; +}; +layout (std140, binding = 9) readonly buffer Textures { + Texture textures[]; +}; +layout (std140, binding = 10) readonly buffer DrawCalls { + DrawCall drawCalls[]; +}; + layout (location = 0) in vec2 inUv; layout (location = 1) in flat uint inPushConstantPass; @@ -177,7 +233,9 @@ float random(vec3 seed, int i){ } float shadowFactor( Light light, uint shadowMap ) { - vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0); + vec3 point = position.world; + + vec4 positionClip = light.projection * light.view * vec4(point, 1.0); positionClip.xyz /= positionClip.w; if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0; @@ -199,12 +257,14 @@ float shadowFactor( Light light, uint shadowMap ) { vec2 uv = positionClip.xy * 0.5 + 0.5; float bias = light.depthBias; - if ( !true ) { +/* + if ( true ) { float cosTheta = clamp(dot(normal.eye, normalize(light.position.xyz - position.eye)), 0, 1); bias = clamp(bias * tan(acos(cosTheta)), 0, 0.01); } else if ( true ) { - bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias); - } + bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias); + } +*/ float eyeDepth = positionClip.z; int samples = poissonDisk.length(); @@ -391,39 +451,30 @@ void pbr( Light light, vec3 albedo, float metallic, float roughness, vec3 lightP vec3 N = normalize(normal.eye); vec3 L = light.position.xyz - position.eye; float dist = length(L); -// if ( light.radius > 0.001 && light.radius < dist ) return; - vec3 D = normalize(L); + L = normalize(L); vec3 V = normalize(-position.eye); - vec3 H = normalize(V + D); + vec3 H = normalize(V + L); - float NdotD = max(dot(N, D), 0.0); + float NdotL = max(dot(N, L), 0.0); float NdotV = max(dot(N, V), 0.0); - - vec3 radiance = light.color.rgb * light.power / (dist * dist); -/* - if ( light.radius > 0.0001 ) { - radiance *= clamp( light.radius / (pow(dist, 2.0) + 1.0), 0.0, 1.0 ); - } else if ( false ) { - radiance /= dist * dist; - } -*/ + float attenuation = light.power / (dist * dist); + vec3 radiance = light.color.rgb * attenuation; // cook-torrance brdf float NDF = DistributionGGX(N, H, roughness); - float G = GeometrySmith(N, V, D, roughness); + float G = GeometrySmith(N, V, L, roughness); vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; + vec3 kD = vec3(1.0) - F; + kD *= 1.0 - metallic; vec3 numerator = NDF * G * F; - float denominator = 4.0 * NdotV * NdotD; + float denominator = 4.0 * NdotV * NdotL; vec3 specular = numerator / max(denominator, 0.001); // add to outgoing radiance Lo - i += (kD * albedo / PI + specular) * radiance * NdotD; + i += (kD * albedo / PI + specular) * radiance * NdotL; } vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, vec3 rayOrigin, vec3 rayDir ) { @@ -496,12 +547,34 @@ void fog( inout vec3 i, float scale ) { i.rgb = mix(i.rgb, color, factor); } +vec3 decodeNormals( vec2 enc ) { + vec2 fenc = enc*4-2; + float f = dot(fenc,fenc); + float g = sqrt(1-f/4); + vec3 n; + n.xy = fenc*g; + n.z = 1-f/2; + return normalize(n); +} +/* +vec4 sampleTexture( uint drawId, int textureIndex, vec2 uv, vec4 base ) { + if ( TEXTURES <= textureIndex || textureIndex < 0 ) return base; + Texture t = textures[textureIndex+1]; + return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, uv ) ); +} +*/ + +bool validTextureIndex( int textureIndex ) { + return 0 <= textureIndex && textureIndex < TEXTURES; +} +vec4 sampleTexture( uint drawId, int textureIndex, vec2 uv, vec4 base ) { + if ( !validTextureIndex( textureIndex ) ) return base; + Texture t = textures[textureIndex+1]; +// if ( 0 <= t.remap && t.remap <= TEXTURES && t.remap != textureIndex ) t = textures[t.remap+1]; + return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, uv ) ); +} + void main() { - vec4 albedoMetallic = subpassLoad(samplerAlbedoMetallic); - vec4 normalRoughness = subpassLoad(samplerNormalRoughness); -// vec4 positionAO = subpassLoad(samplerPositionAO); - - normal.eye = normalRoughness.rgb; { mat4 iProj = inverse( ubo.matrices.projection[inPushConstantPass] ); mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] ); @@ -515,12 +588,34 @@ void main() { vec4 positionWorld = iView * positionEye; position.world = positionWorld.xyz; } + + normal.eye = decodeNormals( subpassLoad(samplerNormal).xy ); + + uvec2 ID = subpassLoad(samplerId).xy; + uint drawId = ID.x; + + DrawCall drawCall = drawCalls[drawId]; + uint materialId = ID.y + 1; + materialId += drawCall.materialIndex; + + Material material = materials[materialId]; + vec4 C = material.colorBase; + +#if UF_DEFERRED_SAMPLING + vec2 uv = subpassLoad(samplerUv).xy; + C = sampleTexture( drawId, drawCall.textureIndex + material.indexAlbedo, uv, C ); +#else + C = subpassLoad(samplerAlbedo); +#endif + + float M = material.factorMetallic; + float R = 0.5; //material.factorRoughness; + float AO = material.factorOcclusion; bool usePbr = true; bool gammaCorrect = false; float litFactor = 1.0; - float ao = 1; // positionAO.a; - vec3 fragColor = albedoMetallic.rgb * ubo.ambient.rgb * ao; + vec3 fragColor = C.rgb * ubo.ambient.rgb * AO; for ( uint i = 0; i < LIGHTS; ++i ) { Light light = ubo.lights[i]; @@ -533,12 +628,12 @@ void main() { light.power *= factor; litFactor += light.power; } + if ( light.power <= 0.0001 ) continue; if ( usePbr ) { - pbr( light, albedoMetallic.rgb, albedoMetallic.a, normalRoughness.a, lightPositionWorld, fragColor ); + pbr( light, C.rgb, M, R, lightPositionWorld, fragColor ); } else - phong( light, albedoMetallic, fragColor ); + phong( light, C, fragColor ); } - if ( gammaCorrect ) { fragColor = fragColor / (fragColor + vec3(1.0)); fragColor = pow(fragColor, vec3(1.0/2.2)); @@ -551,9 +646,9 @@ void main() { //dither1(fragColor); fragColor += dither2(); } +*/ if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) { whitenoise(fragColor); } -*/ outFragColor = vec4(fragColor,1); } \ No newline at end of file diff --git a/bin/data/shaders/display.subpass.stereo.frag.glsl b/bin/data/shaders/display.subpass.old.frag.glsl similarity index 93% rename from bin/data/shaders/display.subpass.stereo.frag.glsl rename to bin/data/shaders/display.subpass.old.frag.glsl index 8b5a0afe..705a45d0 100644 --- a/bin/data/shaders/display.subpass.stereo.frag.glsl +++ b/bin/data/shaders/display.subpass.old.frag.glsl @@ -5,7 +5,7 @@ layout (constant_id = 0) const uint LIGHTS = 256; layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedoMetallic; layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormalRoughness; -layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerPositionAO; +layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerDepth; layout (binding = 5) uniform sampler3D samplerNoise; layout (binding = 6) uniform sampler2D samplerShadows[LIGHTS]; @@ -177,10 +177,7 @@ float random(vec3 seed, int i){ } float shadowFactor( Light light, uint shadowMap ) { - vec3 point = position.world; -// point += normalize(normal.world) * light.depthBias; - - vec4 positionClip = light.projection * light.view * vec4(point, 1.0); + vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0); positionClip.xyz /= positionClip.w; if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0; @@ -202,14 +199,12 @@ float shadowFactor( Light light, uint shadowMap ) { vec2 uv = positionClip.xy * 0.5 + 0.5; float bias = light.depthBias; -/* - if ( true ) { + if ( !true ) { float cosTheta = clamp(dot(normal.eye, normalize(light.position.xyz - position.eye)), 0, 1); bias = clamp(bias * tan(acos(cosTheta)), 0, 0.01); } else if ( true ) { - bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias); - } -*/ + bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias); + } float eyeDepth = positionClip.z; int samples = poissonDisk.length(); @@ -504,12 +499,20 @@ void fog( inout vec3 i, float scale ) { void main() { vec4 albedoMetallic = subpassLoad(samplerAlbedoMetallic); vec4 normalRoughness = subpassLoad(samplerNormalRoughness); - vec4 positionAO = subpassLoad(samplerPositionAO); +// vec4 positionAO = subpassLoad(samplerPositionAO); normal.eye = normalRoughness.rgb; - position.eye = positionAO.rgb; { + { + mat4 iProj = inverse( ubo.matrices.projection[inPushConstantPass] ); mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] ); - vec4 positionWorld = iView * vec4(position.eye, 1); + float depth = subpassLoad(samplerDepth).r; + + vec4 positionClip = vec4(inUv * 2.0 - 1.0, depth, 1.0); + vec4 positionEye = iProj * positionClip; + positionEye /= positionEye.w; + position.eye = positionEye.xyz; + + vec4 positionWorld = iView * positionEye; position.world = positionWorld.xyz; } @@ -530,7 +533,6 @@ void main() { light.power *= factor; litFactor += light.power; } - if ( light.power <= 0.0001 ) continue; if ( usePbr ) { pbr( light, albedoMetallic.rgb, albedoMetallic.a, normalRoughness.a, lightPositionWorld, fragColor ); } else diff --git a/bin/data/shaders/display.subpass.vert.glsl b/bin/data/shaders/display.subpass.vert.glsl index 9c1d8b67..72ebf0a1 100644 --- a/bin/data/shaders/display.subpass.vert.glsl +++ b/bin/data/shaders/display.subpass.vert.glsl @@ -8,6 +8,7 @@ layout (location = 1) out flat uint outPushConstantPass; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; out gl_PerVertex { diff --git a/bin/data/shaders/gltf.frag.glsl b/bin/data/shaders/gltf.frag.glsl index 285b7b80..1bd32b2d 100644 --- a/bin/data/shaders/gltf.frag.glsl +++ b/bin/data/shaders/gltf.frag.glsl @@ -1,35 +1,138 @@ #version 450 +#define UF_DEFERRED_SAMPLING 0 + layout (constant_id = 0) const uint TEXTURES = 1; layout (binding = 0) uniform sampler2D samplerTextures[TEXTURES]; struct Material { vec4 colorBase; vec4 colorEmissive; + float factorMetallic; float factorRoughness; float factorOcclusion; - float factorMappedBlend; float factorAlphaCutoff; - float factorPadding; + int indexAlbedo; int indexNormal; int indexEmissive; int indexOcclusion; + int indexMetallicRoughness; - int indexMappedTarget; + + int padding1; + int padding2; + int padding3; +}; +struct Texture { + int index; + int samp; + int remap; + float blend; + + vec4 lerp; }; layout (std140, binding = 1) readonly buffer Materials { Material materials[]; }; +layout (std140, binding = 2) readonly buffer Textures { + Texture textures[]; +}; layout (location = 0) in vec2 inUv; layout (location = 1) in vec4 inColor; layout (location = 2) in vec3 inNormal; layout (location = 3) in mat3 inTBN; layout (location = 6) in vec3 inPosition; -layout (location = 7) flat in ivec2 inId; +layout (location = 7) flat in ivec4 inId; +layout (location = 0) out uvec2 outId; +layout (location = 1) out vec2 outNormals; + +#if UF_DEFERRED_SAMPLING + layout (location = 2) out vec2 outUvs; +#else + layout (location = 2) out vec4 outAlbedo; +#endif + +vec2 encodeNormals( vec3 n ) { + float p = sqrt(n.z*8+8); + return n.xy/p + 0.5; +} + +bool validTextureIndex( int textureIndex ) { + return 0 <= textureIndex && textureIndex < TEXTURES; +} +vec4 sampleTexture( int textureIndex, vec2 uv, vec4 base ) { + if ( !validTextureIndex( textureIndex ) ) return base; + Texture t = textures[textureIndex+1]; +// if ( 0 <= t.remap && t.remap <= TEXTURES && t.remap != textureIndex ) t = textures[t.remap+1]; + return texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ); +} + +void main() { +#if UF_DEFERRED_SAMPLING + vec3 N = inNormal; + outUvs = fract(inUv); +#else + int materialId = int(inId.y); + Material material = materials[materialId]; + + vec2 uv = fract(inUv.xy); + + vec4 C = vec4(0, 0, 0, 0); + vec3 N = inNormal; + vec3 P = inPosition; + float M = material.factorMetallic; + float R = material.factorRoughness; + float AO = material.factorOcclusion; + + // sample albedo + // C = sampleTexture( material.indexAlbedo, uv, material.colorBase ); + if ( !validTextureIndex( material.indexAlbedo ) ) { + discard; + } + { + Texture t = textures[material.indexAlbedo + 1]; + C = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ); + } + + // sample normal + if ( validTextureIndex( material.indexNormal ) ) { + Texture t = textures[material.indexNormal + 1]; + N = inTBN * normalize( texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ).xyz * 2.0 - vec3(1.0)); + } + +#if 0 + // sample metallic/roughness + if ( validTextureIndex( material.indexMetallicRoughness ) ) { + Texture t = textures[material.indexMetallicRoughness + 1]; + vec4 sampled = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ); + M = sampled.b; + R = sampled.g; + } + // sample ao + AO = material.factorOcclusion; + if ( validTextureIndex( material.indexOcclusion ) ) { + Texture t = textures[material.indexMetallicRoughness + 1]; + AO = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ).r; + } +#endif + + if ( C.a < abs(material.factorAlphaCutoff) ) { + // outTransparency = C; + discard; + } else { + C.rgb *= inColor.rgb * C.a; + outAlbedo = vec4(C.rgb,1); + } +#endif + outNormals = encodeNormals( N ); + outId = ivec2(inId.w, inId.y); +} + +/* layout (location = 0) out vec4 outAlbedoMetallic; layout (location = 1) out vec4 outNormalRoughness; layout (location = 2) out vec4 outPositionAO; @@ -99,4 +202,5 @@ void main() { outAlbedoMetallic = vec4(C.rgb,M); outNormalRoughness = vec4(N,R); outPositionAO = vec4(P,AO); -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/bin/data/shaders/gltf.instanced.vert.glsl b/bin/data/shaders/gltf.instanced.vert.glsl index e022794d..8af8a834 100644 --- a/bin/data/shaders/gltf.instanced.vert.glsl +++ b/bin/data/shaders/gltf.instanced.vert.glsl @@ -9,14 +9,15 @@ layout (location = 4) in ivec2 inId; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; -layout (binding = 2) uniform UBO { +layout (binding = 3) uniform UBO { mat4 view[PASSES]; mat4 projection[PASSES]; } ubo; -layout (std140, binding = 3) readonly buffer Models { +layout (std140, binding = 4) readonly buffer Models { mat4 models[]; }; @@ -25,10 +26,10 @@ layout (location = 1) out vec4 outColor; layout (location = 2) out vec3 outNormal; layout (location = 3) out mat3 outTBN; layout (location = 6) out vec3 outPosition; -layout (location = 7) out ivec2 outId; +layout (location = 7) out ivec4 outId; out gl_PerVertex { - vec4 gl_Position; + vec4 gl_Position; }; vec4 snap(vec4 vertex, vec2 resolution) { @@ -42,7 +43,7 @@ vec4 snap(vec4 vertex, vec2 resolution) { void main() { outUv = inUv; outColor = vec4(1.0); - outId = inId; + outId = ivec4(inId, PushConstant.pass, PushConstant.draw); mat4 model = models.length() <= 0 ? mat4(1.0) : models[int(inId.x)]; outPosition = vec3(ubo.view[PushConstant.pass] * model * vec4(inPos.xyz, 1.0)); @@ -57,5 +58,5 @@ void main() { } gl_Position = ubo.projection[PushConstant.pass] * ubo.view[PushConstant.pass] * model * vec4(inPos.xyz, 1.0); -// gl_Position = snap( gl_Position, vec2(320.0, 240.0) ); +// gl_Position = snap( gl_Position, vec2(256.0, 224.0) ); } \ No newline at end of file diff --git a/bin/data/shaders/gltf.skinned.instanced.vert.glsl b/bin/data/shaders/gltf.skinned.instanced.vert.glsl index ffc6af51..204bc6ad 100644 --- a/bin/data/shaders/gltf.skinned.instanced.vert.glsl +++ b/bin/data/shaders/gltf.skinned.instanced.vert.glsl @@ -11,18 +11,19 @@ layout (location = 6) in vec4 inWeights; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; -layout (binding = 2) uniform UBO { +layout (binding = 3) uniform UBO { mat4 view[PASSES]; mat4 projection[PASSES]; } ubo; -layout (std140, binding = 3) readonly buffer Models { +layout (std140, binding = 4) readonly buffer Models { mat4 models[]; }; -layout (std140, binding = 4) readonly buffer Joints { +layout (std140, binding = 5) readonly buffer Joints { mat4 joints[]; }; @@ -31,7 +32,7 @@ layout (location = 1) out vec4 outColor; layout (location = 2) out vec3 outNormal; layout (location = 3) out mat3 outTBN; layout (location = 6) out vec3 outPosition; -layout (location = 7) out ivec2 outId; +layout (location = 7) out ivec4 outId; out gl_PerVertex { vec4 gl_Position; @@ -48,7 +49,7 @@ vec4 snap(vec4 vertex, vec2 resolution) { void main() { outUv = inUv; outColor = vec4(1.0); - outId = inId; + outId = ivec4(inId, PushConstant.pass, PushConstant.draw); mat4 model = models.length() <= 0 ? mat4(1.0) : models[int(inId.x)]; mat4 skinnedMatrix = joints.length() <= 0 ? mat4(1.0) : diff --git a/bin/data/shaders/gltf.skinned.vert.glsl b/bin/data/shaders/gltf.skinned.vert.glsl index 09604539..6122e755 100644 --- a/bin/data/shaders/gltf.skinned.vert.glsl +++ b/bin/data/shaders/gltf.skinned.vert.glsl @@ -11,6 +11,7 @@ layout (location = 6) in vec4 inWeights; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; struct Matrices { @@ -18,12 +19,12 @@ struct Matrices { mat4 view[PASSES]; mat4 projection[PASSES]; }; -layout (binding = 2) uniform UBO { +layout (binding = 3) uniform UBO { Matrices matrices; vec4 color; } ubo; -layout (std140, binding = 3) readonly buffer Joints { +layout (std140, binding = 4) readonly buffer Joints { mat4 joints[]; }; @@ -33,7 +34,7 @@ layout (location = 1) out vec4 outColor; layout (location = 2) out vec3 outNormal; layout (location = 3) out mat3 outTBN; layout (location = 6) out vec3 outPosition; -layout (location = 7) out ivec2 outId; +layout (location = 7) out ivec4 outId; out gl_PerVertex { vec4 gl_Position; @@ -50,7 +51,7 @@ vec4 snap(vec4 vertex, vec2 resolution) { void main() { outUv = inUv; outColor = ubo.color; - outId = inId; + outId = ivec4(inId, PushConstant.pass, PushConstant.draw); mat4 skinnedMatrix = joints.length() <= 0 ? mat4(1.0) : inWeights.x * joints[int(inJoints.x)] + diff --git a/bin/data/shaders/gltf.vert.glsl b/bin/data/shaders/gltf.vert.glsl index 232bc9c9..f868b307 100644 --- a/bin/data/shaders/gltf.vert.glsl +++ b/bin/data/shaders/gltf.vert.glsl @@ -9,6 +9,7 @@ layout (location = 4) in ivec2 inId; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; struct Matrices { @@ -17,7 +18,7 @@ struct Matrices { mat4 projection[PASSES]; }; -layout (binding = 2) uniform UBO { +layout (binding = 3) uniform UBO { Matrices matrices; vec4 color; } ubo; @@ -27,7 +28,7 @@ layout (location = 1) out vec4 outColor; layout (location = 2) out vec3 outNormal; layout (location = 3) out mat3 outTBN; layout (location = 6) out vec3 outPosition; -layout (location = 7) out ivec2 outId; +layout (location = 7) out ivec4 outId; out gl_PerVertex { vec4 gl_Position; @@ -44,7 +45,7 @@ vec4 snap(vec4 vertex, vec2 resolution) { void main() { outUv = inUv; outColor = ubo.color; - outId = inId; + outId = ivec4(inId, PushConstant.pass, PushConstant.draw); outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0)); outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0)); diff --git a/bin/data/shaders/gui.text.vert.glsl b/bin/data/shaders/gui.text.vert.glsl index fd888c10..487894d2 100644 --- a/bin/data/shaders/gui.text.vert.glsl +++ b/bin/data/shaders/gui.text.vert.glsl @@ -6,6 +6,7 @@ layout (location = 1) in vec2 inUv; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; struct Matrices { diff --git a/bin/data/shaders/gui.vert.glsl b/bin/data/shaders/gui.vert.glsl index eaae9b8a..9828ff94 100644 --- a/bin/data/shaders/gui.vert.glsl +++ b/bin/data/shaders/gui.vert.glsl @@ -6,6 +6,7 @@ layout (location = 1) in vec2 inUv; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; struct Matrices { diff --git a/bin/data/shaders/heightmap.vert.glsl b/bin/data/shaders/heightmap.vert.glsl index c60999dd..f802c523 100644 --- a/bin/data/shaders/heightmap.vert.glsl +++ b/bin/data/shaders/heightmap.vert.glsl @@ -8,6 +8,7 @@ layout (location = 3) in uint inColor; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; struct Matrices { diff --git a/bin/data/shaders/line.vert.glsl b/bin/data/shaders/line.vert.glsl index da2cfef2..215c618f 100644 --- a/bin/data/shaders/line.vert.glsl +++ b/bin/data/shaders/line.vert.glsl @@ -5,6 +5,7 @@ layout (location = 0) in vec3 inPos; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; struct Matrices { diff --git a/bin/data/shaders/terrain.vert.glsl b/bin/data/shaders/terrain.vert.glsl index 042543c9..7c6d8752 100644 --- a/bin/data/shaders/terrain.vert.glsl +++ b/bin/data/shaders/terrain.vert.glsl @@ -8,6 +8,7 @@ layout (location = 3) in uint inColor; layout( push_constant ) uniform PushBlock { uint pass; + uint draw; } PushConstant; struct Matrices { diff --git a/engine/inc/uf/ext/gltf/graph.h b/engine/inc/uf/ext/gltf/graph.h index 38103750..6201800b 100644 --- a/engine/inc/uf/ext/gltf/graph.h +++ b/engine/inc/uf/ext/gltf/graph.h @@ -13,10 +13,23 @@ #include namespace pod { + struct UF_API DrawCall { + alignas(4) int32_t materialIndex = -1; + alignas(4) uint32_t materials = 0; + alignas(4) int32_t textureIndex = -1; + alignas(4) uint32_t textures = 0; + }; struct UF_API Texture { std::string name = ""; - int32_t index = -1; - int32_t sampler = -1; + struct Storage { + alignas(4) int32_t index = -1; + alignas(4) int32_t sampler = -1; + alignas(4) int32_t remap = -1; + alignas(4) float blend = 0; + + alignas(16) pod::Vector4f lerp = {0, 0, 1, 1}; + } storage; + uf::renderer::Texture2D texture; }; struct UF_API Light { std::string name = ""; @@ -35,24 +48,23 @@ namespace pod { std::string name = ""; // struct Storage { - alignas(16) pod::Vector4f colorBase = { 1, 0, 1, 1 }; - + alignas(16) pod::Vector4f colorBase = { 0, 0, 0, 0 }; alignas(16) pod::Vector4f colorEmissive = { 0, 0, 0, 0 }; alignas(4) float factorMetallic = 0.0f; alignas(4) float factorRoughness = 0.0f; alignas(4) float factorOcclusion = 0.0f; - alignas(4) float factorMappedBlend = 0.0f; - alignas(4) float factorAlphaCutoff = 1.0f; - alignas(4) float factorPadding = 0.0f; + alignas(4) int indexAlbedo = -1; alignas(4) int indexNormal = -1; - alignas(4) int indexEmissive = -1; alignas(4) int indexOcclusion = -1; + alignas(4) int indexMetallicRoughness = -1; - alignas(4) int indexMappedTarget = -1; + alignas(4) int padding1 = -1; + alignas(4) int padding2 = -1; + alignas(4) int padding3 = -1; } storage; }; struct UF_API Node { @@ -69,6 +81,7 @@ namespace pod { uf::Object* entity = NULL; size_t jointBufferIndex = -1; size_t materialBufferIndex = -1; + size_t textureBufferIndex = -1; int32_t skin = -1; Mesh mesh; diff --git a/engine/inc/uf/ext/vulkan/graphic.h b/engine/inc/uf/ext/vulkan/graphic.h index 4be6f7ac..edf3f986 100644 --- a/engine/inc/uf/ext/vulkan/graphic.h +++ b/engine/inc/uf/ext/vulkan/graphic.h @@ -78,7 +78,7 @@ namespace ext { void initialize( Graphic& graphic, GraphicDescriptor& descriptor ); void update( Graphic& graphic ); void update( Graphic& graphic, GraphicDescriptor& descriptor ); - void record( Graphic& graphic, VkCommandBuffer, size_t = 0 ); + void record( Graphic& graphic, VkCommandBuffer, size_t = 0, size_t = 0 ); void destroy(); }; struct UF_API Material { @@ -123,8 +123,8 @@ namespace ext { Pipeline& getPipeline( GraphicDescriptor& descriptor ); void updatePipelines(); - void record( VkCommandBuffer commandBuffer, size_t pass = 0 ); - void record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass = 0 ); + void record( VkCommandBuffer commandBuffer, size_t pass = 0, size_t draw = 0 ); + void record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass = 0, size_t draw = 0 ); bool hasStorage( const std::string& name ); Buffer* getStorageBuffer( const std::string& name ); diff --git a/engine/inc/uf/ext/vulkan/rendertarget.h b/engine/inc/uf/ext/vulkan/rendertarget.h index e6d61fdf..865bd5b2 100644 --- a/engine/inc/uf/ext/vulkan/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/rendertarget.h @@ -35,8 +35,10 @@ namespace ext { Device* device = VK_NULL_HANDLE; VkRenderPass renderPass = VK_NULL_HANDLE; std::vector framebuffers; - uint32_t width = 0, height = 0; + uint32_t width = 0; + uint32_t height = 0; uint8_t multiviews = 1; + uint8_t samples = 1; // RAII void initialize( Device& device ); void destroy(); diff --git a/engine/inc/uf/ext/vulkan/vulkan.h b/engine/inc/uf/ext/vulkan/vulkan.h index 84abe4f8..3a89f21f 100644 --- a/engine/inc/uf/ext/vulkan/vulkan.h +++ b/engine/inc/uf/ext/vulkan/vulkan.h @@ -52,6 +52,7 @@ namespace ext { extern UF_API bool waitOnRenderEnd; extern UF_API bool individualPipelines; extern UF_API bool multithreadedCommandRecording; + extern UF_API std::string deferredMode; extern UF_API bool deferredReconstructPosition; extern UF_API bool deferredAliasOutputToSwapchain; extern UF_API bool multiview; diff --git a/engine/src/engine/asset/asset.cpp b/engine/src/engine/asset/asset.cpp index 2fc6bd2c..c6aeb67a 100644 --- a/engine/src/engine/asset/asset.cpp +++ b/engine/src/engine/asset/asset.cpp @@ -165,6 +165,7 @@ std::string uf::Asset::load( const std::string& uri, const std::string& hash ) { UF_ASSET_REGISTER(pod::Graph) auto& metadata = this->getComponent(); + metadata[uri]["flags"]["ATLAS"] = true; ext::gltf::load_mode_t LOAD_FLAGS = 0; #define LOAD_FLAG(name)\ if ( metadata[uri]["flags"][#name].as() )\ diff --git a/engine/src/engine/object/behaviors/gltf.cpp b/engine/src/engine/object/behaviors/gltf.cpp index f79d9735..ef329bc6 100644 --- a/engine/src/engine/object/behaviors/gltf.cpp +++ b/engine/src/engine/object/behaviors/gltf.cpp @@ -274,7 +274,7 @@ void uf::GltfBehavior::tick( uf::Object& self ) { auto& storageBuffer = *graphic.getStorageBuffer("Models"); graphic.updateBuffer( (void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.instanceBufferIndex /*storageBuffer*/, false ); } - + /* if ( graph.materials.empty() && graphic.hasStorage("Materials") ) { auto& shader = graphic.material.getShader("fragment"); std::vector materials( graph.materials.size() ); @@ -307,8 +307,9 @@ void uf::GltfBehavior::tick( uf::Object& self ) { }); } auto& storageBuffer = *graphic.getStorageBuffer("Materials"); - graphic.updateBuffer( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), graph.root.materialBufferIndex /*storageBuffer*/, false ); + graphic.updateBuffer( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), graph.root.materialBufferIndex /*storageBuffer/, false ); } + */ } } diff --git a/engine/src/ext/bullet/bullet.cpp b/engine/src/ext/bullet/bullet.cpp index ea609a29..652d15c2 100644 --- a/engine/src/ext/bullet/bullet.cpp +++ b/engine/src/ext/bullet/bullet.cpp @@ -9,7 +9,7 @@ class BulletDebugDrawer : public btIDebugDraw { protected: int m; - uf::BaseMesh mesh; + uf::BaseMesh mesh; public: virtual void drawLine( const btVector3& from, const btVector3& to, const btVector3& color ) { drawLine( from, to, color, color ); @@ -51,7 +51,8 @@ public: } int getDebugMode(void) const { return m; } - const uf::BaseMesh& getMesh() const { return mesh; } + uf::BaseMesh& getMesh() { return mesh; } + const uf::BaseMesh& getMesh() const { return mesh; } }; bool ext::bullet::debugDrawEnabled = false; @@ -476,9 +477,11 @@ void UF_API ext::bullet::activateCollision( pod::Bullet& collider, bool enabled } void UF_API ext::bullet::debugDraw( uf::Object& object ) { + auto& mesh = ext::bullet::debugDrawer.getMesh(); + if ( mesh.vertices.empty() ) return; bool create = !object.hasComponent(); auto& graphic = object.getComponent(); - auto mesh = ext::bullet::debugDrawer.getMesh(); + graphic.process = false; if ( create ) { graphic.process = true; @@ -488,16 +491,16 @@ void UF_API ext::bullet::debugDraw( uf::Object& object ) { graphic.material.attachShader("./data/shaders/base.colored.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); graphic.material.attachShader("./data/shaders/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - + graphic.initialize(); - graphic.initializeGeometry( mesh ); + graphic.initializeGeometry( mesh, 0 ); graphic.descriptor.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; graphic.descriptor.fill = VK_POLYGON_MODE_LINE; graphic.descriptor.lineWidth = 8.0f; } else { graphic.process = true; - graphic.initializeGeometry( mesh ); + graphic.initializeGeometry( mesh, 0 ); graphic.getPipeline().update( graphic ); } } \ No newline at end of file diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index 3867d792..d3e9d2e1 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -181,11 +181,13 @@ namespace { vertex.id.x = nodeIndex; vertex.id.y = primitive.material; + /* if ( !(graph.mode & ext::gltf::LoadMode::SEPARATE) && (graph.mode & ext::gltf::LoadMode::ATLAS) ) { auto& material = graph.materials[primitive.material]; auto& texture = graph.textures[material.storage.indexAlbedo]; vertex.uv = graph.atlas->mapUv( vertex.uv, texture.index ); } + */ // required due to reverse-Z projection matrix flipping the X axis as well // default is to proceed with this if ( !(graph.mode & ext::gltf::LoadMode::INVERT) ){ @@ -256,6 +258,7 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t graph.mode = mode; graph.metadata = metadata; + if ( !warn.empty() ) uf::iostream << "glTF warning: " << warn << "\n"; if ( !err.empty() ) uf::iostream << "glTF error: " << err << "\n"; if ( !ret ) { uf::iostream << "glTF error: failed to parse file: " << filename << "\n"; @@ -295,12 +298,28 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t for ( auto& t : model.textures ) { auto& texture = graph.textures.emplace_back(); texture.name = t.name; - texture.index = t.source; - texture.sampler = t.sampler; + + texture.storage.index = t.source; + texture.storage.sampler = t.sampler; + if ( graph.atlas ) { + auto& atlas = *graph.atlas; + auto atlasMin = atlas.mapUv( {0, 0}, t.source ); + auto atlasMax = atlas.mapUv( {1, 1}, t.source ); + + texture.storage.lerp = { + atlasMin.x, + atlasMin.y, + + atlasMax.x, + atlasMax.y, + }; + } } } // load materials { + // null material + // graph.materials.emplace_back(); for ( auto& m : model.materials ) { auto& material = graph.materials.emplace_back(); material.name = m.name; @@ -321,25 +340,33 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t m.emissiveFactor[2], 0 }; + material.storage.factorMetallic = m.pbrMetallicRoughness.metallicFactor; material.storage.factorRoughness = m.pbrMetallicRoughness.roughnessFactor; material.storage.factorOcclusion = m.occlusionTexture.strength; - + + /* if ( 0 <= material.storage.indexAlbedo && material.storage.indexAlbedo < graph.textures.size() ) { - material.storage.indexAlbedo = graph.textures[material.storage.indexAlbedo].index; + auto& texture = graph.textures[material.storage.indexAlbedo]; + material.storage.indexAlbedo = texture.storage.index; } if ( 0 <= material.storage.indexNormal && material.storage.indexNormal < graph.textures.size() ) { - material.storage.indexNormal = graph.textures[material.storage.indexNormal].index; + auto& texture = graph.textures[material.storage.indexNormal]; + material.storage.indexNormal = texture.storage.index; } if ( 0 <= material.storage.indexEmissive && material.storage.indexEmissive < graph.textures.size() ) { - material.storage.indexEmissive = graph.textures[material.storage.indexEmissive].index; + auto& texture = graph.textures[material.storage.indexEmissive]; + material.storage.indexEmissive = texture.storage.index; } if ( 0 <= material.storage.indexOcclusion && material.storage.indexOcclusion < graph.textures.size() ) { - material.storage.indexOcclusion = graph.textures[material.storage.indexOcclusion].index; + auto& texture = graph.textures[material.storage.indexOcclusion]; + material.storage.indexOcclusion = texture.storage.index; } if ( 0 <= material.storage.indexMetallicRoughness && material.storage.indexMetallicRoughness < graph.textures.size() ) { - material.storage.indexMetallicRoughness = graph.textures[material.storage.indexMetallicRoughness].index; + auto& texture = graph.textures[material.storage.indexMetallicRoughness]; + material.storage.indexMetallicRoughness = texture.storage.index; } + */ } } // load node information/meshes diff --git a/engine/src/ext/gltf/graph.cpp b/engine/src/ext/gltf/graph.cpp index 2bf95527..5a4c43ef 100644 --- a/engine/src/ext/gltf/graph.cpp +++ b/engine/src/ext/gltf/graph.cpp @@ -2,6 +2,8 @@ #include #include +#define UF_VK_TESTING 1 + namespace { void initializeGraphics( pod::Graph& graph, uf::Object& entity ) { auto& graphic = entity.getComponent(); @@ -9,25 +11,35 @@ namespace { graphic.material.device = &uf::renderer::device; graphic.descriptor.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; graphic.descriptor.cullMode = !(graph.mode & ext::gltf::LoadMode::INVERT) ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT; // VK_CULL_MODE_NONE - if ( graph.mode & ext::gltf::LoadMode::ATLAS ) { - auto& atlas = *graph.atlas; - auto& texture = graphic.material.textures.emplace_back(); - texture.loadFromImage( atlas.getAtlas() ); - } else { - for ( auto& image : graph.images ) { - auto& texture = graphic.material.textures.emplace_back(); - if ( graph.metadata["filter"].is() ) { - std::string filter = graph.metadata["filter"].as(); - if ( filter == "NEAREST" ) { - texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST; - texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST; - } else if ( filter == "LINEAR" ) { - texture.sampler.descriptor.filter.min = VK_FILTER_LINEAR; - texture.sampler.descriptor.filter.mag = VK_FILTER_LINEAR; - } - } - texture.loadFromImage( image ); + { + #if UF_VK_TESTING + for ( auto& texture : graph.textures ) { + graphic.material.textures.emplace_back().aliasTexture(texture.texture); } + #else + if ( graph.mode & ext::gltf::LoadMode::ATLAS ) { + auto& atlas = *graph.atlas; + auto& texture = graphic.material.textures.emplace_back(); + texture.loadFromImage( atlas.getAtlas() ); + } else { + graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty); + for ( auto& image : graph.images ) { + auto& texture = graphic.material.textures.emplace_back(); + + if ( graph.metadata["filter"].is() ) { + std::string filter = graph.metadata["filter"].as(); + if ( filter == "NEAREST" ) { + texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST; + texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST; + } else if ( filter == "LINEAR" ) { + texture.sampler.descriptor.filter.min = VK_FILTER_LINEAR; + texture.sampler.descriptor.filter.mag = VK_FILTER_LINEAR; + } + } + texture.loadFromImage( image ); + } + } + #endif for ( auto& sampler : graph.samplers ) { graphic.material.samplers.emplace_back( sampler ); } @@ -104,6 +116,51 @@ void uf::graph::process( uf::Object& entity ) { for ( auto index : graph.root.children ) process( graph, index, entity ); } void uf::graph::process( pod::Graph& graph ) { + if ( graph.atlas ) { + auto& texture = *graph.textures.emplace(graph.textures.begin()); + texture.name = "atlas"; + texture.storage.index = 0; + texture.storage.sampler = 0; + texture.storage.remap = 0; + texture.storage.blend = 0; + auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas->getAtlas()); + } +#if UF_VK_TESTING + if ( graph.atlas ) { + auto& image = graph.images[0]; + auto& texture = graph.textures[0].texture; + + if ( graph.metadata["filter"].is() ) { + std::string filter = graph.metadata["filter"].as(); + if ( filter == "NEAREST" ) { + texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST; + texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST; + } else if ( filter == "LINEAR" ) { + texture.sampler.descriptor.filter.min = VK_FILTER_LINEAR; + texture.sampler.descriptor.filter.mag = VK_FILTER_LINEAR; + } + } + texture.loadFromImage( image ); + } else { + for ( size_t i = 0; i < graph.textures.size() && i < graph.images.size(); ++i ) { + auto& image = graph.images[i]; + auto& texture = graph.textures[i].texture; + + if ( graph.metadata["filter"].is() ) { + std::string filter = graph.metadata["filter"].as(); + if ( filter == "NEAREST" ) { + texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST; + texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST; + } else if ( filter == "LINEAR" ) { + texture.sampler.descriptor.filter.min = VK_FILTER_LINEAR; + texture.sampler.descriptor.filter.mag = VK_FILTER_LINEAR; + } + } + texture.loadFromImage( image ); + } + } +#endif + if ( !graph.root.entity ) graph.root.entity = new uf::Object; for ( auto index : graph.root.children ) process( graph, index, *graph.root.entity ); @@ -122,8 +179,7 @@ void uf::graph::process( pod::Graph& graph ) { (void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - true + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ); // Joints storage buffer if ( graph.mode & ext::gltf::LoadMode::SKINNED ) { @@ -134,8 +190,7 @@ void uf::graph::process( pod::Graph& graph ) { (void*) skin.inverseBindMatrices.data(), skin.inverseBindMatrices.size() * sizeof(pod::Matrix4f), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - true + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ); break; } @@ -144,7 +199,6 @@ void uf::graph::process( pod::Graph& graph ) { std::vector materials( graph.materials.size() ); for ( size_t i = 0; i < graph.materials.size(); ++i ) { materials[i] = graph.materials[i].storage; - materials[i].indexMappedTarget = i; if ( graph.metadata["alpha cutoff"].is() ) materials[i].factorAlphaCutoff = graph.metadata["alpha cutoff"].as(); } @@ -152,8 +206,19 @@ void uf::graph::process( pod::Graph& graph ) { (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - true + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + ); + // Texture storage buffer + std::vector textures( graph.textures.size() ); + for ( size_t i = 0; i < graph.textures.size(); ++i ) { + textures[i] = graph.textures[i].storage; + textures[i].remap = i; + } + graph.root.textureBufferIndex = graphic.initializeBuffer( + (void*) textures.data(), + textures.size() * sizeof(pod::Texture::Storage), + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ); } @@ -367,7 +432,6 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) std::vector materials( graph.materials.size() ); for ( size_t i = 0; i < graph.materials.size(); ++i ) { materials[i] = graph.materials[i].storage; - materials[i].indexMappedTarget = i; } if ( !ext::json::isNull( graph.metadata["tags"][node.name] ) ) { auto& info = graph.metadata["tags"][node.name]; @@ -382,6 +446,18 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, true ); + // Texture storage buffer + std::vector textures( graph.textures.size() ); + for ( size_t i = 0; i < graph.textures.size(); ++i ) { + textures[i] = graph.textures[i].storage; + textures[i].remap = i; + } + graph.root.textureBufferIndex = graphic.initializeBuffer( + (void*) textures.data(), + textures.size() * sizeof(pod::Texture::Storage), + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + ); } } diff --git a/engine/src/ext/vulkan/buffer.cpp b/engine/src/ext/vulkan/buffer.cpp index 9f5493ff..6f4f7048 100644 --- a/engine/src/ext/vulkan/buffer.cpp +++ b/engine/src/ext/vulkan/buffer.cpp @@ -212,8 +212,8 @@ void ext::vulkan::Buffers::updateBuffer( void* data, VkDeviceSize length, size_t void ext::vulkan::Buffers::updateBuffer( void* data, VkDeviceSize length, Buffer& buffer, bool stage ) { // assert(buffer.allocationInfo.size == length); - if ( buffer.allocationInfo.size != length ) { - if ( true ) { + if ( length > buffer.allocationInfo.size ) { + if ( !true ) { VK_VALIDATION_MESSAGE("Mismatch buffer update: Requesting " << buffer.allocationInfo.size << ", got " << length << "; Userdata might've been corrupted, please try validating with shader.validate() before updating buffer"); } else { length = buffer.allocationInfo.size; diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index b053d4ca..a5618f52 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -450,16 +450,16 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st size_t size = comp.get_declared_struct_size(base_type); if ( size <= 0 ) break; if ( size > device.properties.limits.maxUniformBufferRange ) { - VK_VALIDATION_MESSAGE("Invalid uniform buffer length of " << size << " for shader " << filename); + //VK_VALIDATION_MESSAGE("Invalid uniform buffer length of " << size << " for shader " << filename); size = device.properties.limits.maxUniformBufferRange; } size_t misalignment = size % device.properties.limits.minStorageBufferOffsetAlignment; if ( misalignment != 0 ) { - VK_VALIDATION_MESSAGE("Invalid uniform buffer alignment of " << misalignment << " for shader " << filename << ", correcting..."); + //VK_VALIDATION_MESSAGE("Invalid uniform buffer alignment of " << misalignment << " for shader " << filename << ", correcting..."); size += misalignment; } { - VK_VALIDATION_MESSAGE("Uniform size of " << size << " for shader " << filename); + //VK_VALIDATION_MESSAGE("Uniform size of " << size << " for shader " << filename); auto& uniform = uniforms.emplace_back(); uniform.create( size ); } @@ -496,7 +496,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st //for ( const auto& resource : res.key ) { #define LOOP_RESOURCES( key, type ) for ( size_t i = 0; i < res.key.size(); ++i ) {\ const auto& resource = res.key[i];\ - VK_VALIDATION_MESSAGE("["< device.properties.limits.maxPushConstantsSize ) { - VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename); + //VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename); size = device.properties.limits.maxPushConstantsSize; } - VK_VALIDATION_MESSAGE("Push constant size of " << size << " for shader " << filename); + //VK_VALIDATION_MESSAGE("Push constant size of " << size << " for shader " << filename); { auto& pushConstant = pushConstants.emplace_back(); pushConstant.create( size ); @@ -557,7 +557,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st } if ( specializationSize > 0 ) { specializationConstants.create( specializationSize ); - VK_VALIDATION_MESSAGE("Specialization constants size of " << specializationSize << " for shader " << filename); + //VK_VALIDATION_MESSAGE("Specialization constants size of " << specializationSize << " for shader " << filename); uint8_t* s = (uint8_t*) (void*) specializationConstants; size_t offset = 0; @@ -599,13 +599,13 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st memcpy( &buffer[0], &v, sizeof(v) ); } break; default: { - VK_VALIDATION_MESSAGE("Unregistered specialization constant type at offset " << offset << " for shader " << filename ); + //VK_VALIDATION_MESSAGE("Unregistered specialization constant type at offset " << offset << " for shader " << filename ); } break; } member["name"] = name; member["size"] = size; member["default"] = member["value"]; - VK_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename ); + //VK_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename ); metadata["specializationConstants"].emplace_back(member); memcpy( &s[offset], &buffer, size ); @@ -675,7 +675,7 @@ bool ext::vulkan::Shader::validate() { if ( it == uniforms.end() ) break; auto& uniform = *(it++); if ( uniform.data().len != buffer.allocationInfo.size ) { - VK_VALIDATION_MESSAGE("Uniform size mismatch: Expected " << buffer.allocationInfo.size << ", got " << uniform.data().len << "; fixing..."); + //VK_VALIDATION_MESSAGE("Uniform size mismatch: Expected " << buffer.allocationInfo.size << ", got " << uniform.data().len << "; fixing..."); uniform.destroy(); uniform.create(buffer.allocationInfo.size); valid = false; @@ -795,7 +795,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des for ( auto& pushConstant : shader.pushConstants ) { size_t len = pushConstant.data().len; if ( len <= 0 || len > device.properties.limits.maxPushConstantsSize ) { - VK_VALIDATION_MESSAGE("Invalid push constant length of " << len << " for shader " << shader.filename); + //VK_VALIDATION_MESSAGE("Invalid push constant length of " << len << " for shader " << shader.filename); // goto PIPELINE_INITIALIZATION_INVALID; len = device.properties.limits.maxPushConstantsSize; } @@ -931,7 +931,8 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des 1, 1, 0 ); VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; - switch ( ext::vulkan::settings::msaa ) { + // switch ( ext::vulkan::settings::msaa ) { + switch ( renderTarget.samples ) { case 64: samples = VK_SAMPLE_COUNT_64_BIT; break; case 32: samples = VK_SAMPLE_COUNT_32_BIT; break; case 16: samples = VK_SAMPLE_COUNT_16_BIT; break; @@ -992,7 +993,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des int32_t& v = ((int32_t*) s)[i]; // failsafe, because for some reason things break if ( payload["validate"].as() && v == 0 ) { - VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`"); + //VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`"); v = payload["value"].is() ? payload["value"].as() : payload["default"].as(); } payload["value"] = v; @@ -1000,7 +1001,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des uint32_t& v = ((uint32_t*) s)[i]; // failsafe, because for some reason things break if ( payload["validate"].as() && v == 0 ) { - VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`"); + //VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`"); v = payload["value"].is() ? payload["value"].as() : payload["default"].as(); } payload["value"] = v; @@ -1008,13 +1009,13 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des float& v = ((float*) s)[i]; // failsafe, because for some reason things break if ( payload["validate"].as() && v == 0 ) { - VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`"); + //VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`"); v = payload["value"].is() ? payload["value"].as() : payload["default"].as(); } payload["value"] = v; } } - VK_VALIDATION_MESSAGE("Specialization constants for shader `" << shader.filename << "`: " << shader.metadata["specializationConstants"].dump(1, '\t')); + //VK_VALIDATION_MESSAGE("Specialization constants for shader `" << shader.filename << "`: " << shader.metadata["specializationConstants"].dump(1, '\t')); { @@ -1046,20 +1047,20 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des pipelineCreateInfo.subpass = descriptor.subpass; VK_CHECK_RESULT(vkCreateGraphicsPipelines( device, device.pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline)); - VK_VALIDATION_MESSAGE("Created graphics pipeline"); + //VK_VALIDATION_MESSAGE("Created graphics pipeline"); } graphic.process = true; return; PIPELINE_INITIALIZATION_INVALID: graphic.process = false; - VK_VALIDATION_MESSAGE("Pipeline initialization invalid, updating next tick..."); + //VK_VALIDATION_MESSAGE("Pipeline initialization invalid, updating next tick..."); uf::thread::add( uf::thread::get("Main"), [&]() -> int { this->initialize( graphic, descriptor ); return 0;}, true ); return; } -void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuffer, size_t pass ) { +void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuffer, size_t pass, size_t draw ) { auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; for ( auto& shader : graphic.material.shaders ) { if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) { @@ -1072,7 +1073,8 @@ void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuf if ( shader.descriptor.stage == VK_SHADER_STAGE_VERTEX_BIT ) { struct PushConstant { uint32_t pass; - } pushConstant = { pass }; + uint32_t draw; + } pushConstant = { pass, draw }; vkCmdPushConstants( commandBuffer, pipelineLayout, shader.descriptor.stage, 0, sizeof(pushConstant), &pushConstant ); } } else { @@ -1253,18 +1255,18 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) { if ( descriptor.pBufferInfo ) { if ( descriptor.pBufferInfo[i].offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) { - VK_VALIDATION_MESSAGE("Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " (Offset: " << descriptor.pBufferInfo[i].offset << ", Range: " << descriptor.pBufferInfo[i].range << "), invalidating..."); + //VK_VALIDATION_MESSAGE("Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " (Offset: " << descriptor.pBufferInfo[i].offset << ", Range: " << descriptor.pBufferInfo[i].range << "), invalidating..."); goto PIPELINE_UPDATE_INVALID; } } if ( descriptor.pImageInfo ) { if ( descriptor.pImageInfo[i].imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ) { - VK_VALIDATION_MESSAGE("Image layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, fixing to VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL"); + //VK_VALIDATION_MESSAGE("Image layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, fixing to VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL"); auto pointer = const_cast(&descriptor.pImageInfo[i]); pointer->imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; } if ( descriptor.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && !descriptor.pImageInfo[i].sampler ) { - VK_VALIDATION_MESSAGE("Image descriptor type is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, yet lacks a sampler, adding default sampler..."); + //VK_VALIDATION_MESSAGE("Image descriptor type is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, yet lacks a sampler, adding default sampler..."); auto pointer = const_cast(&descriptor.pImageInfo[i]); pointer->sampler = emptyTexture.sampler.sampler; } @@ -1285,7 +1287,7 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip PIPELINE_UPDATE_INVALID: graphic.process = false; - VK_VALIDATION_MESSAGE("Pipeline update invalid, updating next tick..."); + //VK_VALIDATION_MESSAGE("Pipeline update invalid, updating next tick..."); uf::thread::add( uf::thread::get("Main"), [&]() -> int { this->update( graphic, descriptor ); return 0;}, true ); @@ -1427,19 +1429,19 @@ void ext::vulkan::Graphic::updatePipelines() { pair.second.update( *this ); } } -void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, size_t pass ) { - return this->record( commandBuffer, descriptor, pass ); +void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, size_t pass, size_t draw ) { + return this->record( commandBuffer, descriptor, pass, draw ); } -void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass ) { +void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass, size_t draw ) { if ( !process ) return; if ( !this->hasPipeline( descriptor ) ) { - VK_VALIDATION_MESSAGE(this << ": has no valid pipeline"); + //VK_VALIDATION_MESSAGE(this << ": has no valid pipeline"); return; } auto& pipeline = this->getPipeline( descriptor ); if ( pipeline.descriptorSet == VK_NULL_HANDLE ) { - VK_VALIDATION_MESSAGE(this << ": has no valid pipeline descriptor set"); + //VK_VALIDATION_MESSAGE(this << ": has no valid pipeline descriptor set"); return; } @@ -1451,7 +1453,7 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescrip } assert( vertexBuffer && indexBuffer ); - pipeline.record(*this, commandBuffer, pass); + pipeline.record(*this, commandBuffer, pass, draw); // Bind triangle vertex buffer (contains position and colors) VkDeviceSize offsets[1] = { 0 }; vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer->buffer, offsets); diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index 430387bf..a0ecda1b 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -18,7 +18,8 @@ const std::string ext::vulkan::RenderMode::getType() const { return ""; } const std::string ext::vulkan::RenderMode::getName() const { - return this->metadata["name"].as(); + auto& metadata = *const_cast(&this->metadata); + return metadata["name"].as(); } ext::vulkan::RenderTarget& ext::vulkan::RenderMode::getRenderTarget( size_t i ) { return renderTarget; diff --git a/engine/src/ext/vulkan/rendermodes/base.cpp b/engine/src/ext/vulkan/rendermodes/base.cpp index 34c2717b..610bcf62 100644 --- a/engine/src/ext/vulkan/rendermodes/base.cpp +++ b/engine/src/ext/vulkan/rendermodes/base.cpp @@ -208,7 +208,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) { std::array attachments = {}; // Color attachment - attachments[0].format = ext::vulkan::settings::formats::color; // Use the color format selected by the swapchain + attachments[0].format = ext::vulkan::settings::formats::color; // Use the color format selected by the swapchain attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; // We don't use multi sampling in this example attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear this attachment at the start of the render pass attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // Keep it's contents after the render pass is finished (for displaying it) @@ -218,7 +218,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) { attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; // Layout to which the attachment is transitioned when the render pass is finished // As we want to present the color buffer to the swapchain, we transition to PRESENT_KHR // Depth attachment - attachments[1].format = ext::vulkan::settings::formats::depth; // A proper depth format is selected in the example base + attachments[1].format = ext::vulkan::settings::formats::depth; // A proper depth format is selected in the example base attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at start of first subpass attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // We don't need depth after render pass has finished (DONT_CARE may result in better performance) diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index 9a23fe8c..4e1d7eb9 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -10,6 +10,7 @@ #include #include +#include const std::string ext::vulkan::DeferredRenderMode::getType() const { return "Deferred"; @@ -37,20 +38,21 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { ext::vulkan::RenderMode::initialize( device ); { renderTarget.device = &device; - // attach targets + renderTarget.samples = ext::vulkan::settings::msaa; struct { - size_t albedo, normals, position, depth, output, ping, pong; + size_t id, normals, uvs, albedo, depth, output; } attachments; - - attachments.albedo = renderTarget.attach( ext::vulkan::settings::formats::color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // albedo - attachments.normals = renderTarget.attach( ext::vulkan::settings::formats::normal, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals - if ( !settings::experimental::deferredReconstructPosition ) - attachments.position = renderTarget.attach( ext::vulkan::settings::formats::position, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // position - attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth - - // attachments.ping = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo - // attachments.pong = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo - + if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) { + attachments.id = renderTarget.attach( VK_FORMAT_R16G16_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID + attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals + attachments.uvs = renderTarget.attach( VK_FORMAT_R16G16_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // uvs + attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth + } else { + attachments.id = renderTarget.attach( VK_FORMAT_R16G16_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID + attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals + attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID + attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth + } // Attach swapchain's image as output if ( settings::experimental::deferredAliasOutputToSwapchain ) { attachments.output = renderTarget.attachments.size(); @@ -80,8 +82,145 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { } else { attachments.output = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo } - + if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) { + // First pass: fill the G-Buffer + { + renderTarget.addPass( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + { attachments.id, attachments.normals, attachments.uvs }, + {}, + attachments.depth + ); + } + // Second pass: write to output + { + renderTarget.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + { attachments.output }, + { attachments.id, attachments.normals, attachments.uvs, attachments.depth }, + attachments.depth + ); + } + } else { + // First pass: fill the G-Buffer + { + renderTarget.addPass( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + { attachments.id, attachments.normals, attachments.albedo }, + {}, + attachments.depth + ); + } + // Second pass: write to output + { + renderTarget.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + { attachments.output }, + { attachments.id, attachments.normals, attachments.albedo, attachments.depth }, + attachments.depth + ); + } + } + /* + #if UF_VK_TESTING + struct { + size_t normals, uvs, id, depth, output; + } attachments; + attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals + attachments.uvs = renderTarget.attach( VK_FORMAT_R16G16_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // uvs + attachments.id = renderTarget.attach( VK_FORMAT_R16G16_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID + attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth + #else + // attach targets + struct { + size_t normals, albedo, depth, output; + } attachments; + //VK_FORMAT_R16G16B16A16_SFLOAT + attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals + attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID + attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth + #endif + // Attach swapchain's image as output + if ( settings::experimental::deferredAliasOutputToSwapchain ) { + attachments.output = renderTarget.attachments.size(); + RenderTarget::Attachment swapchainAttachment; + swapchainAttachment.format = ext::vulkan::settings::formats::color; //device.formats.color; + swapchainAttachment.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchainAttachment.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + swapchainAttachment.aliased = true; + { + VkBool32 blendEnabled = VK_TRUE; + VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( + writeMask, + blendEnabled + ); + if ( blendEnabled == VK_TRUE ) { + blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; + blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; + } + swapchainAttachment.blendState = blendAttachmentState; + } + renderTarget.attachments.push_back(swapchainAttachment); + } else { + attachments.output = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo + } + #if UF_VK_TESTING // First pass: fill the G-Buffer + { + renderTarget.addPass( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + { attachments.normals, attachments.uvs, attachments.id }, + {}, + attachments.depth + ); + } + // Second pass: write to output + { + renderTarget.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + { attachments.output }, + { attachments.normals, attachments.uvs, attachments.id, attachments.depth }, + attachments.depth + ); + } + #else + // First pass: fill the G-Buffer + { + renderTarget.addPass( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + { attachments.normals, attachments.albedo }, + {}, + attachments.depth + ); + } + // Second pass: write to output + { + renderTarget.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + { attachments.output }, + { attachments.normals, attachments.albedo, attachments.depth }, + attachments.depth + ); + } + #endif + */ + /* + struct { + size_t albedo, normals, position, depth, output, ping, pong; + } attachments; + attachments.albedo = renderTarget.attach( ext::vulkan::settings::formats::color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // albedo + attachments.normals = renderTarget.attach( ext::vulkan::settings::formats::normal, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals + if ( !settings::experimental::deferredReconstructPosition ) + attachments.position = renderTarget.attach( ext::vulkan::settings::formats::position, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // position + attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth + + // attachments.ping = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo + // attachments.pong = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo if ( settings::experimental::deferredReconstructPosition ) { renderTarget.addPass( VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, @@ -113,6 +252,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { attachments.depth ); } + */ } renderTarget.initialize( device ); @@ -133,56 +273,54 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { blitter.initialize( this->getName() ); blitter.initializeGeometry( mesh ); - if ( settings::experimental::deferredReconstructPosition ) { - blitter.material.initializeShaders({ - {"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, - {"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} - }); - } else { - blitter.material.initializeShaders({ - {"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, - {"./data/shaders/display.subpass.stereo.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} - }); - } + + blitter.material.initializeShaders({ + {"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, + {"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} + }); { auto& scene = uf::scene::getCurrentScene(); - auto& metadata = scene.getComponent(); auto& shader = blitter.material.shaders.back(); struct SpecializationConstant { - uint32_t maxLights = 16; + uint32_t maxLights = 256; + uint32_t maxTextures = 256; }; auto& specializationConstants = shader.specializationConstants.get(); + + auto& metadata = scene.getComponent(); specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(); + specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as(); for ( auto& binding : shader.descriptorSetLayoutBindings ) { if ( binding.descriptorCount > 1 ) binding.descriptorCount = specializationConstants.maxLights; } - /* - struct Light { - alignas(16) pod::Vector4f position; - alignas(16) pod::Vector4f color; + std::vector materials(specializationConstants.maxTextures); + std::vector textures(specializationConstants.maxTextures); + std::vector drawCalls(specializationConstants.maxTextures); - alignas(4) int32_t type = 0; - alignas(4) float depthBias = 0; - alignas(4) float padding1 = 0; - alignas(4) float padding2 = 0; - - alignas(16) pod::Matrix4f view; - alignas(16) pod::Matrix4f projection; - }; - std::vector lights; - lights.resize(specializationConstants.maxLights); - - blitter.initializeBuffer( - (void*) lights.data(), - lights.size() * sizeof(Light), + for ( auto& material : materials ) material.colorBase = {0,0,0,0}; + this->metadata["materialBufferIndex"] = blitter.initializeBuffer( + (void*) materials.data(), + materials.size() * sizeof(pod::Material::Storage), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - true + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + ); + + this->metadata["textureBufferIndex"] = blitter.initializeBuffer( + (void*) textures.data(), + textures.size() * sizeof(pod::Texture::Storage), + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + ); + + this->metadata["drawCallBufferIndex"] = blitter.initializeBuffer( + (void*) drawCalls.data(), + drawCalls.size() * sizeof(pod::DrawCall), + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ); - */ } blitter.initializePipeline(); } @@ -286,11 +424,12 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectordescriptor.renderMode != this->getName() ) continue; ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor); - graphic->record( commands[i], descriptor, currentPass ); + graphic->record( commands[i], descriptor, currentPass, currentDraw++ ); } // blit any RT's that request this subpass { diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index 516f6cc7..aa5c89c2 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -6,7 +6,8 @@ #include const std::string ext::vulkan::RenderTargetRenderMode::getTarget() const { - return this->metadata["target"].as(); + auto& metadata = *const_cast(&this->metadata); + return metadata["target"].as(); } void ext::vulkan::RenderTargetRenderMode::setTarget( const std::string& target ) { this->metadata["target"] = target; @@ -56,6 +57,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { attachments.depth ); } else { + #if 1 struct { size_t albedo, normals, position, depth; } attachments; @@ -82,6 +84,35 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { attachments.depth ); } + #else + struct { + size_t normals, uvs, id, depth; + } attachments; + //VK_FORMAT_R16G16B16A16_SFLOAT + attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals + attachments.uvs = renderTarget.attach( VK_FORMAT_R16G16_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // uvs + attachments.id = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID + attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth + + // First pass: fill the G-Buffer + { + renderTarget.addPass( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + { attachments.normals, attachments.uvs, attachments.id }, + {}, + attachments.depth + ); + } + // Second pass: write to output + { + renderTarget.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + { attachments.output }, + { attachments.normals, attachments.uvs, attachments.id, attachments.depth }, + attachments.depth + ); + } + #endif } } @@ -277,10 +308,11 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto vkCmdSetViewport(commands[i], 0, 1, &viewport); vkCmdSetScissor(commands[i], 0, 1, &scissor); for ( size_t currentPass = 0; 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 ); + graphic->record( commands[i], descriptor, currentPass, currentDraw++ ); } if ( currentPass + 1 < subpasses ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); } diff --git a/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp b/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp index a84d1704..d69e62b6 100644 --- a/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp @@ -250,7 +250,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st { &renderTargets.left, &renderBlitters.left }, { &renderTargets.right, &renderBlitters.right }, }; - for ( ext::openvr::renderPass = 0; ext::openvr::renderPass < eyes.size(); ++ext::openvr::renderPass ) { + for ( size_t eyePass = 0; eyePass < eyes.size(); ++eyePass ) { auto& renderTarget = *eyes[ext::openvr::renderPass].renderTarget; auto& blitter = *eyes[ext::openvr::renderPass].blitter; // Fill GBuffer @@ -315,7 +315,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st // 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); - graphic->record( commands[i], descriptor, currentPass ); + graphic->record( commands[i], descriptor, eyePass ); } // render gui layer { diff --git a/engine/src/ext/vulkan/rendertarget.cpp b/engine/src/ext/vulkan/rendertarget.cpp index 16c97403..4b143567 100644 --- a/engine/src/ext/vulkan/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendertarget.cpp @@ -3,10 +3,6 @@ #include #include -namespace { - bool USEVR = false; -} - void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector& colors, const std::vector& inputs, size_t depth ) { Subpass pass; pass.stage = stage; @@ -24,6 +20,19 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa if ( !attachment ) { attachments.resize(attachments.size()+1); attachment = &attachments.back(); + // no MSAA for depth + if ( false && usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) { + } else { + switch ( samples ) { + case 64: attachment->samples = VK_SAMPLE_COUNT_64_BIT; break; + case 32: attachment->samples = VK_SAMPLE_COUNT_32_BIT; break; + case 16: attachment->samples = VK_SAMPLE_COUNT_16_BIT; break; + case 8: attachment->samples = VK_SAMPLE_COUNT_8_BIT; break; + case 4: attachment->samples = VK_SAMPLE_COUNT_4_BIT; break; + case 2: attachment->samples = VK_SAMPLE_COUNT_2_BIT; break; + default: attachment->samples = VK_SAMPLE_COUNT_1_BIT; break; + } + } } else { if ( attachment->view ) { vkDestroyImageView(*device, attachment->view, nullptr); @@ -47,22 +56,9 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa } else { aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; } - - VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; - switch ( ext::vulkan::settings::msaa ) { - case 64: samples = VK_SAMPLE_COUNT_64_BIT; break; - case 32: samples = VK_SAMPLE_COUNT_32_BIT; break; - case 16: samples = VK_SAMPLE_COUNT_16_BIT; break; - case 8: samples = VK_SAMPLE_COUNT_8_BIT; break; - case 4: samples = VK_SAMPLE_COUNT_4_BIT; break; - case 2: samples = VK_SAMPLE_COUNT_2_BIT; break; - default: samples = VK_SAMPLE_COUNT_1_BIT; break; - } - attachment->layout = layout; attachment->format = format; attachment->usage = usage; - attachment->samples = samples; VkImageCreateInfo imageCreateInfo = {}; imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -71,7 +67,7 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa imageCreateInfo.extent = { width, height, 1 }; imageCreateInfo.mipLevels = 1; imageCreateInfo.arrayLayers = this->multiviews; - imageCreateInfo.samples = samples; + imageCreateInfo.samples = attachment->samples; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageCreateInfo.usage = usage; imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index d646a838..3babd8cc 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -29,6 +29,7 @@ bool ext::vulkan::settings::experimental::rebuildOnTickBegin = false; bool ext::vulkan::settings::experimental::waitOnRenderEnd = false; bool ext::vulkan::settings::experimental::individualPipelines = false; bool ext::vulkan::settings::experimental::multithreadedCommandRecording = false; +std::string ext::vulkan::settings::experimental::deferredMode = ""; bool ext::vulkan::settings::experimental::deferredReconstructPosition = false; bool ext::vulkan::settings::experimental::deferredAliasOutputToSwapchain = true; bool ext::vulkan::settings::experimental::multiview = true; diff --git a/engine/src/utils/image/atlas.cpp b/engine/src/utils/image/atlas.cpp index b25767bc..a2bfe53a 100644 --- a/engine/src/utils/image/atlas.cpp +++ b/engine/src/utils/image/atlas.cpp @@ -117,12 +117,10 @@ pod::Vector2f uf::Atlas::mapUv( const pod::Vector2f& uv, size_t index ) { pod::Vector2ui coord = { uv.x * dim.x + it.coord.x, uv.y * dim.y + it.coord.y }; nuv = { (float) coord.x / (float) size.x, (float) coord.y / (float) size.y }; - nuv.y = 1.0f - nuv.y; + // nuv.y = 1.0f - nuv.y; return nuv; } - { // std::cout << "Could not find requested index of " << index << std::endl; - } return uv; } pod::Vector3f uf::Atlas::mapUv( const pod::Vector3f& uv ) { diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 8f2bf1c9..0b789899 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -325,9 +325,11 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { } lights; }; struct SpecializationConstant { - uint32_t maxLights = 32; + uint32_t maxLights = 256; + uint32_t maxTextures = 256; } specializationConstants; specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(); + specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as(); struct LightInfo { uf::Entity* entity = NULL; @@ -336,11 +338,16 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { bool shadows = false; }; std::vector entities; + std::vector graphs; + // std::vector graphs; this->process([&]( uf::Entity* entity ) { if ( !entity ) return; auto& metadata = entity->getComponent(); if ( entity == &controller ) return; if ( entity == this ) return; + if ( entity->hasComponent() ) graphs.emplace_back(&entity->getComponent()); + // if ( entity->hasComponent() && entity->hasComponent() ) graphs.emplace_back(entity); + // if ( entity->getName() != "Light" && !ext::json::isObject( metadata["light"] ) ) return; // if ( entity->hasComponent() ) { @@ -443,7 +450,66 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { graphic.material.textures.clear(); // add noise texture graphic.material.textures.emplace_back().aliasTexture(this->getComponent()); + // add materials + { + size_t attachedTextures = 0; + std::vector materials; + materials.reserve(specializationConstants.maxTextures); + std::vector textures; + textures.reserve(specializationConstants.maxTextures); + + std::vector drawCalls; + drawCalls.reserve(specializationConstants.maxTextures); + + materials.emplace_back().colorBase = {0,0,0,0}; + + for ( auto* entity : graphs ) { + auto& graph = *entity; + + size_t startMaterial = materials.size() - 1; + size_t startTexture = textures.size(); + + { + auto& drawCall = drawCalls.emplace_back(); + drawCall.materialIndex = startMaterial; + drawCall.textureIndex = startTexture; + + drawCall.materials = graph.materials.size() - 1; + drawCall.textures = graph.textures.size(); + } + for ( auto& material : graph.materials ) { + auto& m = materials.emplace_back( material.storage ); + // m.indexAlbedo += startMaterial; + // m.indexNormal += startMaterial; + // m.indexEmissive += startMaterial; + // m.indexOcclusion += startMaterial; + // m.indexMetallicRoughness += startMaterial; + } + for ( auto& texture : graph.textures ) { + auto& t = textures.emplace_back( texture.storage ); + // t.index += startTexture; + // t.remap += startTexture; + } + for ( auto& texture : graph.textures ) { + if ( !texture.texture.device ) continue; + ++attachedTextures; + graphic.material.textures.emplace_back().aliasTexture(texture.texture); + if ( graph.atlas ) break; + } + } + while ( attachedTextures++ < specializationConstants.maxTextures ) { + graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty); + } + + size_t materialBufferIndex = renderMode.metadata["materialBufferIndex"].as(); + size_t textureBufferIndex = renderMode.metadata["textureBufferIndex"].as(); + size_t drawCallBufferIndex = renderMode.metadata["drawCallBufferIndex"].as(); + graphic.updateBuffer( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), materialBufferIndex, false ); + graphic.updateBuffer( (void*) textures.data(), textures.size() * sizeof(pod::Texture::Storage), textureBufferIndex, false ); + graphic.updateBuffer( (void*) drawCalls.data(), drawCalls.size() * sizeof(pod::DrawCall), drawCallBufferIndex, false ); + } + // add lighting int updateThreshold = metadata["system"]["config"]["engine"]["scenes"]["lights"]["update threshold"].as(); std::vector lightPool; lightPool.reserve( entities.size() ); @@ -494,13 +560,18 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { } } else { lightPool.emplace_back(light); - auto& texture = graphic.material.textures.emplace_back(); - texture.aliasTexture(uf::renderer::Texture2D::empty); + graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty); } } - - for ( size_t i = 0; i < specializationConstants.maxLights && i < lightPool.size(); ++i ) - lights[i] = lightPool[i]; + { + size_t lightsAdded = 0; + for ( size_t i = 0; i < specializationConstants.maxLights && i < lightPool.size(); ++i, ++lightsAdded ) lights[i] = lightPool[i]; + // std::cout << "Shadowmaps added: " << lightsAdded << "\t"; + while ( lightsAdded++ < specializationConstants.maxLights ) { + graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty); + } + // std::cout << "Total shadowmaps: " << lightsAdded << std::endl; + } { size_t i = 0; diff --git a/ext/main.cpp b/ext/main.cpp index 321d1f59..3a26a210 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -326,6 +326,7 @@ void EXT_API ext::initialize() { uf::renderer::settings::experimental::waitOnRenderEnd = ::config["engine"]["ext"]["vulkan"]["experimental"]["wait on render end"].as(); uf::renderer::settings::experimental::individualPipelines = ::config["engine"]["ext"]["vulkan"]["experimental"]["individual pipelines"].as(); uf::renderer::settings::experimental::multithreadedCommandRecording = ::config["engine"]["ext"]["vulkan"]["experimental"]["multithreaded command recording"].as(); + uf::renderer::settings::experimental::deferredMode = ::config["engine"]["ext"]["vulkan"]["experimental"]["deferred mode"].as(); uf::renderer::settings::experimental::deferredReconstructPosition = ::config["engine"]["ext"]["vulkan"]["experimental"]["deferred reconstruct position"].as(); uf::renderer::settings::experimental::deferredAliasOutputToSwapchain = ::config["engine"]["ext"]["vulkan"]["experimental"]["deferred alias output to swapchain"].as(); uf::renderer::settings::experimental::hdr = ::config["engine"]["ext"]["vulkan"]["experimental"]["hdr"].as();