neurotic optimizations (overhauled depth pyramid and bloom to ffx-sdp), more fixes
This commit is contained in:
parent
fd9036ee39
commit
6d05ab865a
@ -110,7 +110,7 @@
|
|||||||
"default stage buffers": true,
|
"default stage buffers": true,
|
||||||
"default defer buffer destroy": true,
|
"default defer buffer destroy": true,
|
||||||
"default command buffer immediate": true,
|
"default command buffer immediate": true,
|
||||||
"multithreaded recording": true
|
"multithreaded recording": false
|
||||||
},
|
},
|
||||||
"pipelines": {
|
"pipelines": {
|
||||||
"deferred": true,
|
"deferred": true,
|
||||||
@ -147,7 +147,8 @@
|
|||||||
"deviceCoherentMemory",
|
"deviceCoherentMemory",
|
||||||
"robustBufferAccess",
|
"robustBufferAccess",
|
||||||
"samplerAnisotropy",
|
"samplerAnisotropy",
|
||||||
"sampleRateShading"
|
"sampleRateShading",
|
||||||
|
"samplerFilterMinmax"
|
||||||
],
|
],
|
||||||
"featureChain": []
|
"featureChain": []
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
// "import": "./rp_downtown_v2.json"
|
// "import": "./rp_downtown_v2.json"
|
||||||
"import": "./ss2_medsci1.json"
|
// "import": "./ss2_medsci1.json"
|
||||||
// "import": "./test_grid.json"
|
// "import": "./test_grid.json"
|
||||||
// "import": "./sh2_mcdonalds.json"
|
// "import": "./sh2_mcdonalds.json"
|
||||||
// "import": "./animal_crossing.json"
|
// "import": "./animal_crossing.json"
|
||||||
// "import": "./mds_mcdonalds.json"
|
"import": "./mds_mcdonalds.json"
|
||||||
// "import": "./gm_construct.json"
|
// "import": "./gm_construct.json"
|
||||||
}
|
}
|
||||||
@ -44,6 +44,7 @@ void gammaCorrect( inout vec3 color, float gamma ) {
|
|||||||
}
|
}
|
||||||
void toneMap( inout vec4 color, float exposure ) { toneMap(color.rgb, exposure); }
|
void toneMap( inout vec4 color, float exposure ) { toneMap(color.rgb, exposure); }
|
||||||
void gammaCorrect( inout vec4 color, float gamma ) { gammaCorrect(color.rgb, gamma); }
|
void gammaCorrect( inout vec4 color, float gamma ) { gammaCorrect(color.rgb, gamma); }
|
||||||
|
float luma( vec3 color ) { return dot(color, vec3(0.2126, 0.7152, 0.0722)); }
|
||||||
//
|
//
|
||||||
uint tea(uint val0, uint val1) {
|
uint tea(uint val0, uint val1) {
|
||||||
uint v0 = val0;
|
uint v0 = val0;
|
||||||
@ -152,6 +153,7 @@ vec3 decodeSrgb(vec3 rgb) {
|
|||||||
const vec3 c = step(vec3(0.04045), rgb);
|
const vec3 c = step(vec3(0.04045), rgb);
|
||||||
return mix(a, b, c);
|
return mix(a, b, c);
|
||||||
}
|
}
|
||||||
|
#if !SPD && (DEFERRED || FRAGMENT || COMPUTE || RT)
|
||||||
bool validTextureIndex( int textureIndex ) {
|
bool validTextureIndex( int textureIndex ) {
|
||||||
return 0 <= textureIndex && textureIndex < MAX_TEXTURES;
|
return 0 <= textureIndex && textureIndex < MAX_TEXTURES;
|
||||||
}
|
}
|
||||||
@ -160,7 +162,6 @@ bool validCubemapIndex( int textureIndex ) {
|
|||||||
return 0 <= textureIndex && textureIndex < MAX_CUBEMAPS;
|
return 0 <= textureIndex && textureIndex < MAX_CUBEMAPS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE || RT)
|
|
||||||
bool validTextureIndex( uint id ) {
|
bool validTextureIndex( uint id ) {
|
||||||
return 0 <= id && id < MAX_TEXTURES;
|
return 0 <= id && id < MAX_TEXTURES;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,65 +0,0 @@
|
|||||||
#version 450
|
|
||||||
#pragma shader_stage(compute)
|
|
||||||
|
|
||||||
#define COMPUTE 1
|
|
||||||
#define TEXTURES 0
|
|
||||||
#define CUBEMAPS 0
|
|
||||||
#define BLOOM 1
|
|
||||||
|
|
||||||
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
|
||||||
|
|
||||||
layout( push_constant ) uniform PushBlock {
|
|
||||||
uint eye;
|
|
||||||
uint mode;
|
|
||||||
} PushConstant;
|
|
||||||
|
|
||||||
layout (binding = 0) uniform UBO {
|
|
||||||
float threshold;
|
|
||||||
float smoothness;
|
|
||||||
uint size;
|
|
||||||
float padding1;
|
|
||||||
|
|
||||||
float weights[32];
|
|
||||||
} ubo;
|
|
||||||
|
|
||||||
layout (binding = 1, rgba16f) uniform image2D imageColor;
|
|
||||||
layout (binding = 2, rgba16f) uniform image2D imageBloom;
|
|
||||||
layout (binding = 3, rgba16f) uniform image2D imagePingPong;
|
|
||||||
|
|
||||||
#include "../../common/macros.h"
|
|
||||||
#include "../../common/structs.h"
|
|
||||||
#include "../../common/functions.h"
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
const uint mode = PushConstant.mode;
|
|
||||||
const ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
|
||||||
const ivec2 size = imageSize( imageColor );
|
|
||||||
if ( texel.x >= size.x || texel.y >= size.y ) return;
|
|
||||||
|
|
||||||
if ( mode == 0 ) { // fill bloom
|
|
||||||
vec3 result = imageLoad( imageColor, texel ).rgb;
|
|
||||||
float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722));
|
|
||||||
if( brightness < ubo.threshold ) result = vec3(0.0);
|
|
||||||
imageStore(imageBloom, texel, vec4(result, 1.0));
|
|
||||||
} else if ( mode == 1 ) { // bloom horizontal
|
|
||||||
vec3 result = imageLoad( imageBloom, texel ).rgb * ubo.weights[0];
|
|
||||||
for ( int i = 1; i < int(ubo.size); ++i ) {
|
|
||||||
vec3 c1 = imageLoad( imageBloom, texel + ivec2(i, 0) ).rgb;
|
|
||||||
vec3 c2 = imageLoad( imageBloom, texel - ivec2(i, 0) ).rgb;
|
|
||||||
result += (c1 + c2) * ubo.weights[i];
|
|
||||||
}
|
|
||||||
imageStore( imagePingPong, texel, vec4(result, 1.0) );
|
|
||||||
} else if ( mode == 2 ) { // bloom vertical
|
|
||||||
vec3 result = imageLoad( imagePingPong, texel ).rgb * ubo.weights[0];
|
|
||||||
for( int i = 1; i < int(ubo.size); ++i ) {
|
|
||||||
vec3 c1 = imageLoad( imagePingPong, texel + ivec2(0, i) ).rgb;
|
|
||||||
vec3 c2 = imageLoad( imagePingPong, texel - ivec2(0, i) ).rgb;
|
|
||||||
result += (c1 + c2) * ubo.weights[i];
|
|
||||||
}
|
|
||||||
imageStore(imageBloom, texel, vec4(result, 1.0));
|
|
||||||
} else if ( mode == 3 ) { // combine
|
|
||||||
vec3 base = imageLoad( imageColor, texel ).rgb;
|
|
||||||
vec3 bloom = imageLoad( imageBloom, texel ).rgb;
|
|
||||||
imageStore( imageColor, texel, vec4(base + bloom, 1.0) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
131
bin/data/shaders/display/bloom/down.comp.glsl
Normal file
131
bin/data/shaders/display/bloom/down.comp.glsl
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#version 450
|
||||||
|
#pragma shader_stage(compute)
|
||||||
|
|
||||||
|
#extension GL_KHR_shader_subgroup_quad : require
|
||||||
|
#extension GL_KHR_shader_subgroup_arithmetic : require
|
||||||
|
#extension GL_EXT_samplerless_texture_functions : enable
|
||||||
|
|
||||||
|
#define COMPUTE 1
|
||||||
|
#define SPD 1
|
||||||
|
|
||||||
|
#include "../../common/macros.h"
|
||||||
|
#include "../../common/structs.h"
|
||||||
|
#include "../../common/functions.h"
|
||||||
|
|
||||||
|
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout (constant_id = 0) const uint MIPS = 6;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PushBlock {
|
||||||
|
uint mips;
|
||||||
|
uint numWorkGroups;
|
||||||
|
uint workGroupOffset;
|
||||||
|
} PushConstant_;
|
||||||
|
|
||||||
|
|
||||||
|
layout (binding = 0, rgba16f) uniform image2D imageColor;
|
||||||
|
layout (binding = 1, rgba16f) uniform image2D imageBright; // yucky
|
||||||
|
layout (binding = 2, rgba16f) coherent uniform image2D outImage[MIPS];
|
||||||
|
|
||||||
|
layout (binding = 3, std430) buffer AtomicCounter {
|
||||||
|
uint counter;
|
||||||
|
} spdCounter;
|
||||||
|
|
||||||
|
layout (binding = 4) uniform UBO {
|
||||||
|
float threshold;
|
||||||
|
float smoothness;
|
||||||
|
uint size;
|
||||||
|
float padding1;
|
||||||
|
|
||||||
|
float weights[32];
|
||||||
|
} ubo;
|
||||||
|
|
||||||
|
#define A_GLSL 1
|
||||||
|
#define A_GPU 1
|
||||||
|
#define SPD_NO_WAVE_OPERATIONS 0
|
||||||
|
#include "../../ext/ffx_a.h"
|
||||||
|
|
||||||
|
shared AU1 spd_counter;
|
||||||
|
shared AF4 spd_intermediate[16][16];
|
||||||
|
|
||||||
|
vec3 applySoftKnee(vec3 color, float luminance) {
|
||||||
|
float rq = clamp(luminance - ubo.threshold + ubo.smoothness, 0.0, 2.0 * ubo.smoothness);
|
||||||
|
rq = (rq * rq) / (4.0 * ubo.smoothness + 0.0001);
|
||||||
|
|
||||||
|
float value = max(rq, luminance - ubo.threshold);
|
||||||
|
|
||||||
|
return color * (value / (max(luminance, 0.0001)));
|
||||||
|
}
|
||||||
|
|
||||||
|
AF4 SpdLoadSourceImage(ASU2 p, AU1 slice) {
|
||||||
|
ivec2 size = imageSize(imageColor);
|
||||||
|
|
||||||
|
// sample color if in bound, else black
|
||||||
|
vec3 c0 = p.x < size.x && p.y < size.y ? imageLoad(imageColor, p + ivec2(0, 0)).rgb : vec3(0.0);
|
||||||
|
vec3 c1 = p.x + 1 < size.x && p.y < size.y ? imageLoad(imageColor, p + ivec2(1, 0)).rgb : vec3(0.0);
|
||||||
|
vec3 c2 = p.x < size.x && p.y + 1 < size.y ? imageLoad(imageColor, p + ivec2(0, 1)).rgb : vec3(0.0);
|
||||||
|
vec3 c3 = p.x + 1 < size.x && p.y + 1 < size.y ? imageLoad(imageColor, p + ivec2(1, 1)).rgb : vec3(0.0);
|
||||||
|
|
||||||
|
// get luma
|
||||||
|
float b0 = luma(c0);
|
||||||
|
float b1 = luma(c1);
|
||||||
|
float b2 = luma(c2);
|
||||||
|
float b3 = luma(c3);
|
||||||
|
|
||||||
|
// soften
|
||||||
|
c0 = applySoftKnee(c0, b0);
|
||||||
|
c1 = applySoftKnee(c1, b1);
|
||||||
|
c2 = applySoftKnee(c2, b2);
|
||||||
|
c3 = applySoftKnee(c3, b3);
|
||||||
|
|
||||||
|
// karis luma weighted average
|
||||||
|
float w0 = 1.0 / (b0 + 1.0);
|
||||||
|
float w1 = 1.0 / (b1 + 1.0);
|
||||||
|
float w2 = 1.0 / (b2 + 1.0);
|
||||||
|
float w3 = 1.0 / (b3 + 1.0);
|
||||||
|
float inv_wsum = 1.0 / (w0 + w1 + w2 + w3);
|
||||||
|
|
||||||
|
// store to mip 0
|
||||||
|
if (p.x < size.x && p.y < size.y) imageStore(outImage[0], p + ivec2(0, 0), vec4(c0, 1.0));
|
||||||
|
if (p.x + 1 < size.x && p.y < size.y) imageStore(outImage[0], p + ivec2(1, 0), vec4(c1, 1.0));
|
||||||
|
if (p.x < size.x && p.y + 1 < size.y) imageStore(outImage[0], p + ivec2(0, 1), vec4(c2, 1.0));
|
||||||
|
if (p.x + 1 < size.x && p.y + 1 < size.y) imageStore(outImage[0], p + ivec2(1, 1), vec4(c3, 1.0));
|
||||||
|
|
||||||
|
// average
|
||||||
|
return AF4((c0 * w0 + c1 * w1 + c2 * w2 + c3 * w3) * inv_wsum, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
AF4 SpdLoad(ASU2 p, AU1 slice) {
|
||||||
|
uint loadMip = min(6u - 1, MIPS - 1);
|
||||||
|
return imageLoad(outImage[loadMip + 1], p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpdStore(ASU2 p, AF4 value, AU1 mip, AU1 slice) {
|
||||||
|
if ( mip + 1 < MIPS ) {
|
||||||
|
imageStore(outImage[mip + 1], p, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// average filter
|
||||||
|
AF4 SpdReduce4(AF4 v0, AF4 v1, AF4 v2, AF4 v3) {
|
||||||
|
return (v0 + v1 + v2 + v3) * 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
AF4 SpdLoadIntermediate(AU1 x, AU1 y) { return spd_intermediate[x][y]; }
|
||||||
|
void SpdStoreIntermediate(AU1 x, AU1 y, AF4 value) { spd_intermediate[x][y] = value; }
|
||||||
|
|
||||||
|
void SpdIncreaseAtomicCounter(AU1 slice) { spd_counter = atomicAdd(spdCounter.counter, 1); }
|
||||||
|
AU1 SpdGetAtomicCounter() { return spd_counter; }
|
||||||
|
void SpdResetAtomicCounter(AU1 slice) { spdCounter.counter = 0; }
|
||||||
|
|
||||||
|
#include "../../ext/ffx_spd.h"
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
SpdDownsample(
|
||||||
|
AU2(gl_WorkGroupID.xy),
|
||||||
|
AU1(gl_LocalInvocationIndex),
|
||||||
|
AU1(PushConstant_.mips - 1),
|
||||||
|
AU1(PushConstant_.numWorkGroups),
|
||||||
|
AU1(PushConstant_.workGroupOffset)
|
||||||
|
);
|
||||||
|
}
|
||||||
60
bin/data/shaders/display/bloom/up.comp.glsl
Normal file
60
bin/data/shaders/display/bloom/up.comp.glsl
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#version 450
|
||||||
|
#pragma shader_stage(compute)
|
||||||
|
|
||||||
|
#define COMPUTE 1
|
||||||
|
|
||||||
|
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout (constant_id = 0) const uint MIPS = 6;
|
||||||
|
|
||||||
|
layout (binding = 0, rgba16f) uniform image2D imageColor;
|
||||||
|
layout (binding = 1) uniform sampler2D samplerBloom;
|
||||||
|
|
||||||
|
layout (binding = 2) uniform UBO {
|
||||||
|
float threshold;
|
||||||
|
float smoothness;
|
||||||
|
uint size;
|
||||||
|
float padding1;
|
||||||
|
|
||||||
|
float weights[32];
|
||||||
|
} ubo;
|
||||||
|
|
||||||
|
// 9-tap bilinear tent filter
|
||||||
|
vec3 tentFilter(sampler2D tex, vec2 uv, float lod) {
|
||||||
|
vec2 texSize = vec2(textureSize(tex, int(lod)));
|
||||||
|
vec4 d = (1.0 / texSize.xyxy) * vec4(1.0, 1.0, -1.0, 0.0);
|
||||||
|
|
||||||
|
vec3 s = textureLod(tex, uv - d.xy, lod).rgb;
|
||||||
|
s += textureLod(tex, uv - d.wy, lod).rgb * 2.0;
|
||||||
|
s += textureLod(tex, uv - d.zy, lod).rgb;
|
||||||
|
s += textureLod(tex, uv + d.zw, lod).rgb * 2.0;
|
||||||
|
s += textureLod(tex, uv, lod).rgb * 4.0;
|
||||||
|
s += textureLod(tex, uv + d.xw, lod).rgb * 2.0;
|
||||||
|
s += textureLod(tex, uv + d.zy, lod).rgb;
|
||||||
|
s += textureLod(tex, uv + d.wy, lod).rgb * 2.0;
|
||||||
|
s += textureLod(tex, uv + d.xy, lod).rgb;
|
||||||
|
|
||||||
|
return s * (1.0 / 16.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||||
|
ivec2 size = imageSize(imageColor);
|
||||||
|
if ( texel.x >= size.x || texel.y >= size.y ) return;
|
||||||
|
|
||||||
|
vec2 uv = (vec2(texel) + 0.5) / vec2(size);
|
||||||
|
vec3 bloomAcc = vec3(0.0);
|
||||||
|
float weightSum = 0.0;
|
||||||
|
|
||||||
|
for ( uint i = 0; i < min(MIPS, ubo.size); ++i ) {
|
||||||
|
float w = ubo.weights[i];
|
||||||
|
bloomAcc += textureLod(samplerBloom, uv, float(i)).rgb * w;
|
||||||
|
//bloomAcc += tentFilter(samplerBloom, uv, float(i)) * w;
|
||||||
|
weightSum += w;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( weightSum > 0.0 ) bloomAcc /= weightSum;
|
||||||
|
|
||||||
|
vec3 base = imageLoad( imageColor, texel ).rgb;
|
||||||
|
imageStore( imageColor, texel, vec4(base + bloomAcc, 1.0) );
|
||||||
|
}
|
||||||
@ -159,7 +159,7 @@ void postProcess() {
|
|||||||
#if FOG
|
#if FOG
|
||||||
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
|
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
|
||||||
#endif
|
#endif
|
||||||
float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
|
float brightness = luma(surface.fragment.rgb);
|
||||||
bool bloom = brightness > ubo.settings.bloom.threshold;
|
bool bloom = brightness > ubo.settings.bloom.threshold;
|
||||||
//if ( bloom ) toneMap( surface.fragment.rgb, brightness );
|
//if ( bloom ) toneMap( surface.fragment.rgb, brightness );
|
||||||
vec4 outFragColor = vec4(surface.fragment.rgb, 1.0);
|
vec4 outFragColor = vec4(surface.fragment.rgb, 1.0);
|
||||||
@ -184,7 +184,7 @@ void postProcess() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IMAGE_STORE( imageColor, outFragColor );
|
IMAGE_STORE( imageColor, outFragColor );
|
||||||
IMAGE_STORE( imageBright, outFragBright );
|
//IMAGE_STORE( imageBright, outFragBright );
|
||||||
IMAGE_STORE( imageMotion, vec4(outFragMotion, 0, 0) );
|
IMAGE_STORE( imageMotion, vec4(outFragMotion, 0, 0) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,35 +1,96 @@
|
|||||||
#version 450
|
#version 450
|
||||||
#pragma shader_stage(compute)
|
#pragma shader_stage(compute)
|
||||||
|
|
||||||
//#extension GL_EXT_nonuniform_qualifier : enable
|
#extension GL_KHR_shader_subgroup_quad : require
|
||||||
|
#extension GL_KHR_shader_subgroup_arithmetic : require
|
||||||
layout (constant_id = 0) const uint MIPS = 6;
|
#extension GL_EXT_samplerless_texture_functions : enable
|
||||||
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|
||||||
|
|
||||||
#define COMPUTE 1
|
#define COMPUTE 1
|
||||||
|
#define SPD 1
|
||||||
|
|
||||||
#include "../../common/macros.h"
|
#include "../../common/macros.h"
|
||||||
#include "../../common/structs.h"
|
#include "../../common/structs.h"
|
||||||
|
#include "../../common/functions.h"
|
||||||
|
|
||||||
layout( push_constant ) uniform PushBlock {
|
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||||
uint _;
|
|
||||||
uint pass;
|
layout (constant_id = 0) const uint MIPS = 6;
|
||||||
} PushConstant;
|
|
||||||
|
layout(push_constant) uniform PushBlock {
|
||||||
|
uint mips;
|
||||||
|
uint numWorkGroups;
|
||||||
|
uint workGroupOffset;
|
||||||
|
} PushConstant_;
|
||||||
|
|
||||||
layout (binding = 0) uniform sampler2D samplerDepth;
|
layout (binding = 0) uniform sampler2D samplerDepth;
|
||||||
layout (binding = 1) uniform sampler2D inImage[MIPS];
|
layout (binding = 1, r32f) coherent uniform image2D outImage[MIPS];
|
||||||
layout (binding = 2, r32f) uniform writeonly image2D outImage[MIPS];
|
|
||||||
|
layout (binding = 2, std430) buffer AtomicCounter {
|
||||||
|
uint counter;
|
||||||
|
} spdCounter;
|
||||||
|
|
||||||
|
|
||||||
|
#define A_GLSL 1
|
||||||
|
#define A_GPU 1
|
||||||
|
#define SPD_NO_WAVE_OPERATIONS 0
|
||||||
|
#include "../../ext/ffx_a.h"
|
||||||
|
|
||||||
|
shared AU1 spd_counter;
|
||||||
|
shared AF1 spd_intermediate[16][16];
|
||||||
|
|
||||||
|
AF4 SpdLoadSourceImage(ASU2 p, AU1 slice) {
|
||||||
|
ivec2 size = imageSize(outImage[0]);
|
||||||
|
|
||||||
|
// sample depth if in bound, else 0 (0 for reverse-z projection, use 1 if normal projection)
|
||||||
|
float d0 = p.x < size.x && p.y < size.y ? texelFetch(samplerDepth, p + ivec2(0, 0), 0).x : 0.0;
|
||||||
|
float d1 = p.x + 1 < size.x && p.y < size.y ? texelFetch(samplerDepth, p + ivec2(1, 0), 0).x : 0.0;
|
||||||
|
float d2 = p.x < size.x && p.y + 1 < size.y ? texelFetch(samplerDepth, p + ivec2(0, 1), 0).x : 0.0;
|
||||||
|
float d3 = p.x + 1 < size.x && p.y + 1 < size.y ? texelFetch(samplerDepth, p + ivec2(1, 1), 0).x : 0.0;
|
||||||
|
|
||||||
|
// store to mip 0
|
||||||
|
if (p.x < size.x && p.y < size.y) imageStore(outImage[0], p + ivec2(0, 0), vec4(d0));
|
||||||
|
if (p.x + 1 < size.x && p.y < size.y) imageStore(outImage[0], p + ivec2(1, 0), vec4(d1));
|
||||||
|
if (p.x < size.x && p.y + 1 < size.y) imageStore(outImage[0], p + ivec2(0, 1), vec4(d2));
|
||||||
|
if (p.x + 1 < size.x && p.y + 1 < size.y) imageStore(outImage[0], p + ivec2(1, 1), vec4(d3));
|
||||||
|
|
||||||
|
return AF4(d0, d1, d2, d3);
|
||||||
|
}
|
||||||
|
|
||||||
|
AF4 SpdLoad(ASU2 p, AU1 slice) {
|
||||||
|
uint loadMip = min(6u, MIPS - 1);
|
||||||
|
float d = imageLoad(outImage[loadMip], p).r;
|
||||||
|
return AF4(d, d, d, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpdStore(ASU2 p, AF4 value, AU1 mip, AU1 slice) {
|
||||||
|
if ( mip + 1 < MIPS ) {
|
||||||
|
imageStore(outImage[mip + 1], p, vec4(value.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AF4 SpdLoadIntermediate(AU1 x, AU1 y) {
|
||||||
|
float d = spd_intermediate[x][y];
|
||||||
|
return AF4(d, d, d, d);
|
||||||
|
}
|
||||||
|
void SpdStoreIntermediate(AU1 x, AU1 y, AF4 value) { spd_intermediate[x][y] = value.x; }
|
||||||
|
void SpdIncreaseAtomicCounter(AU1 slice) { spd_counter = atomicAdd(spdCounter.counter, 1); }
|
||||||
|
AU1 SpdGetAtomicCounter() { return spd_counter; }
|
||||||
|
void SpdResetAtomicCounter(AU1 slice) { spdCounter.counter = 0; }
|
||||||
|
|
||||||
|
// min filter
|
||||||
|
AF4 SpdReduce4(AF4 v0, AF4 v1, AF4 v2, AF4 v3) {
|
||||||
|
float minVal = min(min(v0.x, v1.x), min(v2.x, v3.x));
|
||||||
|
return AF4(minVal, minVal, minVal, minVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "../../ext/ffx_spd.h"
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
int mip = int(PushConstant.pass);
|
SpdDownsample(
|
||||||
|
AU2(gl_WorkGroupID.xy),
|
||||||
float depth;
|
AU1(gl_LocalInvocationIndex),
|
||||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
AU1(PushConstant_.mips - 1),
|
||||||
if ( mip == 0 ) {
|
AU1(PushConstant_.numWorkGroups),
|
||||||
depth = texelFetch(samplerDepth, pos, 0).r;
|
AU1(PushConstant_.workGroupOffset)
|
||||||
} else {
|
);
|
||||||
depth = texture(inImage[mip - 1], (vec2(gl_GlobalInvocationID.xy) + vec2(0.5)) / imageSize( outImage[mip] )).x;
|
|
||||||
}
|
|
||||||
|
|
||||||
imageStore(outImage[mip], pos, vec4(depth));
|
|
||||||
}
|
}
|
||||||
1907
bin/data/shaders/ext/ffx_a.h
Normal file
1907
bin/data/shaders/ext/ffx_a.h
Normal file
File diff suppressed because it is too large
Load Diff
1297
bin/data/shaders/ext/ffx_spd.h
Normal file
1297
bin/data/shaders/ext/ffx_spd.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@
|
|||||||
#extension GL_EXT_samplerless_texture_functions : enable
|
#extension GL_EXT_samplerless_texture_functions : enable
|
||||||
|
|
||||||
layout (constant_id = 0) const uint PASSES = 6;
|
layout (constant_id = 0) const uint PASSES = 6;
|
||||||
layout (local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
|
layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
#define COMPUTE 1
|
#define COMPUTE 1
|
||||||
#define QUERY_MIPMAPS 1
|
#define QUERY_MIPMAPS 1
|
||||||
@ -73,106 +73,100 @@ layout (std140, binding = 3) buffer Objects {
|
|||||||
|
|
||||||
layout (binding = 4) uniform sampler2D samplerDepth;
|
layout (binding = 4) uniform sampler2D samplerDepth;
|
||||||
|
|
||||||
|
shared vec4 sharedPlanes[PASSES][6];
|
||||||
|
|
||||||
vec4 normalizePlane( vec4 p ) {
|
vec4 normalizePlane( vec4 p ) {
|
||||||
return p / length(p.xyz);
|
return p / length(p.xyz);
|
||||||
}
|
|
||||||
|
|
||||||
bool frustumCull( uint id ) {
|
|
||||||
if ( PushConstant.passes == 0 ) return true;
|
|
||||||
|
|
||||||
const DrawCommand drawCommand = drawCommands[id];
|
|
||||||
const Instance instance = instances[drawCommand.instanceID];
|
|
||||||
const Object object = objects[instance.objectID];
|
|
||||||
|
|
||||||
if ( drawCommand.indices == 0 || drawCommand.vertices == 0 ) return false;
|
|
||||||
|
|
||||||
bool visible = false;
|
|
||||||
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
|
|
||||||
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * object.model;
|
|
||||||
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] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool insideFrustum = true;
|
|
||||||
for ( uint p = 0; p < 6; ++p ) {
|
|
||||||
float d = max(instance.bounds.min.x * planes[p].x, instance.bounds.max.x * planes[p].x)
|
|
||||||
+ max(instance.bounds.min.y * planes[p].y, instance.bounds.max.y * planes[p].y)
|
|
||||||
+ max(instance.bounds.min.z * planes[p].z, instance.bounds.max.z * planes[p].z);
|
|
||||||
|
|
||||||
if (d < -planes[p].w) {
|
|
||||||
insideFrustum = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( insideFrustum ) {
|
|
||||||
visible = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool occlusionCull( uint id ) {
|
|
||||||
if ( PushConstant.passes == 0 ) return true;
|
|
||||||
|
|
||||||
const DrawCommand drawCommand = drawCommands[id];
|
|
||||||
const Instance instance = instances[drawCommand.instanceID];
|
|
||||||
const Object object = objects[instance.objectID];
|
|
||||||
|
|
||||||
bool visible = false;
|
|
||||||
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
|
|
||||||
vec4 aabb;
|
|
||||||
vec4 sphere = aabbToSphere( instance.bounds );
|
|
||||||
|
|
||||||
float scale = length(object.model[0].xyz);
|
|
||||||
vec3 center = (camera.viewport[pass].view * object.model * vec4(sphere.xyz, 1)).xyz;
|
|
||||||
float radius = scale * sphere.w;
|
|
||||||
|
|
||||||
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 ) ) {
|
|
||||||
vec2 pyramidSize = vec2(textureSize( samplerDepth, 0 ));
|
|
||||||
|
|
||||||
float width = (aabb.z - aabb.x) * pyramidSize.x;
|
|
||||||
float height = (aabb.w - aabb.y) * pyramidSize.y;
|
|
||||||
|
|
||||||
float level = max(0.0, floor(log2(max(width, height))));
|
|
||||||
|
|
||||||
float d1 = textureLod(samplerDepth, vec2(aabb.x, aabb.y), level).x;
|
|
||||||
float d2 = textureLod(samplerDepth, vec2(aabb.z, aabb.y), level).x;
|
|
||||||
float d3 = textureLod(samplerDepth, vec2(aabb.x, aabb.w), level).x;
|
|
||||||
float d4 = textureLod(samplerDepth, vec2(aabb.z, aabb.w), level).x;
|
|
||||||
|
|
||||||
float depth = min(min(d1, d2), min(d3, d4)); // min for reverse-z projection, max for standard
|
|
||||||
float depthSphere = znear / (center.z - radius);
|
|
||||||
|
|
||||||
if ( depthSphere >= depth - DEPTH_BIAS ) {
|
|
||||||
visible = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
visible = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return visible;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
const uint gID = gl_GlobalInvocationID.x;
|
const uint gID = gl_GlobalInvocationID.x;
|
||||||
if ( !(0 <= gID && gID < drawCommands.length()) ) return;
|
const uint lID = gl_LocalInvocationIndex;
|
||||||
|
|
||||||
bool visible = frustumCull( gID );
|
if ( lID == 0 ) {
|
||||||
if ( visible ) visible = occlusionCull( gID );
|
for (uint pass = 0; pass < PushConstant.passes; ++pass) {
|
||||||
drawCommands[gID].instances = visible ? 1 : 0;
|
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view;
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
for (int j = 0; j < 2; ++j) {
|
||||||
|
sharedPlanes[pass][i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
|
||||||
|
sharedPlanes[pass][i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
|
||||||
|
sharedPlanes[pass][i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
|
||||||
|
sharedPlanes[pass][i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
|
||||||
|
sharedPlanes[pass][i*2+j] = normalizePlane( sharedPlanes[pass][i*2+j] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
barrier();
|
||||||
|
|
||||||
|
if ( gID >= drawCommands.length() ) return;
|
||||||
|
|
||||||
|
const DrawCommand drawCommand = drawCommands[gID];
|
||||||
|
if ( drawCommand.indices == 0 || drawCommand.vertices == 0 ) return;
|
||||||
|
|
||||||
|
const Instance instance = instances[drawCommand.instanceID];
|
||||||
|
const Object object = objects[instance.objectID];
|
||||||
|
|
||||||
|
vec4 sphere = aabbToSphere( instance.bounds );
|
||||||
|
vec3 worldCenter = (object.model * vec4(sphere.xyz, 1.0)).xyz;
|
||||||
|
|
||||||
|
float scaleX = length(object.model[0].xyz);
|
||||||
|
float scaleY = length(object.model[1].xyz);
|
||||||
|
float scaleZ = length(object.model[2].xyz);
|
||||||
|
float maxScale = max(max(scaleX, scaleY), scaleZ);
|
||||||
|
float worldRadius = sphere.w * maxScale;
|
||||||
|
|
||||||
|
bool isVisible = false;
|
||||||
|
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
|
||||||
|
bool insideFrustum = true;
|
||||||
|
for ( int p = 0; p < 6; ++p ) {
|
||||||
|
if ( dot(sharedPlanes[pass][p].xyz, worldCenter) + sharedPlanes[pass][p].w < -worldRadius ) {
|
||||||
|
insideFrustum = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( insideFrustum ) {
|
||||||
|
isVisible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isVisible ) {
|
||||||
|
isVisible = false;
|
||||||
|
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
|
||||||
|
vec4 aabb;
|
||||||
|
vec3 viewCenter = ( camera.viewport[pass].view * vec4(worldCenter, 1.0) ).xyz;
|
||||||
|
|
||||||
|
mat4 proj = camera.viewport[pass].projection;
|
||||||
|
float znear = proj[3][2];
|
||||||
|
float P00 = proj[0][0];
|
||||||
|
float P11 = proj[1][1];
|
||||||
|
|
||||||
|
if ( projectSphere(viewCenter, worldRadius, znear, P00, P11, aabb) ) {
|
||||||
|
vec2 pyramidSize = vec2(textureSize( samplerDepth, 0 ));
|
||||||
|
float width = (aabb.z - aabb.x) * pyramidSize.x;
|
||||||
|
float height = (aabb.w - aabb.y) * pyramidSize.y;
|
||||||
|
|
||||||
|
float level = floor(log2(max(width, height)));
|
||||||
|
level = max(0.0, level);
|
||||||
|
|
||||||
|
float d1 = textureLod(samplerDepth, vec2(aabb.x, aabb.y), level).x;
|
||||||
|
float d2 = textureLod(samplerDepth, vec2(aabb.z, aabb.y), level).x;
|
||||||
|
float d3 = textureLod(samplerDepth, vec2(aabb.x, aabb.w), level).x;
|
||||||
|
float d4 = textureLod(samplerDepth, vec2(aabb.z, aabb.w), level).x;
|
||||||
|
|
||||||
|
float depth = min(min(d1, d2), min(d3, d4));
|
||||||
|
float depthSphere = znear / (viewCenter.z - worldRadius);
|
||||||
|
|
||||||
|
if ( depthSphere >= depth - DEPTH_BIAS ) {
|
||||||
|
isVisible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isVisible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawCommands[gID].instances = isVisible ? 1 : 0;
|
||||||
}
|
}
|
||||||
@ -390,7 +390,7 @@ void main() {
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if BLOOM
|
#if BLOOM
|
||||||
float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
|
float brightness = luma(surface.fragment.rgb);
|
||||||
vec4 outFragBright = brightness > ubo.threshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
|
vec4 outFragBright = brightness > ubo.threshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
|
||||||
// imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), outFragBright);
|
// imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), outFragBright);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -111,6 +111,8 @@ namespace pod {
|
|||||||
uf::renderer::Buffer material;
|
uf::renderer::Buffer material;
|
||||||
uf::renderer::Buffer texture;
|
uf::renderer::Buffer texture;
|
||||||
uf::renderer::Buffer light;
|
uf::renderer::Buffer light;
|
||||||
|
|
||||||
|
uf::renderer::Texture2D depthPyramid;
|
||||||
} buffers;
|
} buffers;
|
||||||
}/* storage*/;
|
}/* storage*/;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -28,6 +28,8 @@ namespace ext {
|
|||||||
operator VkCommandBuffer() { return handle; }
|
operator VkCommandBuffer() { return handle; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Texture;
|
||||||
|
|
||||||
struct UF_API Device {
|
struct UF_API Device {
|
||||||
VkInstance instance;
|
VkInstance instance;
|
||||||
VkDebugUtilsMessengerEXT debugMessenger;
|
VkDebugUtilsMessengerEXT debugMessenger;
|
||||||
@ -86,6 +88,7 @@ namespace ext {
|
|||||||
|
|
||||||
uf::stl::vector<Buffer> buffers;
|
uf::stl::vector<Buffer> buffers;
|
||||||
uf::stl::vector<AccelerationStructure> ass;
|
uf::stl::vector<AccelerationStructure> ass;
|
||||||
|
uf::stl::vector<Texture> textures;
|
||||||
} transient;
|
} transient;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@ -42,8 +42,8 @@ namespace ext {
|
|||||||
void record( const Graphic& graphic, const GraphicDescriptor& descriptor, VkCommandBuffer, size_t = 0, size_t = 0, size_t = 0 ) const;
|
void record( const Graphic& graphic, const GraphicDescriptor& descriptor, VkCommandBuffer, size_t = 0, size_t = 0, size_t = 0 ) const;
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
uf::stl::vector<Shader*> getShaders( uf::stl::vector<Shader>& );
|
uf::stl::vector<Shader*> getShaders( uf::stl::vector<Shader>&, const uf::stl::string& = "" );
|
||||||
uf::stl::vector<const Shader*> getShaders( const uf::stl::vector<Shader>& ) const;
|
uf::stl::vector<const Shader*> getShaders( const uf::stl::vector<Shader>&, const uf::stl::string& = "" ) const;
|
||||||
|
|
||||||
void collectBuffers( const Shader& shader, const RenderMode& renderMode, const Graphic& graphic, const std::function<void(const Buffer&)>& lambda ) const;
|
void collectBuffers( const Shader& shader, const RenderMode& renderMode, const Graphic& graphic, const std::function<void(const Buffer&)>& lambda ) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -138,7 +138,7 @@ namespace ext {
|
|||||||
inline void update( uf::Image& image, uint32_t layer = 1 ) { return this->update(image, this->imageLayout, layer); }
|
inline void update( uf::Image& image, uint32_t layer = 1 ) { return this->update(image, this->imageLayout, layer); }
|
||||||
inline void update( void* data, VkDeviceSize size, uint32_t layer = 1 ) { return this->update(data, size, this->imageLayout, layer); }
|
inline void update( void* data, VkDeviceSize size, uint32_t layer = 1 ) { return this->update(data, size, this->imageLayout, layer); }
|
||||||
|
|
||||||
void generateMipmaps(VkCommandBuffer commandBuffer, uint32_t layer = 1);
|
void generateMipmaps(VkCommandBuffer commandBuffer, uint32_t layer = 0);
|
||||||
|
|
||||||
void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, uint32_t texDepth, uint32_t layers, VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL );
|
void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, uint32_t texDepth, uint32_t layers, VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL );
|
||||||
inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, imageUsageFlags, imageLayout); }
|
inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, imageUsageFlags, imageLayout); }
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
#define VK_DEFAULT_STAGE_BUFFERS ext::vulkan::settings::defaultStageBuffers
|
#define VK_DEFAULT_STAGE_BUFFERS ext::vulkan::settings::defaultStageBuffers
|
||||||
#define VK_DEFAULT_DEFER_BUFFER_DESTROY ext::vulkan::settings::defaultDeferBufferDestroy
|
#define VK_DEFAULT_DEFER_BUFFER_DESTROY ext::vulkan::settings::defaultDeferBufferDestroy
|
||||||
#define VK_DEFAULT_COMMAND_BUFFER_IMMEDIATE ext::vulkan::settings::defaultCommandBufferImmediate
|
#define VK_DEFAULT_COMMAND_BUFFER_IMMEDIATE ext::vulkan::settings::defaultCommandBufferImmediate
|
||||||
#define VK_UBO_USE_N_BUFFERS 1
|
#define VK_UBO_USE_N_BUFFERS 0
|
||||||
|
|
||||||
namespace ext {
|
namespace ext {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
|
|||||||
@ -182,10 +182,6 @@ namespace ext {
|
|||||||
extern UF_API uint32_t frameSkip;
|
extern UF_API uint32_t frameSkip;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace gc {
|
|
||||||
extern UF_API uf::stl::vector<ext::vulkan::Texture> textures;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern UF_API Device device;
|
extern UF_API Device device;
|
||||||
|
|
||||||
extern UF_API Allocator allocator;
|
extern UF_API Allocator allocator;
|
||||||
|
|||||||
@ -938,8 +938,9 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
|||||||
#if UF_USE_VULKAN
|
#if UF_USE_VULKAN
|
||||||
// only update this when requested
|
// only update this when requested
|
||||||
// done outside of deserialize because the rendermode might not be initialized in time
|
// done outside of deserialize because the rendermode might not be initialized in time
|
||||||
if ( uf::renderer::settings::pipelines::bloom && metadata.bloom.outOfDate && graphic.material.hasShader("compute", "bloom") ) {
|
if ( uf::renderer::settings::pipelines::bloom && metadata.bloom.outOfDate && graphic.material.hasShader("compute", "bloom-down") ) {
|
||||||
auto& shader = graphic.material.getShader("compute", "bloom");
|
auto& shaderDown = graphic.material.getShader("compute", "bloom-down");
|
||||||
|
auto& shaderUp = graphic.material.getShader("compute", "bloom-up");
|
||||||
|
|
||||||
struct UniformDescriptor {
|
struct UniformDescriptor {
|
||||||
float threshold;
|
float threshold;
|
||||||
@ -974,7 +975,12 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
|||||||
for ( auto i = 0; i < uniforms.size; ++i ) uniforms.weights[i] = tempWeights[i] / sum;
|
for ( auto i = 0; i < uniforms.size; ++i ) uniforms.weights[i] = tempWeights[i] / sum;
|
||||||
|
|
||||||
metadata.bloom.outOfDate = false;
|
metadata.bloom.outOfDate = false;
|
||||||
if ( shader.hasUniform("UBO") ) shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
|
if ( shaderDown.hasUniform("UBO") ) {
|
||||||
|
shaderDown.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shaderDown.getUniformBuffer("UBO") );
|
||||||
|
}
|
||||||
|
if ( shaderUp.hasUniform("UBO") ) {
|
||||||
|
shaderUp.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shaderUp.getUniformBuffer("UBO") );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UniformDescriptor {
|
struct UniformDescriptor {
|
||||||
|
|||||||
@ -196,7 +196,6 @@ namespace {
|
|||||||
|
|
||||||
// compute shader
|
// compute shader
|
||||||
auto& shader = graphic.material.getShader("compute", uf::renderer::settings::pipelines::names::culling);
|
auto& shader = graphic.material.getShader("compute", uf::renderer::settings::pipelines::names::culling);
|
||||||
shader.aliasAttachment("depthPyramid");
|
|
||||||
}
|
}
|
||||||
// vxgi pipeline
|
// vxgi pipeline
|
||||||
if ( uf::renderer::settings::pipelines::vxgi ) {
|
if ( uf::renderer::settings::pipelines::vxgi ) {
|
||||||
@ -479,6 +478,9 @@ namespace {
|
|||||||
shader.aliasBuffer( "indirect", *indirect );
|
shader.aliasBuffer( "indirect", *indirect );
|
||||||
shader.aliasBuffer( "instance", storage.buffers.instance );
|
shader.aliasBuffer( "instance", storage.buffers.instance );
|
||||||
shader.aliasBuffer( "object", storage.buffers.object );
|
shader.aliasBuffer( "object", storage.buffers.object );
|
||||||
|
|
||||||
|
shader.textures.clear();
|
||||||
|
shader.textures.emplace_back().aliasTexture( storage.buffers.depthPyramid );
|
||||||
}
|
}
|
||||||
|
|
||||||
// vxgi pipeline
|
// vxgi pipeline
|
||||||
@ -1532,10 +1534,12 @@ void uf::graph::destroy( uf::Object& object, bool soft ) {
|
|||||||
void uf::graph::destroy( pod::Graph::Storage& storage, bool soft ) {
|
void uf::graph::destroy( pod::Graph::Storage& storage, bool soft ) {
|
||||||
soft = false;
|
soft = false;
|
||||||
#if UF_USE_VULKAN
|
#if UF_USE_VULKAN
|
||||||
|
/*
|
||||||
for ( auto& texture : uf::renderer::gc::textures ) {
|
for ( auto& texture : uf::renderer::gc::textures ) {
|
||||||
texture.destroy( false );
|
texture.destroy( false );
|
||||||
}
|
}
|
||||||
uf::renderer::gc::textures.clear();
|
uf::renderer::gc::textures.clear();
|
||||||
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// cleanup graphic handles
|
// cleanup graphic handles
|
||||||
|
|||||||
@ -41,7 +41,7 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
|
|||||||
this->metadata.type = descriptor.pipeline;
|
this->metadata.type = descriptor.pipeline;
|
||||||
Device& device = *graphic.device;
|
Device& device = *graphic.device;
|
||||||
|
|
||||||
auto shaders = getShaders( graphic.material.shaders );
|
auto shaders = getShaders( graphic.material.shaders, descriptor.pipeline );
|
||||||
assert( shaders.size() > 0 );
|
assert( shaders.size() > 0 );
|
||||||
|
|
||||||
uint32_t subpass = descriptor.subpass;
|
uint32_t subpass = descriptor.subpass;
|
||||||
@ -397,7 +397,10 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, VkCommandBuffer comm
|
|||||||
return record( graphic, descriptor, commandBuffer, pass, draw, offset );
|
return record( graphic, descriptor, commandBuffer, pass, draw, offset );
|
||||||
}
|
}
|
||||||
void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescriptor& descriptor, VkCommandBuffer commandBuffer, size_t pass, size_t draw, size_t offset ) const {
|
void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescriptor& descriptor, VkCommandBuffer commandBuffer, size_t pass, size_t draw, size_t offset ) const {
|
||||||
auto shaders = getShaders( graphic.material.shaders );
|
auto shaders = getShaders( graphic.material.shaders, descriptor.pipeline );
|
||||||
|
for ( auto i = 0; i < shaders.size(); ++i ) {
|
||||||
|
// UF_MSG_DEBUG("{} | {}: {}", descriptor.pipeline, i, shaders[i]->filename);
|
||||||
|
}
|
||||||
|
|
||||||
// create dynamic offset ranges
|
// create dynamic offset ranges
|
||||||
static thread_local uf::stl::vector<uint32_t> dynamicOffsets;
|
static thread_local uf::stl::vector<uint32_t> dynamicOffsets;
|
||||||
@ -427,6 +430,7 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescrip
|
|||||||
else continue;
|
else continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// automatically bind to our default push constants
|
||||||
if ( shader->metadata.definitions.pushConstants.count("PushConstant") > 0 ) {
|
if ( shader->metadata.definitions.pushConstants.count("PushConstant") > 0 ) {
|
||||||
struct PushConstant {
|
struct PushConstant {
|
||||||
uint32_t pass;
|
uint32_t pass;
|
||||||
@ -450,7 +454,10 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescrip
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no matching bind point for shaders, skip
|
// no matching bind point for shaders, skip
|
||||||
if ( !bound ) return;
|
if ( !bound ) {
|
||||||
|
UF_MSG_DEBUG("No shaders found to bind...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Bind descriptor sets describing shader binding points
|
// Bind descriptor sets describing shader binding points
|
||||||
#if VK_UBO_USE_N_BUFFERS
|
#if VK_UBO_USE_N_BUFFERS
|
||||||
@ -506,7 +513,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
|||||||
RenderMode& renderMode = ext::vulkan::getRenderMode(descriptor.renderMode, true);
|
RenderMode& renderMode = ext::vulkan::getRenderMode(descriptor.renderMode, true);
|
||||||
auto& renderTarget = renderMode.getRenderTarget(/*descriptor.renderTarget*/);
|
auto& renderTarget = renderMode.getRenderTarget(/*descriptor.renderTarget*/);
|
||||||
|
|
||||||
auto shaders = getShaders( graphic.material.shaders );
|
auto shaders = getShaders( graphic.material.shaders, descriptor.pipeline );
|
||||||
uf::stl::vector<VkWriteDescriptorSet> writeDescriptorSets;
|
uf::stl::vector<VkWriteDescriptorSet> writeDescriptorSets;
|
||||||
uf::stl::vector<uf::renderer::AccelerationStructure> tlases;
|
uf::stl::vector<uf::renderer::AccelerationStructure> tlases;
|
||||||
|
|
||||||
@ -947,32 +954,32 @@ void ext::vulkan::Pipeline::destroy() {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
uf::stl::vector<ext::vulkan::Shader*> ext::vulkan::Pipeline::getShaders( uf::stl::vector<ext::vulkan::Shader>& shaders ) {
|
uf::stl::vector<ext::vulkan::Shader*> ext::vulkan::Pipeline::getShaders( uf::stl::vector<ext::vulkan::Shader>& shaders, const uf::stl::string& type ) {
|
||||||
uf::stl::unordered_map<uf::stl::string, ext::vulkan::Shader*> map;
|
uf::stl::unordered_map<uf::stl::string, ext::vulkan::Shader*> map;
|
||||||
uf::stl::vector<ext::vulkan::Shader*> res;
|
uf::stl::vector<ext::vulkan::Shader*> res;
|
||||||
bool isCompute = false;
|
bool isCompute = false;
|
||||||
for ( auto& shader : shaders ) {
|
for ( auto& shader : shaders ) {
|
||||||
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != metadata.type ) continue;
|
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != (type == "" ? metadata.type : type) ) continue;
|
||||||
if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) isCompute = true;
|
if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) isCompute = true;
|
||||||
}
|
}
|
||||||
for ( auto& shader : shaders ) {
|
for ( auto& shader : shaders ) {
|
||||||
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != metadata.type ) continue;
|
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != (type == "" ? metadata.type : type) ) continue;
|
||||||
if ( isCompute && shader.descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
if ( isCompute && shader.descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
||||||
map[shader.metadata.type] = &shader;
|
map[shader.metadata.type] = &shader;
|
||||||
}
|
}
|
||||||
for ( auto pair : map ) res.insert( res.begin(), pair.second);
|
for ( auto pair : map ) res.insert( res.begin(), pair.second);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
uf::stl::vector<const ext::vulkan::Shader*> ext::vulkan::Pipeline::getShaders( const uf::stl::vector<ext::vulkan::Shader>& shaders ) const {
|
uf::stl::vector<const ext::vulkan::Shader*> ext::vulkan::Pipeline::getShaders( const uf::stl::vector<ext::vulkan::Shader>& shaders, const uf::stl::string& type ) const {
|
||||||
uf::stl::unordered_map<uf::stl::string, const ext::vulkan::Shader*> map;
|
uf::stl::unordered_map<uf::stl::string, const ext::vulkan::Shader*> map;
|
||||||
uf::stl::vector<const ext::vulkan::Shader*> res;
|
uf::stl::vector<const ext::vulkan::Shader*> res;
|
||||||
bool isCompute = false;
|
bool isCompute = false;
|
||||||
for ( auto& shader : shaders ) {
|
for ( auto& shader : shaders ) {
|
||||||
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != metadata.type ) continue;
|
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != (type == "" ? metadata.type : type) ) continue;
|
||||||
if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) isCompute = true;
|
if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) isCompute = true;
|
||||||
}
|
}
|
||||||
for ( auto& shader : shaders ) {
|
for ( auto& shader : shaders ) {
|
||||||
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != metadata.type ) continue;
|
if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != (type == "" ? metadata.type : type) ) continue;
|
||||||
if ( isCompute && shader.descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
if ( isCompute && shader.descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
||||||
map[shader.metadata.type] = &shader;
|
map[shader.metadata.type] = &shader;
|
||||||
}
|
}
|
||||||
@ -1839,19 +1846,19 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, size_t pass, s
|
|||||||
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicDescriptor& descriptor, size_t pass, size_t draw, size_t offset ) const {
|
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicDescriptor& descriptor, size_t pass, size_t draw, size_t offset ) const {
|
||||||
if ( !process ) return;
|
if ( !process ) return;
|
||||||
if ( !this->hasPipeline( descriptor ) ) {
|
if ( !this->hasPipeline( descriptor ) ) {
|
||||||
VK_DEBUG_VALIDATION_MESSAGE(this << ": has no valid pipeline ({} {})", descriptor.renderMode, descriptor.renderTarget);
|
//UF_MSG_DEBUG("{} has no valid pipeline ({}:{}:{})", (void*) this, descriptor.renderMode, descriptor.renderTarget, descriptor.pipeline);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& pipeline = this->getPipeline( descriptor );
|
auto& pipeline = this->getPipeline( descriptor );
|
||||||
if ( pipeline.descriptorSet == VK_NULL_HANDLE ) {
|
if ( pipeline.descriptorSet == VK_NULL_HANDLE ) {
|
||||||
VK_DEBUG_VALIDATION_MESSAGE(this << ": has no valid pipeline descriptor set ({} {})", descriptor.renderMode, descriptor.renderTarget);
|
//UF_MSG_DEBUG("{} has no valid pipeline descriptor set ({}:{}:{})", (void*) this, descriptor.renderMode, descriptor.renderTarget, descriptor.pipeline);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( !pipeline.metadata.process ) return;
|
if ( !pipeline.metadata.process ) return;
|
||||||
pipeline.record(*this, descriptor, commandBuffer, pass, draw, offset);
|
pipeline.record(*this, descriptor, commandBuffer, pass, draw, offset);
|
||||||
|
|
||||||
auto shaders = pipeline.getShaders( material.shaders );
|
auto shaders = pipeline.getShaders( material.shaders, descriptor.pipeline );
|
||||||
for ( auto* shader : shaders ) {
|
for ( auto* shader : shaders ) {
|
||||||
if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) return;
|
if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) return;
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -273,8 +273,8 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
|||||||
// swapchain.destroy();
|
// swapchain.destroy();
|
||||||
swapchain.initialize( device );
|
swapchain.initialize( device );
|
||||||
// bind swapchain images
|
// bind swapchain images
|
||||||
images.resize( ext::vulkan::swapchain.buffers );
|
::images.resize( ext::vulkan::swapchain.buffers );
|
||||||
VK_CHECK_RESULT(vkGetSwapchainImagesKHR( device, swapchain.swapChain, &swapchain.buffers, images.data()));
|
VK_CHECK_RESULT(vkGetSwapchainImagesKHR( device, swapchain.swapChain, &swapchain.buffers, ::images.data()));
|
||||||
// create image views for swapchain images
|
// create image views for swapchain images
|
||||||
|
|
||||||
renderTarget.attachments.clear();
|
renderTarget.attachments.clear();
|
||||||
@ -302,7 +302,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
|||||||
colorAttachmentView.subresourceRange.layerCount = 1;
|
colorAttachmentView.subresourceRange.layerCount = 1;
|
||||||
colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
colorAttachmentView.flags = 0;
|
colorAttachmentView.flags = 0;
|
||||||
colorAttachmentView.image = images[frame];
|
colorAttachmentView.image = ::images[frame];
|
||||||
|
|
||||||
VK_CHECK_RESULT(vkCreateImageView( device, &colorAttachmentView, nullptr, &renderTarget.attachments[frame].view));
|
VK_CHECK_RESULT(vkCreateImageView( device, &colorAttachmentView, nullptr, &renderTarget.attachments[frame].view));
|
||||||
VK_REGISTER_HANDLE( renderTarget.attachments[frame].view );
|
VK_REGISTER_HANDLE( renderTarget.attachments[frame].view );
|
||||||
@ -312,7 +312,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
|||||||
renderTarget.attachments[frame].descriptor.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
renderTarget.attachments[frame].descriptor.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
renderTarget.attachments[frame].descriptor.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
renderTarget.attachments[frame].descriptor.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
renderTarget.attachments[frame].descriptor.aliased = true;
|
renderTarget.attachments[frame].descriptor.aliased = true;
|
||||||
renderTarget.attachments[frame].image = images[frame];
|
renderTarget.attachments[frame].image = ::images[frame];
|
||||||
renderTarget.attachments[frame].mem = VK_NULL_HANDLE;
|
renderTarget.attachments[frame].mem = VK_NULL_HANDLE;
|
||||||
|
|
||||||
metadata.attachments["color["+std::to_string((int) frame)+"]"] = attachmentIndex++;
|
metadata.attachments["color["+std::to_string((int) frame)+"]"] = attachmentIndex++;
|
||||||
@ -530,7 +530,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
|||||||
// Create framebuffer
|
// Create framebuffer
|
||||||
{
|
{
|
||||||
// Create a frame buffer for every image in the swapchain
|
// Create a frame buffer for every image in the swapchain
|
||||||
renderTarget.framebuffers.resize(images.size());
|
renderTarget.framebuffers.resize(::images.size());
|
||||||
for (size_t frame = 0; frame < renderTarget.framebuffers.size(); frame++)
|
for (size_t frame = 0; frame < renderTarget.framebuffers.size(); frame++)
|
||||||
{
|
{
|
||||||
std::array<VkImageView, 2> attachments;
|
std::array<VkImageView, 2> attachments;
|
||||||
@ -555,7 +555,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
|||||||
#if 0
|
#if 0
|
||||||
if ( true ) {
|
if ( true ) {
|
||||||
auto commandBuffer = device.fetchCommandBuffer(uf::renderer::QueueEnum::TRANSFER);
|
auto commandBuffer = device.fetchCommandBuffer(uf::renderer::QueueEnum::TRANSFER);
|
||||||
for ( size_t frame = 0; frame < images.size(); ++frame ) {
|
for ( size_t frame = 0; frame < ::images.size(); ++frame ) {
|
||||||
VkImageMemoryBarrier imageMemoryBarrier = {};
|
VkImageMemoryBarrier imageMemoryBarrier = {};
|
||||||
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
imageMemoryBarrier.srcAccessMask = 0;
|
imageMemoryBarrier.srcAccessMask = 0;
|
||||||
@ -652,10 +652,11 @@ void ext::vulkan::BaseRenderMode::destroy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ( auto& image : ::images ) {
|
for ( auto& image : ::images ) {
|
||||||
// vkDestroyImage( *device, image, nullptr );
|
// vkDestroyImage( *device, image, nullptr ); // destroyed via vkDestroySwapchainKHR
|
||||||
VK_UNREGISTER_HANDLE( image );
|
VK_UNREGISTER_HANDLE( image );
|
||||||
image = VK_NULL_HANDLE;
|
image = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
::images.clear();
|
||||||
|
|
||||||
ext::vulkan::RenderMode::destroy();
|
ext::vulkan::RenderMode::destroy();
|
||||||
|
|
||||||
|
|||||||
@ -26,22 +26,34 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const uf::stl::string DEFERRED_MODE = "compute";
|
const uf::stl::string DEFERRED_MODE = "compute";
|
||||||
ext::vulkan::Texture depthPyramid;
|
|
||||||
uf::stl::vector<VkImageView> depthPyramidViews;
|
uf::stl::vector<VkImageView> depthPyramidViews;
|
||||||
|
uf::stl::vector<VkImageView> bloomViews;
|
||||||
|
|
||||||
void cmdImageBarrier(VkCommandBuffer commandBuffer, VkImage image, VkAccessFlags srcAccess, VkAccessFlags dstAccess, VkImageLayout oldLayout, VkImageLayout newLayout) {
|
ext::vulkan::Buffer atomicCounterBloom;
|
||||||
VkImageMemoryBarrier barrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
|
ext::vulkan::Buffer atomicCounterDepth;
|
||||||
barrier.srcAccessMask = srcAccess;
|
|
||||||
barrier.dstAccessMask = dstAccess;
|
|
||||||
barrier.oldLayout = oldLayout;
|
|
||||||
barrier.newLayout = newLayout;
|
|
||||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
barrier.image = image;
|
|
||||||
barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
|
struct AtomicCounter {
|
||||||
|
uint32_t counter;
|
||||||
};
|
};
|
||||||
|
struct PushConstants {
|
||||||
|
uint32_t mips;
|
||||||
|
uint32_t numWorkGroups;
|
||||||
|
uint32_t workGroupOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
void destroyImageView( ext::vulkan::RenderMode* self, VkImageView view ) {
|
||||||
|
ext::vulkan::mutex.lock();
|
||||||
|
auto& texture = self->device->transient.textures.emplace_back();
|
||||||
|
ext::vulkan::mutex.unlock();
|
||||||
|
|
||||||
|
texture.device = self->device;
|
||||||
|
texture.view = view;
|
||||||
|
/*
|
||||||
|
vkDestroyImageView(self->device.logicalDevice, view, nullptr);
|
||||||
|
VK_UNREGISTER_HANDLE(view);
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "./transition.inl"
|
#include "./transition.inl"
|
||||||
@ -64,8 +76,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
size_t id, bary, depth, uv, normal;
|
size_t id, bary, depth, uv, normal;
|
||||||
size_t color, bright, motion, scratch, output;
|
size_t color, bright, motion, output;
|
||||||
size_t depthPyramid;
|
|
||||||
} attachments = {};
|
} attachments = {};
|
||||||
|
|
||||||
bool blend = true; // !ext::vulkan::settings::invariant::deferredSampling;
|
bool blend = true; // !ext::vulkan::settings::invariant::deferredSampling;
|
||||||
@ -108,7 +119,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||||
/*.format = */ext::vulkan::settings::formats::depth,
|
/*.format = */ext::vulkan::settings::formats::depth,
|
||||||
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||||
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
/*.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 | VK_IMAGE_USAGE_STORAGE_BIT,
|
||||||
/*.blend = */false,
|
/*.blend = */false,
|
||||||
/*.samples = */msaa,
|
/*.samples = */msaa,
|
||||||
//*.mips = */1,
|
//*.mips = */1,
|
||||||
@ -127,13 +138,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
/*.blend =*/ blend,
|
/*.blend =*/ blend,
|
||||||
/*.samples =*/ 1,
|
/*.samples =*/ 1,
|
||||||
});
|
/*.mips =*/ mips,
|
||||||
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
|
||||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
|
||||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
||||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
|
||||||
/*.blend =*/ blend,
|
|
||||||
/*.samples =*/ 1,
|
|
||||||
});
|
});
|
||||||
attachments.motion = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
attachments.motion = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||||
// /*.format = */VK_FORMAT_R32G32B32A32_SFLOAT,
|
// /*.format = */VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
@ -143,14 +148,6 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
/*.blend = */false,
|
/*.blend = */false,
|
||||||
/*.samples = */1,
|
/*.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 = */mips,
|
|
||||||
});
|
|
||||||
|
|
||||||
metadata.attachments["id"] = attachments.id;
|
metadata.attachments["id"] = attachments.id;
|
||||||
|
|
||||||
@ -164,10 +161,8 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
metadata.attachments["depth"] = attachments.depth;
|
metadata.attachments["depth"] = attachments.depth;
|
||||||
metadata.attachments["depthPyramid"] = attachments.depthPyramid;
|
|
||||||
metadata.attachments["color"] = attachments.color;
|
metadata.attachments["color"] = attachments.color;
|
||||||
metadata.attachments["bright"] = attachments.bright;
|
metadata.attachments["bright"] = attachments.bright;
|
||||||
metadata.attachments["scratch"] = attachments.scratch;
|
|
||||||
metadata.attachments["motion"] = attachments.motion;
|
metadata.attachments["motion"] = attachments.motion;
|
||||||
|
|
||||||
metadata.attachments["output"] = attachments.color;
|
metadata.attachments["output"] = attachments.color;
|
||||||
@ -339,13 +334,67 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( settings::pipelines::bloom ) {
|
if ( settings::pipelines::bloom ) {
|
||||||
uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/bloom/comp.spv");
|
uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/bloom/up.comp.spv");
|
||||||
blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "bloom");
|
blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "bloom-up");
|
||||||
|
|
||||||
|
auto& shader = blitter.material.getShader("compute", "bloom-up");
|
||||||
|
|
||||||
auto& shader = blitter.material.getShader("compute", "bloom");
|
|
||||||
shader.aliasAttachment("color", this, VK_IMAGE_LAYOUT_GENERAL);
|
shader.aliasAttachment("color", this, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
shader.aliasAttachment("bright", this, VK_IMAGE_LAYOUT_GENERAL);
|
shader.aliasAttachment("bright", this, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
shader.aliasAttachment("scratch", this, VK_IMAGE_LAYOUT_GENERAL);
|
}
|
||||||
|
|
||||||
|
if ( settings::pipelines::bloom ) {
|
||||||
|
uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/bloom/down.comp.spv");
|
||||||
|
blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "bloom-down");
|
||||||
|
|
||||||
|
auto& shader = blitter.material.getShader("compute", "bloom-down");
|
||||||
|
auto mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
||||||
|
|
||||||
|
shader.aliasAttachment("color", this, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
shader.aliasAttachment("bright", this, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
|
||||||
|
shader.setSpecializationConstants({
|
||||||
|
{ "MIPS", mips },
|
||||||
|
});
|
||||||
|
shader.setDescriptorCounts({
|
||||||
|
{ "outImage", mips },
|
||||||
|
});
|
||||||
|
|
||||||
|
// atomic counter buffer
|
||||||
|
::atomicCounterBloom.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE );
|
||||||
|
shader.aliasBuffer("atomicCounterBloom", ::atomicCounterBloom);
|
||||||
|
|
||||||
|
for ( auto& view : ::bloomViews ) ::destroyImageView( this, view );
|
||||||
|
::bloomViews.clear();
|
||||||
|
::bloomViews.resize(mips);
|
||||||
|
shader.textures.clear();
|
||||||
|
|
||||||
|
ext::vulkan::Texture2D source; source.aliasAttachment( this->getAttachment("bright") );
|
||||||
|
for ( auto i = 0; i < mips; ++i ) {
|
||||||
|
auto& view = ::bloomViews[i];
|
||||||
|
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));
|
||||||
|
VK_REGISTER_HANDLE(view);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto& texture = shader.textures.emplace_back();
|
||||||
|
texture.aliasTexture( source );
|
||||||
|
texture.view = view;
|
||||||
|
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
texture.updateDescriptors();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( settings::pipelines::culling ) {
|
if ( settings::pipelines::culling ) {
|
||||||
@ -354,28 +403,32 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
|
|
||||||
auto& shader = blitter.material.getShader("compute", "depth-pyramid");
|
auto& shader = blitter.material.getShader("compute", "depth-pyramid");
|
||||||
auto mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
auto mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
||||||
|
// depth pyramid
|
||||||
|
shader.aliasAttachment("depth", this);
|
||||||
|
|
||||||
shader.setSpecializationConstants({
|
shader.setSpecializationConstants({
|
||||||
{ "MIPS", mips },
|
{ "MIPS", mips },
|
||||||
});
|
});
|
||||||
shader.setDescriptorCounts({
|
shader.setDescriptorCounts({
|
||||||
{ "inImage", mips },
|
|
||||||
{ "outImage", mips },
|
{ "outImage", mips },
|
||||||
});
|
});
|
||||||
|
|
||||||
shader.aliasAttachment("depth", this);
|
// atomic counter buffer
|
||||||
|
::atomicCounterDepth.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE );
|
||||||
|
shader.aliasBuffer("atomicCounterDepth", ::atomicCounterDepth);
|
||||||
|
|
||||||
ext::vulkan::Texture2D source; source.aliasAttachment( this->getAttachment("depthPyramid") );
|
for ( auto& view : ::depthPyramidViews ) ::destroyImageView( this, view );
|
||||||
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);
|
|
||||||
VK_UNREGISTER_HANDLE(view);
|
|
||||||
}
|
|
||||||
::depthPyramidViews.clear();
|
::depthPyramidViews.clear();
|
||||||
::depthPyramidViews.resize(mips);
|
::depthPyramidViews.resize(mips);
|
||||||
shader.textures.clear();
|
shader.textures.clear();
|
||||||
|
|
||||||
|
storage.buffers.depthPyramid.destroy(true);
|
||||||
|
storage.buffers.depthPyramid.fromBuffers( NULL, 0, VK_FORMAT_R32_SFLOAT, width, height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||||
|
|
||||||
|
ext::vulkan::Texture2D& source = storage.buffers.depthPyramid;
|
||||||
|
source.sampler.descriptor.reduction.enabled = true;
|
||||||
|
source.sampler.descriptor.reduction.mode = VK_SAMPLER_REDUCTION_MODE_MIN;
|
||||||
|
|
||||||
for ( auto i = 0; i < mips; ++i ) {
|
for ( auto i = 0; i < mips; ++i ) {
|
||||||
auto& view = ::depthPyramidViews[i];
|
auto& view = ::depthPyramidViews[i];
|
||||||
VkImageViewCreateInfo viewCreateInfo = {};
|
VkImageViewCreateInfo viewCreateInfo = {};
|
||||||
@ -392,22 +445,14 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
|
|
||||||
VK_CHECK_RESULT(vkCreateImageView(device.logicalDevice, &viewCreateInfo, nullptr, &view));
|
VK_CHECK_RESULT(vkCreateImageView(device.logicalDevice, &viewCreateInfo, nullptr, &view));
|
||||||
VK_REGISTER_HANDLE(view);
|
VK_REGISTER_HANDLE(view);
|
||||||
}
|
|
||||||
|
|
||||||
for ( auto i = 0; i < mips; ++i ) {
|
{
|
||||||
auto& texture = shader.textures.emplace_back();
|
auto& texture = shader.textures.emplace_back();
|
||||||
texture.aliasTexture( source );
|
texture.aliasTexture( source );
|
||||||
texture.view = ::depthPyramidViews[i];
|
texture.view = view;
|
||||||
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
texture.updateDescriptors();
|
texture.updateDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( auto i = 0; i < mips; ++i ) {
|
|
||||||
auto& texture = shader.textures.emplace_back();
|
|
||||||
texture.aliasTexture( source );
|
|
||||||
texture.view = ::depthPyramidViews[i];
|
|
||||||
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
||||||
texture.updateDescriptors();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +482,18 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( settings::pipelines::bloom ) {
|
if ( settings::pipelines::bloom ) {
|
||||||
descriptor.pipeline = "bloom";
|
descriptor.aux = uf::vector::mips( pod::Vector2ui{ width, height } );
|
||||||
|
descriptor.pipeline = "bloom-down";
|
||||||
|
descriptor.subpass = 0;
|
||||||
|
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||||
|
if ( !blitter.hasPipeline( descriptor ) ) {
|
||||||
|
blitter.initializePipeline( descriptor );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( settings::pipelines::bloom ) {
|
||||||
|
descriptor.aux = {};
|
||||||
|
descriptor.pipeline = "bloom-up";
|
||||||
descriptor.subpass = 0;
|
descriptor.subpass = 0;
|
||||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||||
if ( !blitter.hasPipeline( descriptor ) ) {
|
if ( !blitter.hasPipeline( descriptor ) ) {
|
||||||
@ -474,6 +530,49 @@ void ext::vulkan::DeferredRenderMode::tick() {
|
|||||||
rebuild = true;
|
rebuild = true;
|
||||||
renderTarget.initialize( *renderTarget.device );
|
renderTarget.initialize( *renderTarget.device );
|
||||||
|
|
||||||
|
if ( settings::pipelines::bloom ) {
|
||||||
|
auto& shader = blitter.material.getShader("compute", "bloom-down");
|
||||||
|
auto mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
||||||
|
shader.setSpecializationConstants({
|
||||||
|
{ "MIPS", mips },
|
||||||
|
});
|
||||||
|
shader.setDescriptorCounts({
|
||||||
|
{ "outImage", mips },
|
||||||
|
});
|
||||||
|
|
||||||
|
for ( auto& view : ::bloomViews ) ::destroyImageView( this, view );
|
||||||
|
::bloomViews.clear();
|
||||||
|
::bloomViews.resize(mips);
|
||||||
|
shader.textures.clear();
|
||||||
|
|
||||||
|
ext::vulkan::Texture2D source; source.aliasAttachment( this->getAttachment("bright") );
|
||||||
|
for ( auto i = 0; i < mips; ++i ) {
|
||||||
|
auto& view = ::bloomViews[i];
|
||||||
|
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));
|
||||||
|
VK_REGISTER_HANDLE(view);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto& texture = shader.textures.emplace_back();
|
||||||
|
texture.aliasTexture( source );
|
||||||
|
texture.view = view;
|
||||||
|
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
texture.updateDescriptors();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( settings::pipelines::culling ) {
|
if ( settings::pipelines::culling ) {
|
||||||
auto& shader = blitter.material.getShader("compute", "depth-pyramid");
|
auto& shader = blitter.material.getShader("compute", "depth-pyramid");
|
||||||
auto mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
auto mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
||||||
@ -481,20 +580,17 @@ void ext::vulkan::DeferredRenderMode::tick() {
|
|||||||
{ "MIPS", mips },
|
{ "MIPS", mips },
|
||||||
});
|
});
|
||||||
shader.setDescriptorCounts({
|
shader.setDescriptorCounts({
|
||||||
{ "inImage", mips },
|
|
||||||
{ "outImage", mips },
|
{ "outImage", mips },
|
||||||
});
|
});
|
||||||
|
|
||||||
shader.aliasAttachment("depth", this);
|
storage.buffers.depthPyramid.destroy(true);
|
||||||
|
storage.buffers.depthPyramid.fromBuffers( NULL, 0, VK_FORMAT_R32_SFLOAT, width, height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||||
|
|
||||||
ext::vulkan::Texture2D source; source.aliasAttachment( this->getAttachment("depthPyramid") );
|
ext::vulkan::Texture2D& source = storage.buffers.depthPyramid;
|
||||||
source.sampler.descriptor.reduction.enabled = true;
|
source.sampler.descriptor.reduction.enabled = true;
|
||||||
source.sampler.descriptor.reduction.mode = VK_SAMPLER_REDUCTION_MODE_MIN;
|
source.sampler.descriptor.reduction.mode = VK_SAMPLER_REDUCTION_MODE_MIN;
|
||||||
|
|
||||||
for ( auto& view : ::depthPyramidViews ) {
|
for ( auto& view : ::depthPyramidViews ) ::destroyImageView( this, view );
|
||||||
vkDestroyImageView(device->logicalDevice, view, nullptr);
|
|
||||||
VK_UNREGISTER_HANDLE(view);
|
|
||||||
}
|
|
||||||
::depthPyramidViews.clear();
|
::depthPyramidViews.clear();
|
||||||
::depthPyramidViews.resize(mips);
|
::depthPyramidViews.resize(mips);
|
||||||
shader.textures.clear();
|
shader.textures.clear();
|
||||||
@ -516,22 +612,13 @@ void ext::vulkan::DeferredRenderMode::tick() {
|
|||||||
VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view));
|
VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &view));
|
||||||
VK_REGISTER_HANDLE(view);
|
VK_REGISTER_HANDLE(view);
|
||||||
|
|
||||||
}
|
{
|
||||||
|
auto& texture = shader.textures.emplace_back();
|
||||||
for ( auto i = 0; i < mips; ++i ) {
|
texture.aliasTexture( source );
|
||||||
auto& texture = shader.textures.emplace_back();
|
texture.view = view;
|
||||||
texture.aliasTexture( source );
|
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
texture.view = ::depthPyramidViews[i];
|
texture.updateDescriptors();
|
||||||
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
}
|
||||||
texture.updateDescriptors();
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( auto i = 0; i < mips; ++i ) {
|
|
||||||
auto& texture = shader.textures.emplace_back();
|
|
||||||
texture.aliasTexture( source );
|
|
||||||
texture.view = ::depthPyramidViews[i];
|
|
||||||
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
||||||
texture.updateDescriptors();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -582,7 +669,20 @@ void ext::vulkan::DeferredRenderMode::tick() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( settings::pipelines::bloom ) {
|
if ( settings::pipelines::bloom ) {
|
||||||
descriptor.pipeline = "bloom";
|
descriptor.aux = uf::vector::mips( pod::Vector2ui{ width, height } );
|
||||||
|
descriptor.pipeline = "bloom-down";
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( settings::pipelines::bloom ) {
|
||||||
|
descriptor.aux = {};
|
||||||
|
descriptor.pipeline = "bloom-up";
|
||||||
descriptor.subpass = 0;
|
descriptor.subpass = 0;
|
||||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||||
if ( blitter.hasPipeline( descriptor ) ) {
|
if ( blitter.hasPipeline( descriptor ) ) {
|
||||||
@ -659,6 +759,21 @@ void ext::vulkan::DeferredRenderMode::render() {
|
|||||||
//unlockMutex( this->mostRecentCommandPoolId );
|
//unlockMutex( this->mostRecentCommandPoolId );
|
||||||
}
|
}
|
||||||
void ext::vulkan::DeferredRenderMode::destroy() {
|
void ext::vulkan::DeferredRenderMode::destroy() {
|
||||||
|
// cleanup
|
||||||
|
::atomicCounterDepth.destroy(false);
|
||||||
|
::atomicCounterBloom.destroy(false);
|
||||||
|
|
||||||
|
for ( auto& view : ::bloomViews ) {
|
||||||
|
vkDestroyImageView(device->logicalDevice, view, nullptr);
|
||||||
|
VK_UNREGISTER_HANDLE(view);
|
||||||
|
}
|
||||||
|
::bloomViews.clear();
|
||||||
|
for ( auto& view : ::depthPyramidViews ) {
|
||||||
|
vkDestroyImageView(device->logicalDevice, view, nullptr);
|
||||||
|
VK_UNREGISTER_HANDLE(view);
|
||||||
|
}
|
||||||
|
::depthPyramidViews.clear();
|
||||||
|
|
||||||
ext::vulkan::RenderMode::destroy();
|
ext::vulkan::RenderMode::destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,18 +859,6 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
|||||||
|
|
||||||
size_t currentSubpass = 0;
|
size_t currentSubpass = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
// transition layers for read
|
|
||||||
for ( auto layer : layers ) {
|
|
||||||
layer->pipelineBarrier( commandBuffer, 0 );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
|
||||||
// VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
||||||
|
|
||||||
// VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
|
|
||||||
// VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
for ( auto& attachment : renderTarget.attachments ) {
|
for ( auto& attachment : renderTarget.attachments ) {
|
||||||
// transition attachments to general attachments for imageStore
|
// transition attachments to general attachments for imageStore
|
||||||
@ -863,11 +966,61 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
|||||||
::transitionAttachmentsFrom( this, shader, commandBuffer );
|
::transitionAttachmentsFrom( this, shader, commandBuffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( settings::pipelines::bloom && blitter.material.hasShader("compute", "bloom") ) {
|
if ( settings::pipelines::bloom && blitter.material.hasShader("compute", "bloom-down") ) {
|
||||||
auto& shader = blitter.material.getShader("compute", "bloom");
|
auto& shader = blitter.material.getShader("compute", "bloom-down");
|
||||||
|
auto mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
||||||
|
|
||||||
|
uint32_t dispatchX = (width + 63) / 64;
|
||||||
|
uint32_t dispatchY = (height + 63) / 64;
|
||||||
|
uint32_t numWorkGroups = dispatchX * dispatchY;
|
||||||
|
auto& pushConstant = shader.pushConstants.front().get<::PushConstants>();
|
||||||
|
pushConstant = {
|
||||||
|
.mips = mips,
|
||||||
|
.numWorkGroups = numWorkGroups,
|
||||||
|
.workGroupOffset = 0,
|
||||||
|
};
|
||||||
|
|
||||||
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
|
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
|
||||||
descriptor.renderMode = "";
|
descriptor.renderMode = "";
|
||||||
descriptor.pipeline = "bloom";
|
descriptor.aux = mips;
|
||||||
|
descriptor.pipeline = "bloom-down";
|
||||||
|
descriptor.bind.width = dispatchX * 256;
|
||||||
|
descriptor.bind.height = dispatchY;
|
||||||
|
descriptor.bind.depth = metadata.eyes;
|
||||||
|
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||||
|
descriptor.subpass = 0;
|
||||||
|
|
||||||
|
// reset counter buffer
|
||||||
|
vkCmdFillBuffer(commandBuffer, ::atomicCounterBloom.buffer, 0, 4, 0);
|
||||||
|
VkMemoryBarrier counterBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
|
||||||
|
counterBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
counterBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
|
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &counterBarrier, 0, nullptr, 0, nullptr);
|
||||||
|
|
||||||
|
// transition attachments to general attachments for imageStore
|
||||||
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" );
|
||||||
|
::transitionAttachmentsTo( this, shader, commandBuffer );
|
||||||
|
|
||||||
|
// dispatch compute shader
|
||||||
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "bloom[down]" );
|
||||||
|
blitter.record( commandBuffer, descriptor );
|
||||||
|
|
||||||
|
/*
|
||||||
|
ext::vulkan::Texture2D source;
|
||||||
|
source.aliasAttachment( this->getAttachment("bright") );
|
||||||
|
source.generateMipmaps( commandBuffer );
|
||||||
|
*/
|
||||||
|
|
||||||
|
// transition attachments back to shader read layouts
|
||||||
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" );
|
||||||
|
::transitionAttachmentsFrom( this, shader, commandBuffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( settings::pipelines::bloom && blitter.material.hasShader("compute", "bloom-up") ) {
|
||||||
|
auto& shader = blitter.material.getShader("compute", "bloom-up");
|
||||||
|
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
|
||||||
|
descriptor.renderMode = "";
|
||||||
|
descriptor.pipeline = "bloom-up";
|
||||||
descriptor.bind.width = width;
|
descriptor.bind.width = width;
|
||||||
descriptor.bind.height = height;
|
descriptor.bind.height = height;
|
||||||
descriptor.bind.depth = metadata.eyes;
|
descriptor.bind.depth = metadata.eyes;
|
||||||
@ -879,20 +1032,8 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
|||||||
::transitionAttachmentsTo( this, shader, commandBuffer );
|
::transitionAttachmentsTo( this, shader, commandBuffer );
|
||||||
|
|
||||||
// dispatch compute shader
|
// dispatch compute shader
|
||||||
auto& attachmentColor = this->getAttachment("color"); // color
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "bloom[up]" );
|
||||||
auto& attachmentBright = this->getAttachment("bright"); // bloom
|
blitter.record( commandBuffer, descriptor );
|
||||||
auto& attachmentScratch = this->getAttachment("scratch"); // pingpong
|
|
||||||
|
|
||||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "bloom[1]" );
|
|
||||||
blitter.record( commandBuffer, descriptor, 0, 1 );
|
|
||||||
cmdImageBarrier( commandBuffer, attachmentScratch.image, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL );
|
|
||||||
|
|
||||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "bloom[2]" );
|
|
||||||
blitter.record( commandBuffer, descriptor, 0, 2 );
|
|
||||||
cmdImageBarrier( commandBuffer, attachmentBright.image, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL );
|
|
||||||
|
|
||||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "bloom[3]" );
|
|
||||||
blitter.record( commandBuffer, descriptor, 0, 3 );
|
|
||||||
|
|
||||||
// transition attachments back to shader read layouts
|
// transition attachments back to shader read layouts
|
||||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" );
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" );
|
||||||
@ -900,80 +1041,51 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
|||||||
}
|
}
|
||||||
|
|
||||||
// construct depth-pyramid
|
// construct depth-pyramid
|
||||||
#if 1
|
|
||||||
if ( settings::pipelines::culling && blitter.material.hasShader("compute", "depth-pyramid") ) {
|
if ( settings::pipelines::culling && blitter.material.hasShader("compute", "depth-pyramid") ) {
|
||||||
auto& shader = blitter.material.getShader("compute", "depth-pyramid");
|
auto& shader = blitter.material.getShader("compute", "depth-pyramid");
|
||||||
auto mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
auto mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
||||||
|
|
||||||
|
uint32_t dispatchX = (width + 63) / 64;
|
||||||
|
uint32_t dispatchY = (height + 63) / 64;
|
||||||
|
uint32_t numWorkGroups = dispatchX * dispatchY;
|
||||||
|
auto& pushConstant = shader.pushConstants.front().get<::PushConstants>();
|
||||||
|
pushConstant = {
|
||||||
|
.mips = mips,
|
||||||
|
.numWorkGroups = numWorkGroups,
|
||||||
|
.workGroupOffset = 0,
|
||||||
|
};
|
||||||
|
|
||||||
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
|
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
|
||||||
descriptor.renderMode = "";
|
descriptor.renderMode = "";
|
||||||
descriptor.aux = mips;
|
descriptor.aux = mips;
|
||||||
descriptor.pipeline = "depth-pyramid";
|
descriptor.pipeline = "depth-pyramid";
|
||||||
|
descriptor.bind.width = dispatchX * 256;
|
||||||
|
descriptor.bind.height = dispatchY;
|
||||||
descriptor.bind.depth = metadata.eyes;
|
descriptor.bind.depth = metadata.eyes;
|
||||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||||
descriptor.subpass = 0;
|
descriptor.subpass = 0;
|
||||||
|
|
||||||
// dispatch compute shader
|
// reset counter buffer
|
||||||
VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
|
vkCmdFillBuffer(commandBuffer, ::atomicCounterDepth.buffer, 0, 4, 0);
|
||||||
memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
VkMemoryBarrier counterBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
|
||||||
memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
counterBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
counterBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
|
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &counterBarrier, 0, nullptr, 0, nullptr);
|
||||||
|
|
||||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" );
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" );
|
||||||
::transitionAttachmentsTo( this, shader, commandBuffer );
|
::transitionAttachmentsTo( this, shader, commandBuffer );
|
||||||
|
|
||||||
for ( auto i = 0; i < mips; ++i ) {
|
blitter.record(commandBuffer, descriptor);
|
||||||
// for some reason it dispatches at half the width without offsetting back...
|
|
||||||
descriptor.bind.width = std::max(1u, width >> (i - 1));
|
|
||||||
descriptor.bind.height = std::max(1u, height >> (i - 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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" );
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "setImageLayout" );
|
||||||
::transitionAttachmentsFrom( this, shader, commandBuffer );
|
::transitionAttachmentsFrom( this, shader, commandBuffer );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
// post-renderpass commands
|
// post-renderpass commands
|
||||||
VK_COMMAND_BUFFER_CALLBACK( CALLBACK_END, commandBuffer, frame, {
|
VK_COMMAND_BUFFER_CALLBACK( CALLBACK_END, commandBuffer, frame, {
|
||||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "callback[end]" );
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "callback[end]" );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
#if 0
|
|
||||||
if ( this->hasAttachment("depth") ) {
|
|
||||||
auto& attachment = this->getAttachment("depth");
|
|
||||||
ext::vulkan::Texture texture; texture.aliasAttachment( attachment );
|
|
||||||
texture.width = width;
|
|
||||||
texture.height = height;
|
|
||||||
texture.depth = 1;
|
|
||||||
|
|
||||||
texture.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
|
||||||
texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
|
||||||
#if 1
|
|
||||||
imageMemoryBarrier.subresourceRange.layerCount = metadata.eyes;
|
|
||||||
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
||||||
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(commandBuffer, eye);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
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
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
for ( auto layer : layers ) {
|
|
||||||
layer->pipelineBarrier( commandBuffer, 1 );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::END, "end" );
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::END, "end" );
|
||||||
|
|||||||
@ -9,24 +9,41 @@ namespace {
|
|||||||
subresourceRange.baseMipLevel = 0;
|
subresourceRange.baseMipLevel = 0;
|
||||||
subresourceRange.levelCount = 1;
|
subresourceRange.levelCount = 1;
|
||||||
subresourceRange.baseArrayLayer = 0;
|
subresourceRange.baseArrayLayer = 0;
|
||||||
subresourceRange.layerCount = 1;
|
|
||||||
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
subresourceRange.layerCount = self->metadata.eyes;
|
subresourceRange.layerCount = self->metadata.eyes;
|
||||||
|
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
|
||||||
for ( auto& descriptor : shader.metadata.aliases.attachments ) {
|
for ( auto& descriptor : shader.metadata.aliases.attachments ) {
|
||||||
if ( descriptor.layout == VK_IMAGE_LAYOUT_UNDEFINED ) continue;
|
if ( descriptor.layout == VK_IMAGE_LAYOUT_UNDEFINED ) continue;
|
||||||
VkImage image = VK_NULL_HANDLE;
|
VkImage image = VK_NULL_HANDLE;
|
||||||
|
VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
size_t mips = 1;
|
||||||
|
|
||||||
if ( descriptor.renderMode ) {
|
if ( descriptor.renderMode ) {
|
||||||
if ( descriptor.renderMode->hasAttachment(descriptor.name) )
|
if ( descriptor.renderMode->hasAttachment(descriptor.name) ) {
|
||||||
image = descriptor.renderMode->getAttachment(descriptor.name).image;
|
auto& attachment = descriptor.renderMode->getAttachment(descriptor.name);
|
||||||
|
image = attachment.image;
|
||||||
|
mips = attachment.descriptor.mips;
|
||||||
|
initialLayout = attachment.descriptor.layout;
|
||||||
|
}
|
||||||
|
|
||||||
} else if ( self->hasAttachment(descriptor.name) ) {
|
} else if ( self->hasAttachment(descriptor.name) ) {
|
||||||
if ( self->hasAttachment(descriptor.name) )
|
if ( self->hasAttachment(descriptor.name) ) {
|
||||||
image = self->getAttachment(descriptor.name).image;
|
auto& attachment = self->getAttachment(descriptor.name);
|
||||||
|
image = attachment.image;
|
||||||
|
mips = attachment.descriptor.mips;
|
||||||
|
initialLayout = attachment.descriptor.layout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( image == VK_NULL_HANDLE ) continue;
|
if ( image == VK_NULL_HANDLE ) continue;
|
||||||
|
subresourceRange.baseMipLevel = 0;
|
||||||
|
subresourceRange.levelCount = 1;
|
||||||
subresourceRange.aspectMask = descriptor.name == "depth" ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
|
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 );
|
uf::renderer::Texture::setImageLayout( commandBuffer, image, layout, descriptor.layout, subresourceRange );
|
||||||
|
if ( mips > 1 ) {
|
||||||
|
subresourceRange.baseMipLevel = 1;
|
||||||
|
subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||||
|
uf::renderer::Texture::setImageLayout( commandBuffer, image, initialLayout, descriptor.layout, subresourceRange );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void transitionAttachmentsFrom(
|
void transitionAttachmentsFrom(
|
||||||
@ -39,24 +56,41 @@ namespace {
|
|||||||
subresourceRange.baseMipLevel = 0;
|
subresourceRange.baseMipLevel = 0;
|
||||||
subresourceRange.levelCount = 1;
|
subresourceRange.levelCount = 1;
|
||||||
subresourceRange.baseArrayLayer = 0;
|
subresourceRange.baseArrayLayer = 0;
|
||||||
subresourceRange.layerCount = 1;
|
|
||||||
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
subresourceRange.layerCount = self->metadata.eyes;
|
subresourceRange.layerCount = self->metadata.eyes;
|
||||||
|
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
|
||||||
for ( auto& descriptor : shader.metadata.aliases.attachments ) {
|
for ( auto& descriptor : shader.metadata.aliases.attachments ) {
|
||||||
if ( descriptor.layout == VK_IMAGE_LAYOUT_UNDEFINED ) continue;
|
if ( descriptor.layout == VK_IMAGE_LAYOUT_UNDEFINED ) continue;
|
||||||
VkImage image = VK_NULL_HANDLE;
|
VkImage image = VK_NULL_HANDLE;
|
||||||
|
VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
size_t mips = 1;
|
||||||
|
|
||||||
if ( descriptor.renderMode ) {
|
if ( descriptor.renderMode ) {
|
||||||
if ( descriptor.renderMode->hasAttachment(descriptor.name) )
|
if ( descriptor.renderMode->hasAttachment(descriptor.name) ) {
|
||||||
image = descriptor.renderMode->getAttachment(descriptor.name).image;
|
auto& attachment = descriptor.renderMode->getAttachment(descriptor.name);
|
||||||
|
image = attachment.image;
|
||||||
|
mips = attachment.descriptor.mips;
|
||||||
|
initialLayout = attachment.descriptor.layout;
|
||||||
|
}
|
||||||
|
|
||||||
} else if ( self->hasAttachment(descriptor.name) ) {
|
} else if ( self->hasAttachment(descriptor.name) ) {
|
||||||
if ( self->hasAttachment(descriptor.name) )
|
if ( self->hasAttachment(descriptor.name) ) {
|
||||||
image = self->getAttachment(descriptor.name).image;
|
auto& attachment = self->getAttachment(descriptor.name);
|
||||||
|
image = attachment.image;
|
||||||
|
mips = attachment.descriptor.mips;
|
||||||
|
initialLayout = attachment.descriptor.layout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( image == VK_NULL_HANDLE ) continue;
|
if ( image == VK_NULL_HANDLE ) continue;
|
||||||
|
subresourceRange.baseMipLevel = 0;
|
||||||
|
subresourceRange.levelCount = 1;
|
||||||
subresourceRange.aspectMask = descriptor.name == "depth" ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
|
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 );
|
uf::renderer::Texture::setImageLayout( commandBuffer, image, descriptor.layout, layout, subresourceRange );
|
||||||
|
if ( mips > 1 ) {
|
||||||
|
subresourceRange.baseMipLevel = 1;
|
||||||
|
subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||||
|
uf::renderer::Texture::setImageLayout( commandBuffer, image, descriptor.layout, initialLayout, subresourceRange );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,8 +12,8 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#define VK_DEBUG_VALIDATION_MESSAGE(x)\
|
#define VK_DEBUG_VALIDATION_MESSAGE(...)\
|
||||||
// VK_VALIDATION_MESSAGE(x);
|
//VK_VALIDATION_MESSAGE(__VA_ARGS__);
|
||||||
|
|
||||||
#define UF_SHADER_PARSE_AS_JSON 0
|
#define UF_SHADER_PARSE_AS_JSON 0
|
||||||
#if UF_SHADER_PARSE_AS_JSON
|
#if UF_SHADER_PARSE_AS_JSON
|
||||||
@ -94,7 +94,7 @@ ext::vulkan::userdata_t ext::vulkan::jsonToUserdata( const ext::json::Value& pay
|
|||||||
#if UF_SHADER_TRACK_NAMES
|
#if UF_SHADER_TRACK_NAMES
|
||||||
uf::stl::string path = uf::string::join(variableName, ".");
|
uf::stl::string path = uf::string::join(variableName, ".");
|
||||||
path = uf::string::replace( path, ".[", "[" );
|
path = uf::string::replace( path, ".[", "[" );
|
||||||
VK_VALIDATION_MESSAGE("[" << (byteBuffer - byteBufferStart) << " / "<< (byteBufferEnd - byteBuffer) <<"]\tInserting: " << path << " = " << value.dump());
|
//VK_VALIDATION_MESSAGE("[" << (byteBuffer - byteBufferStart) << " / "<< (byteBufferEnd - byteBuffer) <<"]\tInserting: " << path << " = " << value.dump());
|
||||||
#endif
|
#endif
|
||||||
// is strictly an int
|
// is strictly an int
|
||||||
if ( value.is<int>(true) ) {
|
if ( value.is<int>(true) ) {
|
||||||
@ -120,7 +120,7 @@ ext::vulkan::userdata_t ext::vulkan::jsonToUserdata( const ext::json::Value& pay
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
#if UF_SHADER_TRACK_NAMES
|
#if UF_SHADER_TRACK_NAMES
|
||||||
VK_VALIDATION_MESSAGE("Updating {} in {}", name, filename);
|
//VK_VALIDATION_MESSAGE("Updating {} in {}", name, filename);
|
||||||
// VK_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer));
|
// VK_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer));
|
||||||
#endif
|
#endif
|
||||||
parse(payload);
|
parse(payload);
|
||||||
@ -264,7 +264,7 @@ ext::vulkan::userdata_t ext::vulkan::jsonToUserdata( const ext::json::Value& pay
|
|||||||
#if UF_SHADER_TRACK_NAMES
|
#if UF_SHADER_TRACK_NAMES
|
||||||
uf::stl::string path = uf::string::join(variableName, ".");
|
uf::stl::string path = uf::string::join(variableName, ".");
|
||||||
path = uf::string::replace( path, ".[", "[" );
|
path = uf::string::replace( path, ".[", "[" );
|
||||||
VK_VALIDATION_MESSAGE("[" << (byteBuffer - byteBufferStart) << " / "<< (byteBufferEnd - byteBuffer) <<"]\tInserting: " << path << " = (" << primitive << ") " << input.dump());
|
//VK_VALIDATION_MESSAGE("[" << (byteBuffer - byteBufferStart) << " / "<< (byteBufferEnd - byteBuffer) <<"]\tInserting: " << path << " = (" << primitive << ") " << input.dump());
|
||||||
#endif
|
#endif
|
||||||
pushValue( primitive, input );
|
pushValue( primitive, input );
|
||||||
}
|
}
|
||||||
@ -275,12 +275,12 @@ ext::vulkan::userdata_t ext::vulkan::jsonToUserdata( const ext::json::Value& pay
|
|||||||
};
|
};
|
||||||
auto& definitions = metadata.json["definitions"]["uniforms"][name];
|
auto& definitions = metadata.json["definitions"]["uniforms"][name];
|
||||||
#if UF_SHADER_TRACK_NAMES
|
#if UF_SHADER_TRACK_NAMES
|
||||||
VK_VALIDATION_MESSAGE("Updating " << name << " in " << filename);
|
//VK_VALIDATION_MESSAGE("Updating " << name << " in " << filename);
|
||||||
VK_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer));
|
//VK_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer));
|
||||||
#endif
|
#endif
|
||||||
parseDefinition(payload, definitions);
|
parseDefinition(payload, definitions);
|
||||||
#if UF_SHADER_TRACK_NAMES
|
#if UF_SHADER_TRACK_NAMES
|
||||||
VK_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer));
|
//VK_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer));
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return userdata;
|
return userdata;
|
||||||
@ -489,14 +489,14 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
|||||||
size_t bufferSize = comp.get_declared_struct_size(base_type);
|
size_t bufferSize = comp.get_declared_struct_size(base_type);
|
||||||
if ( bufferSize <= 0 ) break;
|
if ( bufferSize <= 0 ) break;
|
||||||
if ( bufferSize > device.properties.limits.maxUniformBufferRange ) {
|
if ( bufferSize > device.properties.limits.maxUniformBufferRange ) {
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("Invalid uniform buffer length of " << bufferSize << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Invalid uniform buffer length of {} for shader {}", bufferSize, filename);
|
||||||
bufferSize = device.properties.limits.maxUniformBufferRange;
|
bufferSize = device.properties.limits.maxUniformBufferRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferSize = ALIGNED_SIZE( bufferSize, device.properties.limits.minUniformBufferOffsetAlignment );
|
bufferSize = ALIGNED_SIZE( bufferSize, device.properties.limits.minUniformBufferOffsetAlignment );
|
||||||
|
|
||||||
{
|
{
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("Uniform size of " << bufferSize << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Uniform size of {} for shader {}", bufferSize, filename);
|
||||||
// auto& uniform = uniforms.emplace_back();
|
// auto& uniform = uniforms.emplace_back();
|
||||||
// uniform.create( bufferSize );
|
// uniform.create( bufferSize );
|
||||||
}
|
}
|
||||||
@ -564,7 +564,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
|||||||
|
|
||||||
#define LOOP_RESOURCES( key, type ) for ( size_t i = 0; i < res.key.size(); ++i ) {\
|
#define LOOP_RESOURCES( key, type ) for ( size_t i = 0; i < res.key.size(); ++i ) {\
|
||||||
const auto& resource = res.key[i];\
|
const auto& resource = res.key[i];\
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("["<<filename<<"] Found resource: "#type " with binding: " << comp.get_decoration(resource.id, spv::DecorationBinding));\
|
VK_DEBUG_VALIDATION_MESSAGE("[{}] Found resource: {} with binding: {}", filename, #type, comp.get_decoration(resource.id, spv::DecorationBinding));\
|
||||||
parseResource( resource, type, i );\
|
parseResource( resource, type, i );\
|
||||||
}
|
}
|
||||||
LOOP_RESOURCES( sampled_images, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER );
|
LOOP_RESOURCES( sampled_images, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER );
|
||||||
@ -667,16 +667,17 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
|||||||
if ( size <= 0 ) continue;
|
if ( size <= 0 ) continue;
|
||||||
// not a multiple of 4, for some reason
|
// not a multiple of 4, for some reason
|
||||||
if ( size % 4 != 0 ) {
|
if ( size % 4 != 0 ) {
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename << ", must be multiple of 4, correcting...");
|
VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of {} for shader {}, must be multiple of 4, correcting...", size, filename);
|
||||||
size /= 4;
|
size /= 4;
|
||||||
++size;
|
++size;
|
||||||
size *= 4;
|
size *= 4;
|
||||||
}
|
}
|
||||||
if ( size > device.properties.limits.maxPushConstantsSize ) {
|
if ( size > device.properties.limits.maxPushConstantsSize ) {
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of {} for shader {}", size, filename);
|
||||||
|
//VK_DEBUG_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename);
|
||||||
size = device.properties.limits.maxPushConstantsSize;
|
size = device.properties.limits.maxPushConstantsSize;
|
||||||
}
|
}
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("Push constant size of " << size << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Push constant size of {} for shader {},", size, filename);
|
||||||
{
|
{
|
||||||
auto& pushConstant = pushConstants.emplace_back();
|
auto& pushConstant = pushConstants.emplace_back();
|
||||||
pushConstant.create( size );
|
pushConstant.create( size );
|
||||||
@ -724,7 +725,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
|||||||
specializationMapEntries.emplace_back(specializationMapEntry);
|
specializationMapEntries.emplace_back(specializationMapEntry);
|
||||||
}
|
}
|
||||||
specializationConstants.create( specializationSize );
|
specializationConstants.create( specializationSize );
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("Specialization constants size of " << specializationSize << " for shader " << filename);
|
VK_DEBUG_VALIDATION_MESSAGE("Specialization constants size of {} for shader {}", specializationSize, filename);
|
||||||
|
|
||||||
uint8_t* s = (uint8_t*) (void*) specializationConstants;
|
uint8_t* s = (uint8_t*) (void*) specializationConstants;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
@ -798,7 +799,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
|||||||
definition.validate = false;
|
definition.validate = false;
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("Unregistered specialization constant type at offset " << offset << " for shader " << filename );
|
VK_DEBUG_VALIDATION_MESSAGE("Unregistered specialization constant type at offset {} for shader {}", offset, filename );
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
#if UF_SHADER_PARSE_AS_JSON
|
#if UF_SHADER_PARSE_AS_JSON
|
||||||
@ -806,7 +807,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
|||||||
member["size"] = size;
|
member["size"] = size;
|
||||||
member["default"] = member["value"];
|
member["default"] = member["value"];
|
||||||
metadata.json["specializationConstants"].emplace_back(member);
|
metadata.json["specializationConstants"].emplace_back(member);
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as<uf::stl::string>() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename );
|
//VK_DEBUG_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as<uf::stl::string>() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memcpy( &s[offset], &buffer, size );
|
memcpy( &s[offset], &buffer, size );
|
||||||
@ -859,7 +860,7 @@ bool ext::vulkan::Shader::validate() {
|
|||||||
if ( it == uniforms.end() ) break;
|
if ( it == uniforms.end() ) break;
|
||||||
auto& uniform = *(it++);
|
auto& uniform = *(it++);
|
||||||
if ( uniform.data().len != buffer.allocationInfo.size ) {
|
if ( uniform.data().len != buffer.allocationInfo.size ) {
|
||||||
VK_DEBUG_VALIDATION_MESSAGE("Uniform size mismatch: Expected " << buffer.allocationInfo.size << ", got " << uniform.data().len << "; fixing...");
|
VK_DEBUG_VALIDATION_MESSAGE("Uniform size mismatch: Expected {}, got {}; fixing...", buffer.allocationInfo.size, uniform.data().len);
|
||||||
uniform.destroy();
|
uniform.destroy();
|
||||||
uniform.create(buffer.allocationInfo.size);
|
uniform.create(buffer.allocationInfo.size);
|
||||||
valid = false;
|
valid = false;
|
||||||
|
|||||||
@ -205,12 +205,15 @@ void ext::vulkan::Texture::destroy( bool defer ) {
|
|||||||
if ( !device || !device->logicalDevice || aliased ) return; // device->logicalDevice should never be null, but it happens, somehow
|
if ( !device || !device->logicalDevice || aliased ) return; // device->logicalDevice should never be null, but it happens, somehow
|
||||||
|
|
||||||
if ( defer ) {
|
if ( defer ) {
|
||||||
ext::vulkan::gc::textures.emplace_back( *this );
|
ext::vulkan::mutex.lock();
|
||||||
|
device->transient.textures.emplace_back(*this);
|
||||||
|
ext::vulkan::mutex.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( view != VK_NULL_HANDLE ) {
|
if ( view != VK_NULL_HANDLE ) {
|
||||||
vkDestroyImageView(device->logicalDevice, view, nullptr);
|
vkDestroyImageView(device->logicalDevice, view, nullptr);
|
||||||
|
VK_UNREGISTER_HANDLE( view );
|
||||||
view = VK_NULL_HANDLE;
|
view = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
if ( image != VK_NULL_HANDLE ) {
|
if ( image != VK_NULL_HANDLE ) {
|
||||||
@ -581,6 +584,7 @@ void ext::vulkan::Texture::fromBuffers(
|
|||||||
viewCreateInfo.subresourceRange.levelCount = this->mips;
|
viewCreateInfo.subresourceRange.levelCount = this->mips;
|
||||||
viewCreateInfo.image = image;
|
viewCreateInfo.image = image;
|
||||||
VK_CHECK_RESULT(vkCreateImageView(device.logicalDevice, &viewCreateInfo, nullptr, &view));
|
VK_CHECK_RESULT(vkCreateImageView(device.logicalDevice, &viewCreateInfo, nullptr, &view));
|
||||||
|
VK_REGISTER_HANDLE( view );
|
||||||
|
|
||||||
{
|
{
|
||||||
auto commandBuffer = device.fetchCommandBuffer(uf::renderer::QueueEnum::GRAPHICS);
|
auto commandBuffer = device.fetchCommandBuffer(uf::renderer::QueueEnum::GRAPHICS);
|
||||||
@ -890,7 +894,7 @@ void ext::vulkan::Texture::generateMipmaps( VkCommandBuffer commandBuffer, uint3
|
|||||||
|
|
||||||
int32_t mipWidth = width;
|
int32_t mipWidth = width;
|
||||||
int32_t mipHeight = height;
|
int32_t mipHeight = height;
|
||||||
int32_t mipDepth = depth;
|
int32_t mipDepth = MAX(1, depth);
|
||||||
for ( size_t i = 1; i < this->mips; ++i ) {
|
for ( size_t i = 1; i < this->mips; ++i ) {
|
||||||
// transition previous layer to read from it
|
// transition previous layer to read from it
|
||||||
barrier.subresourceRange.baseMipLevel = i - 1;
|
barrier.subresourceRange.baseMipLevel = i - 1;
|
||||||
@ -1150,7 +1154,7 @@ uf::Image ext::vulkan::Texture3D::screenshot( uint32_t layerID ) {
|
|||||||
imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
imageCopy.dstSubresource.baseArrayLayer = 0;
|
imageCopy.dstSubresource.baseArrayLayer = 0;
|
||||||
imageCopy.dstSubresource.layerCount = 1;
|
imageCopy.dstSubresource.layerCount = 1;
|
||||||
imageCopy.dstOffset = { 0, 0, 0 };
|
imageCopy.dstOffset = { 0, 0, layerID };
|
||||||
imageCopy.extent = { this->width, this->height, 1 };
|
imageCopy.extent = { this->width, this->height, 1 };
|
||||||
|
|
||||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "copyImage" );
|
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "copyImage" );
|
||||||
|
|||||||
@ -116,8 +116,6 @@ uint32_t ext::vulkan::states::frameAccumulate = 0;
|
|||||||
bool ext::vulkan::states::frameAccumulateReset = false;
|
bool ext::vulkan::states::frameAccumulateReset = false;
|
||||||
uint32_t ext::vulkan::states::frameSkip = 0;
|
uint32_t ext::vulkan::states::frameSkip = 0;
|
||||||
|
|
||||||
uf::stl::vector<ext::vulkan::Texture> ext::vulkan::gc::textures;
|
|
||||||
|
|
||||||
uf::ThreadUnique<ext::vulkan::RenderMode*> ext::vulkan::currentRenderMode;
|
uf::ThreadUnique<ext::vulkan::RenderMode*> ext::vulkan::currentRenderMode;
|
||||||
|
|
||||||
ext::vulkan::Buffer ext::vulkan::scratchBuffer;
|
ext::vulkan::Buffer ext::vulkan::scratchBuffer;
|
||||||
@ -495,6 +493,7 @@ void ext::vulkan::initialize( bool soft ) {
|
|||||||
void ext::vulkan::tick() {
|
void ext::vulkan::tick() {
|
||||||
// ext::vulkan::mutex.lock();
|
// ext::vulkan::mutex.lock();
|
||||||
if ( ext::vulkan::states::resized || ext::vulkan::settings::experimental::rebuildOnTickBegin ) {
|
if ( ext::vulkan::states::resized || ext::vulkan::settings::experimental::rebuildOnTickBegin ) {
|
||||||
|
synchronize(0b11);
|
||||||
ext::vulkan::states::rebuild = true;
|
ext::vulkan::states::rebuild = true;
|
||||||
::skip = true;
|
::skip = true;
|
||||||
}
|
}
|
||||||
@ -534,13 +533,6 @@ void ext::vulkan::tick() {
|
|||||||
|
|
||||||
uf::thread::execute( tasks );
|
uf::thread::execute( tasks );
|
||||||
|
|
||||||
/*
|
|
||||||
for ( auto& texture : ext::vulkan::gc::textures ) {
|
|
||||||
texture.destroy( false );
|
|
||||||
}
|
|
||||||
ext::vulkan::gc::textures.clear();
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( ext::vulkan::states::rebuild && ext::vulkan::settings::experimental::skipRenderOnRebuild ) ::skip = true;
|
if ( ext::vulkan::states::rebuild && ext::vulkan::settings::experimental::skipRenderOnRebuild ) ::skip = true;
|
||||||
|
|
||||||
ext::vulkan::states::rebuild = false;
|
ext::vulkan::states::rebuild = false;
|
||||||
@ -666,6 +658,9 @@ void ext::vulkan::render() {
|
|||||||
for ( auto& buffer : transient.buffers ) buffer.destroy(false);
|
for ( auto& buffer : transient.buffers ) buffer.destroy(false);
|
||||||
transient.buffers.clear();
|
transient.buffers.clear();
|
||||||
|
|
||||||
|
for ( auto& texture : transient.textures ) texture.destroy(false);
|
||||||
|
transient.textures.clear();
|
||||||
|
|
||||||
for ( auto& as : transient.ass ) {
|
for ( auto& as : transient.ass ) {
|
||||||
uf::renderer::vkDestroyAccelerationStructureKHR(device, as.handle, nullptr);
|
uf::renderer::vkDestroyAccelerationStructureKHR(device, as.handle, nullptr);
|
||||||
VK_UNREGISTER_HANDLE( as.handle );
|
VK_UNREGISTER_HANDLE( as.handle );
|
||||||
@ -677,7 +672,7 @@ void ext::vulkan::destroy( bool soft ) {
|
|||||||
ext::vulkan::flushCommandBuffers();
|
ext::vulkan::flushCommandBuffers();
|
||||||
|
|
||||||
// ext::vulkan::mutex.lock();
|
// ext::vulkan::mutex.lock();
|
||||||
synchronize();
|
synchronize(0b11);
|
||||||
|
|
||||||
#if UF_USE_FFX_FSR
|
#if UF_USE_FFX_FSR
|
||||||
if ( settings::pipelines::fsr ) {
|
if ( settings::pipelines::fsr ) {
|
||||||
@ -725,7 +720,7 @@ void ext::vulkan::destroy( bool soft ) {
|
|||||||
// ext::vulkan::mutex.unlock();
|
// ext::vulkan::mutex.unlock();
|
||||||
|
|
||||||
// check for any leaked resources
|
// check for any leaked resources
|
||||||
if ( false ) {
|
if ( ext::vulkan::settings::validation::checkpoints ) {
|
||||||
UF_MSG_DEBUG("Leaked resources:");
|
UF_MSG_DEBUG("Leaked resources:");
|
||||||
|
|
||||||
for ( auto& resource : ext::vulkan::Resource<VkBuffer_T*>::handles ) {
|
for ( auto& resource : ext::vulkan::Resource<VkBuffer_T*>::handles ) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user