Commit for 2021.05.19.7z
This commit is contained in:
parent
e7da8db000
commit
cc470641d4
@ -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"
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
#define TEXTURES 1
|
||||
#define CUBEMAPS 1
|
||||
#define DEFERRED_SAMPLING 0
|
||||
#define MULTISAMPLING 0
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#pragma shader_stage(fragment)
|
||||
|
||||
#define TEXTURES 1
|
||||
#define CUBEMAPS 1
|
||||
#define DEFERRED_SAMPLING 0
|
||||
|
||||
#include "../common/macros.h"
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#pragma shader_stage(fragment)
|
||||
|
||||
#define TEXTURES 1
|
||||
#define CUBEMAPS 1
|
||||
#define DEFERRED_SAMPLING 0
|
||||
|
||||
#include "../common/macros.h"
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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 );
|
||||
};
|
||||
}
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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};
|
||||
|
||||
|
||||
@ -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 = {};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
/*
|
||||
*/
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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};
|
||||
|
||||
@ -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 = {};
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user