Commit for 2021.05.19.7z

This commit is contained in:
mrq 2021-05-19 00:00:00 -05:00
parent e7da8db000
commit cc470641d4
37 changed files with 978 additions and 801 deletions

View File

@ -2,6 +2,7 @@
#pragma shader_stage(fragment)
#define TEXTURES 1
#define CUBEMAPS 1
#define MAX_TEXTURES TEXTURES
#include "../common/macros.h"
#include "../common/structs.h"

View File

@ -12,16 +12,6 @@ vec3 orthogonal(vec3 u){
const vec3 v = vec3(0.99146, 0.11664, 0.05832); // Pick any normalized vector.
return abs(dot(u, v)) > 0.99999f ? cross(u, vec3(0, 1, 0)) : cross(u, v);
}
void whitenoise(inout vec3 color, const vec4 parameters) {
const float flicker = parameters.x;
const float pieces = parameters.y;
const float blend = parameters.z;
const float time = parameters.w;
if ( blend < 0.0001 ) return;
const float freq = sin(pow(mod(time, flicker) + flicker, 1.9));
const float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
color = mix( color, vec3(whiteNoise), blend );
}
vec3 decodeNormals( vec2 enc ) {
const vec2 ang = enc*2-1;
const vec2 scth = vec2( sin(ang.x * PI), cos(ang.x * PI) );
@ -33,14 +23,12 @@ vec2 encodeNormals( vec3 n ) {
// return n.xy/p + 0.5;
return (vec2(atan(n.y,n.x)/PI, n.z)+1.0)*0.5;
}
float mipLevel( in vec2 uv ) {
const vec2 dx_vtc = dFdx(uv);
const vec2 dy_vtc = dFdy(uv);
return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < MAX_TEXTURES;
}
bool validCubemapIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < CUBEMAPS;
}
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, in Ray ray ) {
const vec3 t0 = (boundsMin - ray.origin) / ray.direction;
const vec3 t1 = (boundsMax - ray.origin) / ray.direction;
@ -50,6 +38,28 @@ vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, in Ray ray ) {
const float tEnd = max(0, min( tmax.x, min(tmax.y, tmax.z) ) - tStart);
return vec2(tStart, tEnd);
}
#if VXGI
float cascadePower( uint x ) {
return pow(1 + x, ubo.cascadePower);
// return max( 1, x * ubo.cascadePower );
}
#endif
#if !COMPUTE
void whitenoise(inout vec3 color, const vec4 parameters) {
const float flicker = parameters.x;
const float pieces = parameters.y;
const float blend = parameters.z;
const float time = parameters.w;
if ( blend < 0.0001 ) return;
const float freq = sin(pow(mod(time, flicker) + flicker, 1.9));
const float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
color = mix( color, vec3(whiteNoise), blend );
}
float mipLevel( in vec2 uv ) {
const vec2 dx_vtc = dFdx(uv);
const vec2 dy_vtc = dFdy(uv);
return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
vec4 resolve( subpassInputMS t, const uint samples ) {
vec4 resolved = vec4(0);
for ( int i = 0; i < samples; ++i ) resolved += subpassLoad(t, i);
@ -62,6 +72,7 @@ uvec4 resolve( usubpassInputMS t, const uint samples ) {
resolved /= uvec4(samples);
return resolved;
}
#endif
vec4 resolve( sampler2DMS t, ivec2 uv ) {
vec4 resolved = vec4(0);
int samples = textureSamples(t);

View File

@ -22,7 +22,6 @@ void pbr() {
for ( uint i = 0; i < ubo.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Lp = light.position;
const vec3 Liu = vec3(ubo.matrices.view[surface.pass] * vec4(light.position, 1)) - surface.position.eye;
const vec3 Li = normalize(Liu);
const float Ls = shadowFactor( light, 0.0 );

View File

@ -20,15 +20,94 @@ const vec2 poissonDisk[16] = vec2[](
#ifndef SHADOW_SAMPLES
#define SHADOW_SAMPLES ubo.shadowSamples
#endif
#if VXGI
float voxelShadowFactor( const Light, float def );
#endif
#if CUBEMAPS
float omniShadowMap( const Light light, float def ) {
return 1.0;
}
#else
float omniShadowMap( const Light light, float def ) {
float factor = 1.0;
const mat4 views[6] = {
mat4( 0, 0, 1, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 1 ),
mat4( 0, 0,-1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 ),
mat4( 1, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1 ),
mat4( 1, 0, 0, 0, 0, 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1 ),
mat4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ),
mat4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0,-1, 0, 0, 0, 0, 1 ),
};
const vec3 D = normalize(surface.position.world - light.position);
const vec3 N = abs(D);
uint A = N.y > N.x ? 1 : 0;
A = N.z > N[A] ? 2 : A;
uint index = A * 2;
if ( D[A] < 0.0 ) ++index;
vec4 positionClip = light.projection * views[index] * vec4(surface.position.world - light.position, 1.0);
positionClip.xy /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0;
if ( positionClip.z < -1 || positionClip.z >= 1 ) return 0.0;
const float eyeDepthScale = 1.0;
const float sampledDepthScale = light.view[1][1]; // light view matricies will incorporate scaling factors for some retarded reason, so we need to rescale it by grabbing from here, hopefully it remains coherent between all light matrices to ever exist in engine
const float bias = light.depthBias;
const float eyeDepth = abs(positionClip.z / positionClip.w) * eyeDepthScale;
const vec3 sampleOffsetDirections[20] = {
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1),
vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
};
float sampled = 0;
const int samples = int(SHADOW_SAMPLES);
if ( light.typeMap == 1 ) {
if ( samples < 1 ) {
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D).r * sampledDepthScale;
} else {
for ( int i = 0; i < samples; ++i ) {
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
vec2 poisson = poissonDisk[idx] / 700.0;
vec3 P = vec3( poisson.xy, (poisson.x + poisson.y) * 0.5 );
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D + P ).r * sampledDepthScale;
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
}
return factor;
}
} else if ( light.typeMap == 2 ) {
const vec2 uv = positionClip.xy * 0.5 + 0.5;
if ( samples < 1 ) {
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv).r * sampledDepthScale;
} else {
for ( int i = 0; i < samples; ++i ) {
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv + poissonDisk[idx] / 700.0 ).r * sampledDepthScale;
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
}
return factor;
}
}
return eyeDepth < sampled - bias ? 0.0 : factor;
}
#endif
float shadowFactor( const Light light, float def ) {
if ( !validTextureIndex(light.mapIndex) ) {
if ( light.typeMap != 0 ) return omniShadowMap( light, def );
if ( !validTextureIndex(light.indexMap) )
#if VXGI
return voxelShadowFactor( light, def );
#else
return 1.0;
#endif
}
vec4 positionClip = light.projection * light.view * vec4(surface.position.world, 1.0);
positionClip.xyz /= positionClip.w;
@ -54,10 +133,10 @@ float shadowFactor( const Light light, float def ) {
const float bias = light.depthBias;
const float eyeDepth = positionClip.z;
const int samples = int(SHADOW_SAMPLES);
if ( samples < 1 ) return eyeDepth < texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv).r - bias ? 0.0 : factor;
if ( samples < 1 ) return eyeDepth < texture(samplerTextures[nonuniformEXT(light.indexMap)], uv).r - bias ? 0.0 : factor;
for ( int i = 0; i < samples; ++i ) {
const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
const float lightDepth = texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv + poissonDisk[index] / 700.0 ).r;
const float lightDepth = texture(samplerTextures[nonuniformEXT(light.indexMap)], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
return factor;

View File

@ -59,9 +59,9 @@ struct Light {
float power;
int type;
int mapIndex;
int typeMap;
int indexMap;
float depthBias;
float padding;
mat4 view;
mat4 projection;
@ -135,4 +135,13 @@ struct Voxel {
vec3 normal;
vec2 uv;
vec4 color;
};
};
struct VoxelInfo {
vec3 min;
vec3 max;
float mipmapLevels;
float radianceSize;
float radianceSizeRecip;
} voxelInfo;

View File

@ -1,16 +1,4 @@
// GI
struct VoxelInfo {
vec3 min;
vec3 max;
float mipmapLevels;
float radianceSize;
float radianceSizeRecip;
} voxelInfo;
float cascadePower( uint x ) {
return pow(1 + x, ubo.cascadePower);
// return max( 1, x * ubo.cascadePower );
}
uint cascadeIndex( vec3 v ) {
float x = max3( abs( v ) );
for ( uint cascade = 0; cascade < CASCADES; ++cascade )
@ -82,7 +70,7 @@ vec4 voxelTrace( inout Ray ray, float maxDistance ) {
}
uint voxelShadowsCount = 0;
float voxelShadowFactor( const Light light, float def ) {
if ( voxelShadowsCount++ > ubo.shadowSamples ) return 1.0;
if ( voxelShadowsCount++ > ubo.vxgiShadowSamples ) return 1.0;
const float SHADOW_APERTURE = 0.2;
const float DEPTH_BIAS = 0.0;

View File

@ -3,6 +3,7 @@
#extension GL_EXT_samplerless_texture_functions : require
#define TEXTURES 1
#define CUBEMAPS 1
#define DEFERRED_SAMPLING 0
#include "../common/macros.h"

View File

@ -3,6 +3,7 @@
#extension GL_EXT_samplerless_texture_functions : require
#define TEXTURES 1
#define CUBEMAPS 1
#define DEFERRED_SAMPLING 0
#define MULTISAMPLING 0

View File

@ -5,10 +5,6 @@
void main() {
populateSurface();
const vec3 ambient = ubo.ambient.rgb * surface.material.occlusion;
surface.fragment.rgb += (0 <= surface.material.indexLightmap) ? (surface.material.albedo.rgb + ambient) : (surface.material.albedo.rgb * ambient);
pbr();
directLighting();
postProcess();
}

View File

@ -5,8 +5,9 @@
#include "../common/macros.h"
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
#if VXGI
layout (constant_id = 1) const uint CASCADES = 16;
layout (constant_id = 2) const uint CASCADES = 16;
#endif
#if !MULTISAMPLING
@ -49,6 +50,11 @@ layout (binding = 4) uniform UBO {
uint msaa;
uint shadowSamples;
float cascadePower;
uint indexSkybox;
uint vxgiShadowSamples;
float pointLightEyeDepthScale;
uint padding2;
} ubo;
layout (std140, binding = 5) readonly buffer Lights {
@ -64,33 +70,29 @@ layout (std140, binding = 8) readonly buffer DrawCalls {
DrawCall drawCalls[];
};
layout (binding = 9) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 10) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 11) uniform sampler3D samplerNoise;
#if VXGI
layout (binding = 9) uniform usampler3D voxelId[CASCADES];
layout (binding = 10) uniform sampler3D voxelUv[CASCADES];
layout (binding = 11) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 12) uniform sampler3D voxelRadiance[CASCADES];
layout (binding = 13) uniform sampler3D samplerNoise;
layout (binding = 14) uniform samplerCube samplerSkybox;
layout (binding = 15) uniform sampler2D samplerTextures[TEXTURES];
#else
layout (binding = 9) uniform sampler3D samplerNoise;
layout (binding = 10) uniform samplerCube samplerSkybox;
layout (binding = 11) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 12) uniform usampler3D voxelId[CASCADES];
layout (binding = 13) uniform sampler3D voxelUv[CASCADES];
layout (binding = 14) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 15) uniform sampler3D voxelRadiance[CASCADES];
#endif
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat uint inPushConstantPass;
layout (location = 0) out vec4 outFragColor;
layout (location = 1) out vec4 outDebugColor;
#include "../common/functions.h"
#include "../common/fog.h"
#include "../common/pbr.h"
#include "../common/shadows.h"
#if VXGI
#include "../common/vxgi.h"
#endif
#include "../common/shadows.h"
void postProcess() {
#if FOG
@ -165,7 +167,7 @@ void populateSurface() {
surface.normal.eye = vec3( ubo.matrices.view[surface.pass] * vec4(surface.normal.world, 0.0) );
if ( ID.x == 0 || ID.y == 0 ) {
surface.fragment.rgb = texture( samplerSkybox, surface.ray.direction ).rgb;
surface.fragment.rgb = texture( samplerCubemaps[ubo.indexSkybox], surface.ray.direction ).rgb;
surface.fragment.a = 0.0;
postProcess();
return;
@ -216,4 +218,17 @@ void populateSurface() {
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = material.factorOcclusion;
surface.material.indexLightmap = material.indexLightmap;
}
void directLighting() {
const vec3 ambient = ubo.ambient.rgb * surface.material.occlusion + surface.material.indirect.rgb;
surface.fragment.rgb += (0 <= surface.material.indexLightmap) ? (surface.material.albedo.rgb + ambient) : (surface.material.albedo.rgb * ambient);
#if PBR
pbr();
#elif LAMBERT
lambert();
#elif PHONG
phong();
#endif
}

View File

@ -6,10 +6,6 @@
void main() {
populateSurface();
const vec3 ambient = ubo.ambient.rgb * surface.material.occlusion;
surface.fragment.rgb += (0 <= surface.material.indexLightmap) ? (surface.material.albedo.rgb + ambient) : (surface.material.albedo.rgb * ambient);
pbr();
directLighting();
postProcess();
}

View File

@ -2,16 +2,11 @@
#pragma shader_stage(fragment)
#define VXGI 1
#include "./subpass.h"
void main() {
populateSurface();
indirectLighting();
const vec3 ambient = ubo.ambient.rgb * surface.material.occlusion + surface.material.indirect.rgb;
surface.fragment.rgb += (0 <= surface.material.indexLightmap) ? (surface.material.albedo.rgb + ambient) : (surface.material.albedo.rgb * ambient);
pbr();
directLighting();
postProcess();
}

View File

@ -8,10 +8,6 @@
void main() {
populateSurface();
indirectLighting();
const vec3 ambient = ubo.ambient.rgb * surface.material.occlusion + surface.material.indirect.rgb;
surface.fragment.rgb += (0 <= surface.material.indexLightmap) ? (surface.material.albedo.rgb + ambient) : (surface.material.albedo.rgb * ambient);
pbr();
directLighting();
postProcess();
}

View File

@ -11,136 +11,15 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
#define LAMBERT 1
#define PBR 0
#define VXGI 1
#define COMPUTE 1
const float PI = 3.14159265359;
const float EPSILON = 0.00001;
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
layout (constant_id = 2) const uint CASCADES = 16;
const float LIGHT_POWER_CUTOFF = 0.005;
layout (constant_id = 0) const uint CASCADES = 16;
layout (constant_id = 1) const uint TEXTURES = 512;
struct Matrices {
mat4 view[2];
mat4 projection[2];
mat4 iView[2];
mat4 iProjection[2];
mat4 iProjectionView[2];
vec4 eyePos[2];
mat4 vxgi;
};
struct Space {
vec3 eye;
vec3 world;
};
struct Ray {
vec3 origin;
vec3 direction;
vec3 position;
float distance;
};
struct Fog {
vec3 color;
float stepScale;
vec3 offset;
float densityScale;
float densityThreshold;
float densityMultiplier;
float absorbtion;
float padding1;
vec2 range;
float padding2;
float padding3;
};
struct Mode {
uint type;
uint scalar;
vec2 padding;
vec4 parameters;
};
struct Light {
vec3 position;
float radius;
vec3 color;
float power;
int type;
int mapIndex;
float depthBias;
float padding;
mat4 view;
mat4 projection;
};
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 indexAtlas;
int indexLightmap;
int modeAlpha;
};
struct Texture {
int index;
int samp;
int remap;
float blend;
vec4 lerp;
};
struct DrawCall {
int materialIndex;
uint materials;
int textureIndex;
uint textures;
};
struct SurfaceMaterial {
uint id;
vec4 albedo;
vec4 indirect;
float metallic;
float roughness;
float occlusion;
};
struct Surface {
vec2 uv;
Space position;
Space normal;
Ray ray;
SurfaceMaterial material;
vec4 fragment;
} surface;
#include "../common/macros.h"
#include "../common/structs.h"
layout (binding = 4) uniform UBO {
Matrices matrices;
@ -160,6 +39,11 @@ layout (binding = 4) uniform UBO {
uint msaa;
uint shadowSamples;
float cascadePower;
uint indexSkybox;
uint vxgiShadowSamples;
float pointLightEyeDepthScale;
uint padding2;
} ubo;
layout (std140, binding = 5) readonly buffer Lights {
@ -175,122 +59,22 @@ layout (std140, binding = 8) readonly buffer DrawCalls {
DrawCall drawCalls[];
};
layout (binding = 9, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
layout (binding = 10, rg16f) uniform volatile coherent image3D voxelUv[CASCADES];
layout (binding = 11, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
layout (binding = 9) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 10) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 11) uniform sampler3D samplerNoise;
layout (binding = 12, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
layout (binding = 13, rg16f) uniform volatile coherent image3D voxelUv[CASCADES];
layout (binding = 14, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
#if VXGI_HDR
layout (binding = 12, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES];
layout (binding = 15, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES];
#else
layout (binding = 12, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES];
layout (binding = 15, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES];
#endif
layout (binding = 13) uniform sampler3D samplerNoise;
layout (binding = 14) uniform samplerCube samplerSkybox;
layout (binding = 15) uniform sampler2D samplerTextures[TEXTURES];
// GGX/Towbridge-Reitz normal distribution function.
// Uses Disney's reparametrization of alpha = roughness^2.
float ndfGGX(float cosLh, float roughness) {
const float alpha = roughness * roughness;
const float alphaSq = alpha * alpha;
const float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
return alphaSq / (PI * denom * denom);
}
// Single term for separable Schlick-GGX below.
float gaSchlickG1(float cosTheta, float k) {
return cosTheta / (cosTheta * (1.0 - k) + k);
}
// Schlick-GGX approximation of geometric attenuation function using Smith's method.
float gaSchlickGGX(float cosLi, float cosLo, float roughness) {
const float r = roughness + 1.0;
const float k = (r * r) / 8.0; // Epic suggests using this roughness remapping for analytic lights.
return gaSchlickG1(cosLi, k) * gaSchlickG1(cosLo, k);
}
vec3 fresnelSchlick(vec3 F0, float cosTheta) {
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}
float random(vec3 seed, int i){
return fract(sin(dot(vec4(seed,i), vec4(12.9898,78.233,45.164,94.673))) * 43758.5453);
}
// Returns a vector that is orthogonal to u.
vec3 orthogonal(vec3 u){
u = normalize(u);
const vec3 v = vec3(0.99146, 0.11664, 0.05832); // Pick any normalized vector.
return abs(dot(u, v)) > 0.99999f ? cross(u, vec3(0, 1, 0)) : cross(u, v);
}
float rand2(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453);
}
float rand3(vec3 co){
return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453);
}
vec3 gamma( vec3 i ) {
return pow(i.rgb, vec3(1.0 / 2.2));
}
vec3 decodeNormals( vec2 enc ) {
const vec2 ang = enc*2-1;
const vec2 scth = vec2( sin(ang.x * PI), cos(ang.x * PI) );
const vec2 scphi = vec2(sqrt(1.0 - ang.y*ang.y), ang.y);
return normalize( vec3(scth.y*scphi.x, scth.x*scphi.x, scphi.y) );
}
float wrap( float i ) {
return fract(i);
}
vec2 wrap( vec2 uv ) {
return vec2( wrap( uv.x ), wrap( uv.y ) );
}
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex; // && textureIndex < ubo.textures;
}
float shadowFactor( const Light light, float def ) {
if ( !validTextureIndex(light.mapIndex) ) return 1.0;
vec4 positionClip = light.projection * light.view * vec4(surface.position.world, 1.0);
positionClip.xyz /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return def; //0.0;
if ( positionClip.y < -1 || positionClip.y >= 1 ) return def; //0.0;
if ( positionClip.z <= 0 || positionClip.z >= 1 ) return def; //0.0;
float factor = 1.0;
// spot light
if ( abs(light.type) == 2 || abs(light.type) == 3 ) {
const float dist = length( positionClip.xy );
if ( dist > 0.5 ) return def; //0.0;
// spot light with attenuation
if ( abs(light.type) == 3 ) {
factor = 1.0 - (pow(dist * 2,2.0));
}
}
const vec2 uv = positionClip.xy * 0.5 + 0.5;
const float bias = light.depthBias;
const float eyeDepth = positionClip.z;
const int samples = int(ubo.shadowSamples);
return eyeDepth < texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv).r - bias ? 0.0 : factor;
#if 0
for ( int i = 0; i < samples; ++i ) {
const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
const float lightDepth = texture(samplerTextures[nonuniformEXT(light.mapIndex)], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
return factor;
#endif
}
float cascadePower( uint x ) {
return pow(1 + x, ubo.cascadePower);
// return max( 1, x * ubo.cascadePower );
}
#include "../common/functions.h"
#undef VXGI
#include "../common/shadows.h"
void main() {
const vec3 tUvw = gl_GlobalInvocationID.xzy;

View File

@ -1,6 +1,7 @@
#version 450
#pragma shader_stage(fragment)
#define CUBEMAPS 1
#define MAX_TEXTURES TEXTURES
layout (constant_id = 0) const uint TEXTURES = 1;

View File

@ -10,6 +10,7 @@ layout (binding = 0) uniform sampler2D samplerTextures[TEXTURES];
#define PBR 0
#define LAMBERT 1
#define CUBEMAPS 1
#include "../../common/macros.h"
#include "../../common/structs.h"

View File

@ -3,6 +3,7 @@
#extension GL_EXT_nonuniform_qualifier : enable
#define CUBEMAPS 1
#define MAX_TEXTURES textures.length()
layout (constant_id = 0) const uint TEXTURES = 1;

View File

@ -4,9 +4,10 @@
#define BLEND 1
#define DEPTH_TEST 1
#define CUBEMAPS 1
layout (constant_id = 0) const uint CASCADES = 16;
layout (constant_id = 1) const uint TEXTURES = 512;
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CASCADES = 16;
#define MAX_TEXTURES textures.length()
#include "../common/macros.h"

View File

@ -2,6 +2,7 @@
#pragma shader_stage(fragment)
#define TEXTURES 1
#define CUBEMAPS 1
#define DEFERRED_SAMPLING 0
#include "../common/macros.h"

View File

@ -2,6 +2,7 @@
#pragma shader_stage(fragment)
#define TEXTURES 1
#define CUBEMAPS 1
#define DEFERRED_SAMPLING 0
#include "../common/macros.h"

View File

@ -20,7 +20,11 @@ int main(int argc, char** argv){
std::atexit([]{
uf::iostream << "Termination via std::atexit()!" << "\n";
client::terminated = !(client::ready = ext::ready = false);
ext::ready = false;
client::ready = false;
client::terminated = true;
ext::terminate();
client::terminate();
});
client::initialize();
@ -46,19 +50,12 @@ int main(int argc, char** argv){
std::string hook = "window:Resized";
json["type"] = hook;
json["invoker"] = "ext";
json["window"]["size"] = client::config["window"]["size"];
// json["window"]["size"]["x"] = client::config["window"]["size"]["x"];
// json["window"]["size"]["y"] = client::config["window"]["size"]["y"];
uf::hooks.call(hook, json);
}
#if UF_ENV_DREAMCAST
// UF_TIMER_MULTITRACE_START("==== START FRAME ====");
ext::render();
// UF_TIMER_MULTITRACE("RENDER");
ext::tick();
// UF_TIMER_MULTITRACE("TICK");
// UF_TIMER_MULTITRACE_END("==== END FRAME ====");
#else
client::render();
ext::render();
@ -81,8 +78,8 @@ int main(int argc, char** argv){
}
if ( !client::terminated ) {
uf::iostream << "Natural termination!" << "\n";
ext::terminate();
client::terminate();
}
ext::terminate();
client::terminate();
return 0;
}

View File

@ -40,9 +40,9 @@ namespace pod {
alignas(16) pod::Vector4f color;
alignas(4) int32_t type = 0;
alignas(4) int32_t mapIndex = -1;
alignas(4) int32_t typeMap = 0;
alignas(4) int32_t indexMap = -1;
alignas(4) float depthBias = 0;
alignas(4) float padding = 0;
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;

View File

@ -19,6 +19,7 @@ namespace ext {
VkImage image;
VkDeviceMemory mem;
VkImageView view;
std::vector<VkImageView> views;
VmaAllocation allocation;
VmaAllocationInfo allocationInfo;
VkPipelineColorBlendAttachmentState blendState;
@ -28,6 +29,7 @@ namespace ext {
struct Subpass {
VkPipelineStageFlags stage;
VkAccessFlags access;
uint8_t layer;
bool autoBuildPipeline;
std::vector<VkAttachmentReference> colors;
@ -47,7 +49,7 @@ namespace ext {
// RAII
void initialize( Device& device );
void destroy();
void addPass( VkPipelineStageFlags, VkAccessFlags, const std::vector<size_t>&, const std::vector<size_t>&, const std::vector<size_t>&, size_t, bool = true );
void addPass( VkPipelineStageFlags, VkAccessFlags, const std::vector<size_t>&, const std::vector<size_t>&, const std::vector<size_t>&, size_t, size_t = 0, bool = true );
size_t attach( const Attachment::Descriptor& descriptor, Attachment* attachment = NULL );
};
}

View File

@ -113,6 +113,7 @@ namespace ext {
void asRenderTarget( Device& device, uint32_t texWidth, uint32_t texHeight, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM );
void aliasTexture( const Texture& );
void aliasAttachment( const RenderTarget::Attachment& attachment, bool = true );
void aliasAttachment( const RenderTarget::Attachment& attachment, size_t, bool = true );
void update( uf::Image& image, VkImageLayout, uint32_t layer = 1 );
void update( void*, VkDeviceSize, VkImageLayout, uint32_t layer = 1 );

View File

@ -92,29 +92,41 @@ namespace {
#if UF_USE_VULKAN
{
auto& shader = graphic.material.getShader("fragment", "vxgi");
/*
struct SpecializationConstant {
uint32_t cascades = 16;
uint32_t textures = 1;
uint32_t cascades = 16;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.textures = texture2Ds;
specializationConstants.cascades = texture3Ds / 4; // 5;
ext::json::forEach( shader.metadata["specializationConstants"], [&]( ext::json::Value& sc ){
specializationConstants.cascades = texture3Ds / 4;
*/
uint32_t* specializationConstants = (uint32_t*) (void*) &shader.specializationConstants;
size_t maxTextures = texture2Ds;
size_t maxCascades = texture3Ds / 4;
ext::json::forEach( shader.metadata["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
std::string name = sc["name"].as<std::string>();
if ( name == "TEXTURES" ) sc["value"] = specializationConstants.textures;
else if ( name == "CASCADES" ) sc["value"] = specializationConstants.cascades;
if ( name == "TEXTURES" ) {
sc["value"] = (specializationConstants[i] = maxTextures);
// sc["value"] = specializationConstants.textures;
}
else if ( name == "CASCADES" ) {
sc["value"] = (specializationConstants[i] = maxCascades);
// sc["value"] = specializationConstants.cascades;
}
});
ext::json::forEach( shader.metadata["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
std::string name = t["name"].as<std::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = specializationConstants.textures;
else if ( name == "voxelId" ) layout.descriptorCount = specializationConstants.cascades;
else if ( name == "voxelUv" ) layout.descriptorCount = specializationConstants.cascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = specializationConstants.cascades;
else if ( name == "voxelRadiance" ) layout.descriptorCount = specializationConstants.cascades;
// else if ( name == "voxelDepth" ) layout.descriptorCount = specializationConstants.cascades;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures;
else if ( name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
// else if ( name == "voxelDepth" ) layout.descriptorCount = maxCascades;
}
});
}

View File

@ -12,7 +12,7 @@
#include <regex>
#define VK_DEBUG_VALIDATION_MESSAGE(x)\
//VK_VALIDATION_MESSAGE(x);
// VK_VALIDATION_MESSAGE(x);
namespace {
uint32_t VERTEX_BUFFER_BIND_ID = 0;
@ -239,6 +239,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
void* s = (void*) shader.specializationConstants;
size_t len = shader.specializationConstants.data().len;
bool invalidated = true;
for ( size_t i = 0; i < len / 4; ++i ) {
auto& payload = shader.metadata["specializationConstants"][i];
std::string type = payload["type"].as<std::string>();
@ -248,6 +249,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
if ( payload["validate"].as<bool>() && v == 0 ) {
VK_DEBUG_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>();
invalidated = true;
}
payload["value"] = v;
} else if ( type == "uint32_t" ) {
@ -256,6 +258,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
if ( payload["validate"].as<bool>() && v == 0 ) {
VK_DEBUG_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>();
invalidated = true;
}
payload["value"] = v;
} else if ( type == "float" ) {
@ -264,21 +267,23 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
if ( payload["validate"].as<bool>() && v == 0 ) {
VK_DEBUG_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>();
invalidated = true;
}
payload["value"] = v;
}
}
VK_DEBUG_VALIDATION_MESSAGE("Specialization constants for shader `" << shader.filename << "`: " << shader.metadata["specializationConstants"].dump(1, '\t'));
{
shader.specializationInfo = {};
shader.specializationInfo.mapEntryCount = shader.specializationMapEntries.size();
if ( invalidated ) {
// shader.specializationInfo = {};
// shader.specializationInfo.mapEntryCount = shader.specializationMapEntries.size();
shader.specializationInfo.pMapEntries = shader.specializationMapEntries.data();
shader.specializationInfo.pData = (void*) shader.specializationConstants;
shader.specializationInfo.dataSize = shader.specializationConstants.data().len;
// shader.specializationInfo.dataSize = shader.specializationConstants.data().len;
shader.descriptor.pSpecializationInfo = &shader.specializationInfo;
}
VK_DEBUG_VALIDATION_MESSAGE("Specialization constants for shader `" << shader.filename << "`: " << shader.specializationInfo.dataSize );
shaderDescriptors.push_back(shader.descriptor);
}
@ -371,7 +376,13 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
struct {
std::vector<VkDescriptorBufferInfo> uniform;
std::vector<VkDescriptorBufferInfo> storage;
std::vector<VkDescriptorImageInfo> image;
std::vector<VkDescriptorImageInfo> image2D;
std::vector<VkDescriptorImageInfo> imageCube;
std::vector<VkDescriptorImageInfo> image3D;
std::vector<VkDescriptorImageInfo> imageUnknown;
std::vector<VkDescriptorImageInfo> sampler;
std::vector<VkDescriptorImageInfo> input;
} infos;
@ -380,8 +391,7 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
auto& subpass = renderTarget.passes[descriptor.subpass];
for ( auto& input : subpass.inputs ) {
infos.input.push_back(ext::vulkan::initializers::descriptorImageInfo(
renderTarget.attachments[input.attachment].view,
// input.layout
renderTarget.attachments[input.attachment].views[subpass.layer],
input.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : input.layout
));
}
@ -390,13 +400,26 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
{
for ( auto& texture : graphic.material.textures ) {
infos.image.emplace_back(texture.descriptor);
switch ( texture.viewType ) {
case VK_IMAGE_VIEW_TYPE_2D:
infos.image2D.emplace_back(texture.descriptor);
break;
case VK_IMAGE_VIEW_TYPE_CUBE:
infos.imageCube.emplace_back(texture.descriptor);
break;
case VK_IMAGE_VIEW_TYPE_3D:
infos.image3D.emplace_back(texture.descriptor);
break;
default:
infos.imageUnknown.emplace_back(texture.descriptor);
break;
}
}
for ( auto& sampler : graphic.material.samplers ) {
infos.sampler.emplace_back(sampler.descriptor.info);
}
for ( auto& sampler : graphic.material.samplers ) infos.sampler.emplace_back(sampler.descriptor.info);
}
ext::json::Value bindingMapping;
size_t consumes = 0;
std::vector<std::string> types;
for ( auto* shaderPointer : shaders ) {
auto& shader = *shaderPointer;
@ -413,8 +436,6 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
PARSE_BUFFER(graphic.buffers)
// check if we can even consume that many infos
size_t consumes = 0;
std::vector<std::string> types;
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
switch ( layout.descriptorType ) {
// consume an texture image info
@ -422,43 +443,57 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
consumes += layout.descriptorCount;
std::string imageType = "";
std::string binding = std::to_string(layout.binding);
for ( auto* shaderPointer : shaders ) {
auto& shader = *shaderPointer;
auto& info = shader.metadata["definitions"]["textures"][binding];
if ( ext::json::isNull(info) ) continue;
imageType = info["type"].as<std::string>();
break;
}
std::string imageType = shader.metadata["definitions"]["textures"][binding]["type"].as<std::string>();
types.reserve(consumes);
for ( size_t i = 0; i < layout.descriptorCount; ++i ) types.emplace_back(imageType);
} break;
}
}
for ( size_t i = infos.image.size(); i < consumes; ++i ) {
std::string type = i < types.size() ? types[i] : "";
if ( type == "3D" ) {
infos.image.push_back(Texture3D::empty.descriptor);
} else if ( type == "Cube" ) {
infos.image.push_back(TextureCube::empty.descriptor);
} else {
infos.image.push_back(Texture2D::empty.descriptor);
}
}
}
size_t maxTextures2D = 0;
size_t maxTextures3D = 0;
size_t maxTexturesCube = 0;
size_t maxTexturesUnknown = 0;
for ( auto& type : types ) {
if ( type == "3D" ) ++maxTextures3D;
else if ( type == "Cube" ) ++maxTexturesCube;
else if ( type == "2D" ) ++maxTextures2D;
else ++maxTexturesUnknown;
}
while ( infos.image2D.size() < maxTextures2D ) infos.image2D.push_back(Texture2D::empty.descriptor);
while ( infos.imageCube.size() < maxTexturesCube ) infos.imageCube.push_back(TextureCube::empty.descriptor);
while ( infos.image3D.size() < maxTextures3D ) infos.image3D.push_back(Texture3D::empty.descriptor);
while ( infos.imageUnknown.size() < maxTexturesUnknown ) infos.imageUnknown.push_back(Texture2D::empty.descriptor);
for ( size_t i = infos.image.size(); i < consumes; ++i ) {
std::string type = i < types.size() ? types[i] : "";
if ( type == "3D" ) infos.image.push_back(Texture3D::empty.descriptor);
else if ( type == "Cube" ) infos.image.push_back(TextureCube::empty.descriptor);
else if ( type == "2D" ) infos.image.push_back(Texture2D::empty.descriptor);
else infos.image.push_back(Texture2D::empty.descriptor);
}
auto uniformBufferInfo = infos.uniform.begin();
auto storageBufferInfo = infos.storage.begin();
auto imageInfo = infos.image.begin();
auto image2DInfo = infos.image2D.begin();
auto imageCubeInfo = infos.imageCube.begin();
auto image3DInfo = infos.image3D.begin();
auto imageUnknownInfo = infos.imageUnknown.begin();
auto samplerInfo = infos.sampler.begin();
auto inputInfo = infos.input.begin();
#define BREAK_ASSERT(condition, ...) if ( condition ) { VK_VALIDATION_MESSAGE(#condition << "\t" << __VA_ARGS__); break; }
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
for ( auto* shaderPointer : shaders ) {
auto& shader = *shaderPointer;
// UF_DEBUG_MSG(shader.filename << ": ");
// UF_DEBUG_MSG("\tAVAILABLE UNIFORM BUFFERS: " << infos.uniform.size());
// UF_DEBUG_MSG("\tAVAILABLE STORAGE BUFFERS: " << infos.storage.size());
@ -475,10 +510,53 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
// if ( layout.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ) UF_DEBUG_MSG("\t\tCOMBINED_IMAGE_SAMPLER");
// if ( layout.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ) UF_DEBUG_MSG("\t\tSAMPLED_IMAGE");
// if ( layout.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ) UF_DEBUG_MSG("\t\tSTORAGE_IMAGE");
if ( layout.descriptorCount == 1 ) {
VkDescriptorImageInfo i = (*imageInfo);
// UF_DEBUG_MSG(i.imageView << "\t" << i.imageLayout);
// if ( layout.descriptorCount == 1 ) UF_DEBUG_MSG(i.imageView << "\t" << (*imageInfo).imageLayout);
#if 1
std::string binding = std::to_string(layout.binding);
std::string imageType = shader.metadata["definitions"]["textures"][binding]["type"].as<std::string>();
if ( imageType == "2D" ) {
BREAK_ASSERT( image2DInfo == infos.image2D.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
layout.binding,
&(*image2DInfo),
layout.descriptorCount
));
image2DInfo += layout.descriptorCount;
} else if ( imageType == "Cube" ) {
BREAK_ASSERT( imageCubeInfo == infos.imageCube.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
layout.binding,
&(*imageCubeInfo),
layout.descriptorCount
));
imageCubeInfo += layout.descriptorCount;
} else if ( imageType == "3D" ) {
BREAK_ASSERT( image3DInfo == infos.image3D.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
layout.binding,
&(*image3DInfo),
layout.descriptorCount
));
image3DInfo += layout.descriptorCount;
} else {
BREAK_ASSERT( imageUnknownInfo == infos.imageUnknown.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
layout.binding,
&(*imageUnknownInfo),
layout.descriptorCount
));
imageUnknownInfo += layout.descriptorCount;
}
#else
BREAK_ASSERT( imageInfo == infos.image.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
@ -488,6 +566,7 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
layout.descriptorCount
));
imageInfo += layout.descriptorCount;
#endif
} break;
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
// UF_DEBUG_MSG("\t["<< layout.binding << "] INSERTING " << layout.descriptorCount << " INPUT_ATTACHMENT");

View File

@ -121,6 +121,13 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.samples =*/ 1,
});
}
attachments.debug = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R32G32B32A32_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ false,
/*.samples =*/ 1,
});
metadata["outputs"].emplace_back(attachments.output);
#if 0
attachments.debug = renderTarget.attach(RenderTarget::Attachment::Descriptor{
@ -141,6 +148,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.inputs =*/ {},
/*.resolve =*/ {},
/*.depth = */ attachments.depth,
/*.layer = */0,
/*.autoBuildPipeline =*/ true
);
}
@ -148,10 +156,11 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
{
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
/*.colors =*/ { attachments.output },
/*.colors =*/ { attachments.output, attachments.debug },
/*.inputs =*/ { attachments.id, attachments.normals, attachments.uvs, attachments.depth },
/*.resolve =*/ {},
/*.depth = */ attachments.depth,
/*.layer = */0,
/*.autoBuildPipeline =*/ false
);
}
@ -164,6 +173,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.inputs =*/ {},
/*.resolve =*/ {},
/*.depth = */ attachments.depth,
/*.layer = */0,
/*.autoBuildPipeline =*/ true
);
}
@ -171,10 +181,11 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
{
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
/*.colors =*/ { attachments.output },
/*.colors =*/ { attachments.output, attachments.debug },
/*.inputs =*/ { attachments.id, attachments.normals, attachments.albedo, attachments.depth },
/*.resolve =*/ {},
/*.depth = */ attachments.depth,
/*.layer = */0,
/*.autoBuildPipeline =*/ false
);
}
@ -213,25 +224,37 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
auto& shader = blitter.material.shaders.back();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>(512);
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(128);
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
if ( ext::vulkan::settings::experimental::deferredMode == "vxgi" ) {
/*
struct SpecializationConstant {
uint32_t maxTextures = 512;
uint32_t maxTextures2D = 512;
uint32_t maxTexturesCube = 128;
uint32_t maxCascades = 16;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.maxTextures = maxTextures;
specializationConstants.maxTextures2D = maxTextures2D;
specializationConstants.maxTexturesCube = maxTexturesCube;
specializationConstants.maxCascades = maxCascades;
*/
uint32_t* specializationConstants = (uint32_t*) (void*) &shader.specializationConstants;
ext::json::forEach( shader.metadata["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
std::string name = sc["name"].as<std::string>();
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures2D);
else if ( name == "CUBEMAPS" ) sc["value"] = (specializationConstants[i] = maxTexturesCube);
else if ( name == "CASCADES" ) sc["value"] = (specializationConstants[i] = maxCascades);
});
ext::json::forEach( shader.metadata["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
std::string name = t["name"].as<std::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
else if ( name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = maxCascades;
@ -239,26 +262,37 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
}
});
} else {
/*
struct SpecializationConstant {
uint32_t maxTextures = 256;
uint32_t maxTextures2D = 512;
uint32_t maxTexturesCube = 128;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.maxTextures = maxTextures;
specializationConstants.maxTextures2D = maxTextures2D;
specializationConstants.maxTexturesCube = maxTexturesCube;
*/
uint32_t* specializationConstants = (uint32_t*) (void*) &shader.specializationConstants;
ext::json::forEach( shader.metadata["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
std::string name = sc["name"].as<std::string>();
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures2D);
else if ( name == "CUBEMAPS" ) sc["value"] = (specializationConstants[i] = maxTexturesCube);
});
ext::json::forEach( shader.metadata["definitions"]["textures"], [&]( ext::json::Value& t ){
if ( t["name"].as<std::string>() != "samplerTextures" ) return;
size_t binding = t["binding"].as<size_t>();
std::string name = t["name"].as<std::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding == binding ) layout.descriptorCount = maxTextures;
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
}
});
}
std::vector<pod::Light::Storage> lights(maxLights);
std::vector<pod::Material::Storage> materials(maxTextures);
std::vector<pod::Texture::Storage> textures(maxTextures);
std::vector<pod::DrawCall::Storage> drawCalls(maxTextures);
std::vector<pod::Material::Storage> materials(maxTextures2D);
std::vector<pod::Texture::Storage> textures(maxTextures2D);
std::vector<pod::DrawCall::Storage> drawCalls(maxTextures2D);
for ( auto& material : materials ) material.colorBase = {0,0,0,0};

View File

@ -62,140 +62,61 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
std::string type = metadata["type"].as<std::string>();
size_t subpasses = metadata["subpasses"].as<size_t>();
size_t msaa = metadata["samples"].is<size_t>() ? ext::vulkan::sampleCount(metadata["samples"].as<size_t>()) : ext::vulkan::settings::msaa;
metadata["outputs"] = ext::json::array();
if ( subpasses == 0 ) subpasses = 1;
renderTarget.device = &device;
for ( size_t currentPass = 0; currentPass < subpasses; ++currentPass ) {
if ( type == "depth" || type == "vxgi" ) {
struct {
size_t depth;
} attachments;
if ( type == "depth" || type == "vxgi" ) {
renderTarget.views = subpasses;
struct {
size_t depth;
} attachments;
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
for ( size_t currentPass = 0; currentPass < subpasses; ++currentPass ) {
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{},
{},
{},
attachments.depth,
currentPass,
true
);
} else if ( type == "single" ) {
struct {
size_t albedo, depth;
} attachments;
}
} else {
for ( size_t currentPass = 0; currentPass < subpasses; ++currentPass ) {
if ( type == "depth" || type == "vxgi" ) {
struct {
size_t depth;
} attachments;
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */true,
/*.samples = */msaa,
});
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo },
{},
{},
attachments.depth,
true
);
} else {
#if 0
struct {
size_t albedo, normals, position, depth;
} attachments;
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::color,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ true,
/*.samples = */ 1,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::normal,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
if ( !settings::experimental::deferredReconstructPosition )
attachments.position = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::position,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
// First pass: write to target
if ( settings::experimental::deferredReconstructPosition ) {
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals },
{},
{},
attachments.depth
{},
attachments.depth,
0,
true
);
} else {
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals, attachments.position },
{},
{},
attachments.depth
);
}
#else
struct {
size_t id, normals, uvs, albedo, depth, output;
} attachments;
} else if ( type == "single" ) {
struct {
size_t albedo, depth;
} attachments;
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UINT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_SFLOAT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
if ( false && ext::vulkan::settings::experimental::deferredMode != "" ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
} else {
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
@ -203,70 +124,183 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
/*.blend = */true,
/*.samples = */msaa,
});
}
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ true,
/*.samples =*/ 1,
});
if ( false && ext::vulkan::settings::experimental::deferredMode != "" ) {
// 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,
true
);
}
// 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,
false
);
}
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo },
{},
{},
attachments.depth,
0,
true
);
} else {
// First pass: fill the G-Buffer
{
#if 0
struct {
size_t albedo, normals, position, depth;
} attachments;
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::color,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ true,
/*.samples = */ 1,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::normal,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
if ( !settings::experimental::deferredReconstructPosition )
attachments.position = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::position,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
// First pass: write to target
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,
{ attachments.id, attachments.normals, attachments.albedo },
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals },
{},
{},
attachments.depth,
true
attachments.depth
);
} else {
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals, attachments.position },
{},
{},
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,
false
);
#else
struct {
size_t id, normals, uvs, albedo, depth, output;
} attachments;
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UINT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_SFLOAT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
if ( false && ext::vulkan::settings::experimental::deferredMode != "" ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
} else {
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */true,
/*.samples = */msaa,
});
}
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ true,
/*.samples =*/ 1,
});
if ( false && ext::vulkan::settings::experimental::deferredMode != "" ) {
// 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,
0,
true
);
}
// 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,
0,
false
);
}
} 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,
0,
true
);
}
// 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,
0,
false
);
}
}
// metadata["outputs"][0] = attachments.output;
metadata["outputs"].emplace_back(attachments.output);
#endif
}
metadata["outputs"][0] = attachments.output;
#endif
}
}
@ -347,27 +381,40 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
if ( metadata["type"].as<std::string>() == "vxgi" ) {
auto& scene = uf::scene::getCurrentScene();
auto& shader = blitter.material.getShader("compute");
struct SpecializationConstant {
uint32_t maxCascades = 16;
uint32_t maxTextures = 512;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>(512);
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(1);
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
specializationConstants.maxTextures = maxTextures;
auto& shader = blitter.material.getShader("compute");
/*
struct SpecializationConstant {
uint32_t maxTextures2D = 512;
uint32_t maxTexturesCube = 128;
uint32_t maxCascades = 16;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.maxTextures2D = maxTextures2D;
specializationConstants.maxTexturesCube = maxTexturesCube;
specializationConstants.maxCascades = maxCascades;
*/
uint32_t* specializationConstants = (uint32_t*) (void*) &shader.specializationConstants;
ext::json::forEach( shader.metadata["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
std::string name = sc["name"].as<std::string>();
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures2D);
else if ( name == "CUBEMAPS" ) sc["value"] = (specializationConstants[i] = maxTexturesCube);
else if ( name == "CASCADES" ) sc["value"] = (specializationConstants[i] = maxCascades);
});
ext::json::forEach( shader.metadata["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
std::string name = t["name"].as<std::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
else if ( name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = maxCascades;
@ -376,9 +423,9 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
});
std::vector<pod::Light::Storage> lights(maxLights);
std::vector<pod::Material::Storage> materials(specializationConstants.maxTextures);
std::vector<pod::Texture::Storage> textures(specializationConstants.maxTextures);
std::vector<pod::DrawCall::Storage> drawCalls(specializationConstants.maxTextures);
std::vector<pod::Material::Storage> materials(maxTextures2D);
std::vector<pod::Texture::Storage> textures(maxTextures2D);
std::vector<pod::DrawCall::Storage> drawCalls(maxTextures2D);
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
@ -581,14 +628,16 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
{
std::vector<VkClearValue> clearValues;
for ( auto& attachment : renderTarget.attachments ) {
VkClearValue clearValue;
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
clearValue.color = { { 0.0f, 0.0f, 0.0f, 0.0f } };
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
clearValue.depthStencil = { 0.0f, 0 };
for ( size_t j = 0; j < renderTarget.views; ++j ) {
for ( auto& attachment : renderTarget.attachments ) {
VkClearValue clearValue;
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
clearValue.color = { { 0.0f, 0.0f, 0.0f, 0.0f } };
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
clearValue.depthStencil = { 0.0f, 0 };
}
clearValues.push_back(clearValue);
}
clearValues.push_back(clearValue);
}
VkRenderPassBeginInfo renderPassBeginInfo = {};

View File

@ -5,15 +5,15 @@
#include <uf/ext/vulkan/initializers.h>
#include <uf/utils/window/window.h>
void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector<size_t>& colors, const std::vector<size_t>& inputs, const std::vector<size_t>& resolves, size_t depth, bool autoBuildPipeline ) {
void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector<size_t>& colors, const std::vector<size_t>& inputs, const std::vector<size_t>& resolves, size_t depth, size_t layer, bool autoBuildPipeline ) {
Subpass pass;
pass.stage = stage;
pass.access = access;
pass.layer = layer;
pass.autoBuildPipeline = autoBuildPipeline;
for ( auto& i : colors ) pass.colors.push_back( { (uint32_t) i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } );
for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
for ( auto& i : resolves ) pass.resolves.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
// for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
if ( depth < attachments.size() ) pass.depth = { (uint32_t) depth, attachments[depth].descriptor.layout };
if ( !resolves.empty() && resolves.size() != colors.size() )
@ -22,14 +22,21 @@ void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFla
passes.push_back(pass);
}
size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descriptor, Attachment* attachment ) {
if ( this->views == 0 ) this->views = 1;
size_t index = attachments.size();
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
if ( attachment ) {
if ( attachment->view ) {
vkDestroyImageView(*device, attachment->view, nullptr);
attachment->view = VK_NULL_HANDLE;
if ( attachment->view != attachment->views.front() ) {
vkDestroyImageView(*device, attachment->view, nullptr);
attachment->view = VK_NULL_HANDLE;
}
}
for ( size_t i = 0; i < this->views; ++i ) vkDestroyImageView(*device, attachment->views[i], nullptr);
attachment->views.clear();
if ( attachment->image ) {
vmaDestroyImage( allocator, attachment->image, attachment->allocation );
attachment->image = VK_NULL_HANDLE;
@ -40,6 +47,7 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
} else {
attachment = &attachments.emplace_back();
attachment->descriptor = descriptor;
attachment->views.resize(this->views);
}
// un-request transient attachments if not supported yet requested
if ( attachment->descriptor.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ) {
@ -71,6 +79,9 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = attachment->descriptor.usage;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
if ( this->views == 6 ) {
imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
@ -89,7 +100,7 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
}
VkImageViewCreateInfo imageView = {};
imageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageView.viewType = this->views == 6 ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D;
imageView.format = attachment->descriptor.format;
imageView.subresourceRange = {};
imageView.subresourceRange.aspectMask = aspectMask;
@ -98,9 +109,19 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
imageView.subresourceRange.baseArrayLayer = 0;
imageView.subresourceRange.layerCount = this->views;
imageView.image = attachment->image;
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->view));
if ( this->views == 1 ) {
attachment->views[0] = attachment->view;
} else {
imageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageView.subresourceRange.layerCount = 1;
for ( size_t i = 0; i < this->views; ++i ) {
imageView.subresourceRange.baseArrayLayer = i;
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->views[i]));
}
}
{
VkBool32 blendEnabled = VK_FALSE;
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT;
@ -125,7 +146,7 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
attachment->blendState = blendAttachmentState;
}
return attachments.size()-1;
return index;
}
void ext::vulkan::RenderTarget::initialize( Device& device ) {
// Bind
@ -146,24 +167,35 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
// Create render pass
if ( !renderPass ) {
std::vector<VkAttachmentDescription> attachments; attachments.reserve( this->attachments.size() );
for ( auto& attachment : this->attachments ) {
VkAttachmentDescription description;
description.format = attachment.descriptor.format;
description.samples = ext::vulkan::sampleCount( attachment.descriptor.samples );
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
description.storeOp = attachment.descriptor.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
description.finalLayout = attachment.descriptor.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : attachment.descriptor.layout;
description.flags = 0;
for ( size_t i = 0; i < this->views; ++i ) {
for ( auto& attachment : this->attachments ) {
VkAttachmentDescription description;
description.format = attachment.descriptor.format;
description.samples = ext::vulkan::sampleCount( attachment.descriptor.samples );
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
description.storeOp = attachment.descriptor.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
description.finalLayout = attachment.descriptor.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : attachment.descriptor.layout;
description.flags = 0;
attachments.push_back(description);
attachments.push_back(description);
}
}
// ensure that the subpasses are already described
auto passes = this->passes;
assert( passes.size() > 0 );
// expand attachment indices
for ( auto& pass : passes ) {
for ( auto& input : pass.inputs ) input.attachment += pass.layer * this->attachments.size();
for ( auto& color : pass.colors ) color.attachment += pass.layer * this->attachments.size();
for ( auto& resolve : pass.resolves ) resolve.attachment += pass.layer * this->attachments.size();
pass.depth.attachment += pass.layer * this->attachments.size();
}
std::vector<VkSubpassDescription> descriptions;
std::vector<VkSubpassDependency> dependencies;
@ -297,7 +329,6 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
// std::cout << renderPass << ": " << attachments.size() << std::endl;
}
{
// destroy previous framebuffers
for ( auto& framebuffer : framebuffers ) vkDestroyFramebuffer( device, framebuffer, nullptr );
@ -305,19 +336,21 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
RenderMode& base = ext::vulkan::getRenderMode( "Swapchain", false );
framebuffers.resize(ext::vulkan::swapchain.buffers);
for ( size_t i = 0; i < framebuffers.size(); ++i ) {
std::vector<VkImageView> attachments;
for ( auto& attachment : this->attachments ) {
if ( attachment.descriptor.aliased && attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) {
attachments.push_back(base.renderTarget.attachments[i].view);
} else attachments.push_back(attachment.view);
std::vector<VkImageView> attachmentViews;
for ( size_t j = 0; j < this->views; ++j ) {
for ( auto& attachment : this->attachments ) {
if ( attachment.descriptor.aliased && attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) {
attachmentViews.push_back(base.renderTarget.attachments[i].view);
} else attachmentViews.push_back(attachment.views[j]);
}
}
VkFramebufferCreateInfo frameBufferCreateInfo = {};
frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
// All frame buffers use the same renderpass setup
frameBufferCreateInfo.renderPass = renderPass;
frameBufferCreateInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
frameBufferCreateInfo.pAttachments = attachments.data();
frameBufferCreateInfo.attachmentCount = static_cast<uint32_t>(attachmentViews.size());
frameBufferCreateInfo.pAttachments = attachmentViews.data();
frameBufferCreateInfo.width = width;
frameBufferCreateInfo.height = height;
frameBufferCreateInfo.layers = 1;
@ -335,8 +368,14 @@ void ext::vulkan::RenderTarget::destroy() {
for ( auto& attachment : attachments ) {
if ( attachment.descriptor.aliased ) continue;
vkDestroyImageView( *device, attachment.view, nullptr );
attachment.view = VK_NULL_HANDLE;
if ( attachment.view ) {
if ( attachment.view != attachment.views.front() ) {
vkDestroyImageView(*device, attachment.view, nullptr);
attachment.view = VK_NULL_HANDLE;
}
}
for ( size_t i = 0; i < this->views; ++i ) vkDestroyImageView(*device, attachment.views[i], nullptr);
attachment.views.clear();
// vkDestroyImage( *device, attachment.image, nullptr );
vmaDestroyImage( allocator, attachment.image, attachment.allocation );
attachment.image = VK_NULL_HANDLE;

View File

@ -13,7 +13,7 @@
#include <regex>
#define VK_DEBUG_VALIDATION_MESSAGE(x)\
//VK_VALIDATION_MESSAGE(x);
// VK_VALIDATION_MESSAGE(x);
ext::json::Value ext::vulkan::definitionToJson(/*const*/ ext::json::Value& definition ) {
ext::json::Value member;
@ -628,7 +628,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
memcpy( &s[offset], &buffer, size );
offset += size;
}
/*
{
specializationInfo = {};
specializationInfo.dataSize = specializationSize;
@ -637,7 +637,6 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
specializationInfo.pData = (void*) specializationConstants;
descriptor.pSpecializationInfo = &specializationInfo;
}
*/
}
/*
*/

View File

@ -558,6 +558,8 @@ void ext::vulkan::Texture::asRenderTarget( Device& device, uint32_t width, uint3
void ext::vulkan::Texture::aliasTexture( const Texture& texture ) {
image = texture.image;
view = texture.view;
type = texture.type;
viewType = texture.viewType;
imageLayout = texture.imageLayout;
deviceMemory = texture.deviceMemory;
width = texture.width;
@ -572,6 +574,8 @@ void ext::vulkan::Texture::aliasTexture( const Texture& texture ) {
}
void ext::vulkan::Texture::aliasAttachment( const RenderTarget::Attachment& attachment, bool createSampler ) {
image = attachment.image;
type = VK_IMAGE_TYPE_2D;
viewType = attachment.views.size() == 6 ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D;
view = attachment.view;
imageLayout = attachment.descriptor.layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : attachment.descriptor.layout;
deviceMemory = attachment.mem;
@ -584,6 +588,22 @@ void ext::vulkan::Texture::aliasAttachment( const RenderTarget::Attachment& atta
this->updateDescriptors();
}
void ext::vulkan::Texture::aliasAttachment( const RenderTarget::Attachment& attachment, size_t layer, bool createSampler ) {
image = attachment.image;
type = VK_IMAGE_TYPE_2D;
viewType = VK_IMAGE_VIEW_TYPE_2D;
view = attachment.views[layer];
imageLayout = attachment.descriptor.layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : attachment.descriptor.layout;
deviceMemory = attachment.mem;
// Create sampler
if ( createSampler ) {
// sampler.initialize( ext::vulkan::device );
sampler = ext::vulkan::Sampler::retrieve( sampler.descriptor );
}
this->updateDescriptors();
}
void ext::vulkan::Texture::update( uf::Image& image, VkImageLayout targetImageLayout, uint32_t layer ) {
if ( width != image.getDimensions()[0] || height != image.getDimensions()[1] ) return;

View File

@ -226,7 +226,7 @@ void ext::BakingBehavior::tick( uf::Object& self ) {
light.color = info.color;
light.type = info.type;
light.mapIndex = -1;
light.indexMap = -1;
light.depthBias = info.bias;
if ( info.shadows && entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
@ -238,14 +238,14 @@ void ext::BakingBehavior::tick( uf::Object& self ) {
graphic.material.textures.emplace_back().aliasAttachment(attachment);
light.mapIndex = textureSlot++;
light.indexMap = textureSlot++;
light.view = camera.getView(view);
light.projection = camera.getProjection(view);
lights.emplace_back(light);
++view;
}
light.mapIndex = -1;
light.indexMap = -1;
} else {
lights.emplace_back(light);
}

View File

@ -227,13 +227,20 @@ void ext::LightBehavior::tick( uf::Object& self ) {
if ( metadata.shadows && std::abs(metadata.type) == 1 ) {
auto transform = camera.getTransform();
std::vector<pod::Quaternion<>> rotations = {
uf::quaternion::axisAngle( { 0, 1, 0 }, 0 * 1.57079633 ),
uf::quaternion::axisAngle( { 0, 1, 0 }, 1 * 1.57079633 ),
uf::quaternion::axisAngle( { 0, 1, 0 }, 2 * 1.57079633 ),
uf::quaternion::axisAngle( { 0, 1, 0 }, 3 * 1.57079633 ),
uf::quaternion::axisAngle( { 1, 0, 0 }, 1 * 1.57079633 ),
uf::quaternion::axisAngle( { 1, 0, 0 }, 3 * 1.57079633 ),
uf::quaternion::axisAngle( { 0, 1, 0 }, 1 * 1.57079633 ), // right
uf::quaternion::axisAngle( { 0, 1, 0 }, 3 * 1.57079633 ), // left
uf::quaternion::axisAngle( { 1, 0, 0 }, 3 * 1.57079633 ), // down
uf::quaternion::axisAngle( { 1, 0, 0 }, 1 * 1.57079633 ), // up
uf::quaternion::axisAngle( { 0, 1, 0 }, 0 * 1.57079633 ), // front
uf::quaternion::axisAngle( { 0, 1, 0 }, 2 * 1.57079633 ), // back
/*
uf::quaternion::axisAngle( { 0, 1, 0 }, 1 * 1.57079633 ), // right
uf::quaternion::axisAngle( { 0, 1, 0 }, -1 * 1.57079633 ), // left
uf::quaternion::axisAngle( { 1, 0, 0 }, -1 * 1.57079633 ), // up
uf::quaternion::axisAngle( { 1, 0, 0 }, 1 * 1.57079633 ), // down
uf::quaternion::axisAngle( { 0, 1, 0 }, 0 * 1.57079633 ), // front
uf::quaternion::axisAngle( { 0, 1, 0 }, 2 * 1.57079633 ), // back
*/
};
for ( size_t i = 0; i < rotations.size(); ++i ) {
auto transform = camera.getTransform();

View File

@ -225,7 +225,12 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
metadataJson["light"]["fog"]["density"]["scale"] = metadata.fog.density.scale;
};
metadata.deserialize = [&](){
metadata.max.textures = ext::config["engine"]["scenes"]["textures"]["max"].as<size_t>();
if ( !metadataJson["light"]["point light eye depth scale"].is<float>() )
metadataJson["light"]["point light eye depth scale"] = ext::config["engine"]["scenes"]["lights"]["point light eye depth scale"];
metadata.max.textures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>();
metadata.max.texturesCube = ext::config["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>();
metadata.max.textures3D = ext::config["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>();
metadata.max.lights = ext::config["engine"]["scenes"]["lights"]["max"].as<size_t>();
metadata.light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as<bool>() && metadataJson["light"]["should"].as<bool>();
@ -238,6 +243,9 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
metadata.light.exposure = metadataJson["light"]["exposure"].as<float>(1.0f);
metadata.light.gamma = metadataJson["light"]["gamma"].as<float>(2.2f);
metadata.light.experimentalMode = ext::config["engine"]["scenes"]["experimental mode"].as<size_t>(0);
metadata.light.vxgiShadowSamples = ext::config["engine"]["scenes"]["vxgi shadow samples"].as<size_t>(0);
metadata.fog.color = uf::vector::decode( metadataJson["light"]["fog"]["color"], pod::Vector3f{ 1, 1, 1 } );
metadata.fog.stepScale = metadataJson["light"]["fog"]["step scale"].as<float>();
metadata.fog.absorbtion = metadataJson["light"]["fog"]["absorbtion"].as<float>();
@ -366,7 +374,9 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
#if UF_ENTITY_METADATA_USE_JSON
metadata.deserialize();
#else
if ( !metadata.max.textures ) metadata.max.textures = ext::config["engine"]["scenes"]["textures"]["max"].as<size_t>();
if ( !metadata.max.textures2D ) metadata.max.textures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>();
if ( !metadata.max.texturesCube ) metadata.max.texturesCube = ext::config["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>();
if ( !metadata.max.textures3D ) metadata.max.textures3D = ext::config["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>();
if ( !metadata.max.lights ) metadata.max.lights = ext::config["engine"]["scenes"]["lights"]["max"].as<size_t>();
if ( !metadata.light.enabled ) metadata.light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as<bool>() && metadataJson["light"]["should"].as<bool>();
@ -453,7 +463,6 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
for ( ; i < metadata.max.lights; ++i ) GL_ERROR_CHECK(glDisable(GL_LIGHT0+i));
}
#elif UF_USE_VULKAN
size_t maxTextures = metadata.max.textures;
struct UniformDescriptor {
struct Matrices {
alignas(16) pod::Matrix4f view[2];
@ -496,11 +505,12 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
alignas(4) uint32_t msaa;
alignas(4) uint32_t shadowSamples;
alignas(4) float cascadePower;
alignas(4) uint32_t indexSkybox;
alignas(4) uint32_t vxgiShadowSamples;
alignas(4) uint32_t padding1;
alignas(4) uint32_t padding2;
};
struct SpecializationConstant {
uint32_t maxTextures = 512;
} specializationConstants;
specializationConstants.maxTextures = maxTextures;
struct LightInfo {
uf::Entity* entity = NULL;
@ -561,190 +571,226 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
}
entities = scratch;
}
auto& sceneTextures = this->getComponent<pod::SceneTextures>();
std::vector<uf::renderer::Texture> textures2D;
std::vector<uf::renderer::Texture> textures3D;
std::vector<uf::renderer::Texture> texturesCube;
int32_t updateThreshold = metadata.light.updateThreshold;
std::vector<pod::Light::Storage> lights;
lights.reserve( metadata.max.lights );
std::vector<pod::Material::Storage> materials;
materials.reserve(metadata.max.textures2D);
materials.emplace_back().colorBase = {0,0,0,0};
std::vector<pod::Texture::Storage> textures;
textures.reserve(metadata.max.textures2D);
std::vector<pod::DrawCall::Storage> drawCalls;
drawCalls.reserve(metadata.max.textures2D);
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
pod::Vector3f max = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
// add materials
for ( auto* g : graphs ) {
auto& graph = *g;
drawCalls.emplace_back(pod::DrawCall::Storage{
materials.size(),
graph.materials.size(),
textures.size(),
graph.textures.size()
});
for ( auto& material : graph.materials ) materials.emplace_back( material.storage );
for ( auto& texture : graph.textures ) textures.emplace_back( texture.storage );
for ( auto& texture : graph.textures ) {
if ( !texture.bind ) continue;
textures2D.emplace_back().aliasTexture(texture.texture);
}
}
// add skyboxes
texturesCube.emplace_back().aliasTexture(sceneTextures.skybox);
textures3D.emplace_back().aliasTexture(sceneTextures.noise);
// add lighting
for ( size_t i = 0; i < entities.size() && lights.size() < metadata.max.lights; ++i ) {
auto& info = entities[i];
uf::Entity* entity = info.entity;
auto& transform = entity->getComponent<pod::Transform<>>();
auto& lightMetadata = entity->getComponent<ext::LightBehavior::Metadata>();
auto& lightCamera = entity->getComponent<uf::Camera>();
lightMetadata.renderer.rendered = true;
pod::Light::Storage light;
light.position = info.position;
light.color = info.color;
light.type = info.type;
light.typeMap = 0;
light.indexMap = -1;
light.depthBias = info.bias;
if ( info.shadows && entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
if ( lightMetadata.renderer.mode == "in-range" && --updateThreshold > 0 ) {
renderMode.execute = true;
// UF_DEBUG_MSG( renderModeName << "\t" << entity->getName() << "\t" << renderMode.execute );
}
// cubemap
if ( metadata.light.experimentalMode > 0 && renderMode.renderTarget.views == 6 ) {
light.typeMap = metadata.light.experimentalMode;
light.view = lightCamera.getView(0);
light.projection = lightCamera.getProjection(0);
if ( light.typeMap == 2 ) {
light.indexMap = textures2D.size();
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
for ( size_t view = 0; view < renderMode.renderTarget.views; ++view ) {
textures2D.emplace_back().aliasAttachment(attachment, view);
}
break;
}
} else {
light.indexMap = texturesCube.size();
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
texturesCube.emplace_back().aliasAttachment(attachment);
break;
}
}
lights.emplace_back(light);
} else {
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
if ( attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
for ( size_t view = 0; view < renderMode.renderTarget.views; ++view ) {
light.indexMap = textures2D.size();
light.view = lightCamera.getView(view);
light.projection = lightCamera.getProjection(view);
lights.emplace_back(light);
textures2D.emplace_back().aliasAttachment(attachment, view);
}
}
}
light.indexMap = -1;
} else {
lights.emplace_back(light);
}
}
// add VXGI
if ( uf::renderer::settings::experimental::deferredMode == "vxgi" ) {
for ( auto& t : sceneTextures.voxels.id ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.uv ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) textures3D.emplace_back().aliasTexture(t);
}
// UF_DEBUG_MSG( "Before: " << textures2D.size() << " | " << metadata.max.textures2D << " || " << texturesCube.size() << " | " << metadata.max.texturesCube << " || " << textures3D.size() << " | " << metadata.max.textures3D );
while ( textures2D.size() < metadata.max.textures2D ) textures2D.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
while ( texturesCube.size() < metadata.max.texturesCube ) texturesCube.emplace_back().aliasTexture(uf::renderer::TextureCube::empty);
while ( textures3D.size() < metadata.max.textures3D ) textures3D.emplace_back().aliasTexture(uf::renderer::Texture3D::empty);
// UF_DEBUG_MSG( "After: " << textures2D.size() << " | " << metadata.max.textures2D << " || " << texturesCube.size() << " | " << metadata.max.texturesCube << " || " << textures3D.size() << " | " << metadata.max.textures3D );
UniformDescriptor uniforms; {
for ( std::size_t i = 0; i < 2; ++i ) {
uniforms.matrices.view[i] = camera.getView( i );
uniforms.matrices.projection[i] = camera.getProjection( i );
uniforms.matrices.iView[i] = uf::matrix::inverse( uniforms.matrices.view[i] );
uniforms.matrices.iProjection[i] = uf::matrix::inverse( uniforms.matrices.projection[i] );
uniforms.matrices.iProjectionView[i] = uf::matrix::inverse( uniforms.matrices.projection[i] * uniforms.matrices.view[i] );
uniforms.matrices.eyePos[i] = camera.getEye( i );
}
uniforms.ambient = metadata.light.ambient;
uniforms.msaa = ext::vulkan::settings::msaa;
uniforms.shadowSamples = shadowSamples;
uniforms.exposure = metadata.light.exposure;
uniforms.gamma = metadata.light.gamma;
uniforms.indexSkybox = 0;
uniforms.vxgiShadowSamples = metadata.light.vxgiShadowSamples;
uniforms.fog.color = metadata.fog.color;
uniforms.fog.color.w = metadata.fog.stepScale;
float timescale = metadata.fog.density.timescale;
uniforms.fog.offset = metadata.fog.density.offset * uf::physics::time::current * timescale;
uniforms.fog.offset.w = metadata.fog.density.scale;
uniforms.fog.densityThreshold = metadata.fog.density.threshold;
uniforms.fog.densityMultiplier = metadata.fog.density.multiplier;
uniforms.fog.absorbtion = metadata.fog.absorbtion;
uniforms.fog.range = metadata.fog.range;
uniforms.mode.type.x = metadataJson["system"]["renderer"]["shader"]["mode"].as<size_t>();
uniforms.mode.type.y = metadataJson["system"]["renderer"]["shader"]["scalar"].as<size_t>();
uniforms.mode.parameters = uf::vector::decode( metadataJson["system"]["renderer"]["shader"]["parameters"], uniforms.mode.parameters );
if ( metadataJson["system"]["renderer"]["shader"]["parameters"][3].as<std::string>() == "time" ) {
uniforms.mode.parameters.w = uf::physics::time::current;
}
uniforms.matrices.vxgi = sceneTextures.voxels.matrix;
uniforms.cascadePower = sceneTextures.voxels.cascadePower;
uniforms.lengths.materials = std::min( materials.size(), metadata.max.textures2D );
uniforms.lengths.textures = std::min( textures.size(), metadata.max.textures2D );
uniforms.lengths.drawCalls = std::min( drawCalls.size(), metadata.max.textures2D );
uniforms.lengths.lights = std::min( lights.size(), metadata.max.lights );
}
for ( auto* blitter : blitters ) {
auto& graphic = *blitter;
if ( !graphic.initialized ) continue;
auto& shader = graphic.material.getShader(isCompute ? "compute" : "fragment");
auto& uniform = shader.getUniform("UBO");
uint8_t* buffer = (uint8_t*) (void*) uniform;
UniformDescriptor* uniforms = (UniformDescriptor*) buffer;
for ( std::size_t i = 0; i < 2; ++i ) {
uniforms->matrices.view[i] = camera.getView( i );
uniforms->matrices.projection[i] = camera.getProjection( i );
uniforms->matrices.iView[i] = uf::matrix::inverse( uniforms->matrices.view[i] );
uniforms->matrices.iProjection[i] = uf::matrix::inverse( uniforms->matrices.projection[i] );
uniforms->matrices.iProjectionView[i] = uf::matrix::inverse( uniforms->matrices.projection[i] * uniforms->matrices.view[i] );
uniforms->matrices.eyePos[i] = camera.getEye( i );
}
uniforms->ambient = metadata.light.ambient;
uniforms->msaa = ext::vulkan::settings::msaa;
uniforms->shadowSamples = shadowSamples;
uniforms->exposure = metadata.light.exposure;
uniforms->gamma = metadata.light.gamma;
uniforms->fog.color = metadata.fog.color;
uniforms->fog.color.w = metadata.fog.stepScale;
float timescale = metadata.fog.density.timescale;
uniforms->fog.offset = metadata.fog.density.offset * uf::physics::time::current * timescale;
uniforms->fog.offset.w = metadata.fog.density.scale;
uniforms->fog.densityThreshold = metadata.fog.density.threshold;
uniforms->fog.densityMultiplier = metadata.fog.density.multiplier;
uniforms->fog.absorbtion = metadata.fog.absorbtion;
uniforms->fog.range = metadata.fog.range;
uniforms->mode.type.x = metadataJson["system"]["renderer"]["shader"]["mode"].as<size_t>();
uniforms->mode.type.y = metadataJson["system"]["renderer"]["shader"]["scalar"].as<size_t>();
uniforms->mode.parameters = uf::vector::decode( metadataJson["system"]["renderer"]["shader"]["parameters"], uniforms->mode.parameters );
if ( metadataJson["system"]["renderer"]["shader"]["parameters"][3].as<std::string>() == "time" ) {
uniforms->mode.parameters.w = uf::physics::time::current;
}
std::vector<VkImage> previousTextures;
for ( auto& texture : graphic.material.textures ) previousTextures.emplace_back(texture.image);
graphic.material.textures.clear();
if ( uf::renderer::settings::experimental::deferredMode == "vxgi" ) {
for ( auto& t : sceneTextures.voxels.id ) {
graphic.material.textures.emplace_back().aliasTexture(t);
}
for ( auto& t : sceneTextures.voxels.uv ) {
graphic.material.textures.emplace_back().aliasTexture(t);
}
for ( auto& t : sceneTextures.voxels.normal ) {
graphic.material.textures.emplace_back().aliasTexture(t);
}
for ( auto& t : sceneTextures.voxels.radiance ) {
graphic.material.textures.emplace_back().aliasTexture(t);
}
// attach our textures
for ( auto& t : textures2D ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : texturesCube ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : textures3D ) graphic.material.textures.emplace_back().aliasTexture(t);
bool shouldUpdate = graphic.material.textures.size() != previousTextures.size();
for ( size_t i = 0; !shouldUpdate && i < previousTextures.size() && i < graphic.material.textures.size(); ++i ) {
if ( previousTextures[i] != graphic.material.textures[i].image )
shouldUpdate = true;
}
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.noise);
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.skybox);
int32_t updateThreshold = metadata.light.updateThreshold;
size_t textureSlot = 0;
std::vector<pod::Light::Storage> lights;
lights.reserve( metadata.max.lights );
std::vector<pod::Material::Storage> materials;
materials.reserve(maxTextures);
materials.emplace_back().colorBase = {0,0,0,0};
std::vector<pod::Texture::Storage> textures;
textures.reserve(maxTextures);
size_t lightBufferIndex = renderMode.metadata["lightBufferIndex"].as<size_t>();
graphic.updateBuffer( (void*) lights.data(), uniforms.lengths.lights * sizeof(pod::Light::Storage), lightBufferIndex, false );
std::vector<pod::DrawCall::Storage> drawCalls;
drawCalls.reserve(maxTextures);
if ( shouldUpdate ) {
size_t materialBufferIndex = renderMode.metadata["materialBufferIndex"].as<size_t>();
graphic.updateBuffer( (void*) materials.data(), uniforms.lengths.materials * sizeof(pod::Material::Storage), materialBufferIndex, false );
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
pod::Vector3f max = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
// add materials
for ( auto* g : graphs ) {
auto& graph = *g;
drawCalls.emplace_back(pod::DrawCall::Storage{
materials.size(),
graph.materials.size(),
textures.size(),
graph.textures.size()
});
size_t textureBufferIndex = renderMode.metadata["textureBufferIndex"].as<size_t>();
graphic.updateBuffer( (void*) textures.data(), uniforms.lengths.textures * sizeof(pod::Texture::Storage), textureBufferIndex, false );
for ( auto& material : graph.materials ) materials.emplace_back( material.storage );
for ( auto& texture : graph.textures ) textures.emplace_back( texture.storage );
size_t drawCallBufferIndex = renderMode.metadata["drawCallBufferIndex"].as<size_t>();
graphic.updateBuffer( (void*) drawCalls.data(), uniforms.lengths.drawCalls * sizeof(pod::DrawCall::Storage), drawCallBufferIndex, false );
for ( auto& texture : graph.textures ) {
if ( !texture.bind ) continue;
graphic.material.textures.emplace_back().aliasTexture(texture.texture);
++textureSlot;
}
graphic.updatePipelines();
}
uniforms->matrices.vxgi = sceneTextures.voxels.matrix;
uniforms->cascadePower = sceneTextures.voxels.cascadePower;
auto& uniform = shader.getUniform("UBO");
memcpy( (void*) uniform, &uniforms, sizeof(uniforms) );
uniforms->lengths.materials = std::min( materials.size(), maxTextures );
uniforms->lengths.textures = std::min( textures.size(), maxTextures );
uniforms->lengths.drawCalls = std::min( drawCalls.size(), maxTextures );
// add lighting
for ( size_t i = 0; i < entities.size() && lights.size() < metadata.max.lights; ++i ) {
auto& info = entities[i];
uf::Entity* entity = info.entity;
auto& transform = entity->getComponent<pod::Transform<>>();
auto& metadata = entity->getComponent<ext::LightBehavior::Metadata>();
auto& camera = entity->getComponent<uf::Camera>();
metadata.renderer.rendered = true;
pod::Light::Storage light;
light.position = info.position;
light.color = info.color;
light.type = info.type;
light.mapIndex = -1;
light.depthBias = info.bias;
if ( info.shadows && entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
if ( metadata.renderer.mode == "in-range" && --updateThreshold > 0 ) {
renderMode.execute = true;
// UF_DEBUG_MSG( renderModeName << "\t" << entity->getName() << "\t" << renderMode.execute );
}
size_t view = 0;
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
if ( attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
graphic.material.textures.emplace_back().aliasAttachment(attachment);
light.mapIndex = textureSlot++;
light.view = camera.getView(view);
light.projection = camera.getProjection(view);
lights.emplace_back(light);
++view;
}
light.mapIndex = -1;
} else {
lights.emplace_back(light);
}
}
{
uniforms->lengths.lights = std::min( lights.size(), metadata.max.lights );
bool shouldUpdate = graphic.material.textures.size() != previousTextures.size();
for ( size_t i = 0; !shouldUpdate && i < previousTextures.size() && i < graphic.material.textures.size(); ++i ) {
if ( previousTextures[i] != graphic.material.textures[i].image )
shouldUpdate = true;
}
size_t lightBufferIndex = renderMode.metadata["lightBufferIndex"].as<size_t>();
graphic.updateBuffer( (void*) lights.data(), uniforms->lengths.lights * sizeof(pod::Light::Storage), lightBufferIndex, false );
if ( shouldUpdate ) {
size_t materialBufferIndex = renderMode.metadata["materialBufferIndex"].as<size_t>();
graphic.updateBuffer( (void*) materials.data(), uniforms->lengths.materials * sizeof(pod::Material::Storage), materialBufferIndex, false );
size_t textureBufferIndex = renderMode.metadata["textureBufferIndex"].as<size_t>();
graphic.updateBuffer( (void*) textures.data(), uniforms->lengths.textures * sizeof(pod::Texture::Storage), textureBufferIndex, false );
size_t drawCallBufferIndex = renderMode.metadata["drawCallBufferIndex"].as<size_t>();
graphic.updateBuffer( (void*) drawCalls.data(), uniforms->lengths.drawCalls * sizeof(pod::DrawCall::Storage), drawCallBufferIndex, false );
graphic.updatePipelines();
}
shader.updateUniform( "UBO", uniform );
}
shader.updateUniform( "UBO", uniform );
}
#endif
}

View File

@ -17,7 +17,9 @@ namespace ext {
struct Metadata {
struct {
size_t textures = 256;
size_t textures2D = 512;
size_t texturesCube = 128;
size_t textures3D = 128;
size_t lights = 256;
} max;
struct {
@ -29,6 +31,9 @@ namespace ext {
pod::Vector4f specular = {1,1,1,1};
float exposure = 1.0f;
float gamma = 1.0f;
size_t experimentalMode = 0;
size_t vxgiShadowSamples = 0;
} light;
struct {
pod::Vector3f color = {1,1,1};

View File

@ -89,14 +89,19 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
renderMode.blitter.descriptor.subpass = -1;
renderMode.blitter.process = true;
size_t maxTextures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
size_t maxTexturesCube = ext::config["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
size_t maxTextures3D = ext::config["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(1);
for ( size_t i = 0; i < maxTextures2D; ++i ) renderMode.blitter.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
for ( size_t i = 0; i < maxTexturesCube; ++i ) renderMode.blitter.material.textures.emplace_back().aliasTexture(uf::renderer::TextureCube::empty);
for ( size_t i = 0; i < maxTextures3D; ++i ) renderMode.blitter.material.textures.emplace_back().aliasTexture(uf::renderer::Texture3D::empty);
for ( auto& t : sceneTextures.voxels.id ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.uv ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.noise);
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.skybox);
renderMode.bindCallback( renderMode.CALLBACK_BEGIN, [&]( VkCommandBuffer commandBuffer ){
// clear textures
VkImageSubresourceRange subresourceRange = {};

View File

@ -774,6 +774,11 @@ void EXT_API ext::terminate() {
/* OpenVR */ if ( ext::openvr::context ) {
ext::openvr::terminate();
}
#endif
#if UF_USE_LUA
{
ext::lua::terminate();
}
#endif
uf::scene::destroy();