vxgi optimizations (to-do: fix the stuttering again from the UBO lagging or something)

This commit is contained in:
ecker 2026-05-06 20:47:54 -05:00
parent ec2122ab12
commit 682dd2c794
28 changed files with 822 additions and 925 deletions

View File

@ -109,7 +109,7 @@
"invariant": { "invariant": {
"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": false,
"multithreaded recording": true "multithreaded recording": true
}, },
"pipelines": { "pipelines": {
@ -117,10 +117,10 @@
"gui": true, "gui": true,
"vsync": true, // vsync on vulkan side rather than engine-side "vsync": true, // vsync on vulkan side rather than engine-side
"hdr": true, "hdr": true,
"vxgi": false, "vxgi": true,
"culling": false, "culling": false,
"bloom": true, "bloom": false,
"dof": true, "dof": false,
"rt": false, "rt": false,
"fsr": false, "fsr": false,
"postProcess": false // "postProcess.chromab" // false "postProcess": false // "postProcess.chromab" // false
@ -299,7 +299,7 @@
"enabled": true "enabled": true
}, },
"imgui": { "imgui": {
"enabled": true "enabled": false
}, },
"fsr": { "fsr": {
"enabled": true, "enabled": true,

View File

@ -2,6 +2,10 @@
float random(vec3 seed, int i){ return fract(sin(dot(vec4(seed,i), vec4(12.9898,78.233,45.164,94.673))) * 43758.5453); } float random(vec3 seed, int i){ return fract(sin(dot(vec4(seed,i), vec4(12.9898,78.233,45.164,94.673))) * 43758.5453); }
float rand2(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453); } float rand2(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453); }
float rand3(vec3 co){ return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453); } float rand3(vec3 co){ return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453); }
float interleavedGradientNoise(vec2 co) {
vec3 seed = vec3(0.06711056, 0.00583715, 52.9829189);
return fract(seed.z * fract(dot(co, seed.xy)));
}
// //
float mipLevel( in vec2 dx_vtc, in vec2 dy_vtc ) { float mipLevel( in vec2 dx_vtc, in vec2 dy_vtc ) {
const float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)); const float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
@ -44,7 +48,8 @@ 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)); } float luma( vec3 color ) { return dot(color, vec3(0.2126, 0.7152, 0.0722)); } // REF 709
float luminance( vec3 color ) { return dot(color, vec3(0.299, 0.587, 0.114)); } // REF 601
// //
uint tea(uint val0, uint val1) { uint tea(uint val0, uint val1) {
uint v0 = val0; uint v0 = val0;

View File

@ -94,19 +94,10 @@ layout (binding = 18) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 19) uniform samplerCube samplerCubemaps[CUBEMAPS]; layout (binding = 19) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 20) uniform sampler3D samplerNoise; layout (binding = 20) uniform sampler3D samplerNoise;
#if VXGI #if VXGI
layout (binding = 21) uniform usampler3D voxelDrawId[CASCADES]; layout (binding = 21) uniform sampler3D voxelOutput[CASCADES];
layout (binding = 22) uniform usampler3D voxelInstanceId[CASCADES];
layout (binding = 23) uniform sampler3D voxelNormalX[CASCADES];
layout (binding = 24) uniform sampler3D voxelNormalY[CASCADES];
layout (binding = 25) uniform sampler3D voxelRadianceR[CASCADES];
layout (binding = 26) uniform sampler3D voxelRadianceG[CASCADES];
layout (binding = 27) uniform sampler3D voxelRadianceB[CASCADES];
layout (binding = 28) uniform sampler3D voxelRadianceA[CASCADES];
layout (binding = 29) uniform sampler3D voxelCount[CASCADES];
layout (binding = 30) uniform sampler3D voxelOutput[CASCADES];
#endif #endif
#if RT #if RT
layout (binding = 31) uniform accelerationStructureEXT tlas; layout (binding = 22) uniform accelerationStructureEXT tlas;
#endif #endif
#if BUFFER_REFERENCE #if BUFFER_REFERENCE
@ -296,7 +287,7 @@ void directLighting() {
surface.material.albedo.rgb = radiance.rgb; surface.material.albedo.rgb = radiance.rgb;
surface.material.indirect.rgb = vec3(0); surface.material.indirect.rgb = vec3(0);
surface.fragment.rgb = radiance.rgb; surface.fragment.rgb = radiance.rgb;
surface.fragment.a = radiance.a; surface.fragment.a = 1; // radiance.a;
//return; //return;
} }
#endif #endif

View File

@ -50,18 +50,11 @@ layout (std140, binding = 7) readonly buffer Lights {
layout (binding = 8) uniform sampler2D samplerTextures[TEXTURES]; layout (binding = 8) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 9) uniform samplerCube samplerCubemaps[CUBEMAPS]; layout (binding = 9) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 10) uniform sampler3D samplerNoise;
layout (binding = 11, r32ui) uniform readonly uimage3D voxelDrawId[CASCADES]; layout (binding = 10, r32ui) uniform readonly uimage3D voxelId[CASCADES];
layout (binding = 12, r32ui) uniform readonly uimage3D voxelInstanceId[CASCADES]; layout (binding = 11, r32ui) uniform readonly uimage3D voxelNormal[CASCADES];
layout (binding = 13, r32ui) uniform readonly uimage3D voxelNormalX[CASCADES]; layout (binding = 12, r32ui) uniform readonly uimage3D voxelRadiance[CASCADES];
layout (binding = 14, r32ui) uniform readonly uimage3D voxelNormalY[CASCADES]; layout (binding = 13, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
layout (binding = 15, r32ui) uniform readonly uimage3D voxelRadianceR[CASCADES];
layout (binding = 16, r32ui) uniform readonly uimage3D voxelRadianceG[CASCADES];
layout (binding = 17, r32ui) uniform readonly uimage3D voxelRadianceB[CASCADES];
layout (binding = 18, r32ui) uniform readonly uimage3D voxelRadianceA[CASCADES];
layout (binding = 19, r32ui) uniform readonly uimage3D voxelCount[CASCADES];
layout (binding = 20, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
#include "../../common/functions.h" #include "../../common/functions.h"
#include "../../common/light.h" #include "../../common/light.h"
@ -71,55 +64,27 @@ layout (binding = 20, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
void main() { void main() {
const vec3 tUvw = gl_GlobalInvocationID.xzy; const vec3 tUvw = gl_GlobalInvocationID.xzy;
for ( uint CASCADE = 0; CASCADE < CASCADES; ++CASCADE ) { for ( uint CASCADE = 0; CASCADE < CASCADES; ++CASCADE ) {
vec2 N_E = vec2( #if 0
uintBitsToFloat(imageLoad(voxelNormalX[CASCADE], ivec3(tUvw) ).x), vec4 A = unpackUnorm4x8(imageLoad(voxelRadiance[CASCADE], ivec3(tUvw)).r);
uintBitsToFloat(imageLoad(voxelNormalY[CASCADE], ivec3(tUvw) ).x) A.a = length(luma(A.rgb)) > 0.001 ? 1 : 0;
); imageStore(voxelOutput[CASCADE], ivec3(tUvw), A);
#else
surface.normal.world = decodeNormals( N_E );
surface.normal.eye = vec3( ubo.settings.vxgi.matrix * vec4( surface.normal.world, 0.0f ) );
surface.position.eye = (vec3(gl_GlobalInvocationID.xyz) / vec3(imageSize(voxelOutput[CASCADE])) * 2.0f - 1.0f) * cascadePower(CASCADE);
surface.position.world = vec3( inverse(ubo.settings.vxgi.matrix) * vec4( surface.position.eye, 1.0f ) );
surface.pass = 0; // PushConstant.pass; surface.pass = 0; // PushConstant.pass;
surface.fragment = vec4(0); surface.fragment = vec4(0);
surface.light = vec4(0); surface.light = vec4(0);
surface.motion = vec2(0); surface.motion = vec2(0);
surface.material.indirect = vec4(0); surface.material.indirect = vec4(0);
#if 0 const uint packedID = imageLoad(voxelId[CASCADE], ivec3(tUvw) ).x;
#if 0
vec4 A = imageLoad(voxelOutput[CASCADE], ivec3(tUvw) );
#else
vec4 A = vec4(0);
A.r = imageLoad(voxelRadianceR[CASCADE], ivec3(tUvw) ).r;
A.g = imageLoad(voxelRadianceG[CASCADE], ivec3(tUvw) ).r;
A.b = imageLoad(voxelRadianceB[CASCADE], ivec3(tUvw) ).r;
A.a = imageLoad(voxelRadianceA[CASCADE], ivec3(tUvw) ).r;
A /= 256.0;
uint count = imageLoad(voxelCount[CASCADE], ivec3(tUvw) ).r;
if ( count > 0 ) A /= count;
/*
vec4 A = vec4(surface.normal.world, 1.0);
*/
#endif
surface.material.albedo = A;
surface.fragment.rgb = surface.material.albedo.rgb;
const bool DISCARD_DUE_TO_DIVERGENCE = surface.material.albedo.a == 0;
#else
const uvec2 ID = uvec2( const uvec2 ID = uvec2(
imageLoad(voxelDrawId[CASCADE], ivec3(tUvw) ).x, (packedID & 0xFFFF),
imageLoad(voxelInstanceId[CASCADE], ivec3(tUvw) ).x (packedID >> 16)
); );
const bool DISCARD_DUE_TO_DIVERGENCE = ID.x == 0 || ID.y == 0; const bool DISCARD_DUE_TO_DIVERGENCE = ID.x == 0 || ID.y == 0;
const uint drawID = ID.x == 0 ? 0 : ID.x - 1; const uint drawID = ID.x == 0 ? 0 : ID.x - 1;
const uint instanceID = ID.y == 0 ? 0 : ID.y - 1; const uint instanceID = ID.y == 0 ? 0 : ID.y - 1;
// if ( ID.x == 0 || ID.y == 0 ) { // if ( ID.x == 0 || ID.y == 0 ) {
#if 1 #if 1
if ( DISCARD_DUE_TO_DIVERGENCE ) { if ( DISCARD_DUE_TO_DIVERGENCE ) {
@ -138,15 +103,8 @@ void main() {
#if 0 #if 0
vec4 A = imageLoad(voxelOutput[CASCADE], ivec3(tUvw) ); vec4 A = imageLoad(voxelOutput[CASCADE], ivec3(tUvw) );
#else #else
vec4 A = vec4(0); vec4 A = unpackUnorm4x8(imageLoad(voxelRadiance[CASCADE], ivec3(tUvw)).r);
A.r = imageLoad(voxelRadianceR[CASCADE], ivec3(tUvw) ).r; A.a = 1.0;
A.g = imageLoad(voxelRadianceG[CASCADE], ivec3(tUvw) ).r;
A.b = imageLoad(voxelRadianceB[CASCADE], ivec3(tUvw) ).r;
A.a = imageLoad(voxelRadianceA[CASCADE], ivec3(tUvw) ).r;
A /= 256.0;
uint count = imageLoad(voxelCount[CASCADE], ivec3(tUvw) ).r;
if ( count > 0 ) A /= count;
#endif #endif
surface.material.albedo = A; surface.material.albedo = A;
@ -205,7 +163,6 @@ void main() {
#endif #endif
} }
surface.fragment.rgb += surface.light.rgb; surface.fragment.rgb += surface.light.rgb;
#endif
#if TONE_MAP #if TONE_MAP
toneMap(surface.fragment.rgb, ubo.settings.bloom.exposure); toneMap(surface.fragment.rgb, ubo.settings.bloom.exposure);
@ -214,14 +171,11 @@ void main() {
gammaCorrect(surface.fragment.rgb, 1.0 / ubo.settings.bloom.gamma); gammaCorrect(surface.fragment.rgb, 1.0 / ubo.settings.bloom.gamma);
#endif #endif
#if 0
imageStore(voxelOutput[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, surface.material.albedo.a));
#else
if ( DISCARD_DUE_TO_DIVERGENCE ) { if ( DISCARD_DUE_TO_DIVERGENCE ) {
imageStore(voxelOutput[CASCADE], ivec3(tUvw), vec4(0)); imageStore(voxelOutput[CASCADE], ivec3(tUvw), vec4(0));
} else { } else {
imageStore(voxelOutput[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, surface.material.albedo.a)); imageStore(voxelOutput[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, surface.material.albedo.a));
} }
#endif #endif
} }
} }

View File

@ -37,16 +37,10 @@ layout (std140, binding = 12) readonly buffer Lights {
Light lights[]; Light lights[];
}; };
layout (binding = 13, r32ui) uniform volatile uimage3D voxelDrawId[CASCADES]; layout (binding = 13, r32ui) uniform volatile uimage3D voxelId[CASCADES];
layout (binding = 14, r32ui) uniform volatile uimage3D voxelInstanceId[CASCADES]; layout (binding = 14, r32ui) uniform volatile uimage3D voxelNormal[CASCADES];
layout (binding = 15, r32ui) uniform volatile uimage3D voxelNormalX[CASCADES]; layout (binding = 15, r32ui) uniform volatile uimage3D voxelRadiance[CASCADES];
layout (binding = 16, r32ui) uniform volatile uimage3D voxelNormalY[CASCADES]; layout (binding = 16, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
layout (binding = 17, r32ui) uniform volatile uimage3D voxelRadianceR[CASCADES];
layout (binding = 18, r32ui) uniform volatile uimage3D voxelRadianceG[CASCADES];
layout (binding = 19, r32ui) uniform volatile uimage3D voxelRadianceB[CASCADES];
layout (binding = 20, r32ui) uniform volatile uimage3D voxelRadianceA[CASCADES];
layout (binding = 21, r32ui) uniform volatile uimage3D voxelCount[CASCADES];
layout (binding = 22, rgba8) uniform writeonly image3D voxelOutput[CASCADES];
layout (location = 0) flat in uvec4 inId; layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0; layout (location = 1) flat in vec4 inPOS0;
@ -94,7 +88,8 @@ void main() {
A.a = 1; A.a = 1;
// alpha mode BLEND // alpha mode BLEND
} else if ( material.modeAlpha == 1 ) { } else if ( material.modeAlpha == 1 ) {
float dither = interleavedGradientNoise(gl_FragCoord.xy);
// if ( A.a < dither ) discard;
// alpha mode MASK // alpha mode MASK
} else if ( material.modeAlpha == 2 ) { } else if ( material.modeAlpha == 2 ) {
if ( A.a < abs(material.factorAlphaCutoff) ) discard; if ( A.a < abs(material.factorAlphaCutoff) ) discard;
@ -121,16 +116,13 @@ void main() {
const ivec3 uvw = ivec3(P * imageSize(voxelOutput[CASCADE])); const ivec3 uvw = ivec3(P * imageSize(voxelOutput[CASCADE]));
imageAtomicMax(voxelDrawId[CASCADE], ivec3(uvw), uint( drawID + 1 ) ); uint packedId = ( instanceID + 1 ) << 16 | ( drawID + 1 );
imageAtomicMax(voxelInstanceId[CASCADE], ivec3(uvw), uint( instanceID + 1 ) ); imageAtomicMax(voxelId[CASCADE], ivec3(uvw), packedId);
vec2 N_E = encodeNormals( normalize( N ) ); vec2 N_E = encodeNormals( normalize( N ) );
imageAtomicMin(voxelNormalX[CASCADE], ivec3(uvw), uint( floatBitsToUint( N_E.x ) ) ); uint packedNormal = packHalf2x16(N_E);
imageAtomicMin(voxelNormalY[CASCADE], ivec3(uvw), uint( floatBitsToUint( N_E.y ) ) ); imageAtomicMin(voxelNormal[CASCADE], uvw, packedNormal);
imageAtomicAdd(voxelRadianceR[CASCADE], ivec3(uvw), uint( A.r * 256 ) ); uint packedRadiance = packUnorm4x8(vec4(A.rgb, luminance(A.rgb)));
imageAtomicAdd(voxelRadianceG[CASCADE], ivec3(uvw), uint( A.g * 256 ) ); imageAtomicMax(voxelRadiance[CASCADE], uvw, packedRadiance);
imageAtomicAdd(voxelRadianceB[CASCADE], ivec3(uvw), uint( A.b * 256 ) );
imageAtomicAdd(voxelRadianceA[CASCADE], ivec3(uvw), uint( A.a * 256 ) );
imageAtomicAdd(voxelCount[CASCADE], ivec3(uvw), uint( 1 ) );
} }

View File

@ -5,15 +5,9 @@ namespace pod {
uf::renderer::Texture3D noise; uf::renderer::Texture3D noise;
uf::renderer::TextureCube skybox; uf::renderer::TextureCube skybox;
struct { struct {
uf::stl::vector<uf::renderer::Texture3D> drawId; uf::stl::vector<uf::renderer::Texture3D> id;
uf::stl::vector<uf::renderer::Texture3D> instanceId; uf::stl::vector<uf::renderer::Texture3D> normal;
uf::stl::vector<uf::renderer::Texture3D> normalX; uf::stl::vector<uf::renderer::Texture3D> radiance;
uf::stl::vector<uf::renderer::Texture3D> normalY;
uf::stl::vector<uf::renderer::Texture3D> radianceR;
uf::stl::vector<uf::renderer::Texture3D> radianceG;
uf::stl::vector<uf::renderer::Texture3D> radianceB;
uf::stl::vector<uf::renderer::Texture3D> radianceA;
uf::stl::vector<uf::renderer::Texture3D> count;
uf::stl::vector<uf::renderer::Texture3D> output; uf::stl::vector<uf::renderer::Texture3D> output;
} voxels; } voxels;
}; };

View File

@ -59,6 +59,7 @@ namespace ext {
VkImageViewType viewType = enums::Image::VIEW_TYPE_2D; VkImageViewType viewType = enums::Image::VIEW_TYPE_2D;
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageUsageFlags usage = {}; VkImageUsageFlags usage = {};
VkImageCreateFlags flags = {};
VkDeviceMemory deviceMemory = VK_NULL_HANDLE; VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
VkDescriptorImageInfo descriptor = {}; VkDescriptorImageInfo descriptor = {};
VkFormat format = enums::Format::R8G8B8A8_UNORM; VkFormat format = enums::Format::R8G8B8A8_UNORM;
@ -102,29 +103,45 @@ namespace ext {
const uf::stl::string& filename, const uf::stl::string& filename,
VkFormat format = DefaultFormat, VkFormat format = DefaultFormat,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
); );
void loadFromFile( void loadFromFile(
const uf::stl::string& filename, const uf::stl::string& filename,
Device& device, Device& device,
VkFormat format = DefaultFormat, VkFormat format = DefaultFormat,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
); );
void loadFromImage( void loadFromImage(
const uf::Image& image, const uf::Image& image,
Device& device, Device& device,
VkFormat format = DefaultFormat, VkFormat format = DefaultFormat,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
); );
void loadFromImage( void loadFromImage(
const uf::Image& image, const uf::Image& image,
VkFormat format = DefaultFormat, VkFormat format = DefaultFormat,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
);
void fromBuffers(
void* buffer,
VkDeviceSize bufferSize,
VkFormat format,
uint32_t texWidth,
uint32_t texHeight,
uint32_t texDepth,
uint32_t layers,
Device& device,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VkImageCreateFlags flags = {}
); );
void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, uint32_t texDepth, uint32_t layers, Device& device, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL );
void asRenderTarget( Device& device, uint32_t texWidth, uint32_t texHeight, VkFormat format = DefaultFormat ); void asRenderTarget( Device& device, uint32_t texWidth, uint32_t texHeight, VkFormat format = DefaultFormat );
Texture alias() const; Texture alias() const;
@ -136,14 +153,14 @@ namespace ext {
void update( uf::Image& image, VkImageLayout, uint32_t layer = 1 ); void update( uf::Image& image, VkImageLayout, uint32_t layer = 1 );
void update( void*, VkDeviceSize, VkImageLayout, uint32_t layer = 1 ); void update( void*, VkDeviceSize, VkImageLayout, uint32_t layer = 1 );
inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, Device& device, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, device, usage, layout); } inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, Device& device, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VkImageCreateFlags flags = {} ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, device, usage, layout, flags); }
inline void update( uf::Image& image, uint32_t layer = 1 ) { return this->update(image, this->layout, layer); } inline void update( uf::Image& image, uint32_t layer = 1 ) { return this->update(image, this->layout, layer); }
inline void update( void* data, VkDeviceSize size, uint32_t layer = 1 ) { return this->update(data, size, this->layout, layer); } inline void update( void* data, VkDeviceSize size, uint32_t layer = 1 ) { return this->update(data, size, this->layout, layer); }
void generateMipmaps(VkCommandBuffer commandBuffer, uint32_t layer = 0); 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 usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = 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 usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VkImageCreateFlags flags = {} );
inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, usage, layout); } inline void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VkImageCreateFlags flags = {} ) { return this->fromBuffers(buffer, bufferSize, format, texWidth, texHeight, 1, 1, usage, layout, flags); }
}; };
class UF_API Texture2D : public Texture { class UF_API Texture2D : public Texture {
public: public:

View File

@ -384,7 +384,9 @@ void ext::GuiGlyphBehavior::initialize( uf::Object& self ) {
bool forced = payload["force"].as(false); bool forced = payload["force"].as(false);
// override // override
// metadata.sdf = false; #if UF_USE_OPENGL
metadata.sdf = false;
#endif
metadataGui.scaling = "none"; metadataGui.scaling = "none";
auto& scene = uf::scene::getCurrentScene(); auto& scene = uf::scene::getCurrentScene();

View File

@ -225,39 +225,11 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
shader.setDescriptorCounts({ shader.setDescriptorCounts({
{ "samplerTextures", maxTextures2D }, { "samplerTextures", maxTextures2D },
{ "samplerCubemaps", maxTexturesCube }, { "samplerCubemaps", maxTexturesCube },
{ "voxelDrawId", maxCascades }, { "voxelId", maxCascades },
{ "voxelInstanceId", maxCascades }, { "voxelNormal", maxCascades },
{ "voxelNormalX", maxCascades }, { "voxelRadiance", maxCascades },
{ "voxelNormalY", maxCascades },
{ "voxelRadianceR", maxCascades },
{ "voxelRadianceG", maxCascades },
{ "voxelRadianceB", maxCascades },
{ "voxelRadianceA", maxCascades },
{ "voxelCount", maxCascades },
{ "voxelOutput", maxCascades }, { "voxelOutput", maxCascades },
}); });
/*
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures2D);
else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxTexturesCube);
else if ( sc.name == "CASCADES" ) sc.value.ui = (specializationConstants[sc.index] = maxCascades);
}
for ( auto pair : shader.metadata.definitions.textures ) {
auto& tx = pair.second;
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != tx.binding ) continue;
if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
else if ( tx.name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelNormal" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
}
*/
} }
} }
} }

View File

@ -740,26 +740,14 @@ void ext::ExtSceneBehavior::destroy( uf::Object& self ) {
} }
if ( this->hasComponent<pod::SceneTextures>() ) { if ( this->hasComponent<pod::SceneTextures>() ) {
auto& sceneTextures = this->getComponent<pod::SceneTextures>(); auto& sceneTextures = this->getComponent<pod::SceneTextures>();
for ( auto& t : sceneTextures.voxels.drawId ) t.destroy(); for ( auto& t : sceneTextures.voxels.id ) t.destroy();
for ( auto& t : sceneTextures.voxels.instanceId ) t.destroy(); for ( auto& t : sceneTextures.voxels.normal ) t.destroy();
for ( auto& t : sceneTextures.voxels.normalX ) t.destroy(); for ( auto& t : sceneTextures.voxels.radiance ) t.destroy();
for ( auto& t : sceneTextures.voxels.normalY ) t.destroy();
for ( auto& t : sceneTextures.voxels.radianceR ) t.destroy();
for ( auto& t : sceneTextures.voxels.radianceG ) t.destroy();
for ( auto& t : sceneTextures.voxels.radianceB ) t.destroy();
for ( auto& t : sceneTextures.voxels.radianceA ) t.destroy();
for ( auto& t : sceneTextures.voxels.count ) t.destroy();
for ( auto& t : sceneTextures.voxels.output ) t.destroy(); for ( auto& t : sceneTextures.voxels.output ) t.destroy();
sceneTextures.voxels.drawId.clear(); sceneTextures.voxels.id.clear();
sceneTextures.voxels.instanceId.clear(); sceneTextures.voxels.normal.clear();
sceneTextures.voxels.normalX.clear(); sceneTextures.voxels.radiance.clear();
sceneTextures.voxels.normalY.clear();
sceneTextures.voxels.radianceR.clear();
sceneTextures.voxels.radianceG.clear();
sceneTextures.voxels.radianceB.clear();
sceneTextures.voxels.radianceA.clear();
sceneTextures.voxels.count.clear();
sceneTextures.voxels.output.clear(); sceneTextures.voxels.output.clear();
sceneTextures.noise.destroy(); sceneTextures.noise.destroy();
@ -1136,17 +1124,14 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
// attach VXGI voxels // attach VXGI voxels
if ( uf::renderer::settings::pipelines::vxgi ) { if ( uf::renderer::settings::pipelines::vxgi ) {
for ( auto& t : sceneTextures.voxels.drawId ) textures3D.emplace_back().aliasTexture(t); /*
for ( auto& t : sceneTextures.voxels.instanceId ) textures3D.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.id ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalX ) textures3D.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.normal ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalY ) textures3D.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.radiance ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceR ) textures3D.emplace_back().aliasTexture(t); */
for ( auto& t : sceneTextures.voxels.radianceG ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceB ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceA ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.count ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.output ) textures3D.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.output ) textures3D.emplace_back().aliasTexture(t);
} }
// bind textures // bind textures
while ( textures2D.size() < metadata.max.textures2D ) textures2D.emplace_back().aliasTexture(uf::renderer::Texture2D::empty); while ( textures2D.size() < metadata.max.textures2D ) textures2D.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
while ( texturesCube.size() < metadata.max.texturesCube ) texturesCube.emplace_back().aliasTexture(uf::renderer::TextureCube::empty); while ( texturesCube.size() < metadata.max.texturesCube ) texturesCube.emplace_back().aliasTexture(uf::renderer::TextureCube::empty);

View File

@ -18,6 +18,7 @@
#include "../scene/behavior.h" #include "../scene/behavior.h"
#include <uf/engine/ext.h> #include <uf/engine/ext.h>
#define ALIAS_OUTPUT_TO_RADIANCE 1
UF_BEHAVIOR_REGISTER_CPP(ext::VoxelizerSceneBehavior) UF_BEHAVIOR_REGISTER_CPP(ext::VoxelizerSceneBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::VoxelizerSceneBehavior, ticks = true, renders = false, thread = "") UF_BEHAVIOR_TRAITS_CPP(ext::VoxelizerSceneBehavior, ticks = true, renders = false, thread = "")
@ -35,44 +36,46 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
for ( size_t i = 0; i < metadata.cascades; ++i ) { for ( size_t i = 0; i < metadata.cascades; ++i ) {
const bool HDR = false; const bool HDR = false;
auto& drawId = sceneTextures.voxels.drawId.emplace_back(); auto& id = sceneTextures.voxels.id.emplace_back();
drawId.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST; id.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
drawId.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST; id.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
drawId.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 ); 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& instanceId = sceneTextures.voxels.instanceId.emplace_back();
instanceId.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
instanceId.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
instanceId.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& normalX = sceneTextures.voxels.normalX.emplace_back(); auto& normal = sceneTextures.voxels.normal.emplace_back();
normalX.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 ); 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& normalY = sceneTextures.voxels.normalY.emplace_back();
normalY.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& radianceR = sceneTextures.voxels.radianceR.emplace_back(); auto& radiance = sceneTextures.voxels.radiance.emplace_back();
radianceR.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.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& radianceG = sceneTextures.voxels.radianceG.emplace_back();
radianceG.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& radianceB = sceneTextures.voxels.radianceB.emplace_back();
radianceB.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& radianceA = sceneTextures.voxels.radianceA.emplace_back();
radianceA.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& count = sceneTextures.voxels.count.emplace_back();
count.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& output = sceneTextures.voxels.output.emplace_back(); auto& output = sceneTextures.voxels.output.emplace_back();
/*
if ( metadata.filtering == "NEAREST" ) { if ( metadata.filtering == "NEAREST" ) {
output.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST; output.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
output.sampler.descriptor.filter.mag = 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.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 );
#if ALIAS_OUTPUT_TO_RADIANCE
output.aliasTexture( radiance );
{
VkImageViewCreateInfo viewCreateInfo = {};
viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewCreateInfo.image = radiance.image;
viewCreateInfo.viewType = radiance.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 = 0;
viewCreateInfo.subresourceRange.levelCount = radiance.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 );
}
#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 ); 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
} }
// initialize render mode // initialize render mode
{ {
@ -120,15 +123,9 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
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 < 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 ( size_t i = 0; i < maxTextures3D; ++i ) renderMode.blitter.material.textures.emplace_back().aliasTexture(uf::renderer::Texture3D::empty);
for ( auto& t : sceneTextures.voxels.drawId ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.id ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.instanceId ) 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.normalX ) 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.normalY ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceR ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceG ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceB ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceA ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.count ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.output ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.output ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
renderMode.bindCallback( renderMode.CALLBACK_BEGIN, [&]( VkCommandBuffer commandBuffer, size_t _ ){ renderMode.bindCallback( renderMode.CALLBACK_BEGIN, [&]( VkCommandBuffer commandBuffer, size_t _ ){
@ -141,15 +138,9 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
subresourceRange.layerCount = 1; subresourceRange.layerCount = 1;
VkClearColorValue clearColor = { 0.0, 0.0, 0.0, 0.0 }; VkClearColorValue clearColor = { 0.0, 0.0, 0.0, 0.0 };
for ( auto& t : sceneTextures.voxels.drawId ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange ); for ( auto& t : sceneTextures.voxels.id ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.instanceId ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange ); for ( auto& t : sceneTextures.voxels.normal ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.normalX ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange ); for ( auto& t : sceneTextures.voxels.radiance ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.normalY ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radianceR ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radianceG ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radianceB ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radianceA ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.count ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.output ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange ); for ( auto& t : sceneTextures.voxels.output ) vkCmdClearColorImage( commandBuffer, t.image, t.layout, &clearColor, 1, &subresourceRange );
}); });
@ -287,15 +278,16 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
} }
void ext::VoxelizerSceneBehavior::render( uf::Object& self ){} void ext::VoxelizerSceneBehavior::render( uf::Object& self ){}
void ext::VoxelizerSceneBehavior::destroy( uf::Object& self ){ void ext::VoxelizerSceneBehavior::destroy( uf::Object& self ){
#if UF_USE_VULKAN #if ALIAS_OUTPUT_TO_RADIANCE
/* auto& sceneTextures = this->getComponent<pod::SceneTextures>();
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) { for ( auto& t : sceneTextures.voxels.output ) {
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>(); ext::vulkan::mutex.lock();
auto& texture = uf::renderer::device.transient.textures.emplace_back();
uf::renderer::removeRenderMode( &renderMode, false ); ext::vulkan::mutex.unlock();
// this->deleteComponent<uf::renderer::RenderTargetRenderMode>();
texture.device = &uf::renderer::device;
texture.view = t.view;
} }
*/
#endif #endif
} }
void ext::VoxelizerSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) { void ext::VoxelizerSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {

View File

@ -80,20 +80,23 @@ namespace {
for ( auto& key : storage.texture2Ds.keys ) graphic.material.textures.emplace_back().aliasTexture( storage.texture2Ds.map[key] ); for ( auto& key : storage.texture2Ds.keys ) graphic.material.textures.emplace_back().aliasTexture( storage.texture2Ds.map[key] );
// bind scene's voxel texture // bind scene's voxel texture
#if UF_USE_VULKAN #if 0 && UF_USE_VULKAN
if ( uf::renderer::settings::pipelines::vxgi ) { if ( uf::renderer::settings::pipelines::vxgi ) {
auto& scene = uf::scene::getCurrentScene(); auto& scene = uf::scene::getCurrentScene();
auto& sceneTextures = scene.getComponent<pod::SceneTextures>(); auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
for ( auto& t : sceneTextures.voxels.drawId ) graphic.material.textures.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.id ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.instanceId ) graphic.material.textures.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.normal ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalX ) graphic.material.textures.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.radiance ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normalY ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceR ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceG ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceB ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radianceA ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.count ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.output ) graphic.material.textures.emplace_back().aliasTexture(t); for ( auto& t : sceneTextures.voxels.output ) graphic.material.textures.emplace_back().aliasTexture(t);
/*
auto& shader = graphic.material.getShader("fragment", uf::renderer::settings::pipelines::names::vxgi);
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);
*/
} }
#endif #endif
} }
@ -219,21 +222,9 @@ namespace {
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, uf::renderer::settings::pipelines::names::vxgi); graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, uf::renderer::settings::pipelines::names::vxgi);
} }
uint32_t voxelTypes = 0;
if ( !sceneTextures.voxels.drawId.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.instanceId.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.normalX.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.normalY.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.radianceR.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.radianceG.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.radianceB.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.radianceA.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.count.empty() ) ++voxelTypes;
if ( !sceneTextures.voxels.output.empty() ) ++voxelTypes;
uint32_t maxTextures = texture2Ds; uint32_t maxTextures = texture2Ds;
uint32_t maxCascades = texture3Ds / voxelTypes; uint32_t maxCascades = sceneTextures.voxels.id.size();
// fragment shader // fragment shader
{ {
auto& shader = graphic.material.getShader("fragment", uf::renderer::settings::pipelines::names::vxgi); auto& shader = graphic.material.getShader("fragment", uf::renderer::settings::pipelines::names::vxgi);
@ -243,17 +234,16 @@ namespace {
}); });
shader.setDescriptorCounts({ shader.setDescriptorCounts({
{ "samplerTextures", maxTextures }, { "samplerTextures", maxTextures },
{ "voxelDrawId", maxCascades }, { "voxelId", maxCascades },
{ "voxelInstanceId", maxCascades }, { "voxelNormal", maxCascades },
{ "voxelNormalX", maxCascades }, { "voxelRadiance", maxCascades },
{ "voxelNormalY", maxCascades },
{ "voxelRadianceR", maxCascades },
{ "voxelRadianceG", maxCascades },
{ "voxelRadianceB", maxCascades },
{ "voxelRadianceA", maxCascades },
{ "voxelCount", maxCascades },
{ "voxelOutput", maxCascades }, { "voxelOutput", maxCascades },
}); });
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);
} }
} }
// baking pipeline // baking pipeline

View File

@ -273,17 +273,17 @@ for ( auto& p : m.primitives ) {
}; };
float r = 1.0f / (deltaTriUV[0].x * deltaTriUV[1].y - deltaTriUV[0].y * deltaTriUV[1].x); float r = 1.0f / (deltaTriUV[0].x * deltaTriUV[1].y - deltaTriUV[0].y * deltaTriUV[1].x);
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r; auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r; auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
for ( auto i = 0; i < 3; ++i ) { for ( auto i = 0; i < 3; ++i ) {
auto& normal = meshlet.vertices[indices[0]].normal; auto& normal = meshlet.vertices[indices[0]].normal;
auto& tangent = meshlet.vertices[indices[0]].tangent; auto& tangent = meshlet.vertices[indices[0]].tangent;
tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri)); tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri));
if (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f) if (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f)
tangent = tangent * -1.0f; tangent = tangent * -1.0f;
} }
} }
} else { } else {
for ( size_t i = 0; i < meshlet.vertices.size() / 3; ++i ) { for ( size_t i = 0; i < meshlet.vertices.size() / 3; ++i ) {
@ -313,17 +313,17 @@ for ( auto& p : m.primitives ) {
}; };
float r = 1.0f / (deltaTriUV[0].x * deltaTriUV[1].y - deltaTriUV[0].y * deltaTriUV[1].x); float r = 1.0f / (deltaTriUV[0].x * deltaTriUV[1].y - deltaTriUV[0].y * deltaTriUV[1].x);
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r; auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r; auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
for ( auto i = 0; i < 3; ++i ) { for ( auto i = 0; i < 3; ++i ) {
auto& normal = meshlet.vertices[indices[0]].normal; auto& normal = meshlet.vertices[indices[0]].normal;
auto& tangent = meshlet.vertices[indices[0]].tangent; auto& tangent = meshlet.vertices[indices[0]].tangent;
tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri)); tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri));
if (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f) if (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f)
tangent = tangent * -1.0f; tangent = tangent * -1.0f;
} }
} }
} }
} }

View File

@ -173,10 +173,12 @@ void ext::imgui::tick() {
auto& renderMode = uf::renderer::getRenderMode("Gui", true); auto& renderMode = uf::renderer::getRenderMode("Gui", true);
// check if rendermode changed // check if rendermode changed
#if UF_USE_VULKAN
if ( ::boundRenderMode != &renderMode ) { if ( ::boundRenderMode != &renderMode ) {
::shutdownRenderer(); ::shutdownRenderer();
::initRenderer(); ::initRenderer();
} }
#endif
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.DeltaTime = uf::physics::time::delta; io.DeltaTime = uf::physics::time::delta;

View File

@ -19,6 +19,7 @@ namespace {
struct Pair { struct Pair {
bool aliased = false; bool aliased = false;
size_t index = 0; size_t index = 0;
size_t size = 0;
}; };
uf::stl::vector<void*> local; uf::stl::vector<void*> local;
uf::stl::vector<void*> aliases; uf::stl::vector<void*> aliases;
@ -105,7 +106,7 @@ void ext::opengl::Device::initialize() {
#endif #endif
#if UF_USE_OPENGL_FIXED_FUNCTION #if UF_USE_OPENGL_FIXED_FUNCTION
{ {
::buffers::type.emplace_back(::buffers::Pair{.aliased = false, .index = 0}); ::buffers::type.emplace_back(::buffers::Pair{.aliased = false, .index = 0, .size = 0});
::buffers::local.emplace_back((void*) NULL); ::buffers::local.emplace_back((void*) NULL);
} }
#endif #endif
@ -172,7 +173,7 @@ GLuint ext::opengl::Device::createBuffer( enums::Buffer::type_t usage, GLsizeipt
#else #else
// CPU-based buffer // CPU-based buffer
index = ::buffers::type.size(); index = ::buffers::type.size();
::buffers::type.emplace_back( ::buffers::Pair{.aliased = aliased, .index = index} ); ::buffers::type.emplace_back( ::buffers::Pair{.aliased = aliased, .index = index, .size = size} );
if ( aliased ) { if ( aliased ) {
::buffers::aliases.emplace_back( data ); ::buffers::aliases.emplace_back( data );
@ -215,11 +216,11 @@ void ext::opengl::Device::destroyBuffer( GLuint& index ) {
auto& buffer = ::buffers::local[type.index]; auto& buffer = ::buffers::local[type.index];
if ( buffer ) { if ( buffer ) {
#if UF_MEMORYPOOL_INVALID_FREE #if UF_MEMORYPOOL_INVALID_FREE
uf::memoryPool::global.free( buffer ); uf::memoryPool::global.free( buffer, type.size );
#else #else
uf::MemoryPool* memoryPool = uf::memoryPool::global.size() > 0 ? &uf::memoryPool::global : NULL; uf::MemoryPool* memoryPool = uf::memoryPool::global.size() > 0 ? &uf::memoryPool::global : NULL;
if ( memoryPool ) memoryPool->free( buffer ); if ( memoryPool ) memoryPool->free( buffer, type.size );
else free( buffer ); else free( buffer, type.size );
#endif #endif
} }
#endif #endif

View File

@ -1226,13 +1226,13 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
uf::stl::vector<VkAccelerationStructureBuildRangeInfoKHR> asBuildOffsetInfo; uf::stl::vector<VkAccelerationStructureBuildRangeInfoKHR> asBuildOffsetInfo;
VkBuildAccelerationStructureFlagsKHR flags{}; VkBuildAccelerationStructureFlagsKHR flags{};
VkAccelerationStructureBuildGeometryInfoKHR buildInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR}; VkAccelerationStructureBuildGeometryInfoKHR buildInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
VkAccelerationStructureBuildSizesInfoKHR sizeInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR}; VkAccelerationStructureBuildSizesInfoKHR sizeInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR};
const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo; const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo;
uf::renderer::AccelerationStructure as; uf::renderer::AccelerationStructure as;
uf::renderer::AccelerationStructure previous; uf::renderer::AccelerationStructure previous;
}; };
uf::stl::vector<BlasData> blasDatas; uf::stl::vector<BlasData> blasDatas;
@ -1297,7 +1297,7 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
triangles.indexData.deviceAddress = indexBufferAddress; triangles.indexData.deviceAddress = indexBufferAddress;
VkAccelerationStructureBuildRangeInfoKHR& offset = blasData.asBuildOffsetInfo.emplace_back(); VkAccelerationStructureBuildRangeInfoKHR& offset = blasData.asBuildOffsetInfo.emplace_back();
offset.firstVertex = vertexInput.first; offset.firstVertex = vertexInput.first;
offset.primitiveCount = vertexInput.count / 3; offset.primitiveCount = vertexInput.count / 3;
offset.primitiveOffset = indexInput.first * indexInput.size; offset.primitiveOffset = indexInput.first * indexInput.size;
offset.transformOffset = 0; offset.transformOffset = 0;
@ -1334,7 +1334,7 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
triangles.indexData.deviceAddress = indexBufferAddress; triangles.indexData.deviceAddress = indexBufferAddress;
VkAccelerationStructureBuildRangeInfoKHR& offset = blasData.asBuildOffsetInfo.emplace_back(); VkAccelerationStructureBuildRangeInfoKHR& offset = blasData.asBuildOffsetInfo.emplace_back();
offset.firstVertex = vertexInput.first; offset.firstVertex = vertexInput.first;
offset.primitiveCount = vertexInput.count / 3; offset.primitiveCount = vertexInput.count / 3;
offset.primitiveOffset = indexInput.first * indexInput.size; offset.primitiveOffset = indexInput.first * indexInput.size;
offset.transformOffset = 0; offset.transformOffset = 0;
@ -1715,7 +1715,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
buildInfo.dstAccelerationStructure = tlas.handle; buildInfo.dstAccelerationStructure = tlas.handle;
buildInfo.scratchData.deviceAddress = scratchBuffer.getAddress(); buildInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
VkAccelerationStructureBuildRangeInfoKHR buildOffsetInfo{countInstance, 0, 0, 0}; VkAccelerationStructureBuildRangeInfoKHR buildOffsetInfo{countInstance, 0, 0, 0};
const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo = &buildOffsetInfo; const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo = &buildOffsetInfo;
auto commandBuffer = device.fetchCommandBuffer(uf::renderer::QueueEnum::COMPUTE); auto commandBuffer = device.fetchCommandBuffer(uf::renderer::QueueEnum::COMPUTE);

View File

@ -329,15 +329,9 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
shader.setDescriptorCounts({ shader.setDescriptorCounts({
{ "samplerTextures", maxTextures2D }, { "samplerTextures", maxTextures2D },
{ "samplerCubemaps", maxTexturesCube }, { "samplerCubemaps", maxTexturesCube },
{ "voxelDrawId", maxCascades }, { "voxelId", maxCascades },
{ "voxelInstanceId", maxCascades }, { "voxelNormal", maxCascades },
{ "voxelNormalX", maxCascades }, { "voxelRadiance", maxCascades },
{ "voxelNormalY", maxCascades },
{ "voxelRadianceR", maxCascades },
{ "voxelRadianceG", maxCascades },
{ "voxelRadianceB", maxCascades },
{ "voxelRadianceA", maxCascades },
{ "voxelCount", maxCascades },
{ "voxelOutput", maxCascades }, { "voxelOutput", maxCascades },
}); });

View File

@ -316,6 +316,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
{uf::io::resolveURI(fragmentShaderFilename), VK_SHADER_STAGE_FRAGMENT_BIT} {uf::io::resolveURI(fragmentShaderFilename), VK_SHADER_STAGE_FRAGMENT_BIT}
}); });
} }
if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) { if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
auto& shader = blitter.material.getShader("compute"); auto& shader = blitter.material.getShader("compute");
@ -333,17 +334,21 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
shader.setDescriptorCounts({ shader.setDescriptorCounts({
{ "samplerTextures", maxTextures2D }, { "samplerTextures", maxTextures2D },
{ "samplerCubemaps", maxTexturesCube }, { "samplerCubemaps", maxTexturesCube },
{ "voxelDrawId", maxCascades }, { "voxelId", maxCascades },
{ "voxelInstanceId", maxCascades }, { "voxelNormal", maxCascades },
{ "voxelNormalX", maxCascades }, { "voxelRadiance", maxCascades },
{ "voxelNormalY", maxCascades },
{ "voxelRadianceR", maxCascades },
{ "voxelRadianceG", maxCascades },
{ "voxelRadianceB", maxCascades },
{ "voxelRadianceA", maxCascades },
{ "voxelCount", maxCascades },
{ "voxelOutput", 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);
} else if ( metadata.type == uf::renderer::settings::pipelines::names::rt ) { } else if ( metadata.type == uf::renderer::settings::pipelines::names::rt ) {
#if 0 #if 0
auto& shader = blitter.material.getShader("fragment"); auto& shader = blitter.material.getShader("fragment");

View File

@ -36,14 +36,14 @@ namespace {
} }
if ( image == VK_NULL_HANDLE ) continue; if ( image == VK_NULL_HANDLE ) continue;
subresourceRange.baseMipLevel = 0; subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1; 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 ) { if ( mips > 1 ) {
subresourceRange.baseMipLevel = 1; subresourceRange.baseMipLevel = 1;
subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
uf::renderer::Texture::setImageLayout( commandBuffer, image, initialLayout, descriptor.layout, subresourceRange ); uf::renderer::Texture::setImageLayout( commandBuffer, image, initialLayout, descriptor.layout, subresourceRange );
} }
} }
} }
void transitionAttachmentsFrom( void transitionAttachmentsFrom(
@ -83,14 +83,14 @@ namespace {
} }
if ( image == VK_NULL_HANDLE ) continue; if ( image == VK_NULL_HANDLE ) continue;
subresourceRange.baseMipLevel = 0; subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1; 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 ) { if ( mips > 1 ) {
subresourceRange.baseMipLevel = 1; subresourceRange.baseMipLevel = 1;
subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
uf::renderer::Texture::setImageLayout( commandBuffer, image, descriptor.layout, initialLayout, subresourceRange ); uf::renderer::Texture::setImageLayout( commandBuffer, image, descriptor.layout, initialLayout, subresourceRange );
} }
} }
} }
} }

View File

@ -371,35 +371,39 @@ void ext::vulkan::Texture::loadFromFile(
const uf::stl::string& filename, const uf::stl::string& filename,
VkFormat format, VkFormat format,
VkImageUsageFlags usage, VkImageUsageFlags usage,
VkImageLayout layout VkImageLayout layout,
VkImageCreateFlags flags
) { ) {
return loadFromFile( filename, ext::vulkan::device, format, usage, layout ); return loadFromFile( filename, ext::vulkan::device, format, usage, layout, flags );
} }
void ext::vulkan::Texture::loadFromFile( void ext::vulkan::Texture::loadFromFile(
const uf::stl::string& filename, const uf::stl::string& filename,
Device& device, Device& device,
VkFormat format, VkFormat format,
VkImageUsageFlags usage, VkImageUsageFlags usage,
VkImageLayout layout VkImageLayout layout,
VkImageCreateFlags flags
) { ) {
uf::Image image; uf::Image image;
image.open( filename ); image.open( filename );
return loadFromImage( image, device, format, usage, layout ); return loadFromImage( image, device, format, usage, layout, flags );
} }
void ext::vulkan::Texture::loadFromImage( void ext::vulkan::Texture::loadFromImage(
const uf::Image& image, const uf::Image& image,
VkFormat format, VkFormat format,
VkImageUsageFlags usage, VkImageUsageFlags usage,
VkImageLayout layout VkImageLayout layout,
VkImageCreateFlags flags
) { ) {
return loadFromImage( image, ext::vulkan::device, format, usage, layout ); return loadFromImage( image, ext::vulkan::device, format, usage, layout, flags );
} }
void ext::vulkan::Texture::loadFromImage( void ext::vulkan::Texture::loadFromImage(
const uf::Image& image, const uf::Image& image,
Device& device, Device& device,
VkFormat format, VkFormat format,
VkImageUsageFlags usage, VkImageUsageFlags usage,
VkImageLayout layout VkImageLayout layout,
VkImageCreateFlags flags
) { ) {
/* /*
switch ( format ) { switch ( format ) {
@ -474,7 +478,8 @@ void ext::vulkan::Texture::loadFromImage(
1, 1,
device, device,
usage, usage,
layout layout,
flags
); );
} }
@ -487,9 +492,10 @@ void ext::vulkan::Texture::fromBuffers(
uint32_t texDepth, uint32_t texDepth,
uint32_t layers, uint32_t layers,
VkImageUsageFlags usage, VkImageUsageFlags usage,
VkImageLayout layout VkImageLayout layout,
VkImageCreateFlags flags
) { ) {
return this->fromBuffers( buffer, bufferSize, format, texWidth, texHeight, texDepth, layers, ext::vulkan::device, usage, layout ); return this->fromBuffers( buffer, bufferSize, format, texWidth, texHeight, texDepth, layers, ext::vulkan::device, usage, layout, flags );
} }
@ -503,11 +509,13 @@ void ext::vulkan::Texture::fromBuffers(
uint32_t layers, uint32_t layers,
Device& device, Device& device,
VkImageUsageFlags usage, VkImageUsageFlags usage,
VkImageLayout layout VkImageLayout layout,
VkImageCreateFlags flags
) { ) {
this->initialize(device, texWidth, texHeight, texDepth, layers); this->initialize( device, texWidth, texHeight, texDepth, layers );
this->layout = VK_IMAGE_LAYOUT_UNDEFINED;
this->usage = usage; this->usage = usage;
this->layout = VK_IMAGE_LAYOUT_UNDEFINED;
this->flags = flags;
if ( this->mips == 0 ) { if ( this->mips == 0 ) {
this->mips = 1; this->mips = 1;
@ -545,6 +553,7 @@ void ext::vulkan::Texture::fromBuffers(
imageCreateInfo.initialLayout = this->layout; imageCreateInfo.initialLayout = this->layout;
imageCreateInfo.extent = { width, height, depth }; imageCreateInfo.extent = { width, height, depth };
imageCreateInfo.usage = this->usage; imageCreateInfo.usage = this->usage;
imageCreateInfo.flags = this->flags;
// Ensure that the TRANSFER_SRC bit is set for mip creation // Ensure that the TRANSFER_SRC bit is set for mip creation
if ( this->mips > 1 && !(imageCreateInfo.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) { if ( this->mips > 1 && !(imageCreateInfo.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) {
imageCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; imageCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
@ -555,7 +564,7 @@ void ext::vulkan::Texture::fromBuffers(
} }
// Ensure cube maps get the compat flag bit // Ensure cube maps get the compat flag bit
if ( this->viewType == ext::vulkan::enums::Image::VIEW_TYPE_CUBE || this->viewType == ext::vulkan::enums::Image::VIEW_TYPE_CUBE_ARRAY ) { if ( this->viewType == ext::vulkan::enums::Image::VIEW_TYPE_CUBE || this->viewType == ext::vulkan::enums::Image::VIEW_TYPE_CUBE_ARRAY ) {
imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; imageCreateInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
} }
VmaAllocationCreateInfo allocInfo = {}; VmaAllocationCreateInfo allocInfo = {};
@ -955,8 +964,8 @@ void ext::vulkan::Texture::generateMipmaps( VkCommandBuffer commandBuffer, uint3
); );
if (mipWidth > 1) mipWidth /= 2; if (mipWidth > 1) mipWidth /= 2;
if (mipHeight > 1) mipHeight /= 2; if (mipHeight > 1) mipHeight /= 2;
if (mipDepth > 1) mipDepth /= 2; if (mipDepth > 1) mipDepth /= 2;
} }
} }

View File

@ -2,7 +2,7 @@
#if UF_USE_XATLAS #if UF_USE_XATLAS
#include <xatlas/xatlas.h> #include <xatlas/xatlas.h>
#define UF_XATLAS_UNWRAP_MULTITHREAD 1 // prone to crashing #define UF_XATLAS_UNWRAP_MULTITHREAD 1
size_t ext::xatlas::unwrap( pod::Graph& graph ) { size_t ext::xatlas::unwrap( pod::Graph& graph ) {
struct Entry { struct Entry {
@ -56,50 +56,49 @@ size_t ext::xatlas::unwrap( pod::Graph& graph ) {
if ( !should ) continue; if ( !should ) continue;
source = mesh; source = mesh;
source.updateDescriptor(); source.updateDescriptor();
for ( size_t viewIdx = 0; viewIdx < source.buffer_views.size(); ++viewIdx ) { for ( size_t viewIdx = 0; viewIdx < source.buffer_views.size(); ++viewIdx ) {
const auto& view = source.buffer_views[viewIdx]; const auto& view = source.buffer_views[viewIdx];
size_t atlasID = 0; size_t atlasID = 0;
if ( view.indirectIndex != -1 ) { if ( view.indirectIndex != -1 ) {
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
atlasID = drawCommands[view.indirectIndex].auxID; atlasID = drawCommands[view.indirectIndex].auxID;
} }
auto& atlas = atlases[atlasID]; auto& atlas = atlases[atlasID];
auto& entry = atlas.entries.emplace_back(); auto& entry = atlas.entries.emplace_back();
entry.index = index; entry.index = index;
entry.commandID = viewIdx; entry.commandID = viewIdx;
auto& decl = entry.decl; auto& decl = entry.decl;
auto posView = view["position"]; auto posView = view["position"];
auto uvView = view["uv"]; auto uvView = view["uv"];
auto idxView = view["index"]; auto idxView = view["index"];
UF_ASSERT( posView.valid() && uvView.valid() ); UF_ASSERT( posView.valid() && uvView.valid() );
decl.vertexCount = view.vertex.count; decl.vertexCount = view.vertex.count;
decl.vertexPositionData = posView.data(view.vertex.first); decl.vertexPositionData = posView.data(view.vertex.first);
decl.vertexPositionStride = posView.stride(); decl.vertexPositionStride = posView.stride();
decl.vertexUvData = uvView.data(view.vertex.first); decl.vertexUvData = uvView.data(view.vertex.first);
decl.vertexUvStride = uvView.stride(); decl.vertexUvStride = uvView.stride();
if ( idxView.valid() ) { if ( idxView.valid() ) {
decl.indexCount = view.index.count; decl.indexCount = view.index.count;
// Pass view.index.first to offset the index pointer! decl.indexData = idxView.data(view.index.first);
decl.indexData = idxView.data(view.index.first);
switch ( idxView.attribute.descriptor.size ) { switch ( idxView.attribute.descriptor.size ) {
case 1: UF_EXCEPTION("xatlas does not support 8-bit indices"); break; case 1: UF_EXCEPTION("xatlas does not support 8-bit indices"); break;
case 2: decl.indexFormat = ::xatlas::IndexFormat::UInt16; break; case 2: decl.indexFormat = ::xatlas::IndexFormat::UInt16; break;
case 4: decl.indexFormat = ::xatlas::IndexFormat::UInt32; break; case 4: decl.indexFormat = ::xatlas::IndexFormat::UInt32; break;
default: UF_EXCEPTION("unsupported index type"); break; default: UF_EXCEPTION("unsupported index type"); break;
} }
} else { } else {
decl.indexCount = 0; decl.indexCount = 0;
} }
} }
} }
::xatlas::ChartOptions chartOptions{}; ::xatlas::ChartOptions chartOptions{};
@ -236,70 +235,63 @@ size_t ext::xatlas::unwrap( pod::Graph& graph ) {
// update vertices // update vertices
for ( auto& pair : atlases ) { for ( auto& pair : atlases ) {
auto& atlas = pair.second; auto& atlas = pair.second;
for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) { for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) {
auto& xmesh = atlas.pointer->meshes[i]; auto& xmesh = atlas.pointer->meshes[i];
auto& entry = atlas.entries[i]; auto& entry = atlas.entries[i];
auto& name = graph.meshes[entry.index]; auto& name = graph.meshes[entry.index];
auto& mesh = storage.meshes[name]; auto& mesh = storage.meshes[name];
auto& source = sources[entry.index]; auto& source = sources[entry.index];
if ( source.vertex.count == 0 ) continue; if ( source.vertex.count == 0 ) continue;
// Grab the read-only view from our unmodified source mesh const auto& srcView = source.buffer_views[entry.commandID];
const auto& srcView = source.buffer_views[entry.commandID];
// We dynamically calculate the destination offsets using the updated draw commands size_t dstVertexFirst = 0;
// Or if it's direct, it's just 0. size_t dstIndexFirst = 0;
size_t dstVertexFirst = 0; if ( mesh.indirect.count > 0 ) {
size_t dstIndexFirst = 0; pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
if ( mesh.indirect.count > 0 ) { dstVertexFirst = drawCommands[entry.commandID].vertexID;
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); dstIndexFirst = drawCommands[entry.commandID].indexID;
dstVertexFirst = drawCommands[entry.commandID].vertexID; }
dstIndexFirst = drawCommands[entry.commandID].indexID;
}
// 1. Copy over the vertices based on the xref mapping for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
for ( auto j = 0; j < xmesh.vertexCount; ++j ) { auto& vertex = xmesh.vertexArray[j];
auto& vertex = xmesh.vertexArray[j]; uint32_t ref = vertex.xref; // original vertex index relative to the sub-mesh
uint32_t ref = vertex.xref; // original vertex index relative to the sub-mesh
for ( auto attrIdx = 0; attrIdx < mesh.vertex.attributes.size(); ++attrIdx ) { for ( auto attrIdx = 0; attrIdx < mesh.vertex.attributes.size(); ++attrIdx ) {
auto srcAttribute = srcView.vertex.attributes[attrIdx]; auto srcAttribute = srcView.vertex.attributes[attrIdx];
auto dstAttribute = mesh.vertex.attributes[attrIdx]; auto dstAttribute = mesh.vertex.attributes[attrIdx];
uint8_t* dstPtr = static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (dstVertexFirst + j); uint8_t* dstPtr = static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (dstVertexFirst + j);
if ( dstAttribute.descriptor.name == "st" ) { if ( dstAttribute.descriptor.name == "st" ) {
// Write new lightmap STs! pod::Vector2f& st = *(pod::Vector2f*)dstPtr;
pod::Vector2f& st = *(pod::Vector2f*)dstPtr; st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height }; } else {
} else { const uint8_t* srcPtr = static_cast<const uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (srcView.vertex.first + ref);
// Copy original vertex data memcpy(dstPtr, srcPtr, srcAttribute.descriptor.size);
const uint8_t* srcPtr = static_cast<const uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (srcView.vertex.first + ref); }
memcpy(dstPtr, srcPtr, srcAttribute.descriptor.size); }
} }
}
}
// 2. Write new indices if ( mesh.index.count ) {
if ( mesh.index.count ) { uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front(); uint8_t* dstIndexPtr = static_cast<uint8_t*>(indexAttribute.pointer) + indexAttribute.stride * dstIndexFirst;
uint8_t* dstIndexPtr = static_cast<uint8_t*>(indexAttribute.pointer) + indexAttribute.stride * dstIndexFirst;
for ( auto idx = 0; idx < xmesh.indexCount; ++idx ) { for ( auto idx = 0; idx < xmesh.indexCount; ++idx ) {
switch ( mesh.index.size ) { switch ( mesh.index.size ) {
case 1: (( uint8_t*) dstIndexPtr)[idx] = (uint8_t) xmesh.indexArray[idx]; break; case 1: (( uint8_t*) dstIndexPtr)[idx] = (uint8_t) xmesh.indexArray[idx]; break;
case 2: ((uint16_t*) dstIndexPtr)[idx] = (uint16_t) xmesh.indexArray[idx]; break; case 2: ((uint16_t*) dstIndexPtr)[idx] = (uint16_t) xmesh.indexArray[idx]; break;
case 4: ((uint32_t*) dstIndexPtr)[idx] = (uint32_t) xmesh.indexArray[idx]; break; case 4: ((uint32_t*) dstIndexPtr)[idx] = (uint32_t) xmesh.indexArray[idx]; break;
} }
} }
} }
mesh.updateDescriptor(); mesh.updateDescriptor();
} }
} }
// cleanup // cleanup
size_t atlasCount = 0; size_t atlasCount = 0;

File diff suppressed because it is too large Load Diff

View File

@ -57,10 +57,10 @@ namespace {
} }
} }
LRESULT CALLBACK globalOnEvent(spec::win32::Window::handle_t handle, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT CALLBACK globalOnEvent(spec::win32::Window::handle_t handle, UINT message, WPARAM wParam, LPARAM lParam) {
#if UF_USE_IMGUI #if UF_USE_IMGUI
if (ImGui_ImplWin32_WndProcHandler(handle, message, wParam, lParam)) if (ImGui_ImplWin32_WndProcHandler(handle, message, wParam, lParam))
return true; return true;
#endif #endif
if (message == WM_CREATE) { if (message == WM_CREATE) {
LONG_PTR window = (LONG_PTR)reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams; LONG_PTR window = (LONG_PTR)reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams;
SetWindowLongPtrW(handle, GWLP_USERDATA, window); SetWindowLongPtrW(handle, GWLP_USERDATA, window);

View File

@ -6,8 +6,8 @@
namespace { namespace {
size_t writeFunction(void *ptr, size_t size, size_t nmemb, uf::stl::string* data) { size_t writeFunction(void *ptr, size_t size, size_t nmemb, uf::stl::string* data) {
data->append((char*) ptr, size * nmemb); data->append((char*) ptr, size * nmemb);
return size * nmemb; return size * nmemb;
} }
} }
@ -39,5 +39,5 @@ uf::Http uf::http::get( const uf::stl::string& url ) {
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl = NULL; curl = NULL;
#endif #endif
return http; return http;
} }

View File

@ -190,11 +190,11 @@ uf::stl::vector<uint8_t>& uf::io::readAsBuffer( uf::stl::vector<uint8_t>& buffer
// Read each range // Read each range
size_t currentOffset = 0; size_t currentOffset = 0;
for (const auto& r : ranges) { for (const auto& r : ranges) {
is.seekg(r.start, std::ios::beg); is.seekg(r.start, std::ios::beg);
is.read(reinterpret_cast<char*>(buffer.data() + currentOffset), r.len); is.read(reinterpret_cast<char*>(buffer.data() + currentOffset), r.len);
currentOffset += static_cast<size_t>(is.gcount()); currentOffset += static_cast<size_t>(is.gcount());
} }
} }
uf::stl::string expected; uf::stl::string expected;

View File

@ -3,18 +3,18 @@
// credit: https://github.com/zeux/meshoptimizer/blob/master/src/quantization.cpp // credit: https://github.com/zeux/meshoptimizer/blob/master/src/quantization.cpp
uint16_t UF_API uf::quant::quantize_f32u16( float v ) { uint16_t UF_API uf::quant::quantize_f32u16( float v ) {
union { float f; uint32_t ui; } u = {v}; union { float f; uint32_t ui; } u = {v};
uint32_t ui = u.ui; uint32_t ui = u.ui;
int s = (ui >> 16) & 0x8000; int s = (ui >> 16) & 0x8000;
int em = ui & 0x7fffffff; int em = ui & 0x7fffffff;
int h = (em - (112 << 23) + (1 << 12)) >> 13; int h = (em - (112 << 23) + (1 << 12)) >> 13;
h = (em < (113 << 23)) ? 0 : h; h = (em < (113 << 23)) ? 0 : h;
h = (em >= (143 << 23)) ? 0x7c00 : h; h = (em >= (143 << 23)) ? 0x7c00 : h;
h = (em > (255 << 23)) ? 0x7e00 : h; h = (em > (255 << 23)) ? 0x7e00 : h;
uint16_t res = (s | h); uint16_t res = (s | h);
return res; return res;
} }
float UF_API uf::quant::dequantize_u16f32( uint16_t h ) { float UF_API uf::quant::dequantize_u16f32( uint16_t h ) {
uint32_t s = unsigned(h & 0x8000) << 16; uint32_t s = unsigned(h & 0x8000) << 16;

View File

@ -10,78 +10,78 @@ static const int B64index[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 };
static const uint8_t base64_table[65] = static const uint8_t base64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uf::stl::string uf::base64::encode( const uint8_t* src, size_t len ) { uf::stl::string uf::base64::encode( const uint8_t* src, size_t len ) {
uint8_t *out, *pos; uint8_t *out, *pos;
const uint8_t *end, *in; const uint8_t *end, *in;
size_t olen; size_t olen;
olen = 4*((len + 2) / 3); olen = 4*((len + 2) / 3);
if (olen < len) if (olen < len)
return uf::stl::string(); return uf::stl::string();
uf::stl::string outStr; uf::stl::string outStr;
outStr.resize(olen); outStr.resize(olen);
out = (uint8_t*)&outStr[0]; out = (uint8_t*)&outStr[0];
end = src + len; end = src + len;
in = src; in = src;
pos = out; pos = out;
while (end - in >= 3) { while (end - in >= 3) {
*pos++ = base64_table[in[0] >> 2]; *pos++ = base64_table[in[0] >> 2];
*pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
*pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
*pos++ = base64_table[in[2] & 0x3f]; *pos++ = base64_table[in[2] & 0x3f];
in += 3; in += 3;
} }
if (end - in) { if (end - in) {
*pos++ = base64_table[in[0] >> 2]; *pos++ = base64_table[in[0] >> 2];
if (end - in == 1) { if (end - in == 1) {
*pos++ = base64_table[(in[0] & 0x03) << 4]; *pos++ = base64_table[(in[0] & 0x03) << 4];
*pos++ = '='; *pos++ = '=';
} }
else { else {
*pos++ = base64_table[((in[0] & 0x03) << 4) | *pos++ = base64_table[((in[0] & 0x03) << 4) |
(in[1] >> 4)]; (in[1] >> 4)];
*pos++ = base64_table[(in[1] & 0x0f) << 2]; *pos++ = base64_table[(in[1] & 0x0f) << 2];
} }
*pos++ = '='; *pos++ = '=';
} }
return outStr; return outStr;
} }
// uf::stl::vector<uint8_t> uf::base64::decode( const uint8_t* data, size_t len ) { // uf::stl::vector<uint8_t> uf::base64::decode( const uint8_t* data, size_t len ) {
uf::stl::vector<uint8_t> uf::base64::decode( const uf::stl::string& data ) { uf::stl::vector<uint8_t> uf::base64::decode( const uf::stl::string& data ) {
size_t len = data.size(); size_t len = data.size();
uint8_t* p = (uint8_t*) &data[0]; uint8_t* p = (uint8_t*) &data[0];
int pad = len > 0 && (len % 4 || p[len - 1] == '='); int pad = len > 0 && (len % 4 || p[len - 1] == '=');
const size_t L = ((len + 3) / 4 - pad) * 4; const size_t L = ((len + 3) / 4 - pad) * 4;
uf::stl::vector<uint8_t> str(L / 4 * 3 + pad, '\0'); uf::stl::vector<uint8_t> str(L / 4 * 3 + pad, '\0');
for (size_t i = 0, j = 0; i < L; i += 4) for (size_t i = 0, j = 0; i < L; i += 4)
{ {
int n = B64index[p[i]] << 18 | B64index[p[i + 1]] << 12 | B64index[p[i + 2]] << 6 | B64index[p[i + 3]]; int n = B64index[p[i]] << 18 | B64index[p[i + 1]] << 12 | B64index[p[i + 2]] << 6 | B64index[p[i + 3]];
str[j++] = n >> 16; str[j++] = n >> 16;
str[j++] = n >> 8 & 0xFF; str[j++] = n >> 8 & 0xFF;
str[j++] = n & 0xFF; str[j++] = n & 0xFF;
} }
if (pad) if (pad)
{ {
int n = B64index[p[L]] << 18 | B64index[p[L + 1]] << 12; int n = B64index[p[L]] << 18 | B64index[p[L + 1]] << 12;
str[str.size() - 1] = n >> 16; str[str.size() - 1] = n >> 16;
if (len > L + 2 && p[L + 2] != '=') if (len > L + 2 && p[L + 2] != '=')
{ {
n |= B64index[p[L + 2]] << 6; n |= B64index[p[L + 2]] << 6;
str.push_back(n >> 8 & 0xFF); str.push_back(n >> 8 & 0xFF);
} }
} }
return str; return str;
} }
uf::stl::string uf::string::base64::encode( const uf::stl::string& input ) { uf::stl::string uf::string::base64::encode( const uf::stl::string& input ) {
@ -95,9 +95,9 @@ uf::stl::string uf::string::base64::decode( const uf::stl::string& input ) {
/* /*
static const uf::stl::string base64_chars = static const uf::stl::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz" "abcdefghijklmnopqrstuvwxyz"
"0123456789+/"; "0123456789+/";
static inline bool is_base64(uint8_t c) { static inline bool is_base64(uint8_t c) {
@ -112,34 +112,34 @@ uf::stl::string uf::base64::encode(const uint8_t* buf, std::size_t bufLen) {
uint8_t char_array_4[4]; uint8_t char_array_4[4];
while (bufLen--) { while (bufLen--) {
char_array_3[i++] = *(buf++); char_array_3[i++] = *(buf++);
if (i == 3) { if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f; char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++) for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]]; ret += base64_chars[char_array_4[i]];
i = 0; i = 0;
} }
} }
if (i) if (i)
{ {
for(j = i; j < 3; j++) for(j = i; j < 3; j++)
char_array_3[j] = '\0'; char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f; char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++) for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]]; ret += base64_chars[char_array_4[j]];
while((i++ < 3)) while((i++ < 3))
ret += '='; ret += '=';
} }
return ret; return ret;
@ -154,33 +154,33 @@ uf::stl::vector<uint8_t> uf::base64::decode(const uf::stl::string& encoded_strin
uf::stl::vector<uint8_t> ret; uf::stl::vector<uint8_t> ret;
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++; char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) { if (i ==4) {
for (i = 0; i <4; i++) for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]); char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++) for (i = 0; (i < 3); i++)
ret.push_back(char_array_3[i]); ret.push_back(char_array_3[i]);
i = 0; i = 0;
} }
} }
if (i) { if (i) {
for (j = i; j <4; j++) for (j = i; j <4; j++)
char_array_4[j] = 0; char_array_4[j] = 0;
for (j = 0; j <4; j++) for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]); char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]); for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]);
} }
return ret; return ret;

View File

@ -9,10 +9,10 @@ namespace {
int status = -4; int status = -4;
std::unique_ptr<char, void(*)(void*)> demangled{ std::unique_ptr<char, void(*)(void*)> demangled{
abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status), abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status),
std::free std::free
}; };
return ( status == 0 ) ? demangled.get() : mangled; return ( status == 0 ) ? demangled.get() : mangled;
/* /*
int status; int status;
char* pointer = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status); char* pointer = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);