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