Commit for 2022.06.23 22-40-45.7z

This commit is contained in:
mrq 2022-06-23 22:40:00 -05:00
parent 70162646cb
commit ddb43b26ea
65 changed files with 1850 additions and 941 deletions

View File

@ -5,7 +5,7 @@
"meshes": { "interleaved": false },
"matrix": { "reverseInfinite": true },
"lights": { "enabled": true,
"useLightmaps": true,
"useLightmaps": false,
"max": 32
},
"shadows": {
@ -22,7 +22,7 @@
}
},
"vxgi": {
"limiter": 1,
"limiter": 0.5,
"size": 128,
"dispatch": 8,
"cascades": 3,
@ -48,7 +48,7 @@
"ext": {
"vulkan": {
"validation": {
"enabled": true,
"enabled": false,
"filters": [
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
"MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
@ -76,16 +76,20 @@
},
"gpu": 1,
"experimental": {
"batch queue submissions": false,
"batch queue submissions": true,
"rebuild on tick begin": false,
"dedicated thread": false
},
"invariant": {},
"invariant": {
// "multithreaded recording": true
},
"pipelines": {
"vsync": false,
"hdr": false,
"vxgi": true,
"culling": true,
"bloom": false
"bloom": false,
"rt": true
},
"formats": {
"depth": "D32_SFLOAT",
@ -108,8 +112,7 @@
"geometryShader",
"multiViewport",
"shaderOutputLayer",
// "shaderUniformBufferArrayDynamicIndexing",
// "shaderStorageBufferArrayDynamicIndexing",
"shaderInt64",
"shaderSampledImageArrayDynamicIndexing",
"shaderStorageImageArrayDynamicIndexing"
],
@ -216,7 +219,7 @@
"component": "128 MiB"
}
},
"render modes": { "gui": true, "deferred": true, "raytrace": true },
"render modes": { "gui": true, "deferred": true },
"limiters": {
"deltaTime": 5,
"framerate": "auto"

View File

@ -52,6 +52,10 @@
#define nonuniformEXT(X) X
#endif
#if ADDRESS_ENABLED
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
#endif
const float PI = 3.14159265359;
const float EPSILON = 0.00001;
const float SQRT2 = 1.41421356237;

View File

@ -136,6 +136,28 @@ struct Instance {
Bounds bounds;
};
#if ADDRESS_ENABLED
struct InstanceAddresses {
uint64_t vertex;
uint64_t index;
uint64_t position;
uint64_t uv;
uint64_t color;
uint64_t st;
uint64_t normal;
uint64_t tangent;
uint64_t joints;
uint64_t weights;
uint64_t id;
uint64_t padding;
};
#endif
struct SurfaceMaterial {
vec4 albedo;
vec4 indirect;

View File

@ -0,0 +1,14 @@
#version 450
#pragma shader_stage(fragment)
#extension GL_EXT_samplerless_texture_functions : require
layout (location = 0) in vec2 inUv;
layout (location = 1) flat in uint inPass;
layout (location = 0) out vec4 outAlbedo;
layout (binding = 0) uniform sampler2D samplerAlbedo;
void main() {
outAlbedo = texture( samplerAlbedo, inUv );
}

View File

@ -0,0 +1,16 @@
#version 450
#pragma shader_stage(vertex)
layout (location = 0) out vec2 outUv;
layout (location = 1) out flat uint outPass;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
void main() {
outUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
outPass = PushConstant.pass;
gl_Position = vec4(outUv * 2.0f + -1.0f, 0.0f, 1.0f);
}

View File

@ -1,9 +1,6 @@
#version 450
#pragma shader_stage(vertex)
layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inUv;
struct Cursor {
vec2 position;
vec2 radius;

View File

@ -1,6 +1,7 @@
#extension GL_EXT_samplerless_texture_functions : require
#extension GL_EXT_nonuniform_qualifier : enable
#define ADDRESS_ENABLED 1
#define DEFERRED 1
#define MAX_TEXTURES TEXTURES
//#define TEXTURE_WORKAROUND 0
@ -83,14 +84,19 @@ layout (std140, binding = 8) readonly buffer Textures {
layout (std140, binding = 9) readonly buffer Lights {
Light lights[];
};
/*
layout (std140, binding = 10) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
*/
layout (binding = 10) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 11) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 12) uniform sampler3D samplerNoise;
layout (binding = 11) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 12) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 13) uniform sampler3D samplerNoise;
#if VXGI
layout (binding = 13) uniform usampler3D voxelId[CASCADES];
layout (binding = 14) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 15) uniform sampler3D voxelRadiance[CASCADES];
layout (binding = 14) uniform usampler3D voxelId[CASCADES];
layout (binding = 15) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 16) uniform sampler3D voxelRadiance[CASCADES];
#endif
layout (location = 0) in vec2 inUv;

View File

@ -66,9 +66,9 @@ layout (binding = 11) uniform sampler3D samplerNoise;
layout (binding = 12, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
layout (binding = 13, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
#if VXGI_HDR
layout (binding = 14, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES];
#else
layout (binding = 14, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES];
#else
layout (binding = 14, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES];
#endif
#include "../common/functions.h"

View File

@ -40,7 +40,7 @@ void main() {
float tMin = 0.001;
float tMax = 10000.0;
hitValue = vec4(1, 0, 1, 1);
hitValue = vec4(0);
traceRayEXT(inTlas, rayFlags, cullMask, 0, 0, 0, surface.ray.origin.xyz, tMin, surface.ray.direction.xyz, tMax, 0);
imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue));

View File

@ -5,5 +5,5 @@
layout(location = 0) rayPayloadInEXT vec4 hitValue;
void main() {
hitValue = vec4(0.2, 0.2, 0.2, 1.0);
hitValue = vec4(0.2, 0.2, 0.2, 0.0);
}

View File

@ -1,7 +1,7 @@
{
"engine": {
"scenes": {
"start": "StartMenu",
"start": "SS2",
"meshes": { "interleaved": false },
"matrix": { "reverseInfinite": false },
"lights": { "enabled": false,

View File

@ -6,6 +6,7 @@
#include <uf/utils/mesh/mesh.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/utils/memory/unordered_map.h>
#include <uf/utils/memory/key_map.h>
#include <queue>
@ -60,46 +61,27 @@ namespace pod {
// Local storage, used for save/load
struct Storage {
template<typename T, typename Key = uf::stl::string>
struct KeyMap {
public:
uf::stl::vector<Key> keys;
uf::stl::unordered_map<Key, T> map;
uf::stl::unordered_map<Key, size_t> indices;
T& operator[]( const Key& key ) {
if ( map.count( key ) == 0 ) {
indices[key] = keys.size();
keys.emplace_back( key );
}
return map[key];
}
uf::stl::KeyMap<pod::Instance> instances;
uf::stl::KeyMap<pod::InstanceAddresses> instanceAddresses;
uf::stl::KeyMap<uf::stl::vector<pod::Primitive>> primitives;
uf::stl::KeyMap<uf::stl::vector<pod::DrawCommand>> drawCommands;
uf::stl::KeyMap<uf::Mesh> meshes;
void reserve( size_t i ) {
keys.reserve(i);
indices.reserve(i);
map.reserve(i);
}
};
KeyMap<pod::Instance> instances;
KeyMap<uf::stl::vector<pod::Primitive>> primitives;
KeyMap<uf::stl::vector<pod::DrawCommand>> drawCommands;
KeyMap<uf::Mesh> meshes;
KeyMap<uf::Image> images;
KeyMap<pod::Material> materials;
KeyMap<pod::Texture> textures;
KeyMap<uf::renderer::Sampler> samplers;
uf::stl::KeyMap<uf::Image> images;
uf::stl::KeyMap<pod::Material> materials;
uf::stl::KeyMap<pod::Texture> textures;
uf::stl::KeyMap<uf::renderer::Sampler> samplers;
uf::stl::vector<pod::Light> lights;
KeyMap<pod::Skin> skins;
KeyMap<pod::Animation> animations;
uf::stl::KeyMap<pod::Skin> skins;
uf::stl::KeyMap<pod::Animation> animations;
// maps without direct analogues
KeyMap<uf::Atlas> atlases;
KeyMap<uf::stl::vector<pod::Matrix4f>> joints;
KeyMap<uf::renderer::Texture2D> texture2Ds;
KeyMap<uf::Entity*> entities;
uf::stl::KeyMap<uf::Atlas> atlases;
uf::stl::KeyMap<uf::stl::vector<pod::Matrix4f>> joints;
uf::stl::KeyMap<uf::renderer::Texture2D> texture2Ds;
uf::stl::KeyMap<uf::Entity*> entities;
uf::stl::vector<uf::renderer::Texture2D> shadow2Ds;
uf::stl::vector<uf::renderer::TextureCube> shadowCubes;
@ -108,6 +90,7 @@ namespace pod {
uf::renderer::Buffer camera;
uf::renderer::Buffer drawCommands;
uf::renderer::Buffer instance;
uf::renderer::Buffer instanceAddresses;
uf::renderer::Buffer joint;
uf::renderer::Buffer material;
uf::renderer::Buffer texture;
@ -132,7 +115,7 @@ namespace uf {
pod::Matrix4f UF_API matrix( pod::Graph&, int32_t );
// void UF_API process( uf::Object& entity );
void UF_API initializeGraphics( pod::Graph& graph, uf::Object& entity );
void UF_API initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::Mesh& mesh );
void UF_API process( pod::Graph& graph );
void UF_API process( pod::Graph& graph, int32_t, uf::Object& parent );
void UF_API cleanup( pod::Graph& graph );

View File

@ -43,6 +43,7 @@ namespace ext {
void* pUserData = NULL;
} allocationInfo;
Buffer alias() const;
void aliasBuffer( const Buffer& buffer );
void* map( GLsizeiptr size = GL_WHOLE_SIZE, GLsizeiptr offset = 0 );

View File

@ -55,7 +55,8 @@ namespace ext {
struct Metadata {
uf::Serializer json;
uf::stl::unordered_map<uf::stl::string, size_t> shaders;
bool autoInitializeUniforms = true;
bool autoInitializeUniformBuffers = true;
bool autoInitializeUniformUserdatas = false;
} metadata;
void initialize( Device& device );

View File

@ -49,6 +49,16 @@ namespace ext {
extern UF_API bool vxgi;
extern UF_API bool culling;
extern UF_API bool bloom;
extern UF_API bool rt;
namespace names {
extern UF_API uf::stl::string vsync;
extern UF_API uf::stl::string hdr;
extern UF_API uf::stl::string vxgi;
extern UF_API uf::stl::string culling;
extern UF_API uf::stl::string bloom;
extern UF_API uf::stl::string rt;
}
}
namespace formats {

View File

@ -45,7 +45,8 @@ namespace ext {
uf::stl::string pipeline = "";
uf::stl::string type = "";
bool autoInitializeUniforms = true;
bool autoInitializeUniformBuffers = true;
bool autoInitializeUniformUserdatas = false;
struct Definition {
struct Texture {

View File

@ -98,7 +98,10 @@ namespace ext {
);
void fromBuffers( void* buffer, size_t bufferSize, enums::Format::type_t format, uint32_t texWidth, uint32_t texHeight, uint32_t texDepth, uint32_t layers, Device& device );
void asRenderTarget( Device& device, uint32_t texWidth, uint32_t texHeight, enums::Format::type_t format = enums::Format::R8G8B8A8_UNORM );
Texture alias() const;
void aliasTexture( const Texture& );
void aliasAttachment( const RenderTarget::Attachment& attachment, bool = true );
void update( uf::Image& image, uint32_t layer = 1 );
@ -115,14 +118,20 @@ namespace ext {
public:
Texture2D();
static Texture2D empty;
Texture2D alias() const;
};
class UF_API Texture3D : public Texture {
public:
Texture3D();
Texture3D alias() const;
};
class UF_API TextureCube : public Texture {
public:
TextureCube();
TextureCube alias() const;
};
}
}

View File

@ -50,6 +50,7 @@ namespace ext {
bool update( const void*, VkDeviceSize, bool = VK_DEFAULT_STAGE_BUFFERS ) const;
void destroy();
Buffer alias() const;
void aliasBuffer( const Buffer& );
};
struct UF_API Buffers {
@ -71,7 +72,13 @@ namespace ext {
inline bool updateBuffer( const void* data, VkDeviceSize length, size_t index = 0, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( data, length, buffers.at(index), stage ); }
// template<typename T> inline bool updateBuffer( const T* data, const Buffer& buffer, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( (const void*) data, static_cast<VkDeviceSize>(sizeof(T)), buffer, stage ); }
template<typename T> inline bool updateBuffer( const T& data, const Buffer& buffer, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( (const void*) &data, static_cast<VkDeviceSize>(sizeof(T)), buffer, stage ); }
// template<typename T> inline bool updateBuffer( const T& data, const Buffer& buffer, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( (const void*) &data, static_cast<VkDeviceSize>(sizeof(T)), buffer, stage ); }
};
struct AccelerationStructure {
VkAccelerationStructureKHR handle{VK_NULL_HANDLE};
size_t deviceAddress{};
size_t instanceID{};
};
}
}

View File

@ -55,7 +55,8 @@ namespace ext {
struct Metadata {
uf::Serializer json;
bool autoInitializeUniforms = true;
bool autoInitializeUniformBuffers = true;
bool autoInitializeUniformUserdatas = false;
uf::stl::unordered_map<uf::stl::string, size_t> shaders;
} metadata;
@ -85,23 +86,20 @@ namespace ext {
} metadata;
struct {
struct {
VkAccelerationStructureKHR handle;
size_t deviceAddress;
Buffer buffer;
} top, bottom;
uf::renderer::AccelerationStructure top;
uf::stl::vector<uf::renderer::AccelerationStructure> bottoms;
} accelerationStructures;
~Graphic();
void initialize( const uf::stl::string& = "" );
void destroy();
// template<typename T, typename U>
// void initializeMesh( uf::Mesh<T, U>& mesh );
// void initializeAttributes( const uf::Mesh::Attributes& mesh );
// raster
void initializeMesh( uf::Mesh& mesh, bool buffer = true );
bool updateMesh( uf::Mesh& mesh );
// raytrace
void generateBottomAccelerationStructures();
void generateTopAccelerationStructure( const uf::stl::vector<uf::renderer::Graphic*>&, const uf::stl::vector<pod::Instance>& );
bool hasPipeline( const GraphicDescriptor& descriptor ) const;
void initializePipeline();
@ -119,7 +117,4 @@ namespace ext {
void record( VkCommandBuffer commandBuffer, const GraphicDescriptor& descriptor, size_t pass = 0, size_t draw = 0 ) const;
};
}
}
#include "graphic.inl"
}

View File

@ -1,8 +0,0 @@
#if 0
template<typename T, typename U>
void ext::vulkan::Graphic::initializeMesh( uf::Mesh<T, U>& mesh, size_t o ) {
if ( mesh.indices.empty() ) mesh.initialize( o );
mesh.updateDescriptor();
initializeAttributes( mesh.attributes );
}
#endif

View File

@ -36,6 +36,7 @@ namespace ext {
uint8_t samples = 1;
uint8_t eyes = 1;
uint8_t views = 1;
bool compute = false;
} metadata;
Device* device = VK_NULL_HANDLE;

View File

@ -5,7 +5,7 @@
namespace ext {
namespace vulkan {
struct UF_API RayTraceRenderMode : public ext::vulkan::RenderMode {
struct UF_API ComputeRenderMode : public ext::vulkan::RenderMode {
ext::vulkan::Graphic blitter;
//

View File

@ -36,7 +36,8 @@ namespace ext {
uf::stl::string pipeline = "";
uf::stl::string type = "";
bool autoInitializeUniforms = true;
bool autoInitializeUniformBuffers = true;
bool autoInitializeUniformUserdatas = false;
struct Definition {
struct InOut {

View File

@ -117,7 +117,10 @@ namespace ext {
);
void fromBuffers( void* buffer, VkDeviceSize bufferSize, VkFormat format, uint32_t texWidth, uint32_t texHeight, uint32_t texDepth, uint32_t layers, Device& device, VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL );
void asRenderTarget( Device& device, uint32_t texWidth, uint32_t texHeight, VkFormat format = DefaultFormat );
Texture alias() const;
void aliasTexture( const Texture& );
void aliasAttachment( const RenderTarget::Attachment& attachment, bool = true );
void aliasAttachment( const RenderTarget::Attachment& attachment, size_t, bool = true );
@ -138,6 +141,7 @@ namespace ext {
static Texture2D empty;
Texture2D();
Texture2D alias() const;
uf::Image screenshot( uint32_t layer = 0 );
};
class UF_API Texture3D : public Texture {
@ -145,12 +149,15 @@ namespace ext {
static Texture3D empty;
Texture3D();
Texture3D alias() const;
uf::Image screenshot( uint32_t layer = 0 );
};
class UF_API TextureCube : public Texture {
public:
static TextureCube empty;
TextureCube();
TextureCube alias() const;
};
}
}

View File

@ -14,5 +14,5 @@
#define VK_CHECK_RESULT(f) { VkResult res = (f); if ( res != VK_SUCCESS ) UF_EXCEPTION(ext::vulkan::errorString( res )); }
#define VK_FLAGS_NONE 0
#define VK_DEFAULT_FENCE_TIMEOUT 5000000000
#define VK_DEFAULT_FENCE_TIMEOUT 100000000000
#define VK_DEFAULT_STAGE_BUFFERS 1

View File

@ -10,19 +10,6 @@
namespace ext {
namespace vulkan {
#if 1
extern UF_API PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
extern UF_API PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR;
extern UF_API PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR;
extern UF_API PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR;
extern UF_API PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
extern UF_API PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR;
extern UF_API PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR;
extern UF_API PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
extern UF_API PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
extern UF_API PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
#endif
VkResult CreateDebugUtilsMessengerEXT(
VkInstance instance,
const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
@ -43,6 +30,17 @@ namespace ext {
void* pUserData
);
extern UF_API PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
extern UF_API PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR;
extern UF_API PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR;
extern UF_API PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR;
extern UF_API PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
extern UF_API PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR;
extern UF_API PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR;
extern UF_API PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
extern UF_API PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
extern UF_API PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
uf::stl::string errorString( VkResult result );
VkSampleCountFlagBits sampleCount( uint8_t );
@ -89,6 +87,16 @@ namespace ext {
extern UF_API bool vxgi;
extern UF_API bool culling;
extern UF_API bool bloom;
extern UF_API bool rt;
namespace names {
extern UF_API uf::stl::string vsync;
extern UF_API uf::stl::string hdr;
extern UF_API uf::stl::string vxgi;
extern UF_API uf::stl::string culling;
extern UF_API uf::stl::string bloom;
extern UF_API uf::stl::string rt;
}
}
namespace formats {

View File

@ -45,6 +45,7 @@
#define UF_IO_COUT std::cout // uf::iostream
#define UF_IO_ENDL std::endl // "\r\n"
#define UF_IO_FMT(...) uf::io::fmt(__VA_ARGS__)
#define UF_MSG(Y, X) UF_IO_COUT << "[" << X << "] " << __FILE__ << ":" << __FUNCTION__ << "@" << __LINE__ << ": " << Y << UF_IO_ENDL;

View File

@ -4,7 +4,7 @@
#include <uf/ext/vulkan/graphic.h>
#include <uf/ext/vulkan/rendermodes/rendertarget.h>
#include <uf/ext/vulkan/rendermodes/deferred.h>
#include <uf/ext/vulkan/rendermodes/raytrace.h>
#include <uf/ext/vulkan/rendermodes/compute.h>
#include <uf/ext/vulkan/rendertarget.h>
namespace spec {

View File

@ -0,0 +1,46 @@
#pragma once
#include <uf/config.h>
#include "./allocator.h"
#include <map>
namespace uf {
namespace stl {
template<typename T, typename Key = uf::stl::string>
struct KeyMap {
public:
uf::stl::vector<Key> keys;
uf::stl::unordered_map<Key, T> map;
uf::stl::unordered_map<Key, size_t> indices;
T& operator[]( const Key& key );
void reserve( size_t i );
uf::stl::vector<T> flatten() const;
};
}
}
template<typename T, typename Key>
T& uf::stl::KeyMap<T,Key>::operator[]( const Key& key ) {
if ( map.count( key ) == 0 ) {
indices[key] = keys.size();
keys.emplace_back( key );
}
return map[key];
}
template<typename T, typename Key>
void uf::stl::KeyMap<T,Key>::reserve( size_t i ) {
keys.reserve(i);
indices.reserve(i);
map.reserve(i);
}
template<typename T, typename Key>
uf::stl::vector<T> uf::stl::KeyMap<T,Key>::flatten() const {
uf::stl::vector<T> res; res.reserve(keys.size());
for ( auto& key : keys ) res.emplace_back(map.at(key));
return res;
}

View File

@ -82,6 +82,26 @@ namespace pod {
} bounds;
};
struct UF_API InstanceAddresses {
alignas(8) uint64_t vertex{};
alignas(8) uint64_t index{};
alignas(8) uint64_t position{};
alignas(8) uint64_t uv{};
alignas(8) uint64_t color{};
alignas(8) uint64_t st{};
alignas(8) uint64_t normal{};
alignas(8) uint64_t tangent{};
alignas(8) uint64_t joints{};
alignas(8) uint64_t weights{};
alignas(8) uint64_t id{};
alignas(8) uint64_t padding{};
};
struct Primitive {
pod::DrawCommand drawCommand;
pod::Instance instance;
@ -152,7 +172,11 @@ namespace uf {
void destroy();
uf::Mesh convert() const;
uf::Mesh copy() const;
uf::Mesh copy(bool) const;
uf::Mesh interleave() const;
uf::Mesh deinterleave() const;
uf::Mesh expand();
uf::Mesh expand(bool);

View File

@ -104,7 +104,10 @@ pod::PointeredUserdata uf::pointeredUserdata::create( uf::MemoryPool& requestedM
#include <stdexcept>
template<typename T>
T& uf::pointeredUserdata::get( pod::PointeredUserdata& userdata, bool validate ) {
if ( validate && !uf::pointeredUserdata::is<T>( userdata ) ) UF_EXCEPTION("PointeredUserdata size|type mismatch"); // : Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata.type << ", " << userdata.len << "}" );
if ( validate && !uf::pointeredUserdata::is<T>( userdata ) ) {
UF_MSG_ERROR("Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata.type << ", " << userdata.len << "}" );
UF_EXCEPTION("PointeredUserdata size|type mismatch");
}
union {
void* original;
T* casted;
@ -114,7 +117,10 @@ T& uf::pointeredUserdata::get( pod::PointeredUserdata& userdata, bool validate )
}
template<typename T>
const T& uf::pointeredUserdata::get( const pod::PointeredUserdata& userdata, bool validate ) {
if ( validate && !uf::pointeredUserdata::is<T>( userdata ) ) UF_EXCEPTION("PointeredUserdata size|type mismatch"); // : Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata.type << ", " << userdata.len << "}" );
if ( validate && !uf::pointeredUserdata::is<T>( userdata ) ) {
UF_MSG_ERROR("Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata.type << ", " << userdata.len << "}" );
UF_EXCEPTION("PointeredUserdata size|type mismatch");
}
union {
const void* original;
const T* casted;

View File

@ -24,7 +24,10 @@ pod::Userdata* uf::userdata::create( uf::MemoryPool& requestedMemoryPool, const
#include <stdexcept>
template<typename T>
T& uf::userdata::get( pod::Userdata* userdata, bool validate ) {
if ( validate && !uf::userdata::is<T>( userdata ) ) UF_EXCEPTION("PointeredUserdata size|type mismatch"); // : Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata->type << ", " << userdata->len << "}" );
if ( validate && !uf::userdata::is<T>( userdata ) ) {
UF_MSG_ERROR("Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata->type << ", " << userdata->len << "}" );
UF_EXCEPTION("PointeredUserdata size|type mismatch");
}
union {
void* original;
T* casted;
@ -34,7 +37,10 @@ T& uf::userdata::get( pod::Userdata* userdata, bool validate ) {
}
template<typename T>
const T& uf::userdata::get( const pod::Userdata* userdata, bool validate ) {
if ( validate && !uf::userdata::is<T>( userdata ) ) UF_EXCEPTION("PointeredUserdata size|type mismatch"); // : Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata->type << ", " << userdata->len << "}" );
if ( validate && !uf::userdata::is<T>( userdata ) ) {
UF_MSG_ERROR("Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata->type << ", " << userdata->len << "}" );
UF_EXCEPTION("PointeredUserdata size|type mismatch");
}
union {
const void* original;
const T* casted;

View File

@ -88,12 +88,8 @@ namespace {
mesh.insertIndirects(drawCommands);
mesh.updateDescriptor();
graphic.initialize();
graphic.initializeMesh( mesh );
graphic.process = true;
uf::graph::initializeGraphics( graph, object );
uf::graph::initializeGraphics( graph, object, mesh );
}
}

View File

@ -258,9 +258,6 @@ namespace {
mesh.updateDescriptor();
// return mesh.expand();
// if ( mesh.isInterleaved() != uf::Mesh::defaultInterleaved ) return mesh.copy(true);
return mesh;
}

View File

@ -62,12 +62,14 @@ pod::Node* uf::graph::find( pod::Graph& graph, const uf::stl::string& name ) {
return NULL;
}
void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::Mesh& mesh ) {
auto& scene = uf::scene::getCurrentScene();
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
auto& graphic = entity.getComponent<uf::Graphic>();
auto& graphic = entity.getComponent<uf::renderer::Graphic>();
graphic.initialize();
graphic.initializeMesh( mesh );
graphic.device = &uf::renderer::device;
graphic.material.device = &uf::renderer::device;
@ -127,10 +129,10 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root );
}
{
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.metadata.autoInitializeUniformBuffers = false;
graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT);
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.metadata.autoInitializeUniformBuffers = true;
}
uf::renderer::Buffer* indirect = NULL;
@ -139,13 +141,13 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
{
auto& shader = graphic.material.getShader("vertex");
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
// // shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands );
shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() );
// // shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() );
#if UF_USE_VULKAN
shader.buffers.emplace_back().aliasBuffer( *indirect );
shader.buffers.emplace_back( indirect->alias() );
#endif
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() );
#if UF_USE_VULKAN
uint32_t maxPasses = 6;
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
@ -158,10 +160,10 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
{
auto& shader = graphic.material.getShader("fragment");
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
#if UF_USE_VULKAN
uint32_t maxTextures = graph.textures.size(); // texture2Ds;
@ -189,20 +191,20 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
if ( indirect ) {
uf::stl::string compShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/cull.comp.spv");
{
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.metadata.autoInitializeUniformBuffers = false;
compShaderFilename = entity.resolveURI( compShaderFilename, root );
graphic.material.attachShader(compShaderFilename, uf::renderer::enums::Shader::COMPUTE, "culling");
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.attachShader(compShaderFilename, uf::renderer::enums::Shader::COMPUTE, uf::renderer::settings::pipelines::names::culling);
graphic.material.metadata.autoInitializeUniformBuffers = true;
}
graphic.descriptor.inputs.dispatch = { graphic.descriptor.inputs.indirect.count, 1, 1 };
auto& shader = graphic.material.getShader("compute", "culling");
auto& shader = graphic.material.getShader("compute", uf::renderer::settings::pipelines::names::culling);
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() );
#if UF_USE_VULKAN
shader.buffers.emplace_back().aliasBuffer( *indirect );
shader.buffers.emplace_back( indirect->alias() );
#endif
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
}
}
if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) {
@ -211,11 +213,11 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
}
// depth only pipeline
{
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.metadata.autoInitializeUniformBuffers = false;
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/depth.frag.spv");
fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root );
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "depth");
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.metadata.autoInitializeUniformBuffers = true;
{
uint32_t maxTextures = graph.textures.size(); // texture2Ds;
@ -233,10 +235,10 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
}
}
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
}
}
// vxgi pipeline
@ -247,13 +249,13 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
{
fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root );
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "vxgi");
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.metadata.autoInitializeUniformBuffers = false;
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, uf::renderer::settings::pipelines::names::vxgi);
graphic.material.metadata.autoInitializeUniformBuffers = true;
}
if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) {
geometryShaderFilename = entity.resolveURI( geometryShaderFilename, root );
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "vxgi");
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, uf::renderer::settings::pipelines::names::vxgi);
}
{
uint32_t voxelTypes = 0;
@ -266,7 +268,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
uint32_t maxTextures = texture2Ds;
uint32_t maxCascades = texture3Ds / voxelTypes;
auto& shader = graphic.material.getShader("fragment", "vxgi");
auto& shader = graphic.material.getShader("fragment", uf::renderer::settings::pipelines::names::vxgi);
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
@ -285,23 +287,23 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
}
}
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
}
}
// baking pipeline
if ( graph.metadata["baking"]["enabled"].as<bool>() ) {
{
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.metadata.autoInitializeUniformBuffers = false;
uf::stl::string vertexShaderFilename = uf::io::resolveURI("/graph/baking/bake.vert.spv");
uf::stl::string geometryShaderFilename = uf::io::resolveURI("/graph/baking/bake.geom.spv");
uf::stl::string fragmentShaderFilename = uf::io::resolveURI("/graph/baking/bake.frag.spv");
graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "baking");
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking");
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "baking");
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.metadata.autoInitializeUniformBuffers = true;
}
{
uint32_t maxPasses = 6;
@ -313,13 +315,13 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
if ( sc.name == "PASSES" ) sc.value.ui = (specializationConstants[sc.index] = maxPasses);
}
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands );
// shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() );
// shader.buffers.emplace_back( uf::graph::storage.buffers.drawCommands.alias() );
#if UF_USE_VULKAN
shader.buffers.emplace_back().aliasBuffer( *indirect );
shader.buffers.emplace_back( indirect->alias() );
#endif
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() );
}
{
@ -343,16 +345,54 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
}
}
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
}
}
// rt pipeline
if ( uf::renderer::settings::pipelines::rt ) {
graphic.generateBottomAccelerationStructures();
}
// grab addresses
{
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer( mesh.indirect ).data();
for ( size_t i = 0; i < mesh.indirect.count; ++i ) {
auto instanceID = drawCommands[i].instanceID;
auto instanceKeyName = std::to_string(instanceID);
auto& instanceAddresses = uf::graph::storage.instanceAddresses.map[instanceKeyName];
if ( mesh.vertex.count ) {
if ( mesh.isInterleaved( mesh.vertex ) ) {
instanceAddresses.vertex = graphic.buffers.at(graphic.descriptor.inputs.vertex.interleaved).getAddress();
} else {
for ( auto& attribute : graphic.descriptor.inputs.vertex.attributes ) {
if ( attribute.buffer < 0 ) continue;
if ( attribute.descriptor.name == "position" ) instanceAddresses.position = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "uv" ) instanceAddresses.uv = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "color" ) instanceAddresses.color = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "st" ) instanceAddresses.st = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "normal" ) instanceAddresses.normal = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "tangent" ) instanceAddresses.tangent = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "joints" ) instanceAddresses.joints = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "weights" ) instanceAddresses.weights = graphic.buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "id" ) instanceAddresses.id = graphic.buffers.at(attribute.buffer).getAddress();
}
}
}
if ( mesh.index.count ) {
if ( mesh.isInterleaved( mesh.index ) ) instanceAddresses.index = graphic.buffers.at(graphic.descriptor.inputs.index.interleaved).getAddress();
else instanceAddresses.index = graphic.buffers.at(graphic.descriptor.inputs.index.attributes.front().buffer).getAddress();
}
}
}
#endif
// uf::instantiator::bind( "GraphBehavior", entity );
// uf::instantiator::unbind( "RenderBehavior", entity );
graphic.process = true;
}
void uf::graph::process( pod::Graph& graph ) {
@ -653,21 +693,30 @@ void uf::graph::process( pod::Graph& graph ) {
mesh.insertIndirects( drawCommands );
}
// slice mesh
{
// auto slices = uf::meshgrid::partition( mesh, 1 );
// uf::meshgrid::print( slices, mesh.index.count );
auto& graphic = graph.root.entity->getComponent<uf::renderer::Graphic>();
uf::graph::initializeGraphics( graph, *graph.root.entity, mesh );
/*
if ( uf::renderer::settings::pipelines::rt ) {
uf::stl::vector<uf::renderer::Graphic*> graphics = { &graphic };
graphic.generateTopAccelerationStructure( graphics, uf::graph::storage.instances.flatten() );
}
*/
}
} else if ( uf::renderer::settings::pipelines::rt ) {
/*
auto& graphic = graph.root.entity->getComponent<uf::renderer::Graphic>();
graphic.initialize("Compute");
{
auto& graphic = graph.root.entity->getComponent<uf::Graphic>();
graphic.initialize();
graphic.initializeMesh( mesh );
graphic.process = true;
uf::graph::initializeGraphics( graph, *graph.root.entity );
uf::stl::vector<uf::renderer::Graphic*> graphics;
for ( auto& node : graph.nodes ) {
if ( !node.entity || !node.entity->hasComponent<uf::renderer::Graphic>() ) continue;
graphics.emplace_back(node.entity->getComponentPointer<uf::renderer::Graphic>());
}
graphic.generateTopAccelerationStructure( graphics, uf::graph::storage.instances.flatten() );
*/
}
}
void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) {
auto& node = graph.nodes[index];
@ -843,14 +892,8 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
}
}
if ( (graph.metadata["flags"]["SEPARATE"].as<bool>()) && graph.metadata["flags"]["RENDER"].as<bool>() ) {
// uf::instantiator::bind("RenderBehavior", entity);
auto& graphic = entity.getComponent<uf::Graphic>();
graphic.initialize();
graphic.initializeMesh( mesh );
graphic.process = true;
uf::graph::initializeGraphics( graph, entity );
// uf::instantiator::bind("RenderBehavior", entity);
uf::graph::initializeGraphics( graph, entity, mesh );
}
{
@ -940,7 +983,7 @@ void uf::graph::initialize( pod::Graph& graph ) {
if ( entity->getUid() == 0 ) entity->initialize();
/*
//UF_MSG_DEBUG( "Initializing... " << uf::string::toString( entity->as<uf::Object>() ) );
if ( !entity->hasComponent<uf::Graphic>() ) {
if ( !entity->hasComponent<uf::renderer::Graphic>() ) {
if ( entity->getUid() == 0 ) entity->initialize();
//UF_MSG_DEBUG( "Initialized " << uf::string::toString( entity->as<uf::Object>() ) );
return;
@ -1077,17 +1120,14 @@ void uf::graph::update( pod::Graph& graph, pod::Node& node ) {
}
void uf::graph::destroy( pod::Graph& graph ) {
#if 0
for ( auto& t : graph.textures ) {
t.texture.destroy();
}
for ( auto& m : graph.meshes ) {
m.destroy();
}
for ( auto& t : graph.textures ) t.texture.destroy();
for ( auto& m : graph.meshes ) m.destroy();
#endif
uf::graph::storage.buffers.camera.destroy();
uf::graph::storage.buffers.drawCommands.destroy();
uf::graph::storage.buffers.instance.destroy();
uf::graph::storage.buffers.instanceAddresses.destroy();
uf::graph::storage.buffers.joint.destroy();
uf::graph::storage.buffers.material.destroy();
uf::graph::storage.buffers.texture.destroy();
@ -1103,49 +1143,56 @@ void uf::graph::initialize() {
uf::graph::storage.buffers.camera.initialize( (const void*) nullptr, sizeof(pod::Camera::Viewports), uf::renderer::enums::Buffer::UNIFORM );
uf::graph::storage.buffers.drawCommands.initialize( (const void*) nullptr, sizeof(pod::DrawCommand) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
uf::graph::storage.buffers.instance.initialize( (const void*) nullptr, sizeof(pod::Instance) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
uf::graph::storage.buffers.instanceAddresses.initialize( (const void*) nullptr, sizeof(pod::InstanceAddresses) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
uf::graph::storage.buffers.joint.initialize( (const void*) nullptr, sizeof(pod::Matrix4f) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
uf::graph::storage.buffers.material.initialize( (const void*) nullptr, sizeof(pod::Material) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
uf::graph::storage.buffers.texture.initialize( (const void*) nullptr, sizeof(pod::Texture) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
uf::graph::storage.buffers.light.initialize( (const void*) nullptr, sizeof(pod::Light) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE );
}
void uf::graph::tick() {
/*
uf::stl::vector<pod::Instance> instances; instances.reserve(uf::graph::storage.instances.map.size());
for ( auto key : uf::graph::storage.instances.keys ) instances.emplace_back( uf::graph::storage.instances.map[key] );
for ( auto& key : uf::graph::storage.instances.keys ) instances.emplace_back( uf::graph::storage.instances.map[key] );
if ( !instances.empty() ) uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) );
*/
uf::stl::vector<pod::Instance> instances = uf::graph::storage.instances.flatten();
uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) );
/*
uf::stl::vector<pod::InstanceAddresses> instanceAddresses; instanceAddresses.reserve(uf::graph::storage.instanceAddresses.map.size());
for ( auto& key : uf::graph::storage.instances.keys ) instanceAddresses.emplace_back( uf::graph::storage.instanceAddresses.map[key] );
if ( !instanceAddresses.empty() ) uf::graph::storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::InstanceAddresses) );
*/
uf::stl::vector<pod::InstanceAddresses> instanceAddresses = uf::graph::storage.instanceAddresses.flatten();
uf::graph::storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::InstanceAddresses) );
uf::stl::vector<pod::Matrix4f> joints; joints.reserve(uf::graph::storage.joints.map.size());
for ( auto key : uf::graph::storage.joints.keys ) {
auto& matrices = uf::graph::storage.joints[key];
for ( auto& key : uf::graph::storage.joints.keys ) {
auto& matrices = uf::graph::storage.joints.map[key];
joints.reserve( joints.size() + matrices.size() );
for ( auto& mat : matrices ) joints.emplace_back( mat );
}
if ( !joints.empty() ) uf::graph::storage.buffers.joint.update( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f) );
/*if ( !joints.empty() )*/ uf::graph::storage.buffers.joint.update( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f) );
if ( ::newGraphAdded ) {
#if 1
uf::stl::vector<pod::Material> materials = uf::graph::storage.materials.flatten();
uf::stl::vector<pod::Texture> textures = uf::graph::storage.textures.flatten();
uf::stl::vector<pod::DrawCommand> drawCommands; drawCommands.reserve(uf::graph::storage.drawCommands.map.size());
for ( auto& key : uf::graph::storage.drawCommands.keys ) drawCommands.insert( drawCommands.end(), uf::graph::storage.drawCommands.map[key].begin(), uf::graph::storage.drawCommands.map[key].end() );
#else
uf::stl::vector<pod::DrawCommand> drawCommands; drawCommands.reserve(uf::graph::storage.drawCommands.map.size());
uf::stl::vector<pod::Material> materials; materials.reserve(uf::graph::storage.materials.map.size());
uf::stl::vector<pod::Texture> textures; textures.reserve(uf::graph::storage.textures.map.size());
for ( auto key : uf::graph::storage.drawCommands.keys ) drawCommands.insert( drawCommands.end(), uf::graph::storage.drawCommands.map[key].begin(), uf::graph::storage.drawCommands.map[key].end() );
#if 1
for ( auto key : uf::graph::storage.materials.keys ) materials.emplace_back( uf::graph::storage.materials.map[key] );
for ( auto key : uf::graph::storage.textures.keys ) textures.emplace_back( uf::graph::storage.textures.map[key] );
#else
uf::stl::map<size_t, uf::stl::string> materialOrderedMap; // materialOrderedMap.reserve( uf::graph::storage.materials.keys.size() );
for ( auto key : uf::graph::storage.materials.keys ) {
materialOrderedMap[uf::graph::storage.materials.indices[key]] = key;
}
for ( auto pair : materialOrderedMap ) materials.emplace_back( uf::graph::storage.materials.map[pair.second] );
uf::stl::map<size_t, uf::stl::string> textureOrderedMap; // textureOrderedMap.reserve( uf::graph::storage.textures.keys.size() );
for ( auto key : uf::graph::storage.textures.keys ) {
textureOrderedMap[uf::graph::storage.textures.indices[key]] = key;
}
for ( auto pair : textureOrderedMap ) textures.emplace_back( uf::graph::storage.textures.map[pair.second] );
for ( auto& key : uf::graph::storage.drawCommands.keys ) drawCommands.insert( drawCommands.end(), uf::graph::storage.drawCommands.map[key].begin(), uf::graph::storage.drawCommands.map[key].end() );
for ( auto& key : uf::graph::storage.materials.keys ) materials.emplace_back( uf::graph::storage.materials.map[key] );
for ( auto& key : uf::graph::storage.textures.keys ) textures.emplace_back( uf::graph::storage.textures.map[key] );
#endif
uf::graph::storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) );
uf::graph::storage.buffers.material.update( (const void*) materials.data(), materials.size() * sizeof(pod::Material) );
uf::graph::storage.buffers.texture.update( (const void*) textures.data(), textures.size() * sizeof(pod::Texture) );
::newGraphAdded = false;
}
}

View File

@ -99,11 +99,10 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::stl::str
uf::Scene* scene = uf::instantiator::objects->has( name ) ? (uf::Scene*) &uf::instantiator::instantiate( name ) : new uf::Scene;
uf::scene::scenes.emplace_back( scene );
const uf::stl::string filename = _filename != "" ? _filename : ("/" + uf::string::lowercase(name) + "/scene.json");
const uf::stl::string filename = _filename != "" ? _filename : (uf::stl::string("/") + uf::string::lowercase(name) + "/scene.json");
scene->load(filename);
if ( uf::renderer::settings::pipelines::vxgi ) {
uf::instantiator::bind( "VoxelizerBehavior", *scene );
}
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
if ( uf::renderer::settings::pipelines::rt ) uf::instantiator::bind( "RayTraceSceneBehavior", *scene );
scene->initialize();
return *scene;
}
@ -111,9 +110,8 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::Serializ
uf::Scene* scene = uf::instantiator::objects->has( name ) ? (uf::Scene*) &uf::instantiator::instantiate( name ) : new uf::Scene;
uf::scene::scenes.emplace_back( scene );
if ( data != "" ) scene->load(data);
if ( uf::renderer::settings::pipelines::vxgi ) {
uf::instantiator::bind( "VoxelizerBehavior", *scene );
}
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
if ( uf::renderer::settings::pipelines::rt ) uf::instantiator::bind( "RayTraceSceneBehavior", *scene );
scene->initialize();
return *scene;
}

View File

@ -83,12 +83,12 @@ namespace {
graphic.material.device = &uf::renderer::device;
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.metadata.autoInitializeUniformBuffers = false;
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.vert.spv", uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.metadata.autoInitializeUniformBuffers = true;
graphic.material.getShader("vertex").buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
graphic.material.getShader("vertex").buffers.emplace_back( uf::graph::storage.buffers.camera.alias() );
graphic.initialize(ext::bullet::debugDrawLayer);
graphic.initializeMesh( mesh );

View File

@ -139,6 +139,13 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
return graph;
}
#if 0
if ( !uf::Mesh::defaultInterleaved ) {
uf::Mesh::defaultInterleaved = true;
UF_MSG_INFO("loading gltf file, defaulting to de-interleaved meshes (makes things easier)");
}
#endif
// load images
{
graph.images.reserve(model.images.size());

View File

@ -186,7 +186,7 @@ if ( meshgrid.grid.divisions.x > 1 || meshgrid.grid.divisions.y > 1 || meshgrid.
size_t vertexID = 0;
mesh.bindIndirect<pod::DrawCommand>();
mesh.bind<UF_GRAPH_MESH_FORMAT>();
mesh.bind<UF_GRAPH_MESH_FORMAT>(false); // default to de-interleaved regardless of requirement (makes things easier)
for ( auto& meshlet : meshlets ) {
auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{

View File

@ -6,6 +6,11 @@
#include <uf/ext/opengl/opengl.h>
#include <uf/ext/opengl/device.h>
ext::opengl::Buffer ext::opengl::Buffer::alias() const {
ext::opengl::Buffer buffer;
buffer.aliasBuffer(*this);
return buffer;
}
void ext::opengl::Buffer::aliasBuffer( const ext::opengl::Buffer& buffer ) {
*this = {
.device = NULL,

View File

@ -133,7 +133,8 @@ void ext::opengl::Material::destroy() {
}
void ext::opengl::Material::attachShader( const uf::stl::string& filename, enums::Shader::type_t stage, const uf::stl::string& pipeline ) {
auto& shader = shaders.emplace_back();
shader.metadata.autoInitializeUniforms = metadata.autoInitializeUniforms;
shader.metadata.autoInitializeUniformBuffers = metadata.autoInitializeUniformBuffers;
shader.metadata.autoInitializeUniformUserdatas = metadata.autoInitializeUniformUserdatas;
shader.initialize( *device, filename, stage );
uf::stl::string type = "unknown";

View File

@ -53,6 +53,14 @@ bool ext::opengl::settings::pipelines::hdr = false;
bool ext::opengl::settings::pipelines::vxgi = false;
bool ext::opengl::settings::pipelines::culling = false;
bool ext::opengl::settings::pipelines::bloom = false;
bool ext::opengl::settings::pipelines::rt = false;
uf::stl::string ext::opengl::settings::pipelines::names::vsync = "vsync";
uf::stl::string ext::opengl::settings::pipelines::names::hdr = "hdr";
uf::stl::string ext::opengl::settings::pipelines::names::vxgi = "vxgi";
uf::stl::string ext::opengl::settings::pipelines::names::culling = "culling";
uf::stl::string ext::opengl::settings::pipelines::names::bloom = "bloom";
uf::stl::string ext::opengl::settings::pipelines::names::rt = "rt";
GLhandle(VkColorSpaceKHR) ext::opengl::settings::formats::colorSpace;
ext::opengl::enums::Format::type_t ext::opengl::settings::formats::color = ext::opengl::enums::Format::R8G8B8A8_UNORM;

View File

@ -35,11 +35,11 @@ uf::stl::vector<ext::opengl::Graphic*> ext::opengl::RenderTargetRenderMode::getB
ext::opengl::GraphicDescriptor ext::opengl::RenderTargetRenderMode::bindGraphicDescriptor( const ext::opengl::GraphicDescriptor& reference, size_t pass ) {
ext::opengl::GraphicDescriptor descriptor = ext::opengl::RenderMode::bindGraphicDescriptor(reference, pass);
descriptor.parse(metadata.json["descriptor"]);
if ( 0 <= pass && pass < metadata.subpasses && metadata.type == "vxgi" ) {
if ( 0 <= pass && pass < metadata.subpasses && metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
// descriptor.cullMode = GL_CULL_MODE_NONE;
descriptor.depth.test = false;
descriptor.depth.write = false;
descriptor.pipeline = "vxgi";
descriptor.pipeline = uf::renderer::settings::pipelines::names::vxgi;
} else if ( metadata.type == "depth" ) {
// descriptor.cullMode = GL_CULL_MODE_NONE;
}

View File

@ -81,7 +81,7 @@ void ext::opengl::Shader::initialize( ext::opengl::Device& device, const uf::stl
module = ::modules[filename];
}
}
if ( metadata.autoInitializeUniforms ) {
if ( metadata.autoInitializeUniformBuffers ) {
initializeBuffer( nullptr, sizeof(pod::Uniform), uf::renderer::enums::Buffer::UNIFORM );
}
#endif

View File

@ -254,6 +254,11 @@ void ext::opengl::Texture::fromBuffers(
void ext::opengl::Texture::asRenderTarget( Device& device, uint32_t width, uint32_t height, enums::Format::type_t format ) {
}
ext::opengl::Texture ext::opengl::Texture::alias() const {
ext::opengl::Texture texture;
texture.aliasTexture(*this);
return texture;
}
void ext::opengl::Texture::aliasTexture( const Texture& texture ) {
image = texture.image;
type = texture.type;
@ -339,4 +344,20 @@ ext::opengl::TextureCube::TextureCube() {
viewType = enums::Image::VIEW_TYPE_CUBE;
}
ext::opengl::Texture2D ext::opengl::Texture2D::alias() const {
ext::opengl::Texture2D texture;
texture.aliasTexture(*this);
return texture;
}
ext::opengl::Texture3D ext::opengl::Texture3D::alias() const {
ext::opengl::Texture3D texture;
texture.aliasTexture(*this);
return texture;
}
ext::opengl::TextureCube ext::opengl::TextureCube::alias() const {
ext::opengl::TextureCube texture;
texture.aliasTexture(*this);
return texture;
}
#endif

View File

@ -160,12 +160,12 @@ namespace {
graphic.material.device = &uf::renderer::device;
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.metadata.autoInitializeUniformBuffers = false;
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.vert.spv", uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.metadata.autoInitializeUniformBuffers = true;
graphic.material.getShader("vertex").buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
graphic.material.getShader("vertex").buffers.emplace_back( uf::graph::storage.buffers.camera.alias() );
graphic.initialize(ext::reactphysics::debugDraw::layer);
graphic.initializeMesh( mesh );

View File

@ -7,21 +7,12 @@
#include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/device.h>
ext::vulkan::Buffer ext::vulkan::Buffer::alias() const {
ext::vulkan::Buffer buffer;
buffer.aliasBuffer(*this);
return buffer;
}
void ext::vulkan::Buffer::aliasBuffer( const ext::vulkan::Buffer& buffer ) {
/*
*this = {
.device = NULL,
.buffer = buffer.buffer,
.memory = buffer.memory,
.descriptor = buffer.descriptor,
.alignment = buffer.alignment,
.mapped = buffer.mapped,
.usage = buffer.usage,
.memoryProperties = buffer.memoryProperties,
.allocation = buffer.allocation,
.allocationInfo = buffer.allocationInfo,
};
*/
this->aliased = true;
this->device = buffer.device;
this->buffer = buffer.buffer;

View File

@ -436,10 +436,10 @@ VkCommandBuffer ext::vulkan::Device::createCommandBuffer( VkCommandBufferLevel l
return commandBuffer;
}
void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, bool free ) {
return flushCommandBuffer( commandBuffer, QueueEnum::TRANSFER, free );
void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, bool wait ) {
return flushCommandBuffer( commandBuffer, QueueEnum::TRANSFER, wait );
}
void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, QueueEnum queue, bool free ) {
void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, QueueEnum queueType, bool wait ) {
if ( commandBuffer == VK_NULL_HANDLE ) return;
VK_CHECK_RESULT( vkEndCommandBuffer( commandBuffer ) );
@ -448,14 +448,12 @@ void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, Que
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
// Create fence to ensure that the command buffer has finished executing
VkFenceCreateInfo fenceInfo = ext::vulkan::initializers::fenceCreateInfo(VK_FLAGS_NONE);
VkFence fence;
VK_CHECK_RESULT(vkCreateFence(logicalDevice, &fenceInfo, nullptr, &fence));
VK_CHECK_RESULT(vkQueueSubmit( getQueue( queue ), 1, &submitInfo, fence));
VK_CHECK_RESULT(vkWaitForFences(logicalDevice, 1, &fence, VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT));
vkDestroyFence(logicalDevice, fence, nullptr);
if ( free ) vkFreeCommandBuffers(logicalDevice, getCommandPool( queue ), 1, &commandBuffer);
auto& queue = getQueue( queueType );
VK_CHECK_RESULT(vkQueueSubmit( queue, 1, &submitInfo, VK_NULL_HANDLE));
if ( wait ) {
VK_CHECK_RESULT(vkQueueWaitIdle( queue ));
vkFreeCommandBuffers(logicalDevice, getCommandPool( queueType ), 1, &commandBuffer);
}
}
#if 0
VkResult ext::vulkan::Device::createBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, VkDeviceSize size, VkBuffer* buffer, VkDeviceMemory* memory, const void* data ) {
@ -792,7 +790,7 @@ void ext::vulkan::Device::initialize() {
// Create logical device
{
bool useSwapChain = true;
VkQueueFlags requestedQueueTypes = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT; // | VK_QUEUE_TRANSFER_BIT;
VkQueueFlags requestedQueueTypes = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT;
uf::stl::vector<uf::stl::string> requestedExtensions;
requestedExtensions.insert( requestedExtensions.end(), ext::vulkan::settings::requestedDeviceExtensions.begin(), ext::vulkan::settings::requestedDeviceExtensions.end() );
#if UF_USE_OPENVR
@ -939,6 +937,7 @@ void ext::vulkan::Device::initialize() {
{
accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
accelerationStructureFeatures.accelerationStructure = VK_TRUE;
// accelerationStructureFeatures.accelerationStructureHostCommands = VK_TRUE;
}
deviceCreateInfo.pNext = &physicalDeviceFeatures2;

View File

@ -19,6 +19,17 @@ namespace {
uint32_t VERTEX_BUFFER_BIND_ID = 0;
}
PFN_vkGetBufferDeviceAddressKHR ext::vulkan::vkGetBufferDeviceAddressKHR = NULL; // = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR"));
PFN_vkCmdBuildAccelerationStructuresKHR ext::vulkan::vkCmdBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast<PFN_vkCmdBuildAccelerationStructuresKHR>(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR"));
PFN_vkBuildAccelerationStructuresKHR ext::vulkan::vkBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast<PFN_vkBuildAccelerationStructuresKHR>(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR"));
PFN_vkCreateAccelerationStructureKHR ext::vulkan::vkCreateAccelerationStructureKHR = NULL; // = reinterpret_cast<PFN_vkCreateAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR"));
PFN_vkDestroyAccelerationStructureKHR ext::vulkan::vkDestroyAccelerationStructureKHR = NULL; // = reinterpret_cast<PFN_vkDestroyAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR"));
PFN_vkGetAccelerationStructureBuildSizesKHR ext::vulkan::vkGetAccelerationStructureBuildSizesKHR = NULL; // = reinterpret_cast<PFN_vkGetAccelerationStructureBuildSizesKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureBuildSizesKHR"));
PFN_vkGetAccelerationStructureDeviceAddressKHR ext::vulkan::vkGetAccelerationStructureDeviceAddressKHR = NULL; // = reinterpret_cast<PFN_vkGetAccelerationStructureDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR"));
PFN_vkCmdTraceRaysKHR ext::vulkan::vkCmdTraceRaysKHR = NULL; // = reinterpret_cast<PFN_vkCmdTraceRaysKHR>(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR"));
PFN_vkGetRayTracingShaderGroupHandlesKHR ext::vulkan::vkGetRayTracingShaderGroupHandlesKHR = NULL; // = reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesKHR>(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR"));
PFN_vkCreateRayTracingPipelinesKHR ext::vulkan::vkCreateRayTracingPipelinesKHR = NULL; // = reinterpret_cast<PFN_vkCreateRayTracingPipelinesKHR>(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR"));
void ext::vulkan::Pipeline::initialize( const Graphic& graphic ) {
return this->initialize( graphic, graphic.descriptor );
}
@ -104,7 +115,13 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
{
uf::stl::vector<VkRayTracingShaderGroupCreateInfoKHR> shaderGroups;
for ( auto* shader : shaders ) {
if ( shader->descriptor.stage != VK_SHADER_STAGE_RAYGEN_BIT_KHR && shader->descriptor.stage != VK_SHADER_STAGE_MISS_BIT_KHR && shader->descriptor.stage != VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ) continue;
if (!(
shader->descriptor.stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_MISS_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR
)) continue;
size_t shaderID = static_cast<uint32_t>(shaderDescriptors.size());
bool isHit = shader->descriptor.stage & (VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
@ -156,9 +173,9 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
size_t rayhitBufferIndex = initializeBuffer((const void*) (shaderHandleStorage.data() + handleSizeAligned * 2), handleSize, bufferUsageFlags);
requestedAlignment = 0;
Buffer raygenBuffer; raygenBuffer.aliasBuffer( buffers[raygenBufferIndex] );
Buffer raymissBuffer; raymissBuffer.aliasBuffer( buffers[raymissBufferIndex] );
Buffer rayhitBuffer; rayhitBuffer.aliasBuffer( buffers[rayhitBufferIndex] );
Buffer raygenBuffer = buffers[raygenBufferIndex].alias();
Buffer raymissBuffer = buffers[raymissBufferIndex].alias();
Buffer rayhitBuffer = buffers[rayhitBufferIndex].alias();
auto& raygenShaderSbtEntry = sbtEntries.emplace_back();
raygenShaderSbtEntry.deviceAddress = raygenBuffer.getAddress();
@ -374,9 +391,13 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescrip
auto shaders = getShaders( graphic.material.shaders );
for ( auto* shader : shaders ) {
if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
if ( shader->descriptor.stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR ) bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
if ( shader->descriptor.stage == VK_SHADER_STAGE_MISS_BIT_KHR ) bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
if ( shader->descriptor.stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ) bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
if (
shader->descriptor.stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_MISS_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR
) bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
#if 1
if ( shader->metadata.definitions.pushConstants.count("PushConstant") > 0 ) {
if ( shader->descriptor.stage == VK_SHADER_STAGE_VERTEX_BIT || shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT || shader->descriptor.stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR ) {
@ -404,7 +425,8 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescrip
vkCmdBindPipeline(commandBuffer, bindPoint, pipeline);
if ( bindPoint == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR ) {
vkCmdTraceRaysKHR(
UF_MSG_DEBUG("vkCmdTraceRaysKHR");
uf::renderer::vkCmdTraceRaysKHR(
commandBuffer,
&sbtEntries[0],
&sbtEntries[1],
@ -841,7 +863,8 @@ void ext::vulkan::Material::destroy() {
void ext::vulkan::Material::attachShader( const uf::stl::string& filename, VkShaderStageFlagBits stage, const uf::stl::string& pipeline ) {
auto& shader = shaders.emplace_back();
shader.metadata.json = metadata.json["shader"];
shader.metadata.autoInitializeUniforms = metadata.autoInitializeUniforms;
shader.metadata.autoInitializeUniformBuffers = metadata.autoInitializeUniformBuffers;
shader.metadata.autoInitializeUniformUserdatas = metadata.autoInitializeUniformUserdatas;
shader.initialize( *device, filename, stage );
// repoint our specialization info descriptor because our shaders will change memory locations when attaching one by one
@ -943,6 +966,14 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
// ensure our descriptors are proper
mesh.updateDescriptor();
#if 0
// it makes my life 10000x easier if we interleave a mesh while also requesting RT pipelines
if ( !mesh.isInterleaved() && uf::renderer::settings::pipelines::rt ) {
auto interleaved = mesh.interleave();
return initializeMesh(interleaved);
}
#endif
// copy descriptors
descriptor.inputs.vertex = mesh.vertex;
descriptor.inputs.index = mesh.index;
@ -958,29 +989,39 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
VkBufferUsageFlags usage;
};
uf::stl::vector<Queue> queue;
descriptor.inputs.bufferOffset = buffers.empty() ? 0 : buffers.size() - 1;
descriptor.inputs.bufferOffset = buffers.size(); // buffers.empty() ? 0 : buffers.size() - 1;
VkBufferUsageFlags baseUsage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR;
/*
#define PARSE_ATTRIBUTE(i, usage) {\
auto& buffer = mesh.buffers[i];\
if ( queue.size() <= i ) queue.resize( i );\
if ( !buffer.empty() ) queue.emplace_back(Queue{ (void*) buffer.data(), buffer.size(), usage | baseUsage });\
}
#define PARSE_INPUT(name, usage){\
if ( mesh.isInterleaved( mesh.name.interleaved ) ) PARSE_ATTRIBUTE(descriptor.inputs.name.interleaved, usage | baseUsage)\
else for ( auto& attribute : descriptor.inputs.name.attributes ) PARSE_ATTRIBUTE(attribute.buffer, usage | baseUsage)\
}
*/
#define PARSE_INPUT(name, usage){\
if ( mesh.isInterleaved( mesh.name.interleaved ) ) {\
auto& buffer = mesh.buffers[mesh.name.interleaved];\
if ( !buffer.empty() ) mesh.name.interleaved = initializeBuffer( (const void*) buffer.data(), buffer.size(), usage | baseUsage );\
else mesh.name.interleaved = -1;\
} else for ( auto& attribute : descriptor.inputs.name.attributes ) {\
auto& buffer = mesh.buffers[attribute.buffer];\
if ( !buffer.empty() ) attribute.buffer = initializeBuffer( (const void*) buffer.data(), buffer.size(), usage | baseUsage );\
else attribute.buffer = -1;\
}\
}
// allocate buffers
auto previousRequestedAlignment = this->requestedAlignment;
this->requestedAlignment = 16;
PARSE_INPUT(vertex, uf::renderer::enums::Buffer::VERTEX)
PARSE_INPUT(index, uf::renderer::enums::Buffer::INDEX)
PARSE_INPUT(instance, uf::renderer::enums::Buffer::VERTEX)
PARSE_INPUT(indirect, uf::renderer::enums::Buffer::INDIRECT | uf::renderer::enums::Buffer::STORAGE)
// allocate buffers
for ( auto i = 0; i < queue.size(); ++i ) {
auto& q = queue[i];
initializeBuffer( q.data, q.size, q.usage );
}
// for ( auto& q : queue ) initializeBuffer( q.data, q.size, q.usage );
this->requestedAlignment = previousRequestedAlignment;
}
if ( mesh.instance.count == 0 && mesh.instance.attributes.empty() ) {
@ -988,6 +1029,9 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
}
}
bool ext::vulkan::Graphic::updateMesh( uf::Mesh& mesh ) {
UF_MSG_ERROR("need to fix");
return false;
// generate indices if not found
// if ( mesh.index.count == 0 ) mesh.generateIndices();
// generate indirect data if not found
@ -1010,33 +1054,530 @@ bool ext::vulkan::Graphic::updateMesh( uf::Mesh& mesh ) {
};
uf::stl::vector<Queue> queue;
/*
#define PARSE_ATTRIBUTE(i, usage) {\
auto& buffer = mesh.buffers[i];\
if ( queue.size() <= i ) queue.resize( i );\
if ( !buffer.empty() ) queue.emplace_back(Queue{ (void*) buffer.data(), buffer.size(), usage });\
}
#define PARSE_INPUT(name, usage){\
if ( mesh.isInterleaved( mesh.name.interleaved ) ) PARSE_ATTRIBUTE(descriptor.inputs.name.interleaved, usage)\
else for ( auto& attribute : descriptor.inputs.name.attributes ) PARSE_ATTRIBUTE(attribute.buffer, usage)\
}
*/
#define PARSE_INPUT(name, usage){\
if ( mesh.isInterleaved( mesh.name.interleaved ) ) {\
auto& buffer = mesh.buffers[mesh.name.interleaved];\
if ( !buffer.empty() ) rebuild = rebuild || updateBuffer( (const void*) buffer.data(), buffer.size(), descriptor.inputs.name.interleaved );\
} else for ( size_t i = 0; i < descriptor.inputs.name.attributes.size(); ++i ) {\
auto& buffer = mesh.buffers[mesh.name.attributes[i].buffer];\
if ( !buffer.empty() ) rebuild = rebuild || updateBuffer( (const void*) buffer.data(), buffer.size(), descriptor.inputs.name.attributes[i].buffer );\
}\
}
bool rebuild = false;
auto previousRequestedAlignment = this->requestedAlignment;
this->requestedAlignment = 16;
PARSE_INPUT(vertex, uf::renderer::enums::Buffer::VERTEX)
PARSE_INPUT(index, uf::renderer::enums::Buffer::INDEX)
PARSE_INPUT(instance, uf::renderer::enums::Buffer::VERTEX)
PARSE_INPUT(indirect, uf::renderer::enums::Buffer::INDIRECT)
this->requestedAlignment = previousRequestedAlignment;
/*
// allocate buffers
bool rebuild = false;
for ( auto i = 0; i < queue.size(); ++i ) {
auto& q = queue[i];
rebuild = rebuild || updateBuffer( q.data, q.size, descriptor.inputs.bufferOffset + i );
}
*/
if ( mesh.instance.count == 0 && mesh.instance.attributes.empty() ) {
descriptor.inputs.instance.count = 1;
}
return rebuild;
}
void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
auto& device = *this->device; // ext::vulkan::device;
VkPhysicalDeviceAccelerationStructurePropertiesKHR acclerationStructureProperties{};
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{};
VkPhysicalDeviceProperties2 deviceProperties2{}; {
acclerationStructureProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
rayTracingPipelineProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
rayTracingPipelineProperties.pNext = &acclerationStructureProperties;
deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
deviceProperties2.pNext = &rayTracingPipelineProperties;
vkGetPhysicalDeviceProperties2(device.physicalDevice, &deviceProperties2);
}
struct BlasData {
uf::stl::vector<VkAccelerationStructureGeometryKHR> asGeom;
uf::stl::vector<VkAccelerationStructureBuildRangeInfoKHR> asBuildOffsetInfo;
VkBuildAccelerationStructureFlagsKHR flags{};
VkAccelerationStructureBuildGeometryInfoKHR buildInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
VkAccelerationStructureBuildSizesInfoKHR sizeInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR};
const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo;
uf::renderer::AccelerationStructure as;
};
uf::stl::vector<BlasData> blasDatas;
uf::renderer::Buffer scratchBuffer;
uf::renderer::Buffer blasBuffer;
// setup BLAS geometry
{
auto& mesh = this->descriptor.inputs;
uf::Mesh::Attribute vertexAttribute;
size_t vertexBufferAddress{};
uf::Mesh::Attribute indexAttribute;
size_t indexBufferAddress{};
/*if ( mesh.vertex.count )*/{
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "position" ) vertexAttribute = attribute;
UF_ASSERT( vertexAttribute.descriptor.name == "position" );
size_t vertexBufferIndex = (0 <= mesh.vertex.interleaved ? mesh.vertex.interleaved : vertexAttribute.buffer) + mesh.bufferOffset;
vertexBufferAddress = this->buffers[vertexBufferIndex].getAddress();
}
if ( mesh.index.count ) {
indexAttribute = mesh.index.attributes.front();
size_t indexBufferIndex = (0 <= mesh.index.interleaved ? mesh.index.interleaved : indexAttribute.buffer) + mesh.bufferOffset;
indexBufferAddress = this->buffers[indexBufferIndex].getAddress();
}
if ( mesh.indirect.count ) {
uf::Mesh::Attribute indirectAttribute = mesh.indirect.attributes.front();
const pod::DrawCommand* drawCommands = (const pod::DrawCommand*) indirectAttribute.pointer;
for ( size_t i = 0; i < mesh.indirect.count; ++i ) {
const auto& drawCommand = drawCommands[i];
uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Input indexInput = mesh.index;
vertexInput.first = drawCommand.vertexID;
vertexInput.count = drawCommand.vertices;
indexInput.first = drawCommand.indexID;
indexInput.count = drawCommand.indices;
auto& blasData = blasDatas.emplace_back();
blasData.as.instanceID = drawCommand.instanceID;
VkAccelerationStructureGeometryKHR& asGeom = blasData.asGeom.emplace_back();
asGeom.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
asGeom.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
asGeom.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
VkAccelerationStructureGeometryTrianglesDataKHR& triangles = asGeom.geometry.triangles;
triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
triangles.vertexFormat = vertexAttribute.descriptor.format;
triangles.vertexData.deviceAddress = vertexBufferAddress;
triangles.vertexStride = vertexAttribute.stride;
triangles.maxVertex = vertexInput.count;
triangles.indexType = VK_INDEX_TYPE_NONE_KHR;
triangles.indexData.deviceAddress = indexBufferAddress;
VkAccelerationStructureBuildRangeInfoKHR& offset = blasData.asBuildOffsetInfo.emplace_back();
offset.firstVertex = vertexInput.first;
offset.primitiveCount = vertexInput.count / 3;
offset.primitiveOffset = indexInput.first * indexInput.size;
offset.transformOffset = 0;
if ( indexInput.count ) {
offset.primitiveCount = indexInput.count / 3;
switch ( indexInput.size ) {
case sizeof( uint8_t): triangles.indexType = VK_INDEX_TYPE_UINT8_EXT; break;
case sizeof(uint16_t): triangles.indexType = VK_INDEX_TYPE_UINT16; break;
case sizeof(uint32_t): triangles.indexType = VK_INDEX_TYPE_UINT32; break;
}
}
}
} else {
uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Input indexInput = mesh.index;
auto& blasData = blasDatas.emplace_back();
blasData.as.instanceID = 0;
VkAccelerationStructureGeometryKHR& asGeom = blasData.asGeom.emplace_back();
asGeom.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
asGeom.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
asGeom.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
VkAccelerationStructureGeometryTrianglesDataKHR& triangles = asGeom.geometry.triangles;
triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
triangles.vertexFormat = vertexAttribute.descriptor.format;
triangles.vertexData.deviceAddress = vertexBufferAddress;
triangles.vertexStride = vertexAttribute.stride;
triangles.maxVertex = vertexInput.count;
triangles.indexType = VK_INDEX_TYPE_NONE_KHR;
triangles.indexData.deviceAddress = indexBufferAddress;
VkAccelerationStructureBuildRangeInfoKHR& offset = blasData.asBuildOffsetInfo.emplace_back();
offset.firstVertex = vertexInput.first;
offset.primitiveCount = vertexInput.count / 3;
offset.primitiveOffset = indexInput.first * indexInput.size;
offset.transformOffset = 0;
if ( indexInput.count ) {
offset.primitiveCount = indexInput.count / 3;
switch ( indexInput.size ) {
case sizeof( uint8_t): triangles.indexType = VK_INDEX_TYPE_UINT8_EXT; break;
case sizeof(uint16_t): triangles.indexType = VK_INDEX_TYPE_UINT16; break;
case sizeof(uint32_t): triangles.indexType = VK_INDEX_TYPE_UINT32; break;
}
}
}
}
// determine BLAS size and its scratch buffer
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
size_t totalBlasBufferSize{};
size_t maxScratchBufferSize{};
for ( auto& blasData : blasDatas ) {
blasData.buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
blasData.buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
blasData.buildInfo.flags = blasData.flags | flags;
blasData.buildInfo.geometryCount = static_cast<uint32_t>(blasData.asGeom.size());
blasData.buildInfo.pGeometries = blasData.asGeom.data();
blasData.rangeInfo = blasData.asBuildOffsetInfo.data();
uf::stl::vector<uint32_t> maxPrimCount(blasData.asBuildOffsetInfo.size());
for(auto _ = 0; _ < blasData.asBuildOffsetInfo.size(); _++) maxPrimCount[_] = blasData.asBuildOffsetInfo[_].primitiveCount;
// UF_MSG_DEBUG("vkGetAccelerationStructureBuildSizesKHR");
uf::renderer::vkGetAccelerationStructureBuildSizesKHR(
device,
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
&blasData.buildInfo,
maxPrimCount.data(),
&blasData.sizeInfo
);
blasData.sizeInfo.accelerationStructureSize = ALIGNED_SIZE(blasData.sizeInfo.accelerationStructureSize, 256);
maxScratchBufferSize = std::max( maxScratchBufferSize, blasData.sizeInfo.buildScratchSize );
totalBlasBufferSize += blasData.sizeInfo.accelerationStructureSize;
}
// create BLAS buffer and handle
size_t blasBufferIndex = this->initializeBuffer( NULL, totalBlasBufferSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
size_t blasBufferOffset = 0;
scratchBuffer.alignment = acclerationStructureProperties.minAccelerationStructureScratchOffsetAlignment;
scratchBuffer.initialize( NULL, maxScratchBufferSize, uf::renderer::enums::Buffer::STORAGE | uf::renderer::enums::Buffer::ADDRESS );
UF_MSG_DEBUG("Scratch buffer size: " << maxScratchBufferSize);
for ( auto& blasData : blasDatas ) {
VkAccelerationStructureCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
createInfo.size = blasData.sizeInfo.accelerationStructureSize;
createInfo.buffer = this->buffers[blasBufferIndex].buffer;
createInfo.offset = blasBufferOffset;
blasBufferOffset += blasData.sizeInfo.accelerationStructureSize;
// UF_MSG_DEBUG("vkCreateAccelerationStructureKHR");
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &createInfo, nullptr, &blasData.as.handle));
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = blasData.as.handle;
blasData.as.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
// write to BLAS
blasData.buildInfo.dstAccelerationStructure = blasData.as.handle;
blasData.buildInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
// UF_MSG_DEBUG("vkCmdBuildAccelerationStructuresKHR");
uf::renderer::vkCmdBuildAccelerationStructuresKHR(
commandBuffer,
1,
&blasData.buildInfo,
&blasData.rangeInfo
);
device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE);
}
for ( auto& blasData : blasDatas ) this->accelerationStructures.bottoms.emplace_back(blasData.as);
scratchBuffer.destroy();
}
void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vector<uf::renderer::Graphic*>& graphics, const uf::stl::vector<pod::Instance>& instances ) {
auto& device = *this->device;
// graphic.process = false;
VkPhysicalDeviceAccelerationStructurePropertiesKHR acclerationStructureProperties{};
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{};
VkPhysicalDeviceProperties2 deviceProperties2{}; {
acclerationStructureProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
rayTracingPipelineProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
rayTracingPipelineProperties.pNext = &acclerationStructureProperties;
deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
deviceProperties2.pNext = &rayTracingPipelineProperties;
vkGetPhysicalDeviceProperties2(device.physicalDevice, &deviceProperties2);
}
uf::renderer::Buffer instanceBuffer;
uf::renderer::Buffer scratchBuffer;
uf::renderer::Buffer tlasBuffer;
uf::stl::vector<VkAccelerationStructureInstanceKHR> instancesVK; instancesVK.reserve( instances.size() );
uf::stl::vector<pod::InstanceAddresses> instanceAddresseses( instances.size() );
for ( auto& graphic : graphics ) {
for ( auto& blas : graphic->accelerationStructures.bottoms ) {
size_t instanceID = blas.instanceID;
auto& instanceAddresses = instanceAddresseses[instanceID];
if ( graphic->descriptor.inputs.vertex.count ) {
if ( 0 <= graphic->descriptor.inputs.vertex.interleaved ) {
instanceAddresses.vertex = graphic->buffers.at(graphic->descriptor.inputs.vertex.interleaved).getAddress();
} else {
for ( auto& attribute : graphic->descriptor.inputs.vertex.attributes ) {
if ( attribute.buffer < 0 ) continue;
if ( attribute.descriptor.name == "position" ) instanceAddresses.position = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "uv" ) instanceAddresses.uv = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "color" ) instanceAddresses.color = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "st" ) instanceAddresses.st = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "normal" ) instanceAddresses.normal = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "tangent" ) instanceAddresses.tangent = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "joints" ) instanceAddresses.joints = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "weights" ) instanceAddresses.weights = graphic->buffers.at(attribute.buffer).getAddress();
else if ( attribute.descriptor.name == "id" ) instanceAddresses.id = graphic->buffers.at(attribute.buffer).getAddress();
}
}
}
if ( graphic->descriptor.inputs.index.count ) {
if ( 0 <= graphic->descriptor.inputs.index.interleaved ) {
instanceAddresses.index = graphic->buffers.at(graphic->descriptor.inputs.index.interleaved).getAddress();
} else {
instanceAddresses.index = graphic->buffers.at(graphic->descriptor.inputs.index.attributes.front().buffer).getAddress();
}
}
auto& instanceVK = instancesVK.emplace_back();
instanceVK.transform = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f
};
auto mat = instances[instanceID].model;
mat = uf::matrix::transpose(mat);
memcpy(&instanceVK.transform, &mat, sizeof(instanceVK.transform));
instanceVK.instanceCustomIndex = blas.instanceID;
instanceVK.accelerationStructureReference = blas.deviceAddress;
instanceVK.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
instanceVK.mask = 0xFF;
instanceVK.instanceShaderBindingTableRecordOffset = 0;
}
}
// do not stage, because apparently vkQueueWaitIdle doesn't actually wait for the transfer to complete
size_t instanceIndex = this->initializeBuffer(
(const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR),
uf::renderer::enums::Buffer::ADDRESS | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, false
);
size_t instanceBufferAddress = this->buffers[instanceIndex].getAddress();
// build SBT
if ( !this->material.hasShader("ray:gen", uf::renderer::settings::pipelines::names::rt) ) {
uf::stl::string rayGenShaderFilename = uf::io::root+"/shaders/raytrace/shader.gen.spv";
uf::stl::string rayMissShaderFilename = uf::io::root+"/shaders/raytrace/shader.miss.spv";
uf::stl::string rayHitShaderFilename = uf::io::root+"/shaders/raytrace/shader.hit.spv";
this->material.attachShader(rayGenShaderFilename, VK_SHADER_STAGE_RAYGEN_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
this->material.attachShader(rayMissShaderFilename, VK_SHADER_STAGE_MISS_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
this->material.attachShader(rayHitShaderFilename, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, uf::renderer::settings::pipelines::names::rt);
}
{
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
bool update = false;
uint32_t countInstance = instancesVK.size();
auto& tlas = this->accelerationStructures.top;
VkAccelerationStructureGeometryInstancesDataKHR instancesVk{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR};
instancesVk.data.deviceAddress = instanceBufferAddress;
VkAccelerationStructureGeometryKHR tlasGeometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR};
tlasGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
tlasGeometry.geometry.instances = instancesVk;
VkAccelerationStructureBuildGeometryInfoKHR buildInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
buildInfo.flags = flags;
buildInfo.geometryCount = 1;
buildInfo.pGeometries = &tlasGeometry;
buildInfo.mode = update ? VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR : VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
buildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
VkAccelerationStructureBuildSizesInfoKHR sizeInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR};
UF_MSG_DEBUG("vkGetAccelerationStructureBuildSizesKHR");
uf::renderer::vkGetAccelerationStructureBuildSizesKHR(
device,
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
&buildInfo,
&countInstance,
&sizeInfo
);
// create BLAS buffer and handle
size_t tlasBufferIndex = this->initializeBuffer( NULL, sizeInfo.accelerationStructureSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
auto& tlasBuffer = this->buffers[tlasBufferIndex]; {
auto& shader = this->material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
shader.buffers.emplace_back( this->buffers[tlasBufferIndex].alias() );
}
VkAccelerationStructureCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
createInfo.size = sizeInfo.accelerationStructureSize;
createInfo.buffer = tlasBuffer.buffer;
UF_MSG_DEBUG("vkCreateAccelerationStructureKHR");
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &createInfo, nullptr, &tlas.handle));
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = tlas.handle;
tlas.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
// write to BLAS
scratchBuffer.alignment = acclerationStructureProperties.minAccelerationStructureScratchOffsetAlignment;
scratchBuffer.initialize( NULL, sizeInfo.buildScratchSize, uf::renderer::enums::Buffer::STORAGE | uf::renderer::enums::Buffer::ADDRESS );
UF_MSG_DEBUG("Scratch buffer size: " << sizeInfo.buildScratchSize);
buildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
buildInfo.dstAccelerationStructure = tlas.handle;
buildInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
VkAccelerationStructureBuildRangeInfoKHR buildOffsetInfo{countInstance, 0, 0, 0};
const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo = &buildOffsetInfo;
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
UF_MSG_DEBUG("vkCmdBuildAccelerationStructuresKHR");
uf::renderer::vkCmdBuildAccelerationStructuresKHR(
commandBuffer,
1,
&buildInfo,
&rangeInfo
);
device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE);
scratchBuffer.destroy();
}
// should be placed outside, in the responsible scene/rendermode
#if 1
{
auto& shader = this->material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& image = shader.textures.emplace_back();
image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, uf::renderer::settings::width, uf::renderer::settings::height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
this->descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
this->descriptor.inputs.width = image.width;
this->descriptor.inputs.height = image.height;
//
struct UniformDescriptor {
struct Matrices {
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
alignas(16) pod::Matrix4f iView;
alignas(16) pod::Matrix4f iProjection;
alignas(16) pod::Matrix4f iProjectionView;
alignas(16) pod::Vector4f eyePos;
} matrices[2];
} uniforms;
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
for ( auto i = 0; i < 2; ++i ) {
uniforms.matrices[i] = UniformDescriptor::Matrices{
.view = camera.getView(i),
.projection = camera.getProjection(i),
.iView = uf::matrix::inverse( camera.getView(i) ),
.iProjection = uf::matrix::inverse( camera.getProjection(i) ),
.iProjectionView = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) ),
.eyePos = camera.getEye( i ),
};
}
bool found = false;
for ( auto& buffer : shader.buffers ) {
if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( buffer.allocationInfo.size != sizeof(UniformDescriptor) ) continue;
found = true;
break;
}
if ( !found ) shader.initializeBuffer( (const void*) &uniforms, sizeof(UniformDescriptor), uf::renderer::enums::Buffer::UNIFORM );
//
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(1);
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
// shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() );
// shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures2D);
else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxTexturesCube);
else if ( sc.name == "CASCADES" ) sc.value.ui = (specializationConstants[sc.index] = maxCascades);
}
for ( auto pair : shader.metadata.definitions.textures ) {
auto& tx = pair.second;
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != tx.binding ) continue;
if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
else if ( tx.name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelNormal" ) layout.descriptorCount = maxCascades;
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
}
}
// UF_MSG_DEBUG("Building pipeline...");
this->initializePipeline();
this->initialized = true;
this->process = true;
#endif
UF_MSG_DEBUG("Generated acceleration structures for " << this << " (" << this->descriptor.renderMode << ")");
}
bool ext::vulkan::Graphic::hasPipeline( const GraphicDescriptor& descriptor ) const {
return pipelines.count( descriptor ) > 0;
}
@ -1063,33 +1604,53 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, size_t pass, s
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicDescriptor& descriptor, size_t pass, size_t draw ) const {
if ( !process ) return;
if ( !this->hasPipeline( descriptor ) ) {
UF_MSG_ERROR(this << ": has no valid pipeline (" << descriptor.renderMode << " " << descriptor.renderTarget << ")");
VK_DEBUG_VALIDATION_MESSAGE(this << ": has no valid pipeline (" << descriptor.renderMode << " " << descriptor.renderTarget << ")");
return;
}
auto& pipeline = this->getPipeline( descriptor );
if ( pipeline.descriptorSet == VK_NULL_HANDLE ) {
UF_MSG_ERROR(this << ": has no valid pipeline descriptor set (" << descriptor.renderMode << " " << descriptor.renderTarget << ")");
VK_DEBUG_VALIDATION_MESSAGE(this << ": has no valid pipeline descriptor set (" << descriptor.renderMode << " " << descriptor.renderTarget << ")");
return;
}
if ( !pipeline.metadata.process ) return;
pipeline.record(*this, descriptor, commandBuffer, pass, draw);
auto shaders = pipeline.getShaders( material.shaders );
for ( auto* shader : shaders ) if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) return;
for ( auto* shader : shaders ) {
if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) return;
if (
shader->descriptor.stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_MISS_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR
) return;
}
struct {
uf::stl::vector<VkBuffer> buffer;
uf::stl::vector<VkDeviceSize> offset;
} vertexInstance;
for ( auto& attribute : descriptor.inputs.vertex.attributes ) {
vertexInstance.buffer.emplace_back( buffers.at((0 <= descriptor.inputs.vertex.interleaved ? descriptor.inputs.vertex.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer );
vertexInstance.offset.emplace_back( 0 <= descriptor.inputs.vertex.interleaved ? descriptor.inputs.vertex.offset : attribute.offset );
if ( 0 <= descriptor.inputs.vertex.interleaved && !descriptor.inputs.vertex.attributes.empty() ) {
vertexInstance.buffer.emplace_back( buffers.at(descriptor.inputs.vertex.interleaved).buffer );
vertexInstance.offset.emplace_back( descriptor.inputs.vertex.offset );
} else {
for ( auto& attribute : descriptor.inputs.vertex.attributes ) {
vertexInstance.buffer.emplace_back( attribute.buffer < 0 ? VK_NULL_HANDLE : buffers.at(attribute.buffer).buffer );
vertexInstance.offset.emplace_back( attribute.offset );
}
}
for ( auto& attribute : descriptor.inputs.instance.attributes ) {
vertexInstance.buffer.emplace_back( buffers.at((0 <= descriptor.inputs.instance.interleaved ? descriptor.inputs.instance.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer );
vertexInstance.offset.emplace_back( 0 <= descriptor.inputs.instance.interleaved ? descriptor.inputs.instance.offset : attribute.offset );
if ( 0 <= descriptor.inputs.instance.interleaved && !descriptor.inputs.instance.attributes.empty() ) {
vertexInstance.buffer.emplace_back( buffers.at(descriptor.inputs.instance.interleaved).buffer );
vertexInstance.offset.emplace_back( descriptor.inputs.instance.offset );
} else {
for ( auto& attribute : descriptor.inputs.instance.attributes ) {
vertexInstance.buffer.emplace_back( attribute.buffer < 0 ? VK_NULL_HANDLE : buffers.at(attribute.buffer).buffer );
vertexInstance.offset.emplace_back( attribute.offset );
}
}
struct {
@ -1099,16 +1660,24 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
size_t index = 0;
} index, indirect;
/*
if ( descriptor.inputs.index.count && !descriptor.inputs.index.attributes.empty() ) {
auto& attribute = descriptor.inputs.index.attributes.front();
index.buffer = buffers.at((0 <= descriptor.inputs.index.interleaved ? descriptor.inputs.index.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer;
index.offset = 0 <= descriptor.inputs.index.interleaved ? descriptor.inputs.index.offset : attribute.offset;
// bool isInterleaved = 0 <= descriptor.inputs.index.interleaved;
// index.buffer = buffers.at((isInterleaved ? descriptor.inputs.index.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer;
// index.offset = isInterleaved ? descriptor.inputs.index.offset : attribute.offset;
// index.buffer = buffers.at(attribute.buffer + descriptor.inputs.bufferOffset).buffer;
// index.offset = attribute.offset;
}
if ( descriptor.inputs.indirect.count && !descriptor.inputs.indirect.attributes.empty() ) {
auto& attribute = descriptor.inputs.indirect.attributes.front();
indirect.buffer = buffers.at((0 <= descriptor.inputs.indirect.interleaved ? descriptor.inputs.indirect.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer;
indirect.offset = 0 <= descriptor.inputs.indirect.interleaved ? descriptor.inputs.indirect.offset : attribute.offset;
// bool isInterleaved = 0 <= descriptor.inputs.indirect.interleaved;
// indirect.buffer = buffers.at((isInterleaved ? descriptor.inputs.indirect.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer;
// indirect.offset = isInterleaved ? descriptor.inputs.indirect.offset : attribute.offset;
// indirect.buffer = buffers.at(attribute.buffer + descriptor.inputs.bufferOffset).buffer;
// indirect.offset = attribute.offset;
}
*/
for ( auto& buffer : buffers ) {
if ( !index.buffer && buffer.usage & uf::renderer::enums::Buffer::INDEX ) index.buffer = buffer.buffer;

View File

@ -0,0 +1,259 @@
#if UF_USE_VULKAN
#include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/rendermodes/compute.h>
#include <uf/ext/vulkan/initializers.h>
#include <uf/utils/window/window.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/ext/vulkan/graphic.h>
#include <uf/engine/graph/graph.h>
#include <uf/utils/camera/camera.h>
const uf::stl::string ext::vulkan::ComputeRenderMode::getTarget() const {
// auto& metadata = *const_cast<uf::Serializer*>(&this->metadata);
// return metadata["target"].as<uf::stl::string>();
return metadata.target;
}
void ext::vulkan::ComputeRenderMode::setTarget( const uf::stl::string& target ) {
// this->metadata["target"] = target;
metadata.target = target;
}
const uf::stl::string ext::vulkan::ComputeRenderMode::getType() const {
return "Compute";
}
const size_t ext::vulkan::ComputeRenderMode::blitters() const {
return 1;
}
ext::vulkan::Graphic* ext::vulkan::ComputeRenderMode::getBlitter( size_t i ) {
return &this->blitter;
}
uf::stl::vector<ext::vulkan::Graphic*> ext::vulkan::ComputeRenderMode::getBlitters() {
return { &this->blitter };
}
ext::vulkan::GraphicDescriptor ext::vulkan::ComputeRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) {
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
descriptor.parse(metadata.json["descriptor"]);
// invalidate
if ( metadata.target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != metadata.target ) {
descriptor.invalidated = true;
} else {
descriptor.renderMode = this->getName();
}
return descriptor;
}
void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
this->setTarget("Compute");
ext::vulkan::RenderMode::initialize( device );
#if 0
{
uf::Mesh mesh;
mesh.bind<pod::Vertex_3F>();
/*
mesh.insertVertices<pod::Vertex_3F>({
{ {-0.5f, -0.5f, 0.0f } },
{ { 0.5f, -0.5f, 0.0f } },
{ { 0.0f, 0.5f, 0.0f } },
});
*/
mesh.insertVertices<pod::Vertex_3F>({
{-1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f, 1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{-1.0f,-1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f,-1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
});
mesh.updateDescriptor();
blitter.initialize( this->getName() );
blitter.initializeMesh( mesh );
ext::vulkan::generateAccelerationStructures( blitter );
}
#endif
}
void ext::vulkan::ComputeRenderMode::tick() {
ext::vulkan::RenderMode::tick();
bool resized = this->width == 0 && this->height == 0 && ext::vulkan::states::resized;
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
#if 0
{
auto& shader = blitter.material.getShader("ray:gen");
auto& image = shader.textures.front();
struct UniformDescriptor {
struct Matrices {
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
alignas(16) pod::Matrix4f iView;
alignas(16) pod::Matrix4f iProjection;
alignas(16) pod::Matrix4f iProjectionView;
alignas(16) pod::Vector4f eyePos;
} matrices[2];
} uniforms;
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
for ( auto i = 0; i < 2; ++i ) {
uniforms.matrices[i] = UniformDescriptor::Matrices{
.view = camera.getView(i),
.projection = camera.getProjection(i),
.iView = uf::matrix::inverse( camera.getView(i) ),
.iProjection = uf::matrix::inverse( camera.getProjection(i) ),
.iProjectionView = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) ),
.eyePos = camera.getEye( i ),
};
}
for ( auto& buffer : shader.buffers ) {
if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( buffer.allocationInfo.size != sizeof(UniformDescriptor) ) continue;
buffer.update( (const void*) &uniforms, sizeof(UniformDescriptor) );
break;
}
if ( resized ) {
image.destroy();
image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, uf::renderer::settings::width, uf::renderer::settings::height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
blitter.descriptor.inputs.width = image.width;
blitter.descriptor.inputs.height = image.height;
blitter.getPipeline().update( blitter );
}
}
#endif
if ( metadata.limiter.frequency > 0 ) {
if ( metadata.limiter.timer > metadata.limiter.frequency ) {
metadata.limiter.timer = 0;
metadata.limiter.execute = true;
} else {
metadata.limiter.timer = metadata.limiter.timer + uf::physics::time::delta;
metadata.limiter.execute = false;
}
}
}
void ext::vulkan::ComputeRenderMode::destroy() {
#if 0
auto& shader = blitter.material.getShader("ray:gen");
auto& image = shader.textures.front();
image.screenshot().save("./data/rt.png");
image.destroy();
blitter.destroy();
#endif
ext::vulkan::RenderMode::destroy();
}
void ext::vulkan::ComputeRenderMode::render() {
if ( commandBufferCallbacks.count(EXECUTE_BEGIN) > 0 ) commandBufferCallbacks[EXECUTE_BEGIN]( VkCommandBuffer{} );
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX ));
VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] ));
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = NULL; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = NULL; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 0; // One wait semaphore
submitInfo.pSignalSemaphores = NULL; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 0; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( uf::renderer::Device::QueueEnum::COMPUTE ), 1, &submitInfo, fences[states::currentBuffer]));
if ( commandBufferCallbacks.count(EXECUTE_END) > 0 ) commandBufferCallbacks[EXECUTE_END]( VkCommandBuffer{} );
this->executed = true;
//unlockMutex( this->mostRecentCommandPoolId );
}
void ext::vulkan::ComputeRenderMode::pipelineBarrier( VkCommandBuffer commandBuffer, uint8_t state ) {
}
void ext::vulkan::ComputeRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
// destroy if exists
float width = this->width > 0 ? this->width : ext::vulkan::settings::width;
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufInfo.pNext = nullptr;
size_t subpasses = 1;
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
// pre-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commands[i] );
// if ( blitter.process ) blitter.getPipeline().record( blitter, blitter.descriptor, commands[i] );
/*
for ( ; currentPass < subpasses; ++currentPass ) {
size_t currentDraw = 0;
for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->getTarget() ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass);
graphic->record( commands[i], descriptor, currentPass, currentDraw++ );
}
if ( commandBufferCallbacks.count( currentPass ) > 0 ) commandBufferCallbacks[currentPass]( commands[i] );
if ( currentPass + 1 < subpasses ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
}
*/
// post-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i] );
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
}
}
#endif

View File

@ -283,12 +283,13 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(128);
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
// shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() );
// shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
// shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
if ( ext::vulkan::settings::pipelines::vxgi ) {
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
@ -565,7 +566,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
for ( auto _ : layers ) {
RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _;
auto& blitter = layer->blitter;
if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass || blitter.accelerationStructures.top.handle ) continue;
if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor, currentSubpass);
blitter.record(commands[i], descriptor);
}
@ -581,7 +582,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
for ( auto _ : layers ) {
RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _;
auto& blitter = layer->blitter;
if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass || blitter.accelerationStructures.top.handle ) continue;
if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor, currentSubpass);
blitter.record(commands[i], descriptor, eye, currentDraw++);
}

View File

@ -1,522 +0,0 @@
#if UF_USE_VULKAN
#include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/rendermodes/raytrace.h>
#include <uf/ext/vulkan/initializers.h>
#include <uf/utils/window/window.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/ext/vulkan/graphic.h>
#include <uf/engine/graph/graph.h>
#include <uf/utils/camera/camera.h>
namespace {
//
struct UniformDescriptor {
struct Matrices {
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
alignas(16) pod::Matrix4f iView;
alignas(16) pod::Matrix4f iProjection;
alignas(16) pod::Matrix4f iProjectionView;
alignas(16) pod::Vector4f eyePos;
} matrices[2];
};
void initializeGraphic( uf::renderer::RayTraceRenderMode& renderMode ) {
auto& device = *renderMode.device;
auto& blitter = *renderMode.getBlitter();
// setup buffers
uf::Mesh mesh;
mesh.bind<pod::Vertex_3F, uint16_t>();
mesh.insertVertices<pod::Vertex_3F>({
{ { -0.5f, -0.5f, 0.0f } },
{ { 0.5f, -0.5f, 0.0f } },
{ { 0.0f, 0.5f, 0.0f } },
});
mesh.insertIndices<uint16_t>({
0, 1, 2
});
mesh.updateDescriptor();
blitter.initialize( renderMode.getName() );
blitter.initializeMesh( mesh );
blitter.process = false;
{
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
UniformDescriptor uniforms;
for ( auto i = 0; i < 2; ++i ) {
uniforms.matrices[i] = UniformDescriptor::Matrices{
.view = camera.getView(i),
.projection = camera.getProjection(i),
.iView = uf::matrix::inverse( camera.getView(i) ),
.iProjection = uf::matrix::inverse( camera.getProjection(i) ),
.iProjectionView = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) ),
.eyePos = camera.getEye( i ),
};
}
blitter.initializeBuffer( (const void*) &uniforms, sizeof(UniformDescriptor), uf::renderer::enums::Buffer::UNIFORM );
}
auto& image = blitter.material.textures.emplace_back();
image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, uf::renderer::settings::width, uf::renderer::settings::height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
pod::Matrix4f transformMatrix = uf::matrix::identity();
auto vertexBufferIndex = blitter.initializeBuffer( (const void*) mesh.vertex.attributes.front().pointer, mesh.vertex.count * mesh.vertex.size, uf::renderer::enums::Buffer::ADDRESS | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR );
auto indexBufferIndex = blitter.initializeBuffer( (const void*) mesh.index.attributes.front().pointer, mesh.index.count * mesh.index.size, uf::renderer::enums::Buffer::ADDRESS | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR );
blitter.requestedAlignment = 16;
auto transformBufferIndex = blitter.initializeBuffer( &transformMatrix[0], sizeof(transformMatrix), uf::renderer::enums::Buffer::ADDRESS | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR );
blitter.requestedAlignment = 0;
uf::renderer::Buffer vertexBuffer;
uf::renderer::Buffer indexBuffer;
uf::renderer::Buffer transformBuffer;
uf::renderer::Buffer blasBuffer;
uf::renderer::Buffer instancesBuffer;
uf::renderer::Buffer tlasBuffer;
uf::renderer::Buffer scratchBuffer;
// build SBT
{
uf::stl::string rayGenShaderFilename = uf::io::root+"/shaders/raytrace/shader.gen.spv";
uf::stl::string rayMissShaderFilename = uf::io::root+"/shaders/raytrace/shader.miss.spv";
uf::stl::string rayHitShaderFilename = uf::io::root+"/shaders/raytrace/shader.hit.spv";
blitter.material.initializeShaders({
{uf::io::resolveURI(rayGenShaderFilename), VK_SHADER_STAGE_RAYGEN_BIT_KHR},
{uf::io::resolveURI(rayMissShaderFilename), VK_SHADER_STAGE_MISS_BIT_KHR},
{uf::io::resolveURI(rayHitShaderFilename), VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR},
});
}
blitter.material.getShader("ray:gen").textures.emplace_back().aliasTexture( image );
VkPhysicalDeviceAccelerationStructurePropertiesKHR acclerationStructureProperties{};
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{};
VkPhysicalDeviceProperties2 deviceProperties2{};
{
acclerationStructureProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
rayTracingPipelineProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
rayTracingPipelineProperties.pNext = &acclerationStructureProperties;
deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
deviceProperties2.pNext = &rayTracingPipelineProperties;
vkGetPhysicalDeviceProperties2(device.physicalDevice, &deviceProperties2);
}
// build blas
{
// get address
VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{};
VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{};
VkDeviceOrHostAddressConstKHR transformBufferDeviceAddress{};
vertexBuffer.aliasBuffer( blitter.buffers[vertexBufferIndex] );
indexBuffer.aliasBuffer( blitter.buffers[indexBufferIndex] );
transformBuffer.aliasBuffer( blitter.buffers[transformBufferIndex] );
UF_ASSERT( vertexBuffer.buffer );
UF_ASSERT( indexBuffer.buffer );
UF_ASSERT( transformBuffer.buffer );
vertexBufferDeviceAddress.deviceAddress = vertexBuffer.getAddress();
indexBufferDeviceAddress.deviceAddress = indexBuffer.getAddress();
transformBufferDeviceAddress.deviceAddress = transformBuffer.getAddress();
// attribute info
uf::Mesh::Attribute vertexAttribute;
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "position" ) vertexAttribute = attribute;
UF_ASSERT( vertexAttribute.descriptor.name == "position" );
// blas info
VkAccelerationStructureGeometryKHR accelerationStructureGeometry{};
accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
accelerationStructureGeometry.geometry.triangles.vertexFormat = vertexAttribute.descriptor.format;
accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress;
accelerationStructureGeometry.geometry.triangles.maxVertex = mesh.vertex.count;
accelerationStructureGeometry.geometry.triangles.vertexStride = vertexAttribute.stride;
accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT16;
accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress;
accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0;
accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr;
accelerationStructureGeometry.geometry.triangles.transformData = transformBufferDeviceAddress;
// size info
VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{};
accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
accelerationStructureBuildGeometryInfo.geometryCount = 1;
accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
const uint32_t numTriangles = 1; // (mesh.index.count ? mesh.index.count : mesh.vertex.count) / 3;
VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{};
accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
UF_MSG_DEBUG("vkGetAccelerationStructureBuildSizesKHR");
uf::renderer::vkGetAccelerationStructureBuildSizesKHR(
device,
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
&accelerationStructureBuildGeometryInfo,
&numTriangles,
&accelerationStructureBuildSizesInfo
);
// build blas buffer
size_t blasBufferIndex = blitter.initializeBuffer( NULL, accelerationStructureBuildSizesInfo.accelerationStructureSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
blitter.accelerationStructures.bottom.buffer.aliasBuffer( blitter.buffers[blasBufferIndex] );
// build blas handle
VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{};
accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
accelerationStructureCreateInfo.buffer = blitter.accelerationStructures.bottom.buffer.buffer;
accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize;
accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
UF_MSG_DEBUG("vkCreateAccelerationStructureKHR");
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &blitter.accelerationStructures.bottom.handle));
// build scratch buffer
scratchBuffer.alignment = acclerationStructureProperties.minAccelerationStructureScratchOffsetAlignment;
scratchBuffer.initialize( NULL, accelerationStructureBuildSizesInfo.buildScratchSize, uf::renderer::enums::Buffer::STORAGE | uf::renderer::enums::Buffer::ADDRESS );
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{};
accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
accelerationBuildGeometryInfo.dstAccelerationStructure = blitter.accelerationStructures.bottom.handle;
accelerationBuildGeometryInfo.geometryCount = 1; // numTriangles;
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{};
accelerationStructureBuildRangeInfo.primitiveCount = numTriangles;
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
accelerationStructureBuildRangeInfo.firstVertex = 0;
accelerationStructureBuildRangeInfo.transformOffset = 0;
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo };
// build blas
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
UF_MSG_DEBUG("vkCmdBuildAccelerationStructuresKHR");
uf::renderer::vkCmdBuildAccelerationStructuresKHR(
commandBuffer,
1,
&accelerationBuildGeometryInfo,
accelerationBuildStructureRangeInfos.data()
);
device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE);
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = blitter.accelerationStructures.bottom.handle;
blitter.accelerationStructures.bottom.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
scratchBuffer.destroy();
}
// build tlas
{
// setup instances buffer
VkAccelerationStructureInstanceKHR instance{};
instance.transform = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f
};
instance.instanceCustomIndex = 0;
instance.mask = 0xFF;
instance.instanceShaderBindingTableRecordOffset = 0;
instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
instance.accelerationStructureReference = blitter.accelerationStructures.bottom.deviceAddress;
auto instancesBufferIndex = blitter.initializeBuffer( NULL, sizeof(instance), uf::renderer::enums::Buffer::ADDRESS | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR );
instancesBuffer.aliasBuffer( blitter.buffers[instancesBufferIndex] );
blitter.updateBuffer( (const void*) &instance, sizeof(instance), instancesBuffer );
VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{};
instanceDataDeviceAddress.deviceAddress = instancesBuffer.getAddress();
VkAccelerationStructureGeometryKHR accelerationStructureGeometry{};
accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE;
accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress;
VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{};
accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
accelerationStructureBuildGeometryInfo.geometryCount = 1;
accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
const uint32_t primitive_count = 1;
VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{};
accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
UF_MSG_DEBUG("vkGetAccelerationStructureBuildSizesKHR");
uf::renderer::vkGetAccelerationStructureBuildSizesKHR(
device,
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
&accelerationStructureBuildGeometryInfo,
&primitive_count,
&accelerationStructureBuildSizesInfo
);
// build tlas buffer
size_t tlasBufferIndex = blitter.initializeBuffer( NULL, accelerationStructureBuildSizesInfo.accelerationStructureSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
blitter.accelerationStructures.top.buffer.aliasBuffer( blitter.buffers[tlasBufferIndex] );
blitter.material.getShader("ray:gen").buffers.emplace_back().aliasBuffer( blitter.buffers[tlasBufferIndex] );
// build tlas handle
VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{};
accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
accelerationStructureCreateInfo.buffer = blitter.accelerationStructures.top.buffer.buffer;
accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize;
accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
UF_MSG_DEBUG("vkCreateAccelerationStructureKHR");
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &blitter.accelerationStructures.top.handle));
// build scratch buffer
scratchBuffer.alignment = acclerationStructureProperties.minAccelerationStructureScratchOffsetAlignment;
scratchBuffer.initialize( NULL, accelerationStructureBuildSizesInfo.buildScratchSize, uf::renderer::enums::Buffer::STORAGE | uf::renderer::enums::Buffer::ADDRESS );
UF_MSG_DEBUG(accelerationStructureBuildSizesInfo.buildScratchSize);
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{};
accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
accelerationBuildGeometryInfo.dstAccelerationStructure = blitter.accelerationStructures.top.handle;
accelerationBuildGeometryInfo.geometryCount = 1;
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{};
accelerationStructureBuildRangeInfo.primitiveCount = 1;
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
accelerationStructureBuildRangeInfo.firstVertex = 0;
accelerationStructureBuildRangeInfo.transformOffset = 0;
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo };
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
UF_MSG_DEBUG("vkCmdBuildAccelerationStructuresKHR");
uf::renderer::vkCmdBuildAccelerationStructuresKHR(
commandBuffer,
1,
&accelerationBuildGeometryInfo,
accelerationBuildStructureRangeInfos.data()
);
device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE);
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = blitter.accelerationStructures.top.handle;
blitter.accelerationStructures.top.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
scratchBuffer.destroy();
}
blitter.descriptor.inputs.width = image.width;
blitter.descriptor.inputs.height = image.height;
blitter.initializePipeline();
blitter.initialized = true;
blitter.process = true;
UF_MSG_DEBUG("Initialized ray tracer");
}
}
const uf::stl::string ext::vulkan::RayTraceRenderMode::getTarget() const {
// auto& metadata = *const_cast<uf::Serializer*>(&this->metadata);
// return metadata["target"].as<uf::stl::string>();
return metadata.target;
}
void ext::vulkan::RayTraceRenderMode::setTarget( const uf::stl::string& target ) {
// this->metadata["target"] = target;
metadata.target = target;
}
const uf::stl::string ext::vulkan::RayTraceRenderMode::getType() const {
return "Compute";
}
const size_t ext::vulkan::RayTraceRenderMode::blitters() const {
return 1;
}
ext::vulkan::Graphic* ext::vulkan::RayTraceRenderMode::getBlitter( size_t i ) {
return &this->blitter;
}
uf::stl::vector<ext::vulkan::Graphic*> ext::vulkan::RayTraceRenderMode::getBlitters() {
return { &this->blitter };
}
ext::vulkan::GraphicDescriptor ext::vulkan::RayTraceRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) {
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
descriptor.parse(metadata.json["descriptor"]);
// invalidate
if ( metadata.target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != metadata.target ) {
descriptor.invalidated = true;
} else {
descriptor.renderMode = this->getName();
}
return descriptor;
}
void ext::vulkan::RayTraceRenderMode::initialize( Device& device ) {
ext::vulkan::RenderMode::initialize( device );
blitter.process = false;
initializeGraphic(*this);
}
void ext::vulkan::RayTraceRenderMode::tick() {
ext::vulkan::RenderMode::tick();
bool resized = this->width == 0 && this->height == 0 && ext::vulkan::states::resized;
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
if ( resized ) {
auto& image = blitter.material.textures.front();
image.destroy();
image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, uf::renderer::settings::width, uf::renderer::settings::height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
auto& shader = blitter.material.getShader("ray:gen");
shader.textures.clear();
shader.textures.emplace_back().aliasTexture( image );
blitter.descriptor.inputs.width = image.width;
blitter.descriptor.inputs.height = image.height;
blitter.getPipeline().update( blitter );
}
{
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
UniformDescriptor uniforms;
for ( auto i = 0; i < 2; ++i ) {
uniforms.matrices[i] = UniformDescriptor::Matrices{
.view = camera.getView(i),
.projection = camera.getProjection(i),
.iView = uf::matrix::inverse( camera.getView(i) ),
.iProjection = uf::matrix::inverse( camera.getProjection(i) ),
.iProjectionView = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) ),
.eyePos = camera.getEye( i ),
};
}
for ( auto& buffer : blitter.buffers ) {
if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( buffer.allocationInfo.size != sizeof(UniformDescriptor) ) continue;
buffer.update( (const void*) &uniforms, sizeof(UniformDescriptor) );
break;
}
}
if ( metadata.limiter.frequency > 0 ) {
if ( metadata.limiter.timer > metadata.limiter.frequency ) {
metadata.limiter.timer = 0;
metadata.limiter.execute = true;
} else {
metadata.limiter.timer = metadata.limiter.timer + uf::physics::time::delta;
metadata.limiter.execute = false;
}
}
// if ( !graphic.initialized ) initializeGraphic(*this);
}
void ext::vulkan::RayTraceRenderMode::destroy() {
auto& image = blitter.material.textures.front();
image.screenshot().save("./data/rt.png");
image.destroy();
blitter.destroy();
ext::vulkan::RenderMode::destroy();
}
void ext::vulkan::RayTraceRenderMode::render() {
if ( commandBufferCallbacks.count(EXECUTE_BEGIN) > 0 ) commandBufferCallbacks[EXECUTE_BEGIN]( VkCommandBuffer{} );
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX ));
VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] ));
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = NULL; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = NULL; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 0; // One wait semaphore
submitInfo.pSignalSemaphores = NULL; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 0; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( uf::renderer::Device::QueueEnum::COMPUTE ), 1, &submitInfo, fences[states::currentBuffer]));
if ( commandBufferCallbacks.count(EXECUTE_END) > 0 ) commandBufferCallbacks[EXECUTE_END]( VkCommandBuffer{} );
this->executed = true;
//unlockMutex( this->mostRecentCommandPoolId );
}
void ext::vulkan::RayTraceRenderMode::pipelineBarrier( VkCommandBuffer commandBuffer, uint8_t state ) {
}
void ext::vulkan::RayTraceRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
// destroy if exists
float width = this->width > 0 ? this->width : ext::vulkan::settings::width;
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufInfo.pNext = nullptr;
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
// pre-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commands[i] );
if ( blitter.process ) {
auto& image = blitter.material.textures.front();
auto descriptor = blitter.descriptor;
descriptor.inputs.width = image.width;
descriptor.inputs.height = image.height;
blitter.getPipeline().record( blitter, descriptor, commands[i] );
}
// post-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i] );
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
}
}
#endif

View File

@ -37,7 +37,7 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicD
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
descriptor.parse(metadata.json["descriptor"]);
if ( 0 <= pass && pass < metadata.subpasses && metadata.type == "vxgi" ) {
if ( 0 <= pass && pass < metadata.subpasses && metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
descriptor.cullMode = VK_CULL_MODE_NONE;
descriptor.depth.test = false;
descriptor.depth.write = false;
@ -67,7 +67,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
buffers.emplace_back().initialize( NULL, sizeof(pod::Camera::Viewports), uf::renderer::enums::Buffer::UNIFORM );
}
if ( metadata.type == "depth" || metadata.type == "vxgi" ) {
if ( metadata.type == "depth" || metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
renderTarget.views = metadata.subpasses;
struct {
size_t depth;
@ -311,7 +311,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
{uf::io::resolveURI(fragmentShaderFilename), VK_SHADER_STAGE_FRAGMENT_BIT}
});
}
if ( metadata.type == "vxgi" ) {
if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
@ -322,12 +322,13 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
auto& shader = blitter.material.getShader("compute");
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
// shader.buffers.emplace_back( uf::graph::storage.buffers.camera.alias() );
// shader.buffers.emplace_back( uf::graph::storage.buffers.joint.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
// shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
@ -348,40 +349,13 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
}
/*
ext::json::forEach( shader.metadata.json["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
uf::stl::string name = sc["name"].as<uf::stl::string>();
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures2D);
else if ( name == "CUBEMAPS" ) sc["value"] = (specializationConstants[i] = maxTexturesCube);
else if ( name == "CASCADES" ) sc["value"] = (specializationConstants[i] = maxCascades);
});
ext::json::forEach( shader.metadata.json["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
uf::stl::string name = t["name"].as<uf::stl::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
else if ( name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
});
*/
} else {
} else if ( metadata.type != uf::renderer::settings::pipelines::names::rt ) {
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
Texture2D& texture = blitter.material.textures.emplace_back();
enums::Filter::type_t filter = VK_FILTER_NEAREST;
/*
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties( device.physicalDevice, texture.format, &formatProperties );
if ( formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT )
filter = VK_FILTER_LINEAR;
*/
texture.sampler.descriptor.filter.min = filter;
texture.sampler.descriptor.filter.mag = filter;
texture.aliasAttachment(attachment);
@ -408,7 +382,7 @@ void ext::vulkan::RenderTargetRenderMode::tick() {
bool resized = this->width == 0 && this->height == 0 && ext::vulkan::states::resized;
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
if ( metadata.type == "vxgi" ) {
if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
if ( resized ) {
renderTarget.initialize( *renderTarget.device );
}
@ -419,15 +393,17 @@ void ext::vulkan::RenderTargetRenderMode::tick() {
}
if ( resized ) {
renderTarget.initialize( *renderTarget.device );
blitter.material.textures.clear();
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
Texture2D& texture = blitter.material.textures.emplace_back();
enums::Filter::type_t filter = VK_FILTER_NEAREST;
if ( metadata.type != uf::renderer::settings::pipelines::names::rt ) {
blitter.material.textures.clear();
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
Texture2D& texture = blitter.material.textures.emplace_back();
enums::Filter::type_t filter = VK_FILTER_NEAREST;
texture.sampler.descriptor.filter.min = filter;
texture.sampler.descriptor.filter.mag = filter;
texture.aliasAttachment(attachment);
texture.sampler.descriptor.filter.min = filter;
texture.sampler.descriptor.filter.mag = filter;
texture.aliasAttachment(attachment);
}
}
}
if ( rebuild && blitter.process ) {
@ -600,30 +576,38 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
// pre-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commands[i] );
for ( auto& pipeline : metadata.pipelines ) {
if ( pipeline == metadata.pipeline ) continue;
if ( this->getName() == "Compute" ) {
for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->getTarget() ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass);
descriptor.pipeline = pipeline;
graphic->record( commands[i], descriptor, 0, metadata.type == "vxgi" ? 0 : MIN(subpasses,6) );
if ( graphic->descriptor.pipeline != uf::renderer::settings::pipelines::names::rt ) continue;
graphic->record( commands[i] );
}
}
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetViewport(commands[i], 0, 1, &viewport);
vkCmdSetScissor(commands[i], 0, 1, &scissor);
for ( ; currentPass < subpasses; ++currentPass ) {
size_t currentDraw = 0;
} else {
for ( auto& pipeline : metadata.pipelines ) {
if ( pipeline == metadata.pipeline ) continue;
for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->getTarget() ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass);
graphic->record( commands[i], descriptor, currentPass, currentDraw++ );
descriptor.pipeline = pipeline;
graphic->record( commands[i], descriptor, 0, metadata.type == uf::renderer::settings::pipelines::names::vxgi ? 0 : MIN(subpasses,6) );
}
if ( commandBufferCallbacks.count( currentPass ) > 0 ) commandBufferCallbacks[currentPass]( commands[i] );
if ( currentPass + 1 < subpasses ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
}
vkCmdEndRenderPass(commands[i]);
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetViewport(commands[i], 0, 1, &viewport);
vkCmdSetScissor(commands[i], 0, 1, &scissor);
for ( ; currentPass < subpasses; ++currentPass ) {
size_t currentDraw = 0;
for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->getTarget() ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass);
graphic->record( commands[i], descriptor, currentPass, currentDraw++ );
}
if ( commandBufferCallbacks.count( currentPass ) > 0 ) commandBufferCallbacks[currentPass]( commands[i] );
if ( currentPass + 1 < subpasses ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
}
vkCmdEndRenderPass(commands[i]);
}
// post-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i] );

View File

@ -575,14 +575,17 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
for ( auto& name : remap ) {
auto& definition = metadata.definitions.uniforms[name];
auto& userdata = uniforms.emplace_back();
userdata.create( definition.size, nullptr );
if ( metadata.autoInitializeUniforms ) initializeBuffer(
(const void*) userdata.data().data,
userdata.data().len,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
);
if ( metadata.autoInitializeUniformBuffers ) {
initializeBuffer(
NULL,
definition.size,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
);
}
if ( metadata.autoInitializeUniformUserdatas ) {
auto& userdata = uniforms.emplace_back();
userdata.create( definition.size, nullptr );
}
}
}
@ -870,10 +873,12 @@ const ext::vulkan::Buffer& ext::vulkan::Shader::getUniformBuffer( const uf::stl:
UF_EXCEPTION("buffer not found: " << name);
}
ext::vulkan::userdata_t& ext::vulkan::Shader::getUniform( const uf::stl::string& name ) {
UF_EXCEPTION("[DEPRECATED] " << filename << " " << name);
UF_ASSERT( hasUniform(name) );
return uniforms[metadata.definitions.uniforms[name].index];
}
const ext::vulkan::userdata_t& ext::vulkan::Shader::getUniform( const uf::stl::string& name ) const {
UF_EXCEPTION("[DEPRECATED] " << filename << " " << name);
UF_ASSERT( hasUniform(name) );
return uniforms.at(metadata.definitions.uniforms.at(name).index);
}

View File

@ -605,6 +605,11 @@ void ext::vulkan::Texture::asRenderTarget( Device& device, uint32_t width, uint3
// Initialize a descriptor for later use
this->updateDescriptors();
}
ext::vulkan::Texture ext::vulkan::Texture::alias() const {
ext::vulkan::Texture texture;
texture.aliasTexture(*this);
return texture;
}
void ext::vulkan::Texture::aliasTexture( const Texture& texture ) {
*this = {
.device = nullptr,
@ -1065,4 +1070,20 @@ ext::vulkan::TextureCube::TextureCube() {
viewType = ext::vulkan::enums::Image::VIEW_TYPE_CUBE;
}
ext::vulkan::Texture2D ext::vulkan::Texture2D::alias() const {
ext::vulkan::Texture2D texture;
texture.aliasTexture(*this);
return texture;
}
ext::vulkan::Texture3D ext::vulkan::Texture3D::alias() const {
ext::vulkan::Texture3D texture;
texture.aliasTexture(*this);
return texture;
}
ext::vulkan::TextureCube ext::vulkan::TextureCube::alias() const {
ext::vulkan::TextureCube texture;
texture.aliasTexture(*this);
return texture;
}
#endif

View File

@ -56,6 +56,14 @@ bool ext::vulkan::settings::pipelines::hdr = true;
bool ext::vulkan::settings::pipelines::vxgi = true;
bool ext::vulkan::settings::pipelines::culling = false;
bool ext::vulkan::settings::pipelines::bloom = false;
bool ext::vulkan::settings::pipelines::rt = false;
uf::stl::string ext::vulkan::settings::pipelines::names::vsync = "vsync";
uf::stl::string ext::vulkan::settings::pipelines::names::hdr = "hdr";
uf::stl::string ext::vulkan::settings::pipelines::names::vxgi = "vxgi";
uf::stl::string ext::vulkan::settings::pipelines::names::culling = "culling";
uf::stl::string ext::vulkan::settings::pipelines::names::bloom = "bloom";
uf::stl::string ext::vulkan::settings::pipelines::names::rt = "rt";
VkColorSpaceKHR ext::vulkan::settings::formats::colorSpace;
ext::vulkan::enums::Format::type_t ext::vulkan::settings::formats::color = ext::vulkan::enums::Format::R8G8B8A8_UNORM;
@ -78,17 +86,6 @@ uf::stl::vector<ext::vulkan::RenderMode*> ext::vulkan::renderModes = {
};
uf::stl::unordered_map<uf::stl::string, ext::vulkan::RenderMode*> ext::vulkan::renderModesMap;
PFN_vkGetBufferDeviceAddressKHR ext::vulkan::vkGetBufferDeviceAddressKHR = NULL; // = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR"));
PFN_vkCmdBuildAccelerationStructuresKHR ext::vulkan::vkCmdBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast<PFN_vkCmdBuildAccelerationStructuresKHR>(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR"));
PFN_vkBuildAccelerationStructuresKHR ext::vulkan::vkBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast<PFN_vkBuildAccelerationStructuresKHR>(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR"));
PFN_vkCreateAccelerationStructureKHR ext::vulkan::vkCreateAccelerationStructureKHR = NULL; // = reinterpret_cast<PFN_vkCreateAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR"));
PFN_vkDestroyAccelerationStructureKHR ext::vulkan::vkDestroyAccelerationStructureKHR = NULL; // = reinterpret_cast<PFN_vkDestroyAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR"));
PFN_vkGetAccelerationStructureBuildSizesKHR ext::vulkan::vkGetAccelerationStructureBuildSizesKHR = NULL; // = reinterpret_cast<PFN_vkGetAccelerationStructureBuildSizesKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureBuildSizesKHR"));
PFN_vkGetAccelerationStructureDeviceAddressKHR ext::vulkan::vkGetAccelerationStructureDeviceAddressKHR = NULL; // = reinterpret_cast<PFN_vkGetAccelerationStructureDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR"));
PFN_vkCmdTraceRaysKHR ext::vulkan::vkCmdTraceRaysKHR = NULL; // = reinterpret_cast<PFN_vkCmdTraceRaysKHR>(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR"));
PFN_vkGetRayTracingShaderGroupHandlesKHR ext::vulkan::vkGetRayTracingShaderGroupHandlesKHR = NULL; // = reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesKHR>(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR"));
PFN_vkCreateRayTracingPipelinesKHR ext::vulkan::vkCreateRayTracingPipelinesKHR = NULL; // = reinterpret_cast<PFN_vkCreateRayTracingPipelinesKHR>(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR"));
VkResult ext::vulkan::CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {
auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
if ( func == nullptr ) return VK_ERROR_EXTENSION_NOT_PRESENT;
@ -456,7 +453,7 @@ void ext::vulkan::render() {
uf::graph::render();
uf::scene::render();
if ( renderMode->getType() == "Compute" ) {
if ( renderMode->metadata.compute ) {
submitsCompute.emplace_back(submitInfo);
} else {
submitsGraphics.emplace_back(submitInfo);

View File

@ -62,10 +62,6 @@ void uf::Mesh::destroy() {
buffers.clear();
}
// implicitly convert to opposite interleaving
uf::Mesh uf::Mesh::convert() const {
return copy( !isInterleaved() );
}
uf::Mesh uf::Mesh::copy( bool interleaved ) const {
uf::Mesh res;
@ -75,6 +71,11 @@ uf::Mesh uf::Mesh::copy( bool interleaved ) const {
return res;
}
uf::Mesh uf::Mesh::copy() const { return copy( isInterleaved() ); }
// implicitly convert to opposite interleaving
uf::Mesh uf::Mesh::convert() const { return copy( !isInterleaved() ); }
uf::Mesh uf::Mesh::interleave() const { return copy(true); }
uf::Mesh uf::Mesh::deinterleave() const { return copy(false); }
void uf::Mesh::updateDescriptor() {
_updateDescriptor(vertex);
_updateDescriptor(index);

View File

@ -0,0 +1,222 @@
#include <uf/config.h>
#if UF_USE_VULKAN
#include "behavior.h"
#include <uf/utils/renderer/renderer.h>
#include <uf/utils/math/transform.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/camera/camera.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/engine/asset/asset.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/ext/xatlas/xatlas.h>
#include "../light/behavior.h"
#include "../scene/behavior.h"
#define TEST 0
UF_BEHAVIOR_REGISTER_CPP(ext::RayTraceSceneBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::RayTraceSceneBehavior, ticks = true, renders = false, multithread = false)
#define this (&self)
void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) {
#if TEST
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
auto& graphic = this->getComponent<uf::renderer::Graphic>(); //metadata.renderer.graphic;
auto& mesh = this->getComponent<uf::Mesh>();
mesh.bind<pod::Vertex_3F>();
mesh.insertVertices<pod::Vertex_3F>({
{-1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f, 1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{-1.0f,-1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f,-1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
});
mesh.updateDescriptor();
graphic.initialize("Compute");
graphic.initializeMesh( mesh );
uf::stl::vector<pod::Instance> instances;
auto& instance = instances.emplace_back();
instance.model = uf::matrix::identity();
graphic.generateBottomAccelerationStructures();
graphic.generateTopAccelerationStructure( { &graphic }, instances );
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& image = shader.textures.front();
if ( !uf::renderer::hasRenderMode("Compute", true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
renderMode->setTarget("Compute");
renderMode->metadata.json["shaders"]["vertex"] = "/shaders/display/renderTargetSimple.vert.spv";
renderMode->metadata.json["shaders"]["fragment"] = "/shaders/display/renderTargetSimple.frag.spv";
renderMode->blitter.descriptor.subpass = 1;
renderMode->metadata.type = uf::renderer::settings::pipelines::names::rt;
renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::rt);
renderMode->execute = false;
uf::renderer::addRenderMode( renderMode, "Compute" );
} else {
auto& renderMode = uf::renderer::getRenderMode("Compute", true);
auto& blitter = *renderMode.getBlitter();
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
shader.textures.emplace_back().aliasTexture( image );
}
}
#else
if ( !uf::renderer::hasRenderMode("Compute", true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
renderMode->setTarget("Compute");
renderMode->metadata.json["shaders"]["vertex"] = "/shaders/display/renderTargetSimple.vert.spv";
renderMode->metadata.json["shaders"]["fragment"] = "/shaders/display/renderTargetSimple.frag.spv";
renderMode->blitter.descriptor.subpass = 1;
renderMode->metadata.type = uf::renderer::settings::pipelines::names::rt;
renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::rt);
renderMode->execute = false;
uf::renderer::addRenderMode( renderMode, "Compute" );
}
#endif
}
void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
#if !TEST
if ( !metadata.renderer.bound ) {
auto instances = uf::graph::storage.instances.flatten();
if ( instances.empty() ) return;
uf::stl::vector<uf::Graphic*> graphics;
this->process([&]( uf::Entity* entity ) {
if ( !entity->hasComponent<uf::Graphic>() ) return;
graphics.emplace_back(entity->getComponentPointer<uf::Graphic>());
});
if ( graphics.empty() ) return;
auto& graphic = this->getComponent<uf::renderer::Graphic>();
graphic.initialize("Compute");
graphic.generateTopAccelerationStructure( graphics, instances );
UF_MSG_DEBUG( graphics.size() << " " << instances.size() );
metadata.renderer.bound = true;
return;
}
if ( !metadata.renderer.bound ) return;
#endif
auto& graphic = this->getComponent<uf::renderer::Graphic>();
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& image = shader.textures.front();
struct UniformDescriptor {
struct Matrices {
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
alignas(16) pod::Matrix4f iView;
alignas(16) pod::Matrix4f iProjection;
alignas(16) pod::Matrix4f iProjectionView;
alignas(16) pod::Vector4f eyePos;
} matrices[2];
} uniforms;
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
for ( auto i = 0; i < 2; ++i ) {
uniforms.matrices[i] = UniformDescriptor::Matrices{
.view = camera.getView(i),
.projection = camera.getProjection(i),
.iView = uf::matrix::inverse( camera.getView(i) ),
.iProjection = uf::matrix::inverse( camera.getProjection(i) ),
.iProjectionView = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) ),
.eyePos = camera.getEye( i ),
};
}
for ( auto& buffer : shader.buffers ) {
if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( buffer.allocationInfo.size != sizeof(UniformDescriptor) ) continue;
buffer.update( (const void*) &uniforms, sizeof(UniformDescriptor) );
break;
}
auto& renderMode = uf::renderer::getRenderMode("Compute", true);
auto& blitter = *renderMode.getBlitter();
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
if ( shader.textures.empty() ) {
shader.textures.emplace_back().aliasTexture( image );
renderMode.execute = true;
}
}
if ( uf::renderer::states::resized ) {
image.destroy();
image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, uf::renderer::settings::width, uf::renderer::settings::height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
graphic.descriptor.inputs.width = image.width;
graphic.descriptor.inputs.height = image.height;
graphic.getPipeline().update( graphic );
if ( blitter.material.hasShader("fragment") ) {
auto& shader = blitter.material.getShader("fragment");
shader.textures.front().aliasTexture( image );
}
}
TIMER(1.0, uf::Window::isKeyPressed("R") && ) {
UF_MSG_DEBUG("Screenshotting RT scene...");
image.screenshot().save("./data/rt.png");
}
}
void ext::RayTraceSceneBehavior::render( uf::Object& self ){}
void ext::RayTraceSceneBehavior::destroy( uf::Object& self ){
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
auto& graphic = this->getComponent<uf::renderer::Graphic>(); // metadata.renderer.graphic;
graphic.destroy();
}
void ext::RayTraceSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {}
void ext::RayTraceSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) {}
#undef this
#endif

View File

@ -0,0 +1,22 @@
#pragma once
#include <uf/config.h>
#include <uf/ext/ext.h>
#include <uf/engine/entity/entity.h>
#include <uf/engine/scene/scene.h>
#include <uf/utils/math/vector.h>
#include <uf/utils/graphic/graphic.h>
namespace ext {
namespace RayTraceSceneBehavior {
UF_BEHAVIOR_DEFINE_TYPE();
EXT_BEHAVIOR_DEFINE_TRAITS();
EXT_BEHAVIOR_DEFINE_FUNCTIONS();
UF_BEHAVIOR_DEFINE_METADATA(
struct {
bool bound = false;
} renderer;
);
}
}

View File

@ -331,7 +331,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
auto& controllerMetadata = controller.getComponent<uf::Serializer>();
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
auto& metadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
auto& metadataVxgi = this->getComponent<ext::VoxelizerBehavior::Metadata>();
auto& metadataVxgi = this->getComponent<ext::VoxelizerSceneBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
struct LightInfo {
@ -394,7 +394,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
auto& controllerMetadata = controller.getComponent<uf::Serializer>();
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
auto& metadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
auto& metadataVxgi = this->getComponent<ext::VoxelizerBehavior::Metadata>();
auto& metadataVxgi = this->getComponent<ext::VoxelizerSceneBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
struct LightInfo {
@ -657,7 +657,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
if ( uf::renderer::settings::pipelines::bloom ) {
auto& renderMode = uf::renderer::getRenderMode("", true);
auto& blitter = *renderMode.getBlitters().front();
auto& blitter = *renderMode.getBlitter();
auto& shader = blitter.material.getShader("compute", "bloom");
struct UniformDescriptor {
@ -683,7 +683,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
.samples = bloom.samples,
};
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
}
}
@ -694,7 +694,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
auto& controllerMetadata = controller.getComponent<uf::Serializer>();
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
auto& metadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
auto& metadataVxgi = this->getComponent<ext::VoxelizerBehavior::Metadata>();
auto& metadataVxgi = this->getComponent<ext::VoxelizerSceneBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
auto& renderMode = uf::renderer::getRenderMode(renderModeName, true);
@ -892,7 +892,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
if ( shouldUpdate ) graphic.updatePipelines();
auto& shader = graphic.material.getShader(isCompute ? "compute" : "fragment");
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
}
#endif
}

View File

@ -1,5 +1,5 @@
#include <uf/config.h>
#if !UF_ENV_DREAMCAST
#if UF_USE_VULKAN
#include "behavior.h"
@ -19,12 +19,12 @@
#include <uf/ext/ext.h>
UF_BEHAVIOR_REGISTER_CPP(ext::VoxelizerBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::VoxelizerBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_REGISTER_CPP(ext::VoxelizerSceneBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::VoxelizerSceneBehavior, ticks = true, renders = false, multithread = false)
#define this (&self)
void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
#if UF_USE_VULKAN
auto& metadata = this->getComponent<ext::VoxelizerBehavior::Metadata>();
auto& metadata = this->getComponent<ext::VoxelizerSceneBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
auto& scene = uf::scene::getCurrentScene();
@ -107,12 +107,12 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
metadata.renderModeName = "VXGI:" + std::to_string((int) this->getUid());
uf::renderer::addRenderMode( &renderMode, metadata.renderModeName );
renderMode.metadata.type = "vxgi";
renderMode.metadata.pipeline = "vxgi";
renderMode.metadata.pipelines.emplace_back("vxgi");
renderMode.metadata.type = uf::renderer::settings::pipelines::names::vxgi;
renderMode.metadata.pipeline = uf::renderer::settings::pipelines::names::vxgi;
if ( uf::renderer::settings::pipelines::culling ) {
renderMode.metadata.pipelines.emplace_back("culling");
renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::culling);
}
renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::vxgi);
renderMode.metadata.samples = 1;
renderMode.metadata.subpasses = metadata.cascades;
@ -335,11 +335,11 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
}
#endif
}
void ext::VoxelizerBehavior::tick( uf::Object& self ) {
void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
#if UF_USE_VULKAN
if ( !this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) return;
auto& metadata = this->getComponent<ext::VoxelizerBehavior::Metadata>();
auto& metadata = this->getComponent<ext::VoxelizerSceneBehavior::Metadata>();
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
auto& scene = uf::scene::getCurrentScene();
@ -388,8 +388,8 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
for ( auto entity : graph ) {
if ( !entity->hasComponent<uf::Graphic>() ) continue;
auto& graphic = entity->getComponent<uf::Graphic>();
if ( graphic.material.hasShader("geometry", "vxgi") ) {
auto& shader = graphic.material.getShader("geometry", "vxgi");
if ( graphic.material.hasShader("geometry", uf::renderer::settings::pipelines::names::vxgi) ) {
auto& shader = graphic.material.getShader("geometry", uf::renderer::settings::pipelines::names::vxgi);
struct UniformDescriptor {
/*alignas(16)*/ pod::Matrix4f matrix;
/*alignas(4)*/ float cascadePower;
@ -430,7 +430,7 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
.traceStartOffsetFactor = metadata.traceStartOffsetFactor,
.shadows = metadata.shadows,
};
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
#endif
}
}
@ -441,8 +441,8 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
ext::ExtSceneBehavior::bindBuffers( scene );
#endif
}
void ext::VoxelizerBehavior::render( uf::Object& self ){}
void ext::VoxelizerBehavior::destroy( uf::Object& self ){
void ext::VoxelizerSceneBehavior::render( uf::Object& self ){}
void ext::VoxelizerSceneBehavior::destroy( uf::Object& self ){
#if UF_USE_VULKAN
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
@ -451,7 +451,7 @@ void ext::VoxelizerBehavior::destroy( uf::Object& self ){
}
#endif
}
void ext::VoxelizerBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {
void ext::VoxelizerSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {
serializer["vxgi"]["size"] = /*this->*/voxelSize.x;
serializer["vxgi"]["limiter"] = /*this->*/limiter.frequency;
serializer["vxgi"]["dispatch"] = /*this->*/dispatchSize.x;
@ -467,7 +467,7 @@ void ext::VoxelizerBehavior::Metadata::serialize( uf::Object& self, uf::Serializ
serializer["vxgi"]["extents"]["min"] = uf::vector::encode(/*this->*/extents.min);
serializer["vxgi"]["extents"]["max"] = uf::vector::encode(/*this->*/extents.max);
}
void ext::VoxelizerBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) {
void ext::VoxelizerSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) {
/*this->*/voxelSize.x = serializer["vxgi"]["size"].as<size_t>(96);
/*this->*/voxelSize.y = serializer["vxgi"]["size"].as<size_t>(96);
/*this->*/voxelSize.z = serializer["vxgi"]["size"].as<size_t>(96);

View File

@ -8,7 +8,7 @@
#include <uf/utils/math/matrix.h>
namespace ext {
namespace VoxelizerBehavior {
namespace VoxelizerSceneBehavior {
UF_BEHAVIOR_DEFINE_TYPE();
EXT_BEHAVIOR_DEFINE_TRAITS();
EXT_BEHAVIOR_DEFINE_FUNCTIONS();

View File

@ -83,7 +83,11 @@ namespace {
UF_VERTEX_DESCRIPTOR(GuiMesh,
UF_VERTEX_DESCRIPTION(GuiMesh, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(GuiMesh, R32G32_SFLOAT, uv)
#if EXT_COLOR_FLOATS
UF_VERTEX_DESCRIPTION(GuiMesh, R32G32B32A32_SFLOAT, color)
#else
UF_VERTEX_DESCRIPTION(GuiMesh, R8G8B8A8_UNORM, color)
#endif
)
uf::stl::vector<pod::GlyphBox> ext::Gui::generateGlyphs( const uf::stl::string& _string ) {
@ -895,9 +899,107 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
if ( !graphic.material.hasShader("vertex") ) return;
auto& shader = graphic.material.getShader("vertex");
#if 1
auto model = uf::matrix::identity();
auto& uniformBuffer = shader.getUniformBuffer("UBO");
isGlyph = isGlyph && uniformBuffer.allocationInfo.size == sizeof(::GlyphUniformDescriptor<>);
if ( isGlyph ) {
auto& metadataGlyph = this->getComponent<ext::GuiBehavior::GlyphMetadata>();
::GlyphUniformDescriptor<> uniforms;
for ( uint_fast8_t i = 0; i < uf::renderer::settings::maxViews; ++i ) {
if ( metadata.mode == 1 ) {
uniforms.matrices[i].model = transform.model;
} else if ( metadata.mode == 2 ) {
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
uniforms.matrices[i].model = camera.getProjection(i) * camera.getView(i) * uf::transform::model( transform );
} else if ( metadata.mode == 3 ) {
pod::Transform<> flatten = uf::transform::flatten( transform );
uniforms.matrices[i].model =
camera.getProjection(i) *
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
uf::quaternion::matrix( flatten.orientation ) *
flatten.model;
} else {
pod::Transform<> flatten = uf::transform::flatten( transform );
uniforms.matrices[i].model =
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
uf::quaternion::matrix( flatten.orientation ) *
flatten.model;
}
}
uniforms.gui = ::UniformDescriptor<>::Gui{
.offset = metadata.uv,
.color = metadata.color,
.mode = metadata.shader,
// .depth = 1 - metadata.depth,
.depth = uf::matrix::reverseInfiniteProjection ? 1 - metadata.depth : metadata.depth,
};
if ( metadataGlyph.sdf ) uniforms.gui.mode &= 1 << 1;
if ( metadataGlyph.shadowbox ) uniforms.gui.mode &= 1 << 2;
uniforms.glyph.stroke = metadataGlyph.stroke;
uniforms.glyph.spread = metadataGlyph.spread;
uniforms.glyph.weight = metadataGlyph.weight;
uniforms.glyph.scale = metadataGlyph.scale;
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), uniformBuffer );
model = uniforms.matrices[0].model;
} else {
UniformDescriptor<> uniforms{};
for ( uint_fast8_t i = 0; i < uf::renderer::settings::maxViews; ++i ) {
if ( metadata.mode == 1 ) {
uniforms.matrices[i].model = transform.model;
} else if ( metadata.mode == 2 ) {
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
uniforms.matrices[i].model = camera.getProjection(i) * camera.getView(i) * uf::transform::model( transform );
} else if ( metadata.mode == 3 ) {
pod::Transform<> flatten = uf::transform::flatten( transform );
uniforms.matrices[i].model =
camera.getProjection(i) *
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
uf::quaternion::matrix( flatten.orientation ) *
flatten.model;
} else {
pod::Transform<> flatten = uf::transform::flatten( transform );
uniforms.matrices[i].model =
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
uf::quaternion::matrix( flatten.orientation ) *
flatten.model;
}
}
uniforms.gui = ::UniformDescriptor<>::Gui{
.offset = metadata.uv,
.color = metadata.color,
.mode = metadata.shader,
// .depth = 1 - metadata.depth,
.depth = uf::matrix::reverseInfiniteProjection ? 1 - metadata.depth : metadata.depth,
};
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), uniformBuffer );
model = uniforms.matrices[0].model;
}
#else
#if UF_UNIFORMS_REUSE
auto& uniform = shader.getUniform("UBO");
auto& uniforms = uniform.get<UniformDescriptor<>>(false); // skip validation
#else
UniformDescriptor<> uniforms{};
#endif
for ( uint_fast8_t i = 0; i < uf::renderer::settings::maxViews; ++i ) {
if ( metadata.mode == 1 ) {
uniforms.matrices[i].model = transform.model;
@ -933,23 +1035,29 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
.depth = uf::matrix::reverseInfiniteProjection ? 1 - metadata.depth : metadata.depth,
};
// set glyph-based uniforms
if ( isGlyph && uniform.size() == sizeof(::GlyphUniformDescriptor<>) ) {
auto& uniforms = uniform.get<::GlyphUniformDescriptor<>>();
if ( isGlyph ) {
::GlyphUniformDescriptor<> gUniforms;
memcpy( &gUniforms, &uniforms, sizeof(uniforms) );
auto& metadataGlyph = this->getComponent<ext::GuiBehavior::GlyphMetadata>();
if ( metadataGlyph.sdf ) uniforms.gui.mode &= 1 << 1;
if ( metadataGlyph.shadowbox ) uniforms.gui.mode &= 1 << 2;
uniforms.glyph.stroke = metadataGlyph.stroke;
uniforms.glyph.spread = metadataGlyph.spread;
uniforms.glyph.weight = metadataGlyph.weight;
uniforms.glyph.scale = metadataGlyph.scale;
gUniforms.glyph.stroke = metadataGlyph.stroke;
gUniforms.glyph.spread = metadataGlyph.spread;
gUniforms.glyph.weight = metadataGlyph.weight;
gUniforms.glyph.scale = metadataGlyph.scale;
shader.updateBuffer( (const void*) &gUniforms, sizeof(gUniforms), shader.getUniformBuffer("UBO") );
} else {
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
}
// shader.updateBuffer( uniform, shader.getUniformBuffer("UBO") );
shader.updateUniform( "UBO", uniform );
// shader.updateUniform( "UBO", uniform );
// calculate click box
auto& model = uniforms.matrices[0].model;
#endif
#endif
pod::Vector2f min = { 1, 1 };
pod::Vector2f max = { -1, -1 };

View File

@ -160,7 +160,7 @@ void ext::GuiManagerBehavior::tick( uf::Object& self ) {
#if UF_UNIFORMS_REUSE
shader.updateUniform( "UBO", uniform );
#else
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
#endif
#endif
}

View File

@ -416,6 +416,7 @@ void EXT_API ext::initialize() {
uf::renderer::settings::pipelines::vxgi = configRenderPipelinesJson["vxgi"].as( uf::renderer::settings::pipelines::vxgi );
uf::renderer::settings::pipelines::culling = configRenderPipelinesJson["culling"].as( uf::renderer::settings::pipelines::culling );
uf::renderer::settings::pipelines::bloom = configRenderPipelinesJson["bloom"].as( uf::renderer::settings::pipelines::bloom );
uf::renderer::settings::pipelines::rt = configRenderPipelinesJson["rt"].as( uf::renderer::settings::pipelines::rt );
#define JSON_TO_VKFORMAT( key ) if ( configRenderJson["formats"][#key].is<uf::stl::string>() ) {\
uf::stl::string format = configRenderJson["formats"][#key].as<uf::stl::string>();\
@ -472,10 +473,24 @@ void EXT_API ext::initialize() {
/* Initialize Vulkan */ {
// setup render mode
#if UF_USE_VULKAN
/*
if ( ::json["engine"]["render modes"]["compute"].as<bool>(true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
renderMode->setTarget("Compute");
renderMode->metadata.json["shaders"]["vertex"] = "/shaders/display/renderTargetSimple.vert.spv";
renderMode->metadata.json["shaders"]["fragment"] = "/shaders/display/renderTargetSimple.frag.spv";
renderMode->blitter.descriptor.subpass = 1;
renderMode->metadata.type = "rt";
renderMode->metadata.pipelines.emplace_back("rt");
uf::renderer::addRenderMode( renderMode, "Compute" );
}
*/
#endif
if ( ::json["engine"]["render modes"]["gui"].as<bool>(true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
uf::renderer::addRenderMode( renderMode, "Gui" );
renderMode->blitter.descriptor.subpass = 1;
uf::renderer::addRenderMode( renderMode, "Gui" );
}
if ( ::json["engine"]["render modes"]["deferred"].as<bool>(true) ) {
uf::renderer::addRenderMode( new uf::renderer::DeferredRenderMode, "" );
@ -484,15 +499,11 @@ void EXT_API ext::initialize() {
renderMode.metadata.eyes = 2;
}
if ( uf::renderer::settings::pipelines::culling ) {
renderMode.metadata.pipelines.emplace_back("culling");
renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::culling);
}
}
#if UF_USE_VULKAN
if ( ::json["engine"]["render modes"]["raytrace"].as<bool>(false) ) {
auto* renderMode = new uf::renderer::RayTraceRenderMode;
uf::renderer::addRenderMode( renderMode, "RayTrace" );
}
/* Callbacks for 2KHR stuffs */ {
uf::hooks.addHook("vulkan:Instance.ExtensionsEnabled", []( const ext::json::Value& json ) {
// UF_MSG_DEBUG("vulkan:Instance.ExtensionsEnabled: " << json);