Commit for 2022.06.23 22-40-45.7z
This commit is contained in:
parent
70162646cb
commit
ddb43b26ea
@ -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"
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
14
bin/data/shaders/display/renderTargetSimple.frag.glsl
Normal file
14
bin/data/shaders/display/renderTargetSimple.frag.glsl
Normal 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 );
|
||||
}
|
||||
16
bin/data/shaders/display/renderTargetSimple.vert.glsl
Normal file
16
bin/data/shaders/display/renderTargetSimple.vert.glsl
Normal 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);
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"engine": {
|
||||
"scenes": {
|
||||
"start": "StartMenu",
|
||||
"start": "SS2",
|
||||
"meshes": { "interleaved": false },
|
||||
"matrix": { "reverseInfinite": false },
|
||||
"lights": { "enabled": false,
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -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{};
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
//
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
46
engine/inc/uf/utils/memory/key_map.h
Normal file
46
engine/inc/uf/utils/memory/key_map.h
Normal 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;
|
||||
}
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -258,9 +258,6 @@ namespace {
|
||||
|
||||
mesh.updateDescriptor();
|
||||
|
||||
// return mesh.expand();
|
||||
// if ( mesh.isInterleaved() != uf::Mesh::defaultInterleaved ) return mesh.copy(true);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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 );
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
259
engine/src/ext/vulkan/rendermodes/compute.cpp
Normal file
259
engine/src/ext/vulkan/rendermodes/compute.cpp
Normal 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
|
||||
@ -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++);
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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] );
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
222
ext/behaviors/raytrace/behavior.cpp
Normal file
222
ext/behaviors/raytrace/behavior.cpp
Normal 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
|
||||
22
ext/behaviors/raytrace/behavior.h
Normal file
22
ext/behaviors/raytrace/behavior.h
Normal 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;
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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 };
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
23
ext/main.cpp
23
ext/main.cpp
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user