Commit for 2021.02.04.7z

This commit is contained in:
mrq 2021-02-04 00:00:00 -06:00
parent dd3d4b8de3
commit 77f24467e9
38 changed files with 890 additions and 246 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -7,6 +7,7 @@ layout (location = 2) in vec3 inNormal;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {

View File

@ -15,6 +15,7 @@ layout (location = 2) out flat Cursor outCursor;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
out gl_PerVertex {

View File

@ -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);
}

View File

@ -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

View File

@ -8,6 +8,7 @@ layout (location = 1) out flat uint outPushConstantPass;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
out gl_PerVertex {

View File

@ -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);
}
}
*/

View File

@ -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) );
}

View File

@ -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) :

View File

@ -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)] +

View File

@ -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));

View File

@ -6,6 +6,7 @@ layout (location = 1) in vec2 inUv;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {

View File

@ -6,6 +6,7 @@ layout (location = 1) in vec2 inUv;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {

View File

@ -8,6 +8,7 @@ layout (location = 3) in uint inColor;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {

View File

@ -5,6 +5,7 @@ layout (location = 0) in vec3 inPos;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {

View File

@ -8,6 +8,7 @@ layout (location = 3) in uint inColor;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {

View File

@ -13,10 +13,23 @@
#include <queue>
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;

View File

@ -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 );

View File

@ -35,8 +35,10 @@ namespace ext {
Device* device = VK_NULL_HANDLE;
VkRenderPass renderPass = VK_NULL_HANDLE;
std::vector<VkFramebuffer> 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();

View File

@ -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;

View File

@ -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<uf::Serializer>();
metadata[uri]["flags"]["ATLAS"] = true;
ext::gltf::load_mode_t LOAD_FLAGS = 0;
#define LOAD_FLAG(name)\
if ( metadata[uri]["flags"][#name].as<bool>() )\

View File

@ -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<pod::Material::Storage> 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 );
}
*/
}
}

View File

@ -9,7 +9,7 @@
class BulletDebugDrawer : public btIDebugDraw {
protected:
int m;
uf::BaseMesh<pod::Vertex_3F2F3F32B> mesh;
uf::BaseMesh<pod::Vertex_3F2F3F4F> 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<pod::Vertex_3F2F3F32B>& getMesh() const { return mesh; }
uf::BaseMesh<pod::Vertex_3F2F3F4F>& getMesh() { return mesh; }
const uf::BaseMesh<pod::Vertex_3F2F3F4F>& 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<uf::Graphic>();
auto& graphic = object.getComponent<uf::Graphic>();
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 );
}
}

View File

@ -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

View File

@ -2,6 +2,8 @@
#include <uf/ext/bullet/bullet.h>
#include <uf/utils/math/physics.h>
#define UF_VK_TESTING 1
namespace {
void initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
auto& graphic = entity.getComponent<uf::Graphic>();
@ -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>() ) {
std::string filter = graph.metadata["filter"].as<std::string>();
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>() ) {
std::string filter = graph.metadata["filter"].as<std::string>();
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>() ) {
std::string filter = graph.metadata["filter"].as<std::string>();
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>() ) {
std::string filter = graph.metadata["filter"].as<std::string>();
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<pod::Material::Storage> 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<float>() )
materials[i].factorAlphaCutoff = graph.metadata["alpha cutoff"].as<float>();
}
@ -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<pod::Texture::Storage> 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<pod::Material::Storage> 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<pod::Texture::Storage> 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
);
}
}

View File

@ -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;

View File

@ -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("["<<filename<<"] Found resource: "#type " with binding: " << comp.get_decoration(resource.id, spv::DecorationBinding));\
if ( false ) VK_VALIDATION_MESSAGE("["<<filename<<"] Found resource: "#type " with binding: " << comp.get_decoration(resource.id, spv::DecorationBinding));\
parseResource( resource, type, i );\
}
LOOP_RESOURCES( sampled_images, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER );
@ -519,16 +519,16 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
if ( size <= 0 ) continue;
// not a multiple of 4, for some reason
if ( size % 4 != 0 ) {
VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename << ", must be multiple of 4, correcting...");
//VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename << ", must be multiple of 4, correcting...");
size /= 4;
++size;
size *= 4;
}
if ( size > 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<std::string>() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename );
//VK_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as<std::string>() << " " << 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<bool>() && 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<int32_t>() ? payload["value"].as<int32_t>() : payload["default"].as<int32_t>();
}
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<bool>() && 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<uint32_t>() ? payload["value"].as<uint32_t>() : payload["default"].as<uint32_t>();
}
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<bool>() && 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<float>() ? payload["value"].as<float>() : payload["default"].as<float>();
}
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<VkDescriptorImageInfo*>(&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<VkDescriptorImageInfo*>(&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);

View File

@ -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<std::string>();
auto& metadata = *const_cast<uf::Serializer*>(&this->metadata);
return metadata["name"].as<std::string>();
}
ext::vulkan::RenderTarget& ext::vulkan::RenderMode::getRenderTarget( size_t i ) {
return renderTarget;

View File

@ -208,7 +208,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
std::array<VkAttachmentDescription, 2> 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)

View File

@ -10,6 +10,7 @@
#include <uf/utils/math/transform.h>
#include <uf/ext/vulkan/graphic.h>
#include <uf/ext/gltf/graph.h>
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<uf::Serializer>();
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<SpecializationConstant>();
auto& metadata = scene.getComponent<uf::Serializer>();
specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
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<pod::Material::Storage> materials(specializationConstants.maxTextures);
std::vector<pod::Texture::Storage> textures(specializationConstants.maxTextures);
std::vector<pod::DrawCall> 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<Light> 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::vector<ex
vkCmdSetViewport(commands[i], 0, 1, &viewport);
vkCmdSetScissor(commands[i], 0, 1, &scissor);
// render to geometry buffers
size_t currentDraw = 0;
for ( auto graphic : graphics ) {
// 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, currentPass, currentDraw++ );
}
// blit any RT's that request this subpass
{

View File

@ -6,7 +6,8 @@
#include <uf/ext/vulkan/graphic.h>
const std::string ext::vulkan::RenderTargetRenderMode::getTarget() const {
return this->metadata["target"].as<std::string>();
auto& metadata = *const_cast<uf::Serializer*>(&this->metadata);
return metadata["target"].as<std::string>();
}
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);
}

View File

@ -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
{

View File

@ -3,10 +3,6 @@
#include <uf/ext/vulkan/initializers.h>
#include <uf/utils/window/window.h>
namespace {
bool USEVR = false;
}
void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector<size_t>& colors, const std::vector<size_t>& 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;

View File

@ -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;

View File

@ -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 ) {

View File

@ -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<size_t>();
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
struct LightInfo {
uf::Entity* entity = NULL;
@ -336,11 +338,16 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
bool shadows = false;
};
std::vector<LightInfo> entities;
std::vector<pod::Graph*> graphs;
// std::vector<uf::Entity*> graphs;
this->process([&]( uf::Entity* entity ) { if ( !entity ) return;
auto& metadata = entity->getComponent<uf::Serializer>();
if ( entity == &controller ) return;
if ( entity == this ) return;
if ( entity->hasComponent<pod::Graph>() ) graphs.emplace_back(&entity->getComponent<pod::Graph>());
// if ( entity->hasComponent<pod::Graph>() && entity->hasComponent<uf::Graphic>() ) graphs.emplace_back(entity);
//
if ( entity->getName() != "Light" && !ext::json::isObject( metadata["light"] ) ) return;
//
if ( entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
@ -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<uf::renderer::Texture2D>());
// add materials
{
size_t attachedTextures = 0;
std::vector<pod::Material::Storage> materials;
materials.reserve(specializationConstants.maxTextures);
std::vector<pod::Texture::Storage> textures;
textures.reserve(specializationConstants.maxTextures);
std::vector<pod::DrawCall> 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>();
size_t textureBufferIndex = renderMode.metadata["textureBufferIndex"].as<size_t>();
size_t drawCallBufferIndex = renderMode.metadata["drawCallBufferIndex"].as<size_t>();
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<size_t>();
std::vector<UniformDescriptor::Light> 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;

View File

@ -326,6 +326,7 @@ void EXT_API ext::initialize() {
uf::renderer::settings::experimental::waitOnRenderEnd = ::config["engine"]["ext"]["vulkan"]["experimental"]["wait on render end"].as<bool>();
uf::renderer::settings::experimental::individualPipelines = ::config["engine"]["ext"]["vulkan"]["experimental"]["individual pipelines"].as<bool>();
uf::renderer::settings::experimental::multithreadedCommandRecording = ::config["engine"]["ext"]["vulkan"]["experimental"]["multithreaded command recording"].as<bool>();
uf::renderer::settings::experimental::deferredMode = ::config["engine"]["ext"]["vulkan"]["experimental"]["deferred mode"].as<std::string>();
uf::renderer::settings::experimental::deferredReconstructPosition = ::config["engine"]["ext"]["vulkan"]["experimental"]["deferred reconstruct position"].as<bool>();
uf::renderer::settings::experimental::deferredAliasOutputToSwapchain = ::config["engine"]["ext"]["vulkan"]["experimental"]["deferred alias output to swapchain"].as<bool>();
uf::renderer::settings::experimental::hdr = ::config["engine"]["ext"]["vulkan"]["experimental"]["hdr"].as<bool>();