alleged optimizations to vxgi (maybe), fixed crash with enabling shadowmapped lights (but they're broken still for some reason)
This commit is contained in:
parent
682dd2c794
commit
a10ed8bc60
@ -4,13 +4,13 @@
|
||||
"start": "StartMenu",
|
||||
"matrix": { "reverseInfinite": true },
|
||||
"meshes": { "interleaved": false },
|
||||
"lights": { "enabled": false,
|
||||
"lights": { "enabled": true,
|
||||
"useLightmaps": false,
|
||||
"max": 16,
|
||||
"max": 32,
|
||||
"shadows": {
|
||||
"enabled": false,
|
||||
"enabled": false, // to-do: fix
|
||||
"update": 4,
|
||||
"max": 16,
|
||||
"max": 8,
|
||||
"samples": 2
|
||||
},
|
||||
"bloom": {
|
||||
@ -29,13 +29,14 @@
|
||||
}
|
||||
},
|
||||
"vxgi": {
|
||||
// "limiter": 0,
|
||||
"limiter": 0.0125,
|
||||
"limiter": 0,
|
||||
// "limiter": 0.0125,
|
||||
// "limiter": 5,
|
||||
"size": 256,
|
||||
"dispatch": 16,
|
||||
"cascades": 3,
|
||||
"cascadePower": 2,
|
||||
"granularity": 10,
|
||||
"cascadePower": 1.5,
|
||||
"granularity": 32,
|
||||
"voxelizeScale": 1,
|
||||
"occlusionFalloff": 2,
|
||||
"traceStartOffsetFactor": 1,
|
||||
@ -117,7 +118,7 @@
|
||||
"gui": true,
|
||||
"vsync": true, // vsync on vulkan side rather than engine-side
|
||||
"hdr": true,
|
||||
"vxgi": true,
|
||||
"vxgi": false,
|
||||
"culling": false,
|
||||
"bloom": false,
|
||||
"dof": false,
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
},
|
||||
"system": {
|
||||
"renderer": {
|
||||
// "limiter": 128
|
||||
"limiter": 128
|
||||
// "mode": "round robin"
|
||||
// "mode": "once"
|
||||
"mode": "in-range"
|
||||
// "mode": "in-range"
|
||||
},
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
|
||||
@ -104,7 +104,7 @@ void main() {
|
||||
vec4 A = imageLoad(voxelOutput[CASCADE], ivec3(tUvw) );
|
||||
#else
|
||||
vec4 A = unpackUnorm4x8(imageLoad(voxelRadiance[CASCADE], ivec3(tUvw)).r);
|
||||
A.a = 1.0;
|
||||
A.a = float(uint(A.a * 255.0 + 0.5) & 0xF) / 15.0;
|
||||
#endif
|
||||
|
||||
surface.material.albedo = A;
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
#version 450
|
||||
#pragma shader_stage(compute)
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
|
||||
|
||||
layout (constant_id = 0) const uint CASCADES = 16;
|
||||
layout (constant_id = 1) const uint MIPS = 16;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint cascade;
|
||||
uint mip;
|
||||
} PushConstant;
|
||||
|
||||
#if VXGI_HDR
|
||||
layout (binding = 1, rgba32f) uniform volatile coherent image3D voxelRadiance[CASCADES * MIPS];
|
||||
#else
|
||||
layout (binding = 1, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES * MIPS];
|
||||
#endif
|
||||
|
||||
const float gaussianWeights[] = {
|
||||
//Top slice
|
||||
1 / 64.0f,
|
||||
1 / 32.0f,
|
||||
1 / 64.0f,
|
||||
1 / 32.0f,
|
||||
1 / 16.0f,
|
||||
1 / 32.0f,
|
||||
1 / 64.0f,
|
||||
1 / 32.0f,
|
||||
1 / 64.0f,
|
||||
|
||||
//Center slice
|
||||
1 / 32.0f,
|
||||
1 / 16.0f,
|
||||
1 / 32.0f,
|
||||
1 / 16.0f,
|
||||
1 / 4.0f,
|
||||
1 / 16.0f,
|
||||
1 / 32.0f,
|
||||
1 / 16.0f,
|
||||
1 / 32.0f,
|
||||
|
||||
//Bottom slice
|
||||
1 / 64.0f,
|
||||
1 / 32.0f,
|
||||
1 / 64.0f,
|
||||
1 / 32.0f,
|
||||
1 / 16.0f,
|
||||
1 / 32.0f,
|
||||
1 / 64.0f,
|
||||
1 / 32.0f,
|
||||
1 / 64.0f,
|
||||
};
|
||||
|
||||
void main() {
|
||||
const ivec3 inUVW = ivec3(gl_GlobalInvocationID.xyz) * 2;
|
||||
const ivec3 outUVW = ivec3(gl_GlobalInvocationID.xyz);
|
||||
const uint CASCADE_IN = PushConstant.cascade * CASCADES + PushConstant.mip;
|
||||
const uint CASCADE_OUT = PushConstant.cascade * CASCADES + (PushConstant.mip + 1);
|
||||
|
||||
vec4 color = vec4(0);
|
||||
for ( int z = -1; z <= 1; ++z ) {
|
||||
for ( int y = -1; y <= 1; ++y ) {
|
||||
for ( int x = -1; x <= 1; ++x ) {
|
||||
color += imageLoad( voxelRadiance[CASCADE_IN], inUVW + ivec3(x,y,z) ) * gaussianWeights[x + 1 + (y + 1) * 3 + (z + 1) * 9];
|
||||
}
|
||||
}
|
||||
}
|
||||
imageStore(voxelRadiance[CASCADE_OUT], ivec3(outUVW), vec4(color));
|
||||
}
|
||||
165
bin/data/shaders/display/vxgi/mips.comp.glsl
Normal file
165
bin/data/shaders/display/vxgi/mips.comp.glsl
Normal file
@ -0,0 +1,165 @@
|
||||
#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 = 8, local_size_y = 8, local_size_z = 8) in;
|
||||
|
||||
layout (constant_id = 0) const uint CASCADES = 8;
|
||||
layout (constant_id = 1) const uint MIPS = 9; // 256^3 texture = 9 mips
|
||||
|
||||
layout(push_constant) uniform PushBlock {
|
||||
uint mips;
|
||||
uint cascade;
|
||||
uint numWorkGroups;
|
||||
uint workGroupOffset;
|
||||
} PushConstant_;
|
||||
|
||||
layout (binding = 0) uniform sampler3D voxelRadiance[CASCADES];
|
||||
layout (binding = 1, rgba8) coherent uniform image3D voxelMips[CASCADES * (MIPS - 1)];
|
||||
|
||||
layout (binding = 2, std430) buffer AtomicCounter {
|
||||
uint counter;
|
||||
} spdCounter;
|
||||
|
||||
|
||||
// 8^3 = 512 threads
|
||||
shared vec4 s_colorAlpha[512];
|
||||
shared uint s_isLastWG;
|
||||
|
||||
vec4 reduce8(vec4 v[8]) {
|
||||
vec3 color = vec3(0.0);
|
||||
float alpha = 0.0;
|
||||
|
||||
for( int i = 0; i < 8; ++i ) {
|
||||
float a = float(uint(v[i].a * 255.0 + 0.5) & 0xF) / 15.0;
|
||||
color += v[i].rgb * a;
|
||||
alpha += a;
|
||||
}
|
||||
|
||||
if ( alpha > 0.001 ) color /= alpha;
|
||||
alpha /= 8.0;
|
||||
|
||||
uint lum4 = uint(clamp(luma(color), 0.0, 1.0) * 15.0) & 0xF;
|
||||
uint alpha4 = uint(clamp(alpha, 0.0, 1.0) * 15.0) & 0xF;
|
||||
return vec4(color, float((lum4 << 4) | alpha4) / 255.0);
|
||||
}
|
||||
|
||||
ivec3 index3D(uint idx, uint sizeX, uint sizeY) {
|
||||
return ivec3( idx % sizeX, (idx / sizeX) % sizeY, idx / (sizeX * sizeY) );
|
||||
}
|
||||
|
||||
vec4 reduceFromShared( uint lid, uint dst ) {
|
||||
ivec3 pos = index3D(lid, dst, dst) * 2;
|
||||
vec4 v[8];
|
||||
uint src = dst * 2;
|
||||
for ( int z = 0; z < 2; ++z ) {
|
||||
for ( int y = 0; y < 2; ++y ) {
|
||||
for ( int x = 0; x < 2; ++x ) {
|
||||
ivec3 p = pos + ivec3(x,y,z);
|
||||
uint flatIdx = p.x + p.y * src + p.z * src * src;
|
||||
v[x + y*2 + z*4] = s_colorAlpha[flatIdx];
|
||||
}
|
||||
}
|
||||
}
|
||||
return reduce8(v);
|
||||
}
|
||||
|
||||
void main() {
|
||||
uint lid = gl_LocalInvocationIndex;
|
||||
ivec3 wgID = ivec3(gl_WorkGroupID);
|
||||
|
||||
// mip 0 => 1
|
||||
if ( 1 < PushConstant_.mips ) {
|
||||
ivec3 gid = wgID * 8 + index3D(lid, 8, 8);
|
||||
ivec3 pos = gid * 2;
|
||||
|
||||
vec4 v[8];
|
||||
v[0] = texelFetch(voxelRadiance[PushConstant_.cascade], pos + ivec3(0,0,0), 0);
|
||||
v[1] = texelFetch(voxelRadiance[PushConstant_.cascade], pos + ivec3(1,0,0), 0);
|
||||
v[2] = texelFetch(voxelRadiance[PushConstant_.cascade], pos + ivec3(0,1,0), 0);
|
||||
v[3] = texelFetch(voxelRadiance[PushConstant_.cascade], pos + ivec3(1,1,0), 0);
|
||||
v[4] = texelFetch(voxelRadiance[PushConstant_.cascade], pos + ivec3(0,0,1), 0);
|
||||
v[5] = texelFetch(voxelRadiance[PushConstant_.cascade], pos + ivec3(1,0,1), 0);
|
||||
v[6] = texelFetch(voxelRadiance[PushConstant_.cascade], pos + ivec3(0,1,1), 0);
|
||||
v[7] = texelFetch(voxelRadiance[PushConstant_.cascade], pos + ivec3(1,1,1), 0);
|
||||
|
||||
vec4 color = reduce8(v);
|
||||
imageStore(voxelMips[PushConstant_.cascade + PushConstant_.mips * 0], gid, color);
|
||||
s_colorAlpha[lid] = color;
|
||||
}
|
||||
memoryBarrierShared(); barrier();
|
||||
|
||||
// mip 1 => 2 => 3 => 4
|
||||
int threads[3] = { 64, 8, 1 };
|
||||
int edges[3] = { 4, 2, 1 };
|
||||
|
||||
{
|
||||
for ( int i = 0; i < 3; ++i ) {
|
||||
uint mipLevel = i + 2;
|
||||
if ( mipLevel < PushConstant_.mips ) {
|
||||
if ( lid < threads[i] ) {
|
||||
vec4 color = reduceFromShared(lid, edges[i]);
|
||||
ivec3 pos = wgID * edges[i] + index3D(lid, edges[i], edges[i]);
|
||||
imageStore(voxelMips[PushConstant_.cascade + PushConstant_.mips * (mipLevel - 1)], pos, color);
|
||||
s_colorAlpha[lid] = color;
|
||||
}
|
||||
}
|
||||
memoryBarrierShared(); barrier();
|
||||
}
|
||||
}
|
||||
if ( PushConstant_.mips <= 5 ) return; // bail if 16^3 or smaller
|
||||
// atomic sync
|
||||
|
||||
{
|
||||
if ( lid == 0 ) {
|
||||
uint ticket = atomicAdd(spdCounter.counter, 1);
|
||||
s_isLastWG = (ticket == PushConstant_.numWorkGroups - 1) ? 1 : 0;
|
||||
}
|
||||
memoryBarrierShared(); barrier();
|
||||
if ( s_isLastWG == 0 ) return; // use last workgroup
|
||||
if ( lid == 0 ) spdCounter.counter = 0; // reset for next frame
|
||||
}
|
||||
// mip 4 => 5
|
||||
if ( 5 < PushConstant_.mips ) {
|
||||
ivec3 pos = index3D(lid, 8, 8) * 2;
|
||||
uint m4_idx = PushConstant_.cascade + PushConstant_.mips * 3;
|
||||
vec4 v[8];
|
||||
v[0] = imageLoad(voxelMips[m4_idx], pos + ivec3(0,0,0));
|
||||
v[1] = imageLoad(voxelMips[m4_idx], pos + ivec3(1,0,0));
|
||||
v[2] = imageLoad(voxelMips[m4_idx], pos + ivec3(0,1,0));
|
||||
v[3] = imageLoad(voxelMips[m4_idx], pos + ivec3(1,1,0));
|
||||
v[4] = imageLoad(voxelMips[m4_idx], pos + ivec3(0,0,1));
|
||||
v[5] = imageLoad(voxelMips[m4_idx], pos + ivec3(1,0,1));
|
||||
v[6] = imageLoad(voxelMips[m4_idx], pos + ivec3(0,1,1));
|
||||
v[7] = imageLoad(voxelMips[m4_idx], pos + ivec3(1,1,1));
|
||||
|
||||
vec4 color = reduce8(v);
|
||||
imageStore(voxelMips[PushConstant_.cascade + PushConstant_.mips * 4], pos / 2, color);
|
||||
s_colorAlpha[lid] = color;
|
||||
}
|
||||
memoryBarrierShared(); barrier();
|
||||
|
||||
// mip 5 => 6 => 7 => 8
|
||||
for ( int i = 0; i < 3; ++i ) {
|
||||
uint mipLevel = i + 6; // Mips 6, 7, 8
|
||||
if ( mipLevel < PushConstant_.mips ) {
|
||||
if ( lid < threads[i] ) {
|
||||
vec4 color = reduceFromShared(lid, edges[i]);
|
||||
ivec3 pos = index3D(lid, edges[i], edges[i]);
|
||||
imageStore(voxelMips[PushConstant_.cascade + PushConstant_.mips * (mipLevel - 1)], pos, color);
|
||||
s_colorAlpha[lid] = color;
|
||||
}
|
||||
}
|
||||
memoryBarrierShared(); barrier();
|
||||
}
|
||||
}
|
||||
@ -116,13 +116,20 @@ void main() {
|
||||
|
||||
const ivec3 uvw = ivec3(P * imageSize(voxelOutput[CASCADE]));
|
||||
|
||||
uint packedId = ( instanceID + 1 ) << 16 | ( drawID + 1 );
|
||||
imageAtomicMax(voxelId[CASCADE], ivec3(uvw), packedId);
|
||||
|
||||
vec2 N_E = encodeNormals( normalize( N ) );
|
||||
uint packedNormal = packHalf2x16(N_E);
|
||||
imageAtomicMin(voxelNormal[CASCADE], uvw, packedNormal);
|
||||
|
||||
uint packedRadiance = packUnorm4x8(vec4(A.rgb, luminance(A.rgb)));
|
||||
imageAtomicMax(voxelRadiance[CASCADE], uvw, packedRadiance);
|
||||
{
|
||||
uint packedId = ( instanceID + 1 ) << 16 | ( drawID + 1 );
|
||||
imageAtomicMax(voxelId[CASCADE], ivec3(uvw), packedId);
|
||||
}
|
||||
{
|
||||
vec2 N_E = encodeNormals( normalize( N ) );
|
||||
uint packedNormal = packHalf2x16(N_E);
|
||||
imageAtomicMin(voxelNormal[CASCADE], uvw, packedNormal);
|
||||
}
|
||||
{
|
||||
uint l = uint(clamp(luma(A.rgb), 0.0, 1.0) * 15.0) & 0xF;
|
||||
uint a = uint(clamp( A.a, 0.0, 1.0) * 15.0) & 0xF;
|
||||
float packedLumaAlpha = float((l << 4) | a) / 255.0;
|
||||
uint packedRadiance = packUnorm4x8(vec4(A.rgb, packedLumaAlpha));
|
||||
imageAtomicMax(voxelRadiance[CASCADE], uvw, packedRadiance);
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,8 @@ namespace pod {
|
||||
uf::stl::vector<uf::renderer::Texture3D> normal;
|
||||
uf::stl::vector<uf::renderer::Texture3D> radiance;
|
||||
uf::stl::vector<uf::renderer::Texture3D> output;
|
||||
|
||||
uf::stl::vector<uf::renderer::Texture3D> outputMipmaps;
|
||||
} voxels;
|
||||
};
|
||||
}
|
||||
@ -99,6 +99,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
uf::stl::string name = "RT:" + std::to_string((int) this->getUid());
|
||||
renderMode.blitter.process = false;
|
||||
renderMode.execute = false;
|
||||
renderMode.width = size.x;
|
||||
renderMode.height = size.y;
|
||||
renderMode.metadata.name = name;
|
||||
@ -182,6 +183,7 @@ void ext::LightBehavior::tick( uf::Object& self ) {
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
// enable renderer every X seconds
|
||||
if ( metadata.renderer.limiter > 0 ) {
|
||||
UF_MSG_DEBUG("limiter={}, timer={}, execute={}", metadata.renderer.limiter, metadata.renderer.timer, renderMode.execute );
|
||||
if ( metadata.renderer.timer > metadata.renderer.limiter ) {
|
||||
metadata.renderer.timer = 0;
|
||||
renderMode.execute = true;
|
||||
|
||||
@ -1111,16 +1111,22 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
||||
// bind scene textures
|
||||
for ( auto& key : storage.texture2Ds.keys ) textures2D.emplace_back().aliasTexture( storage.texture2Ds.map[key] );
|
||||
|
||||
// bind shadow maps
|
||||
for ( auto& texture : storage.shadow2Ds ) textures2D.emplace_back().aliasTexture(texture);
|
||||
for ( auto& texture : storage.shadowCubes ) texturesCube.emplace_back().aliasTexture(texture);
|
||||
size_t indexSkybox = 0;
|
||||
size_t indexNoise = 0;
|
||||
|
||||
// bind skybox
|
||||
size_t indexSkybox = texturesCube.size();
|
||||
texturesCube.emplace_back().aliasTexture(sceneTextures.skybox);
|
||||
// bind noise texture
|
||||
size_t indexNoise = textures3D.size();
|
||||
textures3D.emplace_back().aliasTexture(sceneTextures.noise);
|
||||
// bind only if this is the deferred rendermode
|
||||
if ( shaderPipeline == "deferred" ) {
|
||||
// bind shadow maps
|
||||
for ( auto& texture : storage.shadow2Ds ) textures2D.emplace_back().aliasTexture(texture);
|
||||
for ( auto& texture : storage.shadowCubes ) texturesCube.emplace_back().aliasTexture(texture);
|
||||
|
||||
// bind skybox
|
||||
indexSkybox = texturesCube.size();
|
||||
texturesCube.emplace_back().aliasTexture(sceneTextures.skybox);
|
||||
// bind noise texture
|
||||
indexNoise = textures3D.size();
|
||||
textures3D.emplace_back().aliasTexture(sceneTextures.noise);
|
||||
}
|
||||
|
||||
// attach VXGI voxels
|
||||
if ( uf::renderer::settings::pipelines::vxgi ) {
|
||||
|
||||
@ -19,11 +19,25 @@
|
||||
#include <uf/engine/ext.h>
|
||||
|
||||
#define ALIAS_OUTPUT_TO_RADIANCE 1
|
||||
#define COMPUTE_MIPMAP_GENERATION 1
|
||||
|
||||
namespace {
|
||||
struct AtomicCounter {
|
||||
uint32_t counter;
|
||||
};
|
||||
struct PushConstants {
|
||||
uint32_t mips;
|
||||
uint32_t cascade;
|
||||
uint32_t numWorkGroups;
|
||||
uint32_t workGroupOffset;
|
||||
};
|
||||
}
|
||||
|
||||
UF_BEHAVIOR_REGISTER_CPP(ext::VoxelizerSceneBehavior)
|
||||
UF_BEHAVIOR_TRAITS_CPP(ext::VoxelizerSceneBehavior, ticks = true, renders = false, thread = "")
|
||||
#define this (&self)
|
||||
void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
if ( this->getName() == "Main Menu" ) return; // do not setup
|
||||
#if UF_USE_VULKAN
|
||||
auto& metadata = this->getComponent<ext::VoxelizerSceneBehavior::Metadata>();
|
||||
auto& metadataJson = this->getComponent<uf::Serializer>();
|
||||
@ -34,30 +48,29 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
|
||||
|
||||
auto mips = uf::vector::mips( metadata.voxelSize );
|
||||
for ( size_t i = 0; i < metadata.cascades; ++i ) {
|
||||
const bool HDR = false;
|
||||
auto& id = sceneTextures.voxels.id.emplace_back();
|
||||
id.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
|
||||
id.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
|
||||
id.mips = 0;
|
||||
id.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
|
||||
auto& normal = sceneTextures.voxels.normal.emplace_back();
|
||||
normal.mips = 0;
|
||||
normal.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
|
||||
auto& radiance = sceneTextures.voxels.radiance.emplace_back();
|
||||
radiance.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
radiance.mips = ALIAS_OUTPUT_TO_RADIANCE ? mips : 0;
|
||||
radiance.fromBuffers( NULL, 0, uf::renderer::enums::Format::R32_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL, ALIAS_OUTPUT_TO_RADIANCE ? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT : VkImageCreateFlags{} );
|
||||
|
||||
auto& output = sceneTextures.voxels.output.emplace_back();
|
||||
/*
|
||||
if ( metadata.filtering == "NEAREST" ) {
|
||||
output.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
|
||||
output.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
|
||||
}
|
||||
*/
|
||||
// output.fromBuffers( NULL, 0, uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
output.mips = mips;
|
||||
|
||||
#if ALIAS_OUTPUT_TO_RADIANCE
|
||||
output.aliasTexture( radiance );
|
||||
{
|
||||
output.aliasTexture( radiance );
|
||||
VkImageViewCreateInfo viewCreateInfo = {};
|
||||
viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
viewCreateInfo.image = radiance.image;
|
||||
@ -66,16 +79,39 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
|
||||
viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewCreateInfo.subresourceRange.baseMipLevel = 0;
|
||||
viewCreateInfo.subresourceRange.levelCount = radiance.mips;
|
||||
viewCreateInfo.subresourceRange.levelCount = mips;
|
||||
viewCreateInfo.subresourceRange.baseArrayLayer = 0;
|
||||
viewCreateInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
VK_CHECK_RESULT(vkCreateImageView(uf::renderer::device.logicalDevice, &viewCreateInfo, nullptr, &output.view));
|
||||
VK_REGISTER_HANDLE( output.view );
|
||||
metadata.views.emplace_back( output.view );
|
||||
}
|
||||
#else
|
||||
output.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
#endif
|
||||
|
||||
#if COMPUTE_MIPMAP_GENERATION
|
||||
for ( auto i = 1; i < mips; ++i ) {
|
||||
auto& mip = sceneTextures.voxels.outputMipmaps.emplace_back();
|
||||
mip.aliasTexture( output );
|
||||
VkImageViewCreateInfo viewCreateInfo = {};
|
||||
viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
viewCreateInfo.image = output.image;
|
||||
viewCreateInfo.viewType = output.viewType;
|
||||
viewCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
|
||||
viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewCreateInfo.subresourceRange.baseMipLevel = i;
|
||||
viewCreateInfo.subresourceRange.levelCount = 1;
|
||||
viewCreateInfo.subresourceRange.baseArrayLayer = 0;
|
||||
viewCreateInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
VK_CHECK_RESULT(vkCreateImageView(uf::renderer::device.logicalDevice, &viewCreateInfo, nullptr, &mip.view));
|
||||
VK_REGISTER_HANDLE( mip.view );
|
||||
metadata.views.emplace_back( mip.view );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// initialize render mode
|
||||
{
|
||||
@ -87,6 +123,7 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
renderMode.metadata.name = metadata.renderModeName;
|
||||
if ( uf::renderer::settings::experimental::registerRenderMode ) uf::renderer::addRenderMode( &renderMode, metadata.renderModeName );
|
||||
|
||||
auto& blitter = renderMode.blitter;
|
||||
renderMode.metadata.type = uf::renderer::settings::pipelines::names::vxgi;
|
||||
renderMode.metadata.pipeline = uf::renderer::settings::pipelines::names::vxgi;
|
||||
if ( uf::renderer::settings::pipelines::culling ) {
|
||||
@ -95,38 +132,85 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::vxgi);
|
||||
renderMode.metadata.samples = 1;
|
||||
renderMode.metadata.subpasses = metadata.cascades;
|
||||
|
||||
renderMode.blitter.device = &uf::renderer::device;
|
||||
|
||||
renderMode.width = metadata.fragmentSize.x;
|
||||
renderMode.height = metadata.fragmentSize.y;
|
||||
|
||||
// renderMode.metadata.limiter.frequency = metadata.limiter.frequency;
|
||||
blitter.device = &uf::renderer::device;
|
||||
blitter.material.device = &uf::renderer::device;
|
||||
|
||||
uf::stl::string computeShaderFilename = "/shaders/display/vxgi/comp.spv";
|
||||
if ( renderMode.metadata.samples > 1 ) {
|
||||
computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", "msaa.comp" );
|
||||
}
|
||||
renderMode.metadata.json["shaders"]["compute"] = computeShaderFilename;
|
||||
renderMode.blitter.descriptor.renderMode = metadata.renderModeName;
|
||||
renderMode.blitter.descriptor.subpass = -1;
|
||||
renderMode.blitter.descriptor.bind.width = metadata.voxelSize.x;
|
||||
renderMode.blitter.descriptor.bind.height = metadata.voxelSize.y;
|
||||
renderMode.blitter.descriptor.bind.depth = metadata.voxelSize.z;
|
||||
renderMode.blitter.descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
renderMode.blitter.process = true;
|
||||
blitter.descriptor.renderMode = metadata.renderModeName;
|
||||
blitter.descriptor.subpass = -1;
|
||||
blitter.descriptor.bind.width = metadata.voxelSize.x;
|
||||
blitter.descriptor.bind.height = metadata.voxelSize.y;
|
||||
blitter.descriptor.bind.depth = metadata.voxelSize.z;
|
||||
blitter.descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
blitter.process = true;
|
||||
|
||||
size_t maxLights = uf::config["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
|
||||
size_t maxTextures2D = uf::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
|
||||
size_t maxTexturesCube = uf::config["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
|
||||
size_t maxTextures3D = uf::config["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(1);
|
||||
size_t maxCascades = uf::config["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
|
||||
size_t maxMips = uf::vector::mips( pod::Vector3ui{ 256, 256, 256 } ); // log2(256) = 9
|
||||
|
||||
for ( size_t i = 0; i < maxTextures2D; ++i ) renderMode.blitter.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
|
||||
for ( size_t i = 0; i < maxTexturesCube; ++i ) renderMode.blitter.material.textures.emplace_back().aliasTexture(uf::renderer::TextureCube::empty);
|
||||
for ( size_t i = 0; i < maxTextures3D; ++i ) renderMode.blitter.material.textures.emplace_back().aliasTexture(uf::renderer::Texture3D::empty);
|
||||
|
||||
for ( auto& t : sceneTextures.voxels.id ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.normal ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.radiance ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.output ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
|
||||
renderMode.metadata.json["shaders"] = true;
|
||||
{
|
||||
blitter.material.attachShader( uf::io::root+"/shaders/display/vxgi/comp.spv", uf::renderer::enums::Shader::COMPUTE, "" );
|
||||
auto& shader = blitter.material.getShader("compute", "");
|
||||
|
||||
shader.setSpecializationConstants({
|
||||
{ "TEXTURES", maxTextures2D },
|
||||
{ "CUBEMAPS", maxTexturesCube },
|
||||
{ "CASCADES", maxCascades },
|
||||
});
|
||||
shader.setDescriptorCounts({
|
||||
{ "samplerTextures", maxTextures2D },
|
||||
{ "samplerCubemaps", maxTexturesCube },
|
||||
{ "voxelId", maxCascades },
|
||||
{ "voxelNormal", maxCascades },
|
||||
{ "voxelRadiance", maxCascades },
|
||||
{ "voxelOutput", maxCascades },
|
||||
});
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
|
||||
|
||||
shader.textures.clear();
|
||||
|
||||
for ( auto& t : sceneTextures.voxels.id ) shader.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.normal ) shader.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.radiance ) shader.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.output ) shader.textures.emplace_back().aliasTexture(t);
|
||||
}
|
||||
|
||||
#if COMPUTE_MIPMAP_GENERATION
|
||||
{
|
||||
blitter.material.attachShader( uf::io::root+"/shaders/display/vxgi/mips.comp.spv", uf::renderer::enums::Shader::COMPUTE, "mipmap" );
|
||||
auto& shader = blitter.material.getShader("compute", "mipmap");
|
||||
|
||||
shader.setSpecializationConstants({
|
||||
{ "TEXTURES", maxTextures2D },
|
||||
{ "CUBEMAPS", maxTexturesCube },
|
||||
{ "CASCADES", maxCascades },
|
||||
{ "MIPS", maxMips },
|
||||
});
|
||||
shader.setDescriptorCounts({
|
||||
{ "voxelRadiance", maxCascades },
|
||||
{ "voxelMips", maxCascades * (maxMips - 1) },
|
||||
});
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
|
||||
|
||||
shader.textures.clear();
|
||||
for ( auto& t : sceneTextures.voxels.output ) shader.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.outputMipmaps ) shader.textures.emplace_back().aliasTexture(t);
|
||||
|
||||
metadata.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE );
|
||||
shader.aliasBuffer("atomicCounter", metadata.atomicCounter);
|
||||
}
|
||||
#endif
|
||||
|
||||
renderMode.bindCallback( renderMode.CALLBACK_BEGIN, [&]( VkCommandBuffer commandBuffer, size_t _ ){
|
||||
// clear textures
|
||||
@ -147,12 +231,43 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
//
|
||||
renderMode.bindCallback( renderMode.CALLBACK_END, [&]( VkCommandBuffer commandBuffer, size_t _ ){
|
||||
// parse voxel lighting
|
||||
if ( renderMode.blitter.initialized ) {
|
||||
auto& pipeline = renderMode.blitter.getPipeline();
|
||||
pipeline.record(renderMode.blitter, commandBuffer);
|
||||
if ( blitter.initialized ) {
|
||||
auto descriptor = blitter.descriptor;
|
||||
//descriptor.pipeline = "lighting";
|
||||
|
||||
auto& pipeline = blitter.getPipeline( descriptor );
|
||||
pipeline.record( blitter, commandBuffer );
|
||||
}
|
||||
|
||||
// generate mipmaps
|
||||
#if COMPUTE_MIPMAP_GENERATION
|
||||
if ( blitter.initialized ) {
|
||||
auto& shader = blitter.material.getShader("compute", "mipmap");
|
||||
auto mips = uf::vector::mips( pod::Vector3ui{ blitter.descriptor.bind.width, blitter.descriptor.bind.height, blitter.descriptor.bind.depth } );
|
||||
|
||||
for ( auto cascade = 0; cascade < sceneTextures.voxels.output.size(); ++cascade ) {
|
||||
vkCmdFillBuffer(commandBuffer, metadata.atomicCounter.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);
|
||||
|
||||
|
||||
auto& pushConstant = shader.pushConstants.front().get<::PushConstants>();
|
||||
pushConstant = {
|
||||
.mips = mips,
|
||||
.cascade = cascade,
|
||||
.numWorkGroups = 0,
|
||||
.workGroupOffset = 0,
|
||||
};
|
||||
auto descriptor = blitter.descriptor;
|
||||
descriptor.pipeline = "mipmap";
|
||||
|
||||
auto& pipeline = blitter.getPipeline( descriptor );
|
||||
pipeline.record( blitter, commandBuffer );
|
||||
}
|
||||
}
|
||||
#else
|
||||
VkImageSubresourceRange subresourceRange = {};
|
||||
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
subresourceRange.baseMipLevel = 0;
|
||||
@ -160,22 +275,11 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
subresourceRange.layerCount = 1;
|
||||
for ( auto& t : sceneTextures.voxels.output ) {
|
||||
subresourceRange.levelCount = t.mips;
|
||||
t.setImageLayout(
|
||||
commandBuffer,
|
||||
t.image,
|
||||
t.layout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
subresourceRange
|
||||
);
|
||||
t.setImageLayout( commandBuffer, t.image, t.layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange );
|
||||
t.generateMipmaps( commandBuffer, 0 );
|
||||
t.setImageLayout(
|
||||
commandBuffer,
|
||||
t.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
t.layout,
|
||||
subresourceRange
|
||||
);
|
||||
t.setImageLayout( commandBuffer, t.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, t.layout, subresourceRange );
|
||||
}
|
||||
#endif
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@ -215,14 +319,22 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
|
||||
auto& controller = scene.getController();
|
||||
auto& camera = scene.getCamera( controller ); // controller.getComponent<uf::Camera>();
|
||||
auto controllerTransform = uf::transform::flatten( camera.getTransform() );
|
||||
|
||||
float voxelWorldSizeX = (metadata.extents.max.x - metadata.extents.min.x) / (float)(metadata.voxelSize.x);
|
||||
float voxelWorldSizeY = (metadata.extents.max.y - metadata.extents.min.y) / (float)(metadata.voxelSize.y);
|
||||
float voxelWorldSizeZ = (metadata.extents.max.z - metadata.extents.min.z) / (float)(metadata.voxelSize.z);
|
||||
|
||||
pod::Vector3f controllerPosition = controllerTransform.position - metadata.extents.min;
|
||||
controllerPosition.x = floor(controllerPosition.x);
|
||||
controllerPosition.y = floor(controllerPosition.y);
|
||||
controllerPosition.z = floor(controllerPosition.z);
|
||||
|
||||
controllerPosition.x = std::floor(controllerPosition.x / voxelWorldSizeX) * voxelWorldSizeX;
|
||||
controllerPosition.y = std::floor(controllerPosition.y / voxelWorldSizeY) * voxelWorldSizeY;
|
||||
controllerPosition.z = std::floor(controllerPosition.z / voxelWorldSizeZ) * voxelWorldSizeZ;
|
||||
|
||||
controllerPosition += metadata.extents.min;
|
||||
controllerPosition.x = floor(controllerPosition.x);
|
||||
controllerPosition.y = floor(controllerPosition.y);
|
||||
controllerPosition.z = -floor(controllerPosition.z);
|
||||
|
||||
controllerPosition.x = std::floor(controllerPosition.x / voxelWorldSizeX) * voxelWorldSizeX;
|
||||
controllerPosition.y = std::floor(controllerPosition.y / voxelWorldSizeY) * voxelWorldSizeY;
|
||||
controllerPosition.z = -std::floor(controllerPosition.z / voxelWorldSizeZ) * voxelWorldSizeZ;
|
||||
|
||||
pod::Vector3f min = metadata.extents.min + controllerPosition;
|
||||
pod::Vector3f max = metadata.extents.max + controllerPosition;
|
||||
@ -232,9 +344,9 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
|
||||
auto/*&*/ graph = scene.getGraph();
|
||||
for ( auto entity : graph ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) continue;
|
||||
auto& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( graphic.material.hasShader("geometry", uf::renderer::settings::pipelines::names::vxgi) ) {
|
||||
auto& shader = graphic.material.getShader("geometry", uf::renderer::settings::pipelines::names::vxgi);
|
||||
auto& blitter = entity->getComponent<uf::Graphic>();
|
||||
if ( blitter.material.hasShader("geometry", uf::renderer::settings::pipelines::names::vxgi) ) {
|
||||
auto& shader = blitter.material.getShader("geometry", uf::renderer::settings::pipelines::names::vxgi);
|
||||
struct UniformDescriptor {
|
||||
/*alignas(16)*/ pod::Matrix4f matrix;
|
||||
/*alignas(4)*/ float cascadePower;
|
||||
@ -278,17 +390,16 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
|
||||
}
|
||||
void ext::VoxelizerSceneBehavior::render( uf::Object& self ){}
|
||||
void ext::VoxelizerSceneBehavior::destroy( uf::Object& self ){
|
||||
#if ALIAS_OUTPUT_TO_RADIANCE
|
||||
auto& sceneTextures = this->getComponent<pod::SceneTextures>();
|
||||
for ( auto& t : sceneTextures.voxels.output ) {
|
||||
auto& metadata = this->getComponent<ext::VoxelizerSceneBehavior::Metadata>();
|
||||
metadata.atomicCounter.destroy(false);
|
||||
for ( auto& view : metadata.views ) {
|
||||
ext::vulkan::mutex.lock();
|
||||
auto& texture = uf::renderer::device.transient.textures.emplace_back();
|
||||
ext::vulkan::mutex.unlock();
|
||||
|
||||
texture.device = &uf::renderer::device;
|
||||
texture.view = t.view;
|
||||
texture.view = view;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void ext::VoxelizerSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {
|
||||
serializer["vxgi"]["size"] = /*this->*/voxelSize.x;
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <uf/engine/scene/scene.h>
|
||||
#include <uf/utils/math/vector.h>
|
||||
#include <uf/utils/math/matrix.h>
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
|
||||
namespace ext {
|
||||
namespace VoxelizerSceneBehavior {
|
||||
@ -17,6 +18,9 @@ namespace ext {
|
||||
pod::Vector3ui voxelSize = { 0, 0, 0 };
|
||||
pod::Vector3ui dispatchSize = { 0, 0, 0 };
|
||||
uf::stl::string renderModeName = "VXGI";
|
||||
|
||||
uf::renderer::Buffer atomicCounter;
|
||||
uf::stl::vector<VkImageView> views;
|
||||
|
||||
size_t cascades = 0;
|
||||
float cascadePower = 0;
|
||||
|
||||
@ -66,10 +66,11 @@ const uf::Entity& uf::Scene::getController() const {
|
||||
|
||||
uf::Camera& uf::Scene::getCamera(uf::Entity& controller) {
|
||||
// ???
|
||||
/*
|
||||
if ( auto currentRenderMode = uf::renderer::getCurrentRenderMode(); currentRenderMode && !currentRenderMode->getName().empty() ) {
|
||||
return controller.getComponent<uf::Camera>();
|
||||
}
|
||||
|
||||
*/
|
||||
#if !UF_SCENE_GLOBAL_GRAPH
|
||||
auto& metadata = this->getComponent<uf::SceneBehavior::Metadata>();
|
||||
#endif
|
||||
|
||||
@ -232,7 +232,7 @@ void ext::vulkan::RenderMode::createCommandBuffers() {
|
||||
graphics.emplace_back(&graphic);
|
||||
}
|
||||
|
||||
this->synchronize();
|
||||
// this->synchronize();
|
||||
// bindPipelines( graphics );
|
||||
|
||||
//lockMutex();
|
||||
@ -327,7 +327,7 @@ void ext::vulkan::RenderMode::bindPipelines() {
|
||||
// if ( graphic.descriptor.renderMode != "" && graphic.descriptor.renderMode != this->getName() ) continue;
|
||||
graphics.emplace_back(&graphic);
|
||||
}
|
||||
this->synchronize();
|
||||
//this->synchronize();
|
||||
this->bindPipelines( graphics );
|
||||
this->execute = true;
|
||||
}
|
||||
@ -432,7 +432,7 @@ void ext::vulkan::RenderMode::tick() {
|
||||
cleanupAllCommands();
|
||||
}
|
||||
|
||||
this->synchronize();
|
||||
//this->synchronize();
|
||||
|
||||
if ( metadata.limiter.frequency > 0 ) {
|
||||
if ( metadata.limiter.timer > metadata.limiter.frequency ) {
|
||||
@ -446,7 +446,7 @@ void ext::vulkan::RenderMode::tick() {
|
||||
}
|
||||
|
||||
void ext::vulkan::RenderMode::render() {
|
||||
this->synchronize();
|
||||
//this->synchronize();
|
||||
}
|
||||
|
||||
void ext::vulkan::RenderMode::destroy() {
|
||||
|
||||
@ -884,6 +884,12 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
||||
|
||||
#if 1
|
||||
if ( settings::pipelines::deferred && DEFERRED_MODE == "compute" && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
|
||||
VkMemoryBarrier computeBarrier = {};
|
||||
computeBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
||||
computeBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
||||
computeBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &computeBarrier, 0, nullptr, 0, nullptr );
|
||||
|
||||
auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred");
|
||||
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
|
||||
descriptor.renderMode = "";
|
||||
|
||||
@ -278,6 +278,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
else if ( sType == "geometry" ) type = ext::vulkan::enums::Shader::GEOMETRY;
|
||||
else if ( sType == "compute" ) type = ext::vulkan::enums::Shader::COMPUTE;
|
||||
}
|
||||
if ( filename == "" ) return;
|
||||
blitter.material.attachShader( uf::io::root+filename, type, pipeline );
|
||||
});
|
||||
} else if ( ext::json::isObject( metadata.json["shaders"] ) ) {
|
||||
@ -295,11 +296,12 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
else if ( key == "fragment" ) type = ext::vulkan::enums::Shader::FRAGMENT;
|
||||
else if ( key == "geometry" ) type = ext::vulkan::enums::Shader::GEOMETRY;
|
||||
else if ( key == "compute" ) type = ext::vulkan::enums::Shader::COMPUTE;
|
||||
if ( filename == "" ) return;
|
||||
blitter.material.attachShader( uf::io::root+filename, type, pipeline );
|
||||
});
|
||||
} else if ( metadata.json["shaders"].is<bool>() && !metadata.json["shaders"].as<bool>() ) {
|
||||
} else if ( metadata.json["shaders"].is<bool>() && !ext::json::isNull( metadata.json["shaders"] ) ) {
|
||||
// do not attach if we're requesting no blitter shaders
|
||||
blitter.process = false;
|
||||
blitter.process = metadata.json["shaders"].as<bool>();
|
||||
} else {
|
||||
uf::stl::string vertexShaderFilename = uf::io::root+"/shaders/display/renderTarget/vert.spv";
|
||||
uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/renderTarget/frag.spv"; {
|
||||
@ -318,43 +320,10 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
}
|
||||
|
||||
if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
|
||||
auto& shader = blitter.material.getShader("compute");
|
||||
|
||||
size_t maxLights = uf::config["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
|
||||
size_t maxTextures2D = uf::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
|
||||
size_t maxTexturesCube = uf::config["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
|
||||
size_t maxTextures3D = uf::config["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(1);
|
||||
size_t maxCascades = uf::config["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
|
||||
|
||||
shader.setSpecializationConstants({
|
||||
{ "TEXTURES", maxTextures2D },
|
||||
{ "CUBEMAPS", maxTexturesCube },
|
||||
{ "CASCADES", maxCascades },
|
||||
});
|
||||
shader.setDescriptorCounts({
|
||||
{ "samplerTextures", maxTextures2D },
|
||||
{ "samplerCubemaps", maxTexturesCube },
|
||||
{ "voxelId", maxCascades },
|
||||
{ "voxelNormal", maxCascades },
|
||||
{ "voxelRadiance", maxCascades },
|
||||
{ "voxelOutput", maxCascades },
|
||||
});
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
|
||||
|
||||
shader.textures.clear();
|
||||
|
||||
for ( auto& t : sceneTextures.voxels.id ) shader.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.normal ) shader.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.radiance ) shader.textures.emplace_back().aliasTexture(t);
|
||||
for ( auto& t : sceneTextures.voxels.output ) shader.textures.emplace_back().aliasTexture(t);
|
||||
// handled by its rendermode
|
||||
} else if ( metadata.type == uf::renderer::settings::pipelines::names::rt ) {
|
||||
#if 0
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
shader.aliasAttachment("output", this);
|
||||
#endif
|
||||
} else {
|
||||
// handled by its rendermode
|
||||
} else {
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
for ( auto i = 0; i < renderTarget.attachments.size(); ++i ) {
|
||||
if ( !(renderTarget.attachments[i].descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
|
||||
@ -398,7 +367,7 @@ void ext::vulkan::RenderTargetRenderMode::build( bool resized ) {
|
||||
}
|
||||
|
||||
// (re)initialize pipelines
|
||||
{
|
||||
if ( blitter.process ) {
|
||||
blitter.descriptor.bind.width = width;
|
||||
blitter.descriptor.bind.height = height;
|
||||
|
||||
@ -408,6 +377,30 @@ void ext::vulkan::RenderTargetRenderMode::build( bool resized ) {
|
||||
blitter.getPipeline( blitter.descriptor ).update( blitter, blitter.descriptor );
|
||||
}
|
||||
}
|
||||
|
||||
if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
|
||||
auto descriptor = blitter.descriptor;
|
||||
//descriptor.pipeline = "lighting";
|
||||
descriptor.subpass = -1;
|
||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
if ( blitter.hasPipeline( descriptor ) ) {
|
||||
blitter.getPipeline( descriptor ).update( blitter, descriptor );
|
||||
} else {
|
||||
blitter.initializePipeline( descriptor );
|
||||
}
|
||||
}
|
||||
|
||||
if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
|
||||
auto descriptor = blitter.descriptor;
|
||||
descriptor.pipeline = "mipmap";
|
||||
descriptor.subpass = -1;
|
||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
if ( blitter.hasPipeline( descriptor ) ) {
|
||||
blitter.getPipeline( descriptor ).update( blitter, descriptor );
|
||||
} else {
|
||||
blitter.initializePipeline( descriptor );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ext::vulkan::RenderTargetRenderMode::tick() {
|
||||
|
||||
@ -519,15 +519,16 @@ void ext::vulkan::Texture::fromBuffers(
|
||||
|
||||
if ( this->mips == 0 ) {
|
||||
this->mips = 1;
|
||||
// } else if ( this->depth == 1 ) {
|
||||
} else {
|
||||
// this->mips = static_cast<uint32_t>(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1;
|
||||
this->mips = uf::vector::mips( pod::Vector3ui{ texWidth, texHeight, texDepth } );
|
||||
VkFormatProperties formatProperties;
|
||||
vkGetPhysicalDeviceFormatProperties(device.physicalDevice, format, &formatProperties);
|
||||
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
|
||||
this->mips = 1;
|
||||
// VK_VALIDATION_MESSAGE("Texture image format {} does not support linear blitting", format);
|
||||
// cringe override for 3D textures that explicitly request mipmapping
|
||||
if ( texDepth <= 1 ) {
|
||||
VkFormatProperties formatProperties;
|
||||
vkGetPhysicalDeviceFormatProperties(device.physicalDevice, format, &formatProperties);
|
||||
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
|
||||
this->mips = 1;
|
||||
// VK_VALIDATION_MESSAGE("Texture image format {} does not support linear blitting", format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user