diff --git a/bin/data/config.json b/bin/data/config.json index cd943be8..2e4a764b 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -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" diff --git a/bin/data/shaders/common/macros.h b/bin/data/shaders/common/macros.h index a6c1c75e..6abe4b8a 100644 --- a/bin/data/shaders/common/macros.h +++ b/bin/data/shaders/common/macros.h @@ -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; diff --git a/bin/data/shaders/common/structs.h b/bin/data/shaders/common/structs.h index 07ab058f..2e91443c 100644 --- a/bin/data/shaders/common/structs.h +++ b/bin/data/shaders/common/structs.h @@ -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; diff --git a/bin/data/shaders/display/renderTargetSimple.frag.glsl b/bin/data/shaders/display/renderTargetSimple.frag.glsl new file mode 100644 index 00000000..3a61a822 --- /dev/null +++ b/bin/data/shaders/display/renderTargetSimple.frag.glsl @@ -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 ); +} \ No newline at end of file diff --git a/bin/data/shaders/display/renderTargetSimple.vert.glsl b/bin/data/shaders/display/renderTargetSimple.vert.glsl new file mode 100644 index 00000000..95fd44b3 --- /dev/null +++ b/bin/data/shaders/display/renderTargetSimple.vert.glsl @@ -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); +} \ No newline at end of file diff --git a/bin/data/shaders/display/rendertarget.vert.glsl b/bin/data/shaders/display/rendertarget.vert.glsl index ff305fa6..927782af 100644 --- a/bin/data/shaders/display/rendertarget.vert.glsl +++ b/bin/data/shaders/display/rendertarget.vert.glsl @@ -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; diff --git a/bin/data/shaders/display/subpass.h b/bin/data/shaders/display/subpass.h index da4174d7..6607891f 100644 --- a/bin/data/shaders/display/subpass.h +++ b/bin/data/shaders/display/subpass.h @@ -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; diff --git a/bin/data/shaders/display/vxgi.comp.h b/bin/data/shaders/display/vxgi.comp.h index a31ffeee..0a5301c0 100644 --- a/bin/data/shaders/display/vxgi.comp.h +++ b/bin/data/shaders/display/vxgi.comp.h @@ -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" diff --git a/bin/data/shaders/raytrace/shader.gen.glsl b/bin/data/shaders/raytrace/shader.gen.glsl index 064ed4ea..dd0b6531 100644 --- a/bin/data/shaders/raytrace/shader.gen.glsl +++ b/bin/data/shaders/raytrace/shader.gen.glsl @@ -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)); diff --git a/bin/data/shaders/raytrace/shader.miss.glsl b/bin/data/shaders/raytrace/shader.miss.glsl index 8fb8e091..73866f8d 100644 --- a/bin/data/shaders/raytrace/shader.miss.glsl +++ b/bin/data/shaders/raytrace/shader.miss.glsl @@ -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); } \ No newline at end of file diff --git a/bin/dreamcast/config.json b/bin/dreamcast/config.json index dcaa7e7e..4e1cad53 100644 --- a/bin/dreamcast/config.json +++ b/bin/dreamcast/config.json @@ -1,7 +1,7 @@ { "engine": { "scenes": { - "start": "StartMenu", + "start": "SS2", "meshes": { "interleaved": false }, "matrix": { "reverseInfinite": false }, "lights": { "enabled": false, diff --git a/engine/inc/uf/engine/graph/graph.h b/engine/inc/uf/engine/graph/graph.h index 8baf625b..7267bd14 100644 --- a/engine/inc/uf/engine/graph/graph.h +++ b/engine/inc/uf/engine/graph/graph.h @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -60,46 +61,27 @@ namespace pod { // Local storage, used for save/load struct Storage { - template - struct KeyMap { - public: - uf::stl::vector keys; - uf::stl::unordered_map map; - uf::stl::unordered_map 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 instances; + uf::stl::KeyMap instanceAddresses; + uf::stl::KeyMap> primitives; + uf::stl::KeyMap> drawCommands; + uf::stl::KeyMap meshes; - void reserve( size_t i ) { - keys.reserve(i); - indices.reserve(i); - map.reserve(i); - } - }; - - KeyMap instances; - KeyMap> primitives; - KeyMap> drawCommands; - KeyMap meshes; - - KeyMap images; - KeyMap materials; - KeyMap textures; - KeyMap samplers; + uf::stl::KeyMap images; + uf::stl::KeyMap materials; + uf::stl::KeyMap textures; + uf::stl::KeyMap samplers; uf::stl::vector lights; - KeyMap skins; - KeyMap animations; + uf::stl::KeyMap skins; + uf::stl::KeyMap animations; // maps without direct analogues - KeyMap atlases; - KeyMap> joints; - KeyMap texture2Ds; - KeyMap entities; + uf::stl::KeyMap atlases; + uf::stl::KeyMap> joints; + uf::stl::KeyMap texture2Ds; + uf::stl::KeyMap entities; uf::stl::vector shadow2Ds; uf::stl::vector 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 ); diff --git a/engine/inc/uf/ext/opengl/buffer.h b/engine/inc/uf/ext/opengl/buffer.h index 5f92d00a..0e345948 100644 --- a/engine/inc/uf/ext/opengl/buffer.h +++ b/engine/inc/uf/ext/opengl/buffer.h @@ -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 ); diff --git a/engine/inc/uf/ext/opengl/graphic.h b/engine/inc/uf/ext/opengl/graphic.h index 22857289..8aba4c8f 100644 --- a/engine/inc/uf/ext/opengl/graphic.h +++ b/engine/inc/uf/ext/opengl/graphic.h @@ -55,7 +55,8 @@ namespace ext { struct Metadata { uf::Serializer json; uf::stl::unordered_map shaders; - bool autoInitializeUniforms = true; + bool autoInitializeUniformBuffers = true; + bool autoInitializeUniformUserdatas = false; } metadata; void initialize( Device& device ); diff --git a/engine/inc/uf/ext/opengl/opengl.h b/engine/inc/uf/ext/opengl/opengl.h index 6da22193..69e248ea 100644 --- a/engine/inc/uf/ext/opengl/opengl.h +++ b/engine/inc/uf/ext/opengl/opengl.h @@ -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 { diff --git a/engine/inc/uf/ext/opengl/shader.h b/engine/inc/uf/ext/opengl/shader.h index e8b54896..4419a73a 100644 --- a/engine/inc/uf/ext/opengl/shader.h +++ b/engine/inc/uf/ext/opengl/shader.h @@ -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 { diff --git a/engine/inc/uf/ext/opengl/texture.h b/engine/inc/uf/ext/opengl/texture.h index b31bc054..a614973a 100644 --- a/engine/inc/uf/ext/opengl/texture.h +++ b/engine/inc/uf/ext/opengl/texture.h @@ -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; }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/buffer.h b/engine/inc/uf/ext/vulkan/buffer.h index 7099831e..76b84d5a 100644 --- a/engine/inc/uf/ext/vulkan/buffer.h +++ b/engine/inc/uf/ext/vulkan/buffer.h @@ -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 inline bool updateBuffer( const T* data, const Buffer& buffer, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( (const void*) data, static_cast(sizeof(T)), buffer, stage ); } - template inline bool updateBuffer( const T& data, const Buffer& buffer, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( (const void*) &data, static_cast(sizeof(T)), buffer, stage ); } + // template inline bool updateBuffer( const T& data, const Buffer& buffer, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( (const void*) &data, static_cast(sizeof(T)), buffer, stage ); } + }; + + struct AccelerationStructure { + VkAccelerationStructureKHR handle{VK_NULL_HANDLE}; + size_t deviceAddress{}; + size_t instanceID{}; }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/graphic.h b/engine/inc/uf/ext/vulkan/graphic.h index e3a16114..06108934 100644 --- a/engine/inc/uf/ext/vulkan/graphic.h +++ b/engine/inc/uf/ext/vulkan/graphic.h @@ -55,7 +55,8 @@ namespace ext { struct Metadata { uf::Serializer json; - bool autoInitializeUniforms = true; + bool autoInitializeUniformBuffers = true; + bool autoInitializeUniformUserdatas = false; uf::stl::unordered_map 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 bottoms; } accelerationStructures; ~Graphic(); void initialize( const uf::stl::string& = "" ); void destroy(); - - // template - // void initializeMesh( uf::Mesh& 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&, const uf::stl::vector& ); 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" \ No newline at end of file +} \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/graphic.inl b/engine/inc/uf/ext/vulkan/graphic.inl deleted file mode 100644 index 6d4b4a81..00000000 --- a/engine/inc/uf/ext/vulkan/graphic.inl +++ /dev/null @@ -1,8 +0,0 @@ -#if 0 -template -void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, size_t o ) { - if ( mesh.indices.empty() ) mesh.initialize( o ); - mesh.updateDescriptor(); - initializeAttributes( mesh.attributes ); -} -#endif \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/rendermode.h b/engine/inc/uf/ext/vulkan/rendermode.h index e8913aef..c1ddaeb0 100644 --- a/engine/inc/uf/ext/vulkan/rendermode.h +++ b/engine/inc/uf/ext/vulkan/rendermode.h @@ -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; diff --git a/engine/inc/uf/ext/vulkan/rendermodes/raytrace.h b/engine/inc/uf/ext/vulkan/rendermodes/compute.h similarity index 89% rename from engine/inc/uf/ext/vulkan/rendermodes/raytrace.h rename to engine/inc/uf/ext/vulkan/rendermodes/compute.h index e2e8c495..2a5c8df7 100644 --- a/engine/inc/uf/ext/vulkan/rendermodes/raytrace.h +++ b/engine/inc/uf/ext/vulkan/rendermodes/compute.h @@ -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; // diff --git a/engine/inc/uf/ext/vulkan/shader.h b/engine/inc/uf/ext/vulkan/shader.h index 5c5dca4a..2b88bf8a 100644 --- a/engine/inc/uf/ext/vulkan/shader.h +++ b/engine/inc/uf/ext/vulkan/shader.h @@ -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 { diff --git a/engine/inc/uf/ext/vulkan/texture.h b/engine/inc/uf/ext/vulkan/texture.h index 07b85d99..a731c94e 100644 --- a/engine/inc/uf/ext/vulkan/texture.h +++ b/engine/inc/uf/ext/vulkan/texture.h @@ -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; }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/vk.h b/engine/inc/uf/ext/vulkan/vk.h index 12a19dc7..e7d898cf 100644 --- a/engine/inc/uf/ext/vulkan/vk.h +++ b/engine/inc/uf/ext/vulkan/vk.h @@ -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 \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/vulkan.h b/engine/inc/uf/ext/vulkan/vulkan.h index 8a248552..1979e85b 100644 --- a/engine/inc/uf/ext/vulkan/vulkan.h +++ b/engine/inc/uf/ext/vulkan/vulkan.h @@ -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 { diff --git a/engine/inc/uf/macros.h b/engine/inc/uf/macros.h index 75f0a20c..f799752b 100644 --- a/engine/inc/uf/macros.h +++ b/engine/inc/uf/macros.h @@ -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; diff --git a/engine/inc/uf/spec/renderer/vulkan.h b/engine/inc/uf/spec/renderer/vulkan.h index 43992006..770fb96d 100644 --- a/engine/inc/uf/spec/renderer/vulkan.h +++ b/engine/inc/uf/spec/renderer/vulkan.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include namespace spec { diff --git a/engine/inc/uf/utils/memory/key_map.h b/engine/inc/uf/utils/memory/key_map.h new file mode 100644 index 00000000..f316ac7b --- /dev/null +++ b/engine/inc/uf/utils/memory/key_map.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include "./allocator.h" + +#include + +namespace uf { + namespace stl { + template + struct KeyMap { + public: + uf::stl::vector keys; + uf::stl::unordered_map map; + uf::stl::unordered_map indices; + + T& operator[]( const Key& key ); + void reserve( size_t i ); + uf::stl::vector flatten() const; + }; + } +} + + +template +T& uf::stl::KeyMap::operator[]( const Key& key ) { + if ( map.count( key ) == 0 ) { + indices[key] = keys.size(); + keys.emplace_back( key ); + } + return map[key]; +} + +template +void uf::stl::KeyMap::reserve( size_t i ) { + keys.reserve(i); + indices.reserve(i); + map.reserve(i); +} + +template +uf::stl::vector uf::stl::KeyMap::flatten() const { + uf::stl::vector res; res.reserve(keys.size()); + for ( auto& key : keys ) res.emplace_back(map.at(key)); + return res; +} \ No newline at end of file diff --git a/engine/inc/uf/utils/mesh/mesh.h b/engine/inc/uf/utils/mesh/mesh.h index 222d49bf..d541b636 100644 --- a/engine/inc/uf/utils/mesh/mesh.h +++ b/engine/inc/uf/utils/mesh/mesh.h @@ -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); diff --git a/engine/inc/uf/utils/userdata/pointered.inl b/engine/inc/uf/utils/userdata/pointered.inl index 6210d5e4..17dbe10e 100644 --- a/engine/inc/uf/utils/userdata/pointered.inl +++ b/engine/inc/uf/utils/userdata/pointered.inl @@ -104,7 +104,10 @@ pod::PointeredUserdata uf::pointeredUserdata::create( uf::MemoryPool& requestedM #include template T& uf::pointeredUserdata::get( pod::PointeredUserdata& userdata, bool validate ) { - if ( validate && !uf::pointeredUserdata::is( userdata ) ) UF_EXCEPTION("PointeredUserdata size|type mismatch"); // : Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata.type << ", " << userdata.len << "}" ); + if ( validate && !uf::pointeredUserdata::is( 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 const T& uf::pointeredUserdata::get( const pod::PointeredUserdata& userdata, bool validate ) { - if ( validate && !uf::pointeredUserdata::is( userdata ) ) UF_EXCEPTION("PointeredUserdata size|type mismatch"); // : Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata.type << ", " << userdata.len << "}" ); + if ( validate && !uf::pointeredUserdata::is( 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; diff --git a/engine/inc/uf/utils/userdata/userdata.inl b/engine/inc/uf/utils/userdata/userdata.inl index 9d3e785f..db67ed12 100644 --- a/engine/inc/uf/utils/userdata/userdata.inl +++ b/engine/inc/uf/utils/userdata/userdata.inl @@ -24,7 +24,10 @@ pod::Userdata* uf::userdata::create( uf::MemoryPool& requestedMemoryPool, const #include template T& uf::userdata::get( pod::Userdata* userdata, bool validate ) { - if ( validate && !uf::userdata::is( userdata ) ) UF_EXCEPTION("PointeredUserdata size|type mismatch"); // : Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata->type << ", " << userdata->len << "}" ); + if ( validate && !uf::userdata::is( 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 const T& uf::userdata::get( const pod::Userdata* userdata, bool validate ) { - if ( validate && !uf::userdata::is( userdata ) ) UF_EXCEPTION("PointeredUserdata size|type mismatch"); // : Expecting {" << UF_USERDATA_CTTI(T) << ", " << sizeof(T) << "}, got {" << userdata->type << ", " << userdata->len << "}" ); + if ( validate && !uf::userdata::is( 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; diff --git a/engine/src/engine/graph/convert.cpp b/engine/src/engine/graph/convert.cpp index 517d7f8b..4a6b70a0 100644 --- a/engine/src/engine/graph/convert.cpp +++ b/engine/src/engine/graph/convert.cpp @@ -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 ); } } diff --git a/engine/src/engine/graph/decode.cpp b/engine/src/engine/graph/decode.cpp index 2cb00c2a..abd08fdb 100644 --- a/engine/src/engine/graph/decode.cpp +++ b/engine/src/engine/graph/decode.cpp @@ -258,9 +258,6 @@ namespace { mesh.updateDescriptor(); - // return mesh.expand(); - // if ( mesh.isInterleaved() != uf::Mesh::defaultInterleaved ) return mesh.copy(true); - return mesh; } diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index b9f54af1..fe61f5e2 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -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(); auto& sceneMetadataJson = scene.getComponent(); - auto& graphic = entity.getComponent(); + auto& graphic = entity.getComponent(); + 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("/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("/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() ) { { - 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::graph::initializeGraphics( graph, *graph.root.entity, mesh ); + /* + if ( uf::renderer::settings::pipelines::rt ) { + uf::stl::vector graphics = { &graphic }; + graphic.generateTopAccelerationStructure( graphics, uf::graph::storage.instances.flatten() ); + } + */ } + } else if ( uf::renderer::settings::pipelines::rt ) { + /* + auto& graphic = graph.root.entity->getComponent(); + graphic.initialize("Compute"); - { - auto& graphic = graph.root.entity->getComponent(); - graphic.initialize(); - graphic.initializeMesh( mesh ); - graphic.process = true; - - uf::graph::initializeGraphics( graph, *graph.root.entity ); + uf::stl::vector graphics; + for ( auto& node : graph.nodes ) { + if ( !node.entity || !node.entity->hasComponent() ) continue; + graphics.emplace_back(node.entity->getComponentPointer()); } + 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()) && graph.metadata["flags"]["RENDER"].as() ) { - // uf::instantiator::bind("RenderBehavior", entity); - - auto& graphic = entity.getComponent(); - 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() ) ); - if ( !entity->hasComponent() ) { + if ( !entity->hasComponent() ) { if ( entity->getUid() == 0 ) entity->initialize(); //UF_MSG_DEBUG( "Initialized " << uf::string::toString( entity->as() ) ); 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 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 instances = uf::graph::storage.instances.flatten(); + uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) ); +/* + uf::stl::vector 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 instanceAddresses = uf::graph::storage.instanceAddresses.flatten(); + uf::graph::storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::InstanceAddresses) ); uf::stl::vector 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 materials = uf::graph::storage.materials.flatten(); + uf::stl::vector textures = uf::graph::storage.textures.flatten(); + + uf::stl::vector 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 drawCommands; drawCommands.reserve(uf::graph::storage.drawCommands.map.size()); uf::stl::vector materials; materials.reserve(uf::graph::storage.materials.map.size()); uf::stl::vector 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 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 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; } } diff --git a/engine/src/engine/scene/scene.cpp b/engine/src/engine/scene/scene.cpp index b66d988e..08302bd9 100644 --- a/engine/src/engine/scene/scene.cpp +++ b/engine/src/engine/scene/scene.cpp @@ -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; } diff --git a/engine/src/ext/bullet/bullet.cpp b/engine/src/ext/bullet/bullet.cpp index 08e32a7a..498f5443 100644 --- a/engine/src/ext/bullet/bullet.cpp +++ b/engine/src/ext/bullet/bullet.cpp @@ -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 ); diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index 31f53608..3cc78302 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -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()); diff --git a/engine/src/ext/gltf/processPrimitives2.inl b/engine/src/ext/gltf/processPrimitives2.inl index aedc4935..c674b3f9 100644 --- a/engine/src/ext/gltf/processPrimitives2.inl +++ b/engine/src/ext/gltf/processPrimitives2.inl @@ -186,7 +186,7 @@ if ( meshgrid.grid.divisions.x > 1 || meshgrid.grid.divisions.y > 1 || meshgrid. size_t vertexID = 0; mesh.bindIndirect(); - mesh.bind(); + mesh.bind(false); // default to de-interleaved regardless of requirement (makes things easier) for ( auto& meshlet : meshlets ) { auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{ diff --git a/engine/src/ext/opengl/buffer.cpp b/engine/src/ext/opengl/buffer.cpp index c181b752..9ed00357 100644 --- a/engine/src/ext/opengl/buffer.cpp +++ b/engine/src/ext/opengl/buffer.cpp @@ -6,6 +6,11 @@ #include #include +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, diff --git a/engine/src/ext/opengl/graphic.cpp b/engine/src/ext/opengl/graphic.cpp index 8488d9ef..10a907fa 100644 --- a/engine/src/ext/opengl/graphic.cpp +++ b/engine/src/ext/opengl/graphic.cpp @@ -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"; diff --git a/engine/src/ext/opengl/opengl.cpp b/engine/src/ext/opengl/opengl.cpp index 37907ddf..274c1a1b 100644 --- a/engine/src/ext/opengl/opengl.cpp +++ b/engine/src/ext/opengl/opengl.cpp @@ -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; diff --git a/engine/src/ext/opengl/rendermodes/rendertarget.cpp b/engine/src/ext/opengl/rendermodes/rendertarget.cpp index 38bfe2c0..13af3271 100644 --- a/engine/src/ext/opengl/rendermodes/rendertarget.cpp +++ b/engine/src/ext/opengl/rendermodes/rendertarget.cpp @@ -35,11 +35,11 @@ uf::stl::vector 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; } diff --git a/engine/src/ext/opengl/shader.cpp b/engine/src/ext/opengl/shader.cpp index 49cc7f21..4e547a1c 100644 --- a/engine/src/ext/opengl/shader.cpp +++ b/engine/src/ext/opengl/shader.cpp @@ -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 diff --git a/engine/src/ext/opengl/texture.cpp b/engine/src/ext/opengl/texture.cpp index fe277454..b3481077 100644 --- a/engine/src/ext/opengl/texture.cpp +++ b/engine/src/ext/opengl/texture.cpp @@ -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 \ No newline at end of file diff --git a/engine/src/ext/reactphysics/reactphysics.cpp b/engine/src/ext/reactphysics/reactphysics.cpp index 046edf7a..c2919610 100644 --- a/engine/src/ext/reactphysics/reactphysics.cpp +++ b/engine/src/ext/reactphysics/reactphysics.cpp @@ -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 ); diff --git a/engine/src/ext/vulkan/buffer.cpp b/engine/src/ext/vulkan/buffer.cpp index 81a3f696..14449a10 100644 --- a/engine/src/ext/vulkan/buffer.cpp +++ b/engine/src/ext/vulkan/buffer.cpp @@ -7,21 +7,12 @@ #include #include +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; diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index 7cc348b7..0807c008 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -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 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; diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 469fc994..d2ebf2bf 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -19,6 +19,17 @@ namespace { uint32_t VERTEX_BUFFER_BIND_ID = 0; } +PFN_vkGetBufferDeviceAddressKHR ext::vulkan::vkGetBufferDeviceAddressKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); +PFN_vkCmdBuildAccelerationStructuresKHR ext::vulkan::vkCmdBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR")); +PFN_vkBuildAccelerationStructuresKHR ext::vulkan::vkBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR")); +PFN_vkCreateAccelerationStructureKHR ext::vulkan::vkCreateAccelerationStructureKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR")); +PFN_vkDestroyAccelerationStructureKHR ext::vulkan::vkDestroyAccelerationStructureKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR")); +PFN_vkGetAccelerationStructureBuildSizesKHR ext::vulkan::vkGetAccelerationStructureBuildSizesKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureBuildSizesKHR")); +PFN_vkGetAccelerationStructureDeviceAddressKHR ext::vulkan::vkGetAccelerationStructureDeviceAddressKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR")); +PFN_vkCmdTraceRaysKHR ext::vulkan::vkCmdTraceRaysKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR")); +PFN_vkGetRayTracingShaderGroupHandlesKHR ext::vulkan::vkGetRayTracingShaderGroupHandlesKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR")); +PFN_vkCreateRayTracingPipelinesKHR ext::vulkan::vkCreateRayTracingPipelinesKHR = NULL; // = reinterpret_cast(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 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(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; - 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; +/* #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 asGeom; + uf::stl::vector 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 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(blasData.asGeom.size()); + blasData.buildInfo.pGeometries = blasData.asGeom.data(); + + blasData.rangeInfo = blasData.asBuildOffsetInfo.data(); + + uf::stl::vector 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& graphics, const uf::stl::vector& 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 instancesVK; instancesVK.reserve( instances.size() ); + uf::stl::vector 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(); + + 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(); + size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(512); + size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as(512); + size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as(128); + size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as(1); + size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(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 buffer; uf::stl::vector 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; diff --git a/engine/src/ext/vulkan/rendermodes/compute.cpp b/engine/src/ext/vulkan/rendermodes/compute.cpp new file mode 100644 index 00000000..bce0770f --- /dev/null +++ b/engine/src/ext/vulkan/rendermodes/compute.cpp @@ -0,0 +1,259 @@ +#if UF_USE_VULKAN + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const uf::stl::string ext::vulkan::ComputeRenderMode::getTarget() const { +// auto& metadata = *const_cast(&this->metadata); +// return metadata["target"].as(); + 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::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(); + /* + mesh.insertVertices({ + { {-0.5f, -0.5f, 0.0f } }, + { { 0.5f, -0.5f, 0.0f } }, + { { 0.0f, 0.5f, 0.0f } }, + }); + */ + mesh.insertVertices({ + {-1.0f,-1.0f,-1.0f,}, + {-1.0f,-1.0f, 1.0f,}, + {-1.0f, 1.0f, 1.0f,}, + {1.0f, 1.0f,-1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {-1.0f, 1.0f,-1.0f,}, + {1.0f,-1.0f, 1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {1.0f,-1.0f,-1.0f,}, + {1.0f, 1.0f,-1.0f,}, + {1.0f,-1.0f,-1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {-1.0f, 1.0f, 1.0f,}, + {-1.0f, 1.0f,-1.0f,}, + {1.0f,-1.0f, 1.0f,}, + {-1.0f,-1.0f, 1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {-1.0f, 1.0f, 1.0f,}, + {-1.0f,-1.0f, 1.0f,}, + {1.0f,-1.0f, 1.0f,}, + {1.0f, 1.0f, 1.0f,}, + {1.0f,-1.0f,-1.0f,}, + {1.0f, 1.0f,-1.0f,}, + {1.0f,-1.0f,-1.0f,}, + {1.0f, 1.0f, 1.0f,}, + {1.0f,-1.0f, 1.0f,}, + {1.0f, 1.0f, 1.0f,}, + {1.0f, 1.0f,-1.0f,}, + {-1.0f, 1.0f,-1.0f,}, + {1.0f, 1.0f, 1.0f,}, + {-1.0f, 1.0f,-1.0f,}, + {-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(); + + 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& 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 \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index 2b12afe7..5dd2eac6 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -283,12 +283,13 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as(128); size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(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++); } diff --git a/engine/src/ext/vulkan/rendermodes/raytrace.cpp b/engine/src/ext/vulkan/rendermodes/raytrace.cpp deleted file mode 100644 index 72f962d2..00000000 --- a/engine/src/ext/vulkan/rendermodes/raytrace.cpp +++ /dev/null @@ -1,522 +0,0 @@ -#if UF_USE_VULKAN - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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(); - mesh.insertVertices({ - { { -0.5f, -0.5f, 0.0f } }, - { { 0.5f, -0.5f, 0.0f } }, - { { 0.0f, 0.5f, 0.0f } }, - }); - mesh.insertIndices({ - 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(); - - 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 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 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(&this->metadata); -// return metadata["target"].as(); - 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::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(); - - 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& 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 \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index 50d5b592..0b5fbb55 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -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(); @@ -322,12 +322,13 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as(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(); - 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(); - uf::stl::string name = t["name"].as(); - 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] ); diff --git a/engine/src/ext/vulkan/shader.cpp b/engine/src/ext/vulkan/shader.cpp index 4c68e7b6..2c0fdff4 100644 --- a/engine/src/ext/vulkan/shader.cpp +++ b/engine/src/ext/vulkan/shader.cpp @@ -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); } diff --git a/engine/src/ext/vulkan/texture.cpp b/engine/src/ext/vulkan/texture.cpp index 9a867ad2..01dc2556 100644 --- a/engine/src/ext/vulkan/texture.cpp +++ b/engine/src/ext/vulkan/texture.cpp @@ -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 \ No newline at end of file diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index 22075819..dd5f2453 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -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::renderModes = { }; uf::stl::unordered_map ext::vulkan::renderModesMap; -PFN_vkGetBufferDeviceAddressKHR ext::vulkan::vkGetBufferDeviceAddressKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); -PFN_vkCmdBuildAccelerationStructuresKHR ext::vulkan::vkCmdBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR")); -PFN_vkBuildAccelerationStructuresKHR ext::vulkan::vkBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR")); -PFN_vkCreateAccelerationStructureKHR ext::vulkan::vkCreateAccelerationStructureKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR")); -PFN_vkDestroyAccelerationStructureKHR ext::vulkan::vkDestroyAccelerationStructureKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR")); -PFN_vkGetAccelerationStructureBuildSizesKHR ext::vulkan::vkGetAccelerationStructureBuildSizesKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureBuildSizesKHR")); -PFN_vkGetAccelerationStructureDeviceAddressKHR ext::vulkan::vkGetAccelerationStructureDeviceAddressKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR")); -PFN_vkCmdTraceRaysKHR ext::vulkan::vkCmdTraceRaysKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR")); -PFN_vkGetRayTracingShaderGroupHandlesKHR ext::vulkan::vkGetRayTracingShaderGroupHandlesKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR")); -PFN_vkCreateRayTracingPipelinesKHR ext::vulkan::vkCreateRayTracingPipelinesKHR = NULL; // = reinterpret_cast(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); diff --git a/engine/src/utils/mesh/mesh.cpp b/engine/src/utils/mesh/mesh.cpp index 75c93c29..3aa96814 100644 --- a/engine/src/utils/mesh/mesh.cpp +++ b/engine/src/utils/mesh/mesh.cpp @@ -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); diff --git a/ext/behaviors/raytrace/behavior.cpp b/ext/behaviors/raytrace/behavior.cpp new file mode 100644 index 00000000..cdff6252 --- /dev/null +++ b/ext/behaviors/raytrace/behavior.cpp @@ -0,0 +1,222 @@ +#include +#if UF_USE_VULKAN + +#include "behavior.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#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(); + auto& graphic = this->getComponent(); //metadata.renderer.graphic; + auto& mesh = this->getComponent(); + + + mesh.bind(); + mesh.insertVertices({ + {-1.0f,-1.0f,-1.0f,}, + {-1.0f,-1.0f, 1.0f,}, + {-1.0f, 1.0f, 1.0f,}, + {1.0f, 1.0f,-1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {-1.0f, 1.0f,-1.0f,}, + {1.0f,-1.0f, 1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {1.0f,-1.0f,-1.0f,}, + {1.0f, 1.0f,-1.0f,}, + {1.0f,-1.0f,-1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {-1.0f, 1.0f, 1.0f,}, + {-1.0f, 1.0f,-1.0f,}, + {1.0f,-1.0f, 1.0f,}, + {-1.0f,-1.0f, 1.0f,}, + {-1.0f,-1.0f,-1.0f,}, + {-1.0f, 1.0f, 1.0f,}, + {-1.0f,-1.0f, 1.0f,}, + {1.0f,-1.0f, 1.0f,}, + {1.0f, 1.0f, 1.0f,}, + {1.0f,-1.0f,-1.0f,}, + {1.0f, 1.0f,-1.0f,}, + {1.0f,-1.0f,-1.0f,}, + {1.0f, 1.0f, 1.0f,}, + {1.0f,-1.0f, 1.0f,}, + {1.0f, 1.0f, 1.0f,}, + {1.0f, 1.0f,-1.0f,}, + {-1.0f, 1.0f,-1.0f,}, + {1.0f, 1.0f, 1.0f,}, + {-1.0f, 1.0f,-1.0f,}, + {-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 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(); +#if !TEST + if ( !metadata.renderer.bound ) { + auto instances = uf::graph::storage.instances.flatten(); + if ( instances.empty() ) return; + + uf::stl::vector graphics; + this->process([&]( uf::Entity* entity ) { + if ( !entity->hasComponent() ) return; + graphics.emplace_back(entity->getComponentPointer()); + }); + if ( graphics.empty() ) return; + + auto& graphic = this->getComponent(); + 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(); + 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(); + + 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(); + auto& graphic = this->getComponent(); // 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 \ No newline at end of file diff --git a/ext/behaviors/raytrace/behavior.h b/ext/behaviors/raytrace/behavior.h new file mode 100644 index 00000000..16357d23 --- /dev/null +++ b/ext/behaviors/raytrace/behavior.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + +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; + ); + } +} \ No newline at end of file diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index faccb891..78833d51 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -331,7 +331,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { auto& controllerMetadata = controller.getComponent(); auto& controllerTransform = controller.getComponent>(); auto& metadata = this->getComponent(); - auto& metadataVxgi = this->getComponent(); + auto& metadataVxgi = this->getComponent(); auto& metadataJson = this->getComponent(); struct LightInfo { @@ -394,7 +394,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { auto& controllerMetadata = controller.getComponent(); auto& controllerTransform = controller.getComponent>(); auto& metadata = this->getComponent(); - auto& metadataVxgi = this->getComponent(); + auto& metadataVxgi = this->getComponent(); auto& metadataJson = this->getComponent(); 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(); auto& controllerTransform = controller.getComponent>(); auto& metadata = this->getComponent(); - auto& metadataVxgi = this->getComponent(); + auto& metadataVxgi = this->getComponent(); auto& metadataJson = this->getComponent(); 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 } diff --git a/ext/behaviors/voxelizer/behavior.cpp b/ext/behaviors/voxelizer/behavior.cpp index 5029f4ee..1005244c 100644 --- a/ext/behaviors/voxelizer/behavior.cpp +++ b/ext/behaviors/voxelizer/behavior.cpp @@ -1,5 +1,5 @@ #include -#if !UF_ENV_DREAMCAST +#if UF_USE_VULKAN #include "behavior.h" @@ -19,12 +19,12 @@ #include -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(); + auto& metadata = this->getComponent(); auto& metadataJson = this->getComponent(); 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() ) return; - auto& metadata = this->getComponent(); + auto& metadata = this->getComponent(); auto& renderMode = this->getComponent(); auto& scene = uf::scene::getCurrentScene(); @@ -388,8 +388,8 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) { for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; auto& graphic = entity->getComponent(); - 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() ) { auto& renderMode = this->getComponent(); @@ -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(96); /*this->*/voxelSize.y = serializer["vxgi"]["size"].as(96); /*this->*/voxelSize.z = serializer["vxgi"]["size"].as(96); diff --git a/ext/behaviors/voxelizer/behavior.h b/ext/behaviors/voxelizer/behavior.h index f794a4be..9e44b124 100644 --- a/ext/behaviors/voxelizer/behavior.h +++ b/ext/behaviors/voxelizer/behavior.h @@ -8,7 +8,7 @@ #include namespace ext { - namespace VoxelizerBehavior { + namespace VoxelizerSceneBehavior { UF_BEHAVIOR_DEFINE_TYPE(); EXT_BEHAVIOR_DEFINE_TRAITS(); EXT_BEHAVIOR_DEFINE_FUNCTIONS(); diff --git a/ext/gui/behavior.cpp b/ext/gui/behavior.cpp index 1843ca1f..c15fc2fd 100644 --- a/ext/gui/behavior.cpp +++ b/ext/gui/behavior.cpp @@ -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 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(); + ::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(); + 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(); + 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>(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(); 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 }; diff --git a/ext/gui/manager/behavior.cpp b/ext/gui/manager/behavior.cpp index 6ef7cd52..9fcafdd9 100644 --- a/ext/gui/manager/behavior.cpp +++ b/ext/gui/manager/behavior.cpp @@ -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 } diff --git a/ext/main.cpp b/ext/main.cpp index 3c87483f..8f7c9f47 100644 --- a/ext/main.cpp +++ b/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 format = configRenderJson["formats"][#key].as();\ @@ -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(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(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(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(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);