diff --git a/CMakeLists.txt b/CMakeLists.txt index 90459875..20e6193f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ project(Turbo) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wunused-function") -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -Wno-unused-function -Wno-switch") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") #set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Werror -Wno-switch -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-parameter -Wno-unused-function") set(CMAKE_BUILD_TYPE "debug") diff --git a/README.md b/README.md index db6e401d..4d66e39f 100755 --- a/README.md +++ b/README.md @@ -3661,3 +3661,33 @@ git clone --recursive git@github.com:FuXiii/Turbo.git >* `./engine/core`下`TShader`类析构中增加对`std::vector storageBufferDescriptors`成员的内存释放。 >* `./engine/core`下`TShader`类中增加`const std::vector &GetStorageBufferDescriptors()`成员函数。用于获取着色器中的对应描述符信息。 >* `./engine/core`下`TPipeline`类中`InternalCreate()`成员函数中增加对于`std::vector`描述符的处理。 + +* 2023/10/11 设计架构 + > + >* `./samples`下增加`VulkanKHRRayTracingTestForIntersectionShader`示例。用于研究光追中相交着色器的使用。 + >* `./asset/shaders`下新增`RayTracingKHRTestForIntersection.rgen`文件,用于`VulkanKHRRayTracingTestForIntersectionShader`示例。 + >* `./asset/shaders`下新增`RayTracingKHRTestForIntersection.rchit`文件,用于`VulkanKHRRayTracingTestForIntersectionShader`示例。 + >* `./asset/shaders`下新增`RayTracingKHRTestForIntersection.rmiss`文件,用于`VulkanKHRRayTracingTestForIntersectionShader`示例。 + >* `./asset/shaders`下新增`RayTracingKHRTestForIntersection.rint`文件,用于`VulkanKHRRayTracingTestForIntersectionShader`示例。 + +* 2023/10/29 设计架构 + > + >* 配了一台`3060Ti`显卡的电脑,光追研究继续。 + >* `./engine/render`下`TBuffer.h`中`TUniformBuffer`移除`std::enable_if_t`(`llvm-mingw`编译器不支持,估计是`C++`标准配置不对)。 + >* `./thirdparty`下更新`KTX-Software`到最新`main`分支。 + >* `./engine/render`下`TContext`中移除对于`TDescriptorID`的初始化列表写法使用最原始的结构体赋值法。(`llvm-mingw`好像不支持初始化列表写法,目前不知道如何设置编译器支持初始化列表写法,估计是`C++`标准配置不对)。 + >* `./engine/render`下`TContext`中将`std::is_class_v`改为`std::is_class::value`。 + >* `./samples`下`VulkanTest`中将所有`std::exception(const std::string&)`改为`Turbo::Core::TException`。 + >* `./samples`下`VulkanAllocatorTest`中将所有`std::exception(const std::string&)`改为`Turbo::Core::TException`。 + +* 2023/10/31 设计架构 + > + >* `./engine/render`下`TBuffer.h`中`TUniformBuffer`移除`std::enable_if_t`(`C++14`特性),使用`std::enable_if`替换(`C++11`特性)。 + +* 2023/11/4 设计架构 + > + >* `./samples`下增加`VulkanKHRRayTracingTestForCallableShader`示例。用于研究可调用着色器的使用。 + >* `./asset/shaders`下新增`RayTracingKHRTestForCallableShader.rchit`文件,用于`VulkanKHRRayTracingTestForCallableShader`示例。 + >* `./asset/shaders`下新增`RayTracingKHRTestForCallableShader_R.rchit`文件,用于`VulkanKHRRayTracingTestForCallableShader`示例。 + >* `./asset/shaders`下新增`RayTracingKHRTestForCallableShader_G.rchit`文件,用于`VulkanKHRRayTracingTestForCallableShader`示例。 + >* `./asset/shaders`下新增`RayTracingKHRTestForCallableShader_B.rchit`文件,用于`VulkanKHRRayTracingTestForCallableShader`示例。 diff --git a/asset/shaders/RayTracingKHRTestForCallableShader.rchit b/asset/shaders/RayTracingKHRTestForCallableShader.rchit new file mode 100644 index 00000000..2a38567b --- /dev/null +++ b/asset/shaders/RayTracingKHRTestForCallableShader.rchit @@ -0,0 +1,98 @@ +#version 460 +#extension GL_EXT_ray_tracing : require +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require // we need use [uint64_t] key word +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference2 : require + +struct HitPayload +{ + vec3 color; +}; + +struct Vertex +{ + vec3 position; + vec3 normal; + vec2 texcoord; +}; + +struct CallablePayload +{ + vec3 color; +}; + +struct BottomLevelAccelerationStructureDeviceAddress +{ + uint64_t vertexDeviceAddress; + uint64_t indexDeviceAddress; +}; + +layout(location = 0) rayPayloadInEXT HitPayload HIT_PAY_LOAD; +layout(location = 0) callableDataEXT CallablePayload callablePayload; + +layout(push_constant) uniform my_push_constants +{ + int callableSBTIndex; +} +my_push_constants_data; + +layout(buffer_reference, scalar) buffer Vertices +{ + Vertex v[]; +}; + +layout(buffer_reference, scalar) buffer Indices +{ + ivec3 i[]; +}; + +layout(set = 0, binding = 3, scalar) buffer BottomLevelAccelerationStructureDeviceAddress_ +{ + BottomLevelAccelerationStructureDeviceAddress blas_device_address[]; +} +BLAS_DEVICE_ADDRESS; + +hitAttributeEXT vec2 attribs; + +void main() +{ + BottomLevelAccelerationStructureDeviceAddress blas_device_address = BLAS_DEVICE_ADDRESS.blas_device_address[gl_InstanceCustomIndexEXT]; + + Vertices vertices = Vertices(blas_device_address.vertexDeviceAddress); + Indices indices = Indices(blas_device_address.indexDeviceAddress); + + ivec3 index = indices.i[gl_PrimitiveID]; + + Vertex v0 = vertices.v[index.x]; + Vertex v1 = vertices.v[index.y]; + Vertex v2 = vertices.v[index.z]; + + const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y); + + const vec3 position = v0.position * barycentrics.x + v1.position * barycentrics.y + v2.position * barycentrics.z; + const vec3 world_position = vec3(gl_ObjectToWorldEXT * vec4(position, 1.0)); + + const vec3 normal = v0.normal * barycentrics.x + v1.normal * barycentrics.y + v2.normal * barycentrics.z; + const vec3 world_normal = normalize(vec3(gl_WorldToObjectEXT * vec4(normal, 1.0))); + + const vec3 light_dir = -normalize(vec3(1, 1, 1)); + + // Diffuse + executeCallableEXT(my_push_constants_data.callableSBTIndex, 0); + + const vec3 diffuse_color = callablePayload.color; + float normalDotLight = max(dot(world_normal, light_dir), 0); + vec3 diffuse = diffuse_color * normalDotLight; + + // Specular + const float PI = 3.1415925; + float shininess = 28.0; + float energy_conservation = (2 + shininess) / (2 * PI); + vec3 view_dir = normalize(-gl_WorldRayDirectionEXT); + vec3 reflect_dir = normalize(reflect(-light_dir, world_normal)); + float specular_value = energy_conservation * pow(max(dot(view_dir, reflect_dir), 0), shininess); + vec3 specular = vec3(specular_value); + + HIT_PAY_LOAD.color = diffuse + specular; +} diff --git a/asset/shaders/RayTracingKHRTestForCallableShader_B.rcall b/asset/shaders/RayTracingKHRTestForCallableShader_B.rcall new file mode 100644 index 00000000..6c73ae50 --- /dev/null +++ b/asset/shaders/RayTracingKHRTestForCallableShader_B.rcall @@ -0,0 +1,14 @@ +#version 460 core +#extension GL_EXT_ray_tracing : enable + +struct CallablePayload +{ + vec3 color; +}; + +layout(location = 0) callableDataInEXT CallablePayload callablePayload; + +void main() +{ + callablePayload.color = vec3(0, 0, 1); +} \ No newline at end of file diff --git a/asset/shaders/RayTracingKHRTestForCallableShader_G.rcall b/asset/shaders/RayTracingKHRTestForCallableShader_G.rcall new file mode 100644 index 00000000..62c17ede --- /dev/null +++ b/asset/shaders/RayTracingKHRTestForCallableShader_G.rcall @@ -0,0 +1,14 @@ +#version 460 core +#extension GL_EXT_ray_tracing : enable + +struct CallablePayload +{ + vec3 color; +}; + +layout(location = 0) callableDataInEXT CallablePayload callablePayload; + +void main() +{ + callablePayload.color = vec3(0, 1, 0); +} \ No newline at end of file diff --git a/asset/shaders/RayTracingKHRTestForCallableShader_R.rcall b/asset/shaders/RayTracingKHRTestForCallableShader_R.rcall new file mode 100644 index 00000000..ff8cd61c --- /dev/null +++ b/asset/shaders/RayTracingKHRTestForCallableShader_R.rcall @@ -0,0 +1,14 @@ +#version 460 core +#extension GL_EXT_ray_tracing : enable + +struct CallablePayload +{ + vec3 color; +}; + +layout(location = 0) callableDataInEXT CallablePayload callablePayload; + +void main() +{ + callablePayload.color = vec3(1, 0, 0); +} \ No newline at end of file diff --git a/asset/shaders/RayTracingKHRTestForIntersection.rchit b/asset/shaders/RayTracingKHRTestForIntersection.rchit new file mode 100644 index 00000000..7f90b0a6 --- /dev/null +++ b/asset/shaders/RayTracingKHRTestForIntersection.rchit @@ -0,0 +1,120 @@ +#version 460 +#extension GL_EXT_ray_tracing : require +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require // we need use [uint64_t] key word +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference2 : require + +#define KIND_SPHERE 0 +#define KIND_CUBE 1 + +struct SPHERE +{ + vec3 center; + float radius; +}; + +struct AABB +{ + vec3 minimum; + vec3 maximum; +}; + +struct HitPayload +{ + vec3 color; +}; + +struct Vertex +{ + vec3 position; + vec3 normal; + vec2 texcoord; +}; + +struct BottomLevelAccelerationStructureDeviceAddress +{ + uint64_t vertexDeviceAddress; + uint64_t indexDeviceAddress; + uint64_t aabbsDeviceAddress; +}; + +layout(location = 0) rayPayloadInEXT HitPayload HIT_PAY_LOAD; + +layout(buffer_reference, scalar) buffer Vertices +{ + Vertex v[]; +}; + +layout(buffer_reference, scalar) buffer Indices +{ + ivec3 i[]; +}; + +layout(buffer_reference, scalar) buffer AABBs +{ + AABB boxs[]; +}; + +layout(set = 0, binding = 3, scalar) buffer BottomLevelAccelerationStructureDeviceAddress_ +{ + BottomLevelAccelerationStructureDeviceAddress blas_device_address[]; +} +BLAS_DEVICE_ADDRESS; + +hitAttributeEXT vec2 attribs; + +void main() +{ + BottomLevelAccelerationStructureDeviceAddress blas_device_address = BLAS_DEVICE_ADDRESS.blas_device_address[gl_InstanceCustomIndexEXT]; + + // Vertices vertices = Vertices(blas_device_address.vertexDeviceAddress); + // Indices indices = Indices(blas_device_address.indexDeviceAddress); + AABBs aabbs = AABBs(blas_device_address.aabbsDeviceAddress); + + // ivec3 index = indices.i[gl_PrimitiveID]; + + // Vertex v0 = vertices.v[index.x]; + // Vertex v1 = vertices.v[index.y]; + // Vertex v2 = vertices.v[index.z]; + + // const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y); + + // const vec3 position = v0.position * barycentrics.x + v1.position * barycentrics.y + v2.position * barycentrics.z; + const vec3 world_position = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT; + + AABB aabb = aabbs.boxs[gl_PrimitiveID]; + + // Sphere data + SPHERE sphere; + sphere.center = (aabb.maximum + aabb.minimum) * 0.5; + sphere.radius = ((aabb.maximum - aabb.minimum) * 0.5).x; + + vec3 diffuse_color = vec3(0, 1, 1); + vec3 world_normal = normalize(world_position - sphere.center); + if (gl_HitKindEXT == KIND_CUBE) + { + diffuse_color = vec3(1, 1, 0); + + vec3 absN = abs(world_normal); + float maxC = max(max(absN.x, absN.y), absN.z); + world_normal = (maxC == absN.x) ? vec3(sign(world_normal.x), 0, 0) : (maxC == absN.y) ? vec3(0, sign(world_normal.y), 0) : vec3(0, 0, sign(world_normal.z)); + } + + const vec3 light_dir = -normalize(vec3(1, 1, 1)); + + // Diffuse + float normalDotLight = max(dot(world_normal, light_dir), 0); + vec3 diffuse = diffuse_color * normalDotLight; + + // Specular + const float PI = 3.1415925; + float shininess = 28.0; + float energy_conservation = (2 + shininess) / (2 * PI); + vec3 view_dir = normalize(-gl_WorldRayDirectionEXT); + vec3 reflect_dir = normalize(reflect(-light_dir, world_normal)); + float specular_value = energy_conservation * pow(max(dot(view_dir, reflect_dir), 0), shininess); + vec3 specular = vec3(specular_value); + + HIT_PAY_LOAD.color = 0.3*diffuse + specular; +} diff --git a/asset/shaders/RayTracingKHRTestForIntersection.rgen b/asset/shaders/RayTracingKHRTestForIntersection.rgen new file mode 100644 index 00000000..d84b8270 --- /dev/null +++ b/asset/shaders/RayTracingKHRTestForIntersection.rgen @@ -0,0 +1,52 @@ +#version 460 +#extension GL_EXT_ray_tracing : require + +struct HitPayload +{ + vec3 color; +}; + +layout(location = 0) rayPayloadEXT HitPayload HIT_PAY_LOAD; + +layout(set = 0, binding = 0) uniform accelerationStructureEXT TOP_LEVEL_AS; +layout(set = 0, binding = 1, rgba32f) uniform image2D IMAGE; +layout(set = 0, binding = 2) uniform RAY_TRACING_MATRIXS +{ + mat4 model; + mat4 view; + mat4 project; +} +rayTracingMatrixs; + +void main() +{ + const vec2 pixel_center = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); // 像素中心点 + const vec2 uv = pixel_center / vec2(gl_LaunchSizeEXT.xy); // 归一化 [0,1] + vec2 ndc = uv * 2.0 - 1.0; //[-1,1],为归一化设备坐标(NDC) + + mat4 view_inverse = inverse(rayTracingMatrixs.view); + mat4 project_inverse = inverse(rayTracingMatrixs.project); + + vec4 origin = view_inverse * vec4(0, 0, 0, 1); // 相机的世界坐标 + vec4 target = project_inverse * vec4(ndc.x, ndc.y, 1, 1); // 像素中点(d.x, d.y)向前的向量乘以投影矩阵的逆得到,在View空间下该像素点的正前方向量 + vec4 direction = view_inverse * vec4(normalize(target.xyz), 0); // 归一化View空间下正前方向量,之后转到世界坐标系下 + + uint ray_flags = gl_RayFlagsOpaqueEXT; + float t_min = 0.001; + float t_max = 10000.0; + + traceRayEXT(TOP_LEVEL_AS, // acceleration structure + ray_flags, // rayFlags + 0xFF, // cullMask + 0, // sbtRecordOffset + 0, // sbtRecordStride + 0, // missIndex + origin.xyz, // ray origin + t_min, // ray min range + direction.xyz, // ray direction + t_max, // ray max range + 0 // payload (location = 0) + ); + + imageStore(IMAGE, ivec2(gl_LaunchIDEXT.xy), vec4(HIT_PAY_LOAD.color, 1.0)); +} diff --git a/asset/shaders/RayTracingKHRTestForIntersection.rint b/asset/shaders/RayTracingKHRTestForIntersection.rint new file mode 100644 index 00000000..84d96b9d --- /dev/null +++ b/asset/shaders/RayTracingKHRTestForIntersection.rint @@ -0,0 +1,111 @@ +#version 460 +#extension GL_EXT_ray_tracing : require +#extension GL_EXT_nonuniform_qualifier : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require // we need use [uint64_t] key word +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_buffer_reference2 : require + +#define KIND_SPHERE 0 +#define KIND_CUBE 1 + +struct SPHERE +{ + vec3 center; + float radius; +}; + +struct AABB +{ + vec3 minimum; + vec3 maximum; +}; + +struct BottomLevelAccelerationStructureDeviceAddress +{ + uint64_t vertexDeviceAddress; + uint64_t indexDeviceAddress; + uint64_t aabbsDeviceAddress; +}; + +layout(buffer_reference, scalar) buffer AABBs +{ + AABB boxs[]; +}; + +struct Ray +{ + vec3 origin; + vec3 direction; +}; + +layout(set = 0, binding = 3, scalar) buffer BottomLevelAccelerationStructureDeviceAddress_ +{ + BottomLevelAccelerationStructureDeviceAddress blas_device_address[]; +} +BLAS_DEVICE_ADDRESS; + +// Ray-Sphere intersection +// http://viclw17.github.io/2018/07/16/raytracing-ray-sphere-intersection/ +float hitSphere(const SPHERE s, const Ray r) +{ + vec3 oc = r.origin - s.center; + float a = dot(r.direction, r.direction); + float b = 2.0 * dot(oc, r.direction); + float c = dot(oc, oc) - s.radius * s.radius; + float discriminant = b * b - 4 * a * c; + if (discriminant < 0) + { + return -1.0; + } + else + { + return (-b - sqrt(discriminant)) / (2.0 * a); + } +} + +// Ray-AABB intersection +float hitAabb(const AABB aabb, const Ray r) +{ + vec3 invDir = 1.0 / r.direction; + vec3 tbot = invDir * (aabb.minimum - r.origin); + vec3 ttop = invDir * (aabb.maximum - r.origin); + vec3 tmin = min(ttop, tbot); + vec3 tmax = max(ttop, tbot); + float t0 = max(tmin.x, max(tmin.y, tmin.z)); + float t1 = min(tmax.x, min(tmax.y, tmax.z)); + return t1 > max(t0, 0.0) ? t0 : -1.0; +} + +void main() +{ + Ray ray; + ray.origin = gl_WorldRayOriginEXT; + ray.direction = gl_WorldRayDirectionEXT; + + BottomLevelAccelerationStructureDeviceAddress blas_device_address = BLAS_DEVICE_ADDRESS.blas_device_address[gl_InstanceCustomIndexEXT]; + AABBs aabbs = AABBs(blas_device_address.aabbsDeviceAddress); + + AABB aabb = aabbs.boxs[gl_PrimitiveID]; + + // Sphere data + SPHERE sphere; + sphere.center = (aabb.maximum + aabb.minimum) * 0.5; + sphere.radius = ((aabb.maximum - aabb.minimum) * 0.5).x; + + float tHit = -1; + int hitKind = gl_PrimitiveID % 2 == 0 ? KIND_SPHERE : KIND_CUBE; + if (hitKind == KIND_SPHERE) + { + // Sphere intersection + tHit = hitSphere(sphere, ray); + } + else + { + // AABB intersection + tHit = hitAabb(aabb, ray); + } + + // Report hit point + if (tHit > 0) + reportIntersectionEXT(tHit, hitKind); +} diff --git a/asset/shaders/RayTracingKHRTestForIntersection.rmiss b/asset/shaders/RayTracingKHRTestForIntersection.rmiss new file mode 100644 index 00000000..d15497ca --- /dev/null +++ b/asset/shaders/RayTracingKHRTestForIntersection.rmiss @@ -0,0 +1,14 @@ +#version 460 +#extension GL_EXT_ray_tracing : require + +struct HitPayload +{ + vec3 color; +}; + +layout(location = 0) rayPayloadInEXT HitPayload HIT_PAY_LOAD; + +void main() +{ + HIT_PAY_LOAD.color = vec3(0.0, 0.1, 0.3); +} \ No newline at end of file diff --git a/engine/render/include/TBuffer.h b/engine/render/include/TBuffer.h index 8a26d62b..d0275539 100644 --- a/engine/render/include/TBuffer.h +++ b/engine/render/include/TBuffer.h @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace Turbo @@ -153,7 +154,7 @@ class TIndexBuffer : public Turbo::Render::TBuffer TIndexType GetIndexType() const; }; -template ::value, bool> = true> +template ::value, bool>::type = true> class TUniformBuffer : public Turbo::Render::TBuffer { public: diff --git a/engine/render/include/TContext.h b/engine/render/include/TContext.h index b1e835a9..64d6ff77 100644 --- a/engine/render/include/TContext.h +++ b/engine/render/include/TContext.h @@ -242,6 +242,10 @@ class TContext template void BindDescriptor(TSetID set, TBindingID binding, const std::vector> &uniformBuffers) { + TDescriptorID descriptor_id = {}; + descriptor_id.set = set; + descriptor_id.binding = binding; + auto set_map = this->descriptorMap.find(set); if (set_map != this->descriptorMap.end()) { @@ -251,31 +255,32 @@ class TContext // TODO:更新Set和Binding对应的缓存 // 说明之前已有描述符资源绑定到此,需要在之前的【描述符资源数组】中移除并更新到目标【描述符资源数组】中 TDescriptorMapType descriptor_map_type = binding_map->second; + switch (descriptor_map_type) { case TDescriptorMapType::UNDEFINED: { } break; case TDescriptorMapType::UNIFROM_BUFFER_MAP: { - this->uniformBufferMap.at({set, binding}).clear(); + this->uniformBufferMap.at(descriptor_id).clear(); } break; case TDescriptorMapType::COMBINED_IMAGE_SAMPLER_MAP: { - this->combinedImageSamplerMap.at({set, binding}).clear(); + this->combinedImageSamplerMap.at(descriptor_id).clear(); } break; case TDescriptorMapType::SAMPLED_IMAGE_MAP: { - this->sampledImageMap.at({set, binding}).clear(); + this->sampledImageMap.at(descriptor_id).clear(); } break; case TDescriptorMapType::SAMPLER_MAP: { - this->samplerMap.at({set, binding}).clear(); + this->samplerMap.at(descriptor_id).clear(); } break; } // TODO:更新到目标【描述符资源数组】中 - std::vector &uniform_buffers = this->uniformBufferMap.at({set, binding}); + std::vector &uniform_buffers = this->uniformBufferMap.at(descriptor_id); for (const Turbo::Render::TUniformBuffer &uniform_buffer_item : uniformBuffers) { uniform_buffers.push_back(uniform_buffer_item.buffer); @@ -288,7 +293,7 @@ class TContext { // TODO:增加新的Binding(BindingMap增加新项目)。并将std::vector<各种uinform资源类型>存入相应缓存 // 说明找到了Set,但没有Binding - std::vector &uniform_buffers = this->uniformBufferMap[{set, binding}]; + std::vector &uniform_buffers = this->uniformBufferMap[descriptor_id]; for (const Turbo::Render::TUniformBuffer &uniform_buffer_item : uniformBuffers) { uniform_buffers.push_back(uniform_buffer_item.buffer); @@ -300,7 +305,7 @@ class TContext else { // TODO:增加新的Set,Binding映射(SetMap中增加新项)。并将std::vector<各种uinform资源类型>存入相应缓存 - std::vector &uniform_buffers = this->uniformBufferMap[{set, binding}]; + std::vector &uniform_buffers = this->uniformBufferMap[descriptor_id]; for (const Turbo::Render::TUniformBuffer &uniform_buffer_item : uniformBuffers) { uniform_buffers.push_back(uniform_buffer_item.buffer); diff --git a/engine/render/src/TContext.cpp b/engine/render/src/TContext.cpp index 32fe218e..f4e58410 100644 --- a/engine/render/src/TContext.cpp +++ b/engine/render/src/TContext.cpp @@ -881,7 +881,7 @@ Turbo::Render::TContext::TContext() Turbo::Core::TPhysicalDeviceFeatures physical_device_features = {}; physical_device_features.sampleRateShading = true; - + this->device = new Turbo::Core::TDevice(this->physicalDevice, nullptr, &enable_device_extensions, &physical_device_features); this->graphicsQueue = this->device->GetBestGraphicsQueue(); @@ -1153,6 +1153,10 @@ void Turbo::Render::TContext::BindPipeline(const Turbo::Render::TGraphicsPipelin void Turbo::Render::TContext::BindDescriptor(TSetID set, TBindingID binding, const std::vector &texture2Ds) { + TDescriptorID descriptor_id = {}; + descriptor_id.set = set; + descriptor_id.binding = binding; + auto set_map = this->descriptorMap.find(set); if (set_map != this->descriptorMap.end()) { @@ -1168,25 +1172,25 @@ void Turbo::Render::TContext::BindDescriptor(TSetID set, TBindingID binding, con } break; case TDescriptorMapType::UNIFROM_BUFFER_MAP: { - this->uniformBufferMap.at({set, binding}).clear(); + this->uniformBufferMap.at(descriptor_id).clear(); } break; case TDescriptorMapType::COMBINED_IMAGE_SAMPLER_MAP: { - this->combinedImageSamplerMap.at({set, binding}).clear(); + this->combinedImageSamplerMap.at(descriptor_id).clear(); } break; case TDescriptorMapType::SAMPLED_IMAGE_MAP: { - this->sampledImageMap.at({set, binding}).clear(); + this->sampledImageMap.at(descriptor_id).clear(); } break; case TDescriptorMapType::SAMPLER_MAP: { - this->samplerMap.at({set, binding}).clear(); + this->samplerMap.at(descriptor_id).clear(); } break; } // TODO:更新到目标【描述符资源数组】中 - std::vector &sampled_images = this->sampledImageMap.at({set, binding}); + std::vector &sampled_images = this->sampledImageMap.at(descriptor_id); for (const Turbo::Render::TTexture2D &texture_2d_item : texture2Ds) { sampled_images.push_back(texture_2d_item.imageView); @@ -1199,7 +1203,7 @@ void Turbo::Render::TContext::BindDescriptor(TSetID set, TBindingID binding, con { // TODO:增加新的Binding(BindingMap增加新项目)。并将std::vector<各种uinform资源类型>存入相应缓存 // 说明找到了Set,但没有Binding - std::vector &sampled_images = this->sampledImageMap[{set, binding}]; + std::vector &sampled_images = this->sampledImageMap[descriptor_id]; for (const Turbo::Render::TTexture2D &texture_2d_item : texture2Ds) { sampled_images.push_back(texture_2d_item.imageView); @@ -1211,7 +1215,7 @@ void Turbo::Render::TContext::BindDescriptor(TSetID set, TBindingID binding, con else { // TODO:增加新的Set,Binding映射(SetMap中增加新项)。并将std::vector<各种uinform资源类型>存入相应缓存 - std::vector &sampled_images = this->sampledImageMap[{set, binding}]; + std::vector &sampled_images = this->sampledImageMap[descriptor_id]; for (const Turbo::Render::TTexture2D &texture_2d_item : texture2Ds) { sampled_images.push_back(texture_2d_item.imageView); @@ -1229,6 +1233,10 @@ void Turbo::Render::TContext::BindDescriptor(TSetID set, TBindingID binding, con void Turbo::Render::TContext::BindDescriptor(TSetID set, TBindingID binding, const std::vector &texture3Ds) { + TDescriptorID descriptor_id = {}; + descriptor_id.set = set; + descriptor_id.binding = binding; + auto set_map = this->descriptorMap.find(set); if (set_map != this->descriptorMap.end()) { @@ -1244,25 +1252,25 @@ void Turbo::Render::TContext::BindDescriptor(TSetID set, TBindingID binding, con } break; case TDescriptorMapType::UNIFROM_BUFFER_MAP: { - this->uniformBufferMap.at({set, binding}).clear(); + this->uniformBufferMap.at(descriptor_id).clear(); } break; case TDescriptorMapType::COMBINED_IMAGE_SAMPLER_MAP: { - this->combinedImageSamplerMap.at({set, binding}).clear(); + this->combinedImageSamplerMap.at(descriptor_id).clear(); } break; case TDescriptorMapType::SAMPLED_IMAGE_MAP: { - this->sampledImageMap.at({set, binding}).clear(); + this->sampledImageMap.at(descriptor_id).clear(); } break; case TDescriptorMapType::SAMPLER_MAP: { - this->samplerMap.at({set, binding}).clear(); + this->samplerMap.at(descriptor_id).clear(); } break; } // TODO:更新到目标【描述符资源数组】中 - std::vector &sampled_images = this->sampledImageMap.at({set, binding}); + std::vector &sampled_images = this->sampledImageMap.at(descriptor_id); for (const Turbo::Render::TTexture3D &texture_3d_item : texture3Ds) { sampled_images.push_back(texture_3d_item.imageView); @@ -1275,7 +1283,7 @@ void Turbo::Render::TContext::BindDescriptor(TSetID set, TBindingID binding, con { // TODO:增加新的Binding(BindingMap增加新项目)。并将std::vector<各种uinform资源类型>存入相应缓存 // 说明找到了Set,但没有Binding - std::vector &sampled_images = this->sampledImageMap[{set, binding}]; + std::vector &sampled_images = this->sampledImageMap[descriptor_id]; for (const Turbo::Render::TTexture3D &texture_3d_item : texture3Ds) { sampled_images.push_back(texture_3d_item.imageView); @@ -1287,7 +1295,7 @@ void Turbo::Render::TContext::BindDescriptor(TSetID set, TBindingID binding, con else { // TODO:增加新的Set,Binding映射(SetMap中增加新项)。并将std::vector<各种uinform资源类型>存入相应缓存 - std::vector &sampled_images = this->sampledImageMap[{set, binding}]; + std::vector &sampled_images = this->sampledImageMap[descriptor_id]; for (const Turbo::Render::TTexture3D &texture_3d_item : texture3Ds) { sampled_images.push_back(texture_3d_item.imageView); diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index ae54b49f..9091d0ec 100755 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -330,4 +330,14 @@ target_link_libraries(VulkanKHRRayTracingTestForAnimationTLAS PUBLIC ${LIBS}) add_executable(VulkanKHRRayTracingTestForAnimationBLAS ./VulkanKHRRayTracingTestForAnimationBLAS.cpp ${IMGUI_SOURCE_PATH}) target_include_directories(VulkanKHRRayTracingTestForAnimationBLAS PUBLIC ${INCLUDE_PARTH}) target_link_directories(VulkanKHRRayTracingTestForAnimationBLAS PUBLIC ${LINK_PARTH}) -target_link_libraries(VulkanKHRRayTracingTestForAnimationBLAS PUBLIC ${LIBS}) \ No newline at end of file +target_link_libraries(VulkanKHRRayTracingTestForAnimationBLAS PUBLIC ${LIBS}) + +add_executable(VulkanKHRRayTracingTestForIntersectionShader ./VulkanKHRRayTracingTestForIntersectionShader.cpp ${IMGUI_SOURCE_PATH}) +target_include_directories(VulkanKHRRayTracingTestForIntersectionShader PUBLIC ${INCLUDE_PARTH}) +target_link_directories(VulkanKHRRayTracingTestForIntersectionShader PUBLIC ${LINK_PARTH}) +target_link_libraries(VulkanKHRRayTracingTestForIntersectionShader PUBLIC ${LIBS}) + +add_executable(VulkanKHRRayTracingTestForCallableShader ./VulkanKHRRayTracingTestForCallableShader.cpp ${IMGUI_SOURCE_PATH}) +target_include_directories(VulkanKHRRayTracingTestForCallableShader PUBLIC ${INCLUDE_PARTH}) +target_link_directories(VulkanKHRRayTracingTestForCallableShader PUBLIC ${LINK_PARTH}) +target_link_libraries(VulkanKHRRayTracingTestForCallableShader PUBLIC ${LIBS}) \ No newline at end of file diff --git a/samples/CppStandardTest.cpp b/samples/CppStandardTest.cpp index 5b5996f8..7a0f0996 100644 --- a/samples/CppStandardTest.cpp +++ b/samples/CppStandardTest.cpp @@ -44,7 +44,7 @@ int main() { std::cout << "Hello World" << std::endl; - bool is_class = std::is_class_v; + bool is_class = std::is_class::value; std::cout << is_class << ":A_Test" << std::endl; struct B_Test diff --git a/samples/VulkanAllocatorTest.cpp b/samples/VulkanAllocatorTest.cpp index ef68b38a..bd4c37df 100644 --- a/samples/VulkanAllocatorTest.cpp +++ b/samples/VulkanAllocatorTest.cpp @@ -1,3 +1,4 @@ +#include "core/include/TException.h" #include #if defined(_WIN16) || defined(_WIN32) || defined(_WIN64) @@ -45,7 +46,7 @@ int main() HMODULE library = LoadLibraryA("vulkan-1.dll"); if (!library) { - throw std::exception("Can not found vulkan-1.dll"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "Can not found vulkan-1.dll"); } vk_GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)(void (*)(void))GetProcAddress(library, "vkGetInstanceProcAddr"); @@ -97,7 +98,7 @@ int main() VkResult result = vk_CreateInstance(&vk_instance_create_info, &vk_allocation_callbacks, &instance); if (result != VkResult::VK_SUCCESS) { - throw std::exception("vkCreateInstance failed"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "vkCreateInstance failed"); } std::cout << "vkCreateInstance success" << std::endl; @@ -126,14 +127,14 @@ int main() result = vk_EnumeratePhysicalDevices(instance, &physcial_device_count, nullptr); if (result != VkResult::VK_SUCCESS) { - throw std::exception("vkEnumeratePhysicalDevices get count failed"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "vkEnumeratePhysicalDevices get count failed"); } std::vector physcail_devices(physcial_device_count); result = vk_EnumeratePhysicalDevices(instance, &physcial_device_count, physcail_devices.data()); if (result != VkResult::VK_SUCCESS) { - throw std::exception("vkEnumeratePhysicalDevices failed"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "vkEnumeratePhysicalDevices failed"); } VkPhysicalDevice target_physical_device = VK_NULL_HANDLE; @@ -158,7 +159,7 @@ int main() if (target_physical_device == VK_NULL_HANDLE) { - throw std::exception("Not found suitable GPU"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "Not found suitable GPU"); } std::cout << "Select Physical Device:" << target_physical_device_name << std::endl; @@ -206,7 +207,7 @@ int main() result = vk_CreateDevice(target_physical_device, &vk_device_create_info, nullptr, &vk_device); if (result != VkResult::VK_SUCCESS) { - throw std::exception("vkCreateDevice failed"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "vkCreateDevice failed"); } std::cout << "vkCreateDevice success" << std::endl; @@ -248,7 +249,7 @@ int main() result = vk_CreatePipelineLayout(vk_device, &vk_pipeline_layout_create_info, nullptr, &vk_pipeline_layout); if (result != VkResult::VK_SUCCESS) { - throw std::exception("vkCreatePipelineLayout failed"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "vkCreatePipelineLayout failed"); } vk_DestroyPipelineLayout(vk_device, vk_pipeline_layout, nullptr); diff --git a/samples/VulkanKHRRayTracingTestForAnimationBLAS.cpp b/samples/VulkanKHRRayTracingTestForAnimationBLAS.cpp index 523d112d..7f3664ea 100644 --- a/samples/VulkanKHRRayTracingTestForAnimationBLAS.cpp +++ b/samples/VulkanKHRRayTracingTestForAnimationBLAS.cpp @@ -2120,7 +2120,7 @@ int main() static float f = 0.0f; static int counter = 0; - ImGui::Begin("VulkanKHRRayTracingTestForAnimationTLAS"); + ImGui::Begin("VulkanKHRRayTracingTestForAnimationBLAS"); ImGui::Text("W,A,S,D to move."); ImGui::Text("Push down and drag mouse right button to rotate view."); ImGui::SliderFloat("angle", &angle, 0.0f, 360); diff --git a/samples/VulkanKHRRayTracingTestForCallableShader.cpp b/samples/VulkanKHRRayTracingTestForCallableShader.cpp new file mode 100644 index 00000000..0a3f0335 --- /dev/null +++ b/samples/VulkanKHRRayTracingTestForCallableShader.cpp @@ -0,0 +1,2599 @@ +#include "core/include/TDevice.h" +#include "core/include/TDeviceQueue.h" +#include "core/include/TEngine.h" +#include "core/include/TPhysicalDevice.h" +#include "core/include/TVulkanAllocator.h" + +#include "core/include/TBuffer.h" +#include "core/include/TCommandBuffer.h" +#include "core/include/TCommandBufferPool.h" +#include "core/include/TImage.h" +#include "core/include/TImageView.h" + +#include "core/include/TShader.h" + +#include "core/include/TAttachment.h" +#include "core/include/TGraphicsPipeline.h" +#include "core/include/TRenderPass.h" +#include "core/include/TSubpass.h" + +#include "core/include/TDescriptorPool.h" +#include "core/include/TDescriptorSet.h" +#include "core/include/TDescriptorSetLayout.h" +#include "core/include/TFramebuffer.h" + +#include "core/include/TFence.h" +#include "core/include/TSemaphore.h" + +#include + +#include + +#include "core/include/TSurface.h" +#include "core/include/TSwapchain.h" + +#include + +#include "core/include/TPipelineDescriptorSet.h" +#include "core/include/TSampler.h" + +#include + +#include "core/include/TVulkanLoader.h" +#define TINYGLTF_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_IMPLEMENTATION +// #define TINYGLTF_NOEXCEPTION // optional. disable exception handling. +#include + +#include + +#include + +std::string ReadTextFile(const std::string &filename) +{ + std::vector data; + + std::ifstream file; + + file.open(filename, std::ios::in); + + if (!file.is_open()) + { + throw std::runtime_error("Failed to open file: " + filename); + } + + return std::string{(std::istreambuf_iterator(file)), (std::istreambuf_iterator())}; +} + +static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {}; +static GLFWcursor *g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; + +const std::string IMGUI_VERT_SHADER_STR = ReadTextFile("../../asset/shaders/imgui.vert"); +const std::string IMGUI_FRAG_SHADER_STR = ReadTextFile("../../asset/shaders/imgui.frag"); + +const std::string VERT_SHADER_STR = ReadTextFile("../../asset/shaders/GeometryTest.vert"); +const std::string GEOM_SHADER_STR = ReadTextFile("../../asset/shaders/GeometryTest.geom"); +const std::string FRAG_SHADER_STR = ReadTextFile("../../asset/shaders/GeometryTest.frag"); + +const std::string RAY_GENERATION_SHADER_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForLighting.rgen"); +const std::string MISS_SHADER_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForLighting.rmiss"); +const std::string CLOSEST_HIT_SHADER_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForCallableShader.rchit"); +const std::string CALLABLE_SHADER_R_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForCallableShader_R.rcall"); +const std::string CALLABLE_SHADER_G_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForCallableShader_G.rcall"); +const std::string CALLABLE_SHADER_B_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForCallableShader_B.rcall"); + +typedef struct POSITION +{ + float x; + float y; + float z; +} POSITION; + +typedef struct NORMAL +{ + float x; + float y; + float z; +} NORMAL; + +typedef struct TANGENT +{ + float x; + float y; + float z; + float w; +} TANGENT; + +typedef struct TEXCOORD +{ + float u; + float v; +} TEXCOORD; + +struct MY_BUFFER_DATA +{ + float scale; +}; + +struct MATRIXS_BUFFER_DATA +{ + glm::mat4 m; + glm::mat4 v; + glm::mat4 p; +}; + +struct VERTEX +{ + POSITION position; + NORMAL normal; + TEXCOORD texcoord; +}; + +struct BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS +{ + VkDeviceAddress vertexDeviceAddress; + VkDeviceAddress indexDeviceAddress; +}; + +struct RAY_TRACING_MATRIXS_BUFFER_DATA +{ + glm::mat4 v; + glm::mat4 p; +}; + +struct MY_PUSH_CONSTANTS +{ + int callableSBTIndex; +}; + +int main() +{ + std::cout << "Vulkan Version:" << Turbo::Core::TVulkanLoader::Instance()->GetVulkanVersion().ToString() << std::endl; + + MY_BUFFER_DATA my_buffer_data = {}; + my_buffer_data.scale = 0.03; + + MATRIXS_BUFFER_DATA matrixs_buffer_data = {}; + + MY_PUSH_CONSTANTS my_push_constants = {}; + my_push_constants.callableSBTIndex = 0; + + // + std::vector POSITION_data; + std::vector NORMAL_data; + std::vector TEXCOORD_data; + std::vector TANGENT_data; + std::vector INDICES_data; + { + tinygltf::Model model; + tinygltf::TinyGLTF loader; + std::string err; + std::string warn; + + bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, "../../asset/models/material_sphere_without_Yup.gltf"); + const tinygltf::Scene &scene = model.scenes[model.defaultScene]; + tinygltf::Node &node = model.nodes[scene.nodes[0]]; + tinygltf::Mesh &mesh = model.meshes[node.mesh]; + tinygltf::Primitive &primitive = mesh.primitives[0]; + int mode = primitive.mode; + int position_accesser_index = primitive.attributes["POSITION"]; + int normal_accesser_index = primitive.attributes["NORMAL"]; + int texcoord_0_accesser_index = primitive.attributes["TEXCOORD_0"]; + int tangent_accesser_index = primitive.attributes["TANGENT"]; + int indices_accesser_index = primitive.indices; + tinygltf::Accessor &position_accessor = model.accessors[position_accesser_index]; + tinygltf::Accessor &normal_accessor = model.accessors[normal_accesser_index]; + tinygltf::Accessor &texcoord_0_accessor = model.accessors[texcoord_0_accesser_index]; + tinygltf::Accessor &indices_accessor = model.accessors[indices_accesser_index]; + tinygltf::Accessor &tangent_accessor = model.accessors[tangent_accesser_index]; + + tinygltf::BufferView &position_buffer_view = model.bufferViews[position_accessor.bufferView]; + tinygltf::BufferView &normal_buffer_view = model.bufferViews[normal_accessor.bufferView]; + tinygltf::BufferView &texcoord_0_buffer_view = model.bufferViews[texcoord_0_accessor.bufferView]; + tinygltf::BufferView &indices_buffer_view = model.bufferViews[indices_accessor.bufferView]; + tinygltf::BufferView &tangent_buffer_view = model.bufferViews[tangent_accessor.bufferView]; + + int position_buffer_index = position_buffer_view.buffer; + size_t position_buffer_byteLength = position_buffer_view.byteLength; + int position_buffer_byteOffset = position_buffer_view.byteOffset; + int position_type = position_accessor.type; + + int normal_buffer_index = normal_buffer_view.buffer; + size_t normal_buffer_byteLength = normal_buffer_view.byteLength; + int normal_buffer_byteOffset = normal_buffer_view.byteOffset; + int normal_type = normal_accessor.type; + + int texcoord_0_buffer_index = texcoord_0_buffer_view.buffer; + size_t texcoord_0_buffer_byteLength = texcoord_0_buffer_view.byteLength; + int texcoord_0_buffer_byteOffset = texcoord_0_buffer_view.byteOffset; + int texcoord_0_type = texcoord_0_accessor.type; + + int indices_buffer_index = indices_buffer_view.buffer; + size_t indices_buffer_byteLength = indices_buffer_view.byteLength; + int indices_buffer_byteOffset = indices_buffer_view.byteOffset; + int indices_type = indices_accessor.type; + + int tangent_buffer_index = tangent_buffer_view.buffer; + size_t tangent_buffer_byteLength = tangent_buffer_view.byteLength; + int tangent_buffer_byteOffset = tangent_buffer_view.byteOffset; + int tangent_type = tangent_accessor.type; + + tinygltf::Buffer &position_buffer = model.buffers[position_buffer_index]; + tinygltf::Buffer &normal_buffer = model.buffers[normal_buffer_index]; + tinygltf::Buffer &texcoord_0_buffer = model.buffers[texcoord_0_buffer_index]; + tinygltf::Buffer &indices_buffer = model.buffers[indices_buffer_index]; + tinygltf::Buffer &tangent_buffer = model.buffers[tangent_buffer_index]; + + std::vector &position_data = position_buffer.data; + std::vector &normal_data = normal_buffer.data; + std::vector &texcoord_0_data = texcoord_0_buffer.data; + std::vector &indices_data = indices_buffer.data; + std::vector &tangent_data = tangent_buffer.data; + + std::vector temp_indices_data; + + POSITION_data.resize(position_buffer_byteLength / sizeof(POSITION)); + NORMAL_data.resize(normal_buffer_byteLength / sizeof(NORMAL)); + TEXCOORD_data.resize(texcoord_0_buffer_byteLength / sizeof(TEXCOORD)); + temp_indices_data.resize(indices_buffer_byteLength / sizeof(unsigned short)); + TANGENT_data.resize(tangent_buffer_byteLength / sizeof(TANGENT)); + + memcpy(POSITION_data.data(), position_data.data() + position_buffer_byteOffset, position_buffer_byteLength); + memcpy(NORMAL_data.data(), normal_data.data() + normal_buffer_byteOffset, normal_buffer_byteLength); + memcpy(TEXCOORD_data.data(), texcoord_0_data.data() + texcoord_0_buffer_byteOffset, texcoord_0_buffer_byteLength); + memcpy(temp_indices_data.data(), indices_data.data() + indices_buffer_byteOffset, indices_buffer_byteLength); + memcpy(TANGENT_data.data(), tangent_data.data() + tangent_buffer_byteOffset, tangent_buffer_byteLength); + + for (unsigned short &temp_indices_item : temp_indices_data) + { + INDICES_data.push_back(temp_indices_item); + } + } + // + + uint32_t indices_count = INDICES_data.size(); + Turbo::Core::TEngine engine; + + Turbo::Core::TLayerInfo khronos_validation; + std::vector support_layers = engine.GetInstance().GetSupportLayers(); + for (Turbo::Core::TLayerInfo &layer : support_layers) + { + if (layer.GetLayerType() == Turbo::Core::TLayerType::VK_LAYER_KHRONOS_VALIDATION) + { + khronos_validation = layer; + break; + } + } + + std::vector enable_layer; + if (khronos_validation.GetLayerType() != Turbo::Core::TLayerType::UNDEFINED) + { + enable_layer.push_back(khronos_validation); + } + + std::vector enable_instance_extensions; + std::vector instance_support_extensions = engine.GetInstance().GetSupportExtensions(); + for (Turbo::Core::TExtensionInfo &extension : instance_support_extensions) + { + if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_WIN32_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_WAYLAND_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_XCB_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_XLIB_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2) + { + enable_instance_extensions.push_back(extension); + } + } + + Turbo::Core::TVersion instance_version(1, 2, 0, 0); + Turbo::Core::TInstance *instance = new Turbo::Core::TInstance(&enable_layer, &enable_instance_extensions, &instance_version); + Turbo::Core::TPhysicalDevice *physical_device = instance->GetBestPhysicalDevice(); + + Turbo::Core::TPhysicalDeviceFeatures physical_device_support_features = physical_device->GetDeviceFeatures(); + { + if (physical_device_support_features.accelerationStructure) + { + std::cout << "Support acceleration structure feature" << std::endl; + } + else + { + std::cout << "Not support acceleration structure feature" << std::endl; + } + + if (physical_device_support_features.accelerationStructureCaptureReplay) + { + std::cout << "Support acceleration structure capture replay feature" << std::endl; + } + else + { + std::cout << "Not support acceleration structure capture replay feature" << std::endl; + } + + if (physical_device_support_features.accelerationStructureHostCommands) + { + std::cout << "Support acceleration structure host commands feature" << std::endl; + } + else + { + std::cout << "Not support acceleration structure host commands feature" << std::endl; + } + + if (physical_device_support_features.accelerationStructureIndirectBuild) + { + std::cout << "Support acceleration structure indirect build feature" << std::endl; + } + else + { + std::cout << "Not support acceleration structure indirect build feature" << std::endl; + } + + if (physical_device_support_features.bufferDeviceAddress) + { + std::cout << "Support bufferDeviceAddress feature" << std::endl; + } + else + { + std::cout << "Not support bufferDeviceAddress feature" << std::endl; + } + + if (physical_device_support_features.bufferDeviceAddressCaptureReplay) + { + std::cout << "Support bufferDeviceAddressCaptureReplay feature" << std::endl; + } + else + { + std::cout << "Not support bufferDeviceAddressCaptureReplay feature" << std::endl; + } + + if (physical_device_support_features.bufferDeviceAddressMultiDevice) + { + std::cout << "Support bufferDeviceAddressMultiDevice feature" << std::endl; + } + else + { + std::cout << "Not support bufferDeviceAddressMultiDevice feature" << std::endl; + } + + if (physical_device_support_features.rayTracingPipeline) + { + std::cout << "Support ray tracing pipeline feature" << std::endl; + } + else + { + std::cout << "Not support ray tracing pipeline feature" << std::endl; + } + } + + if (!physical_device_support_features.accelerationStructure || !physical_device_support_features.rayTracingPipeline) + { + delete instance; + std::cout << "Please use a GPU which support hardware real-time ray tracing" << std::endl; + return 0; + } + + if (!glfwInit()) + return -1; + GLFWwindow *window; + int window_width = 1920 / 2.0; + int window_height = 1080 / 2.0; + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + window = glfwCreateWindow(window_width, window_height, "Turbo", NULL, NULL); + VkSurfaceKHR vk_surface_khr = VK_NULL_HANDLE; + VkInstance vk_instance = instance->GetVkInstance(); + glfwCreateWindowSurface(vk_instance, window, NULL, &vk_surface_khr); + + Turbo::Core::TPhysicalDeviceFeatures physical_device_features = {}; + physical_device_features.sampleRateShading = true; + physical_device_features.accelerationStructure = physical_device_support_features.accelerationStructure; + physical_device_features.accelerationStructureCaptureReplay = physical_device_support_features.accelerationStructureCaptureReplay; + physical_device_features.accelerationStructureHostCommands = physical_device_support_features.accelerationStructureHostCommands; + physical_device_features.accelerationStructureIndirectBuild = physical_device_support_features.accelerationStructureIndirectBuild; + physical_device_features.bufferDeviceAddress = physical_device_support_features.bufferDeviceAddress; + physical_device_features.rayTracingPipeline = physical_device_support_features.rayTracingPipeline; + + if (physical_device_support_features.geometryShader) + { + physical_device_features.geometryShader = true; + } + else + { + glfwTerminate(); + delete instance; + throw Turbo::Core::TException(Turbo::Core::TResult::UNSUPPORTED, "Not support geometry shader feature"); + } + + std::vector enable_device_extensions; + std::vector physical_device_support_extensions = physical_device->GetSupportExtensions(); + for (Turbo::Core::TExtensionInfo &extension : physical_device_support_extensions) + { + if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_SWAPCHAIN) + { + enable_device_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_ACCELERATION_STRUCTURE) + { + enable_device_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_SPIRV_1_4) + { + enable_device_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_RAY_TRACING_PIPELINE) + { + enable_device_extensions.push_back(extension); + } + } + + Turbo::Core::TDevice *device = new Turbo::Core::TDevice(physical_device, nullptr, &enable_device_extensions, &physical_device_features); + Turbo::Core::TDeviceQueue *queue = device->GetBestGraphicsQueue(); + + Turbo::Extension::TSurface *surface = new Turbo::Extension::TSurface(device, vk_surface_khr); + uint32_t max_image_count = surface->GetMaxImageCount(); + uint32_t min_image_count = surface->GetMinImageCount(); + + uint32_t swapchain_image_count = max_image_count <= min_image_count ? min_image_count : max_image_count - 1; + + Turbo::Extension::TSwapchain *swapchain = new Turbo::Extension::TSwapchain(surface, swapchain_image_count, Turbo::Core::TFormatType::B8G8R8A8_SRGB, 1, Turbo::Core::TImageUsageBits::IMAGE_COLOR_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_SRC | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_DST, true); + + std::vector swapchain_images = swapchain->GetImages(); + + std::vector swapchain_image_views; + for (Turbo::Core::TImage *swapchain_image_item : swapchain_images) + { + Turbo::Core::TImageView *swapchain_view = new Turbo::Core::TImageView(swapchain_image_item, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, Turbo::Core::TFormatType::B8G8R8A8_SRGB, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + swapchain_image_views.push_back(swapchain_view); + } + + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + + glm::mat4 model = glm::mat4(1.0f); + model = glm::rotate(model, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + + glm::mat4 view = glm::mat4(1.0f); + view = glm::translate(view, glm::vec3(0.0f, 0.0f, -10.0f)); + + glm::mat4 projection = glm::mat4(1.0f); + projection = glm::perspective(glm::radians(45.0f), (float)swapchain->GetWidth() / (float)swapchain->GetHeight(), 0.1f, 100.0f); + + matrixs_buffer_data.m = model; + matrixs_buffer_data.v = view; + matrixs_buffer_data.p = projection; + + Turbo::Core::TBuffer *matrixs_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_UNIFORM_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(matrixs_buffer_data)); + void *mvp_ptr = matrixs_buffer->Map(); + memcpy(mvp_ptr, &matrixs_buffer_data, sizeof(matrixs_buffer_data)); + matrixs_buffer->Unmap(); + + Turbo::Core::TBuffer *my_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_UNIFORM_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(my_buffer_data)); + void *my_buffer_ptr = my_buffer->Map(); + memcpy(my_buffer_ptr, &my_buffer_data, sizeof(my_buffer_data)); + my_buffer->Unmap(); + + Turbo::Core::TBuffer *position_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(POSITION) * POSITION_data.size()); + void *position_buffer_ptr = position_buffer->Map(); + memcpy(position_buffer_ptr, POSITION_data.data(), sizeof(POSITION) * POSITION_data.size()); + position_buffer->Unmap(); + // POSITION_data.clear(); + + Turbo::Core::TBuffer *normal_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(NORMAL) * NORMAL_data.size()); + void *normal_buffer_ptr = normal_buffer->Map(); + memcpy(normal_buffer_ptr, NORMAL_data.data(), sizeof(NORMAL) * NORMAL_data.size()); + normal_buffer->Unmap(); + // NORMAL_data.clear(); + + Turbo::Core::TBuffer *texcoord_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(TEXCOORD) * TEXCOORD_data.size()); + void *texcoord_buffer_ptr = texcoord_buffer->Map(); + memcpy(texcoord_buffer_ptr, TEXCOORD_data.data(), sizeof(TEXCOORD) * TEXCOORD_data.size()); + texcoord_buffer->Unmap(); + // TEXCOORD_data.clear(); + + Turbo::Core::TBuffer *index_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_INDEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(uint32_t) * INDICES_data.size()); + void *index_buffer_ptr = index_buffer->Map(); + memcpy(index_buffer_ptr, INDICES_data.data(), sizeof(uint32_t) * INDICES_data.size()); + index_buffer->Unmap(); + // INDICES_data.clear(); + + Turbo::Core::TBuffer *tangent_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(TANGENT) * TANGENT_data.size()); + void *tangent_buffer_ptr = tangent_buffer->Map(); + memcpy(tangent_buffer_ptr, TANGENT_data.data(), sizeof(TANGENT) * TANGENT_data.size()); + tangent_buffer->Unmap(); + // TANGENT_data.clear(); + + Turbo::Core::TImage *depth_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::D32_SFLOAT, swapchain->GetWidth(), swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_DEPTH_STENCIL_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_INPUT_ATTACHMENT, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, Turbo::Core::TImageLayout::UNDEFINED); + Turbo::Core::TImageView *depth_image_view = new Turbo::Core::TImageView(depth_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, depth_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_DEPTH_BIT, 0, 1, 0, 1); + + Turbo::Core::TVertexShader *vertex_shader = new Turbo::Core::TVertexShader(device, Turbo::Core::TShaderLanguage::GLSL, VERT_SHADER_STR); + Turbo::Core::TGeometryShader *geometry_shader = new Turbo::Core::TGeometryShader(device, Turbo::Core::TShaderLanguage::GLSL, GEOM_SHADER_STR); + Turbo::Core::TFragmentShader *fragment_shader = new Turbo::Core::TFragmentShader(device, Turbo::Core::TShaderLanguage::GLSL, FRAG_SHADER_STR); + + // for ray tracing image + Turbo::Core::TImage *ray_tracing_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::R32G32B32A32_SFLOAT, swapchain->GetWidth(), swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_COLOR_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_SRC | Turbo::Core::TImageUsageBits::IMAGE_STORAGE, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY); + Turbo::Core::TImageView *ray_tracing_image_view = new Turbo::Core::TImageView(ray_tracing_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, ray_tracing_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + { + + Turbo::Core::TCommandBuffer *change_ray_tracing_image_layout_command_buffer = command_pool->Allocate(); + + change_ray_tracing_image_layout_command_buffer->Begin(); + change_ray_tracing_image_layout_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TOP_OF_PIPE_BIT, Turbo::Core::TPipelineStageBits::BOTTOM_OF_PIPE_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::GENERAL, ray_tracing_image_view); + change_ray_tracing_image_layout_command_buffer->End(); + + Turbo::Core::TFence *change_image_layout_fence = new Turbo::Core::TFence(device); + + queue->Submit(nullptr, nullptr, change_ray_tracing_image_layout_command_buffer, change_image_layout_fence); + + change_image_layout_fence->WaitUntil(); + delete change_image_layout_fence; + + command_pool->Free(change_ray_tracing_image_layout_command_buffer); + } + + std::vector descriptor_sizes; + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::UNIFORM_BUFFER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::COMBINED_IMAGE_SAMPLER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::SAMPLER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::SAMPLED_IMAGE, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::STORAGE_IMAGE, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::UNIFORM_TEXEL_BUFFER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::STORAGE_TEXEL_BUFFER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::STORAGE_BUFFER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::UNIFORM_BUFFER_DYNAMIC, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::STORAGE_BUFFER_DYNAMIC, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::INPUT_ATTACHMENT, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::ACCELERATION_STRUCTURE, 1000)); + + Turbo::Core::TDescriptorPool *descriptor_pool = new Turbo::Core::TDescriptorPool(device, descriptor_sizes.size() * 1000, descriptor_sizes); + + const Turbo::Core::TDeviceDriver *device_driver = device->GetDeviceDriver(); + const Turbo::Core::TPhysicalDeviceDriver *physical_device_driver = physical_device->GetPhysicalDeviceDriver(); + + // Acceleration Structure + Turbo::Core::TBuffer *device_local_vertex_buffer = nullptr; + Turbo::Core::TBuffer *device_local_index_buffer = nullptr; + Turbo::Core::TBuffer *bottom_level_acceleration_structure_buffer = nullptr; + VkAccelerationStructureKHR bottom_level_acceleration_structure_khr = VK_NULL_HANDLE; + Turbo::Core::TBuffer *top_level_acceleration_structure_buffer = nullptr; + VkAccelerationStructureKHR top_level_acceleration_structure_khr = VK_NULL_HANDLE; + Turbo::Core::TBuffer *instance_buffer = nullptr; + + Turbo::Core::TBuffer *bottom_level_acceleration_structure_device_address_buffer = nullptr; + + { + VkPhysicalDeviceAccelerationStructurePropertiesKHR vk_physical_device_acceleration_structure_properties_khr = {}; + vk_physical_device_acceleration_structure_properties_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR; + vk_physical_device_acceleration_structure_properties_khr.pNext = nullptr; + vk_physical_device_acceleration_structure_properties_khr.maxGeometryCount = 0; + vk_physical_device_acceleration_structure_properties_khr.maxInstanceCount = 0; + vk_physical_device_acceleration_structure_properties_khr.maxPrimitiveCount = 0; + vk_physical_device_acceleration_structure_properties_khr.maxPerStageDescriptorAccelerationStructures = 0; + vk_physical_device_acceleration_structure_properties_khr.maxPerStageDescriptorUpdateAfterBindAccelerationStructures = 0; + vk_physical_device_acceleration_structure_properties_khr.maxDescriptorSetAccelerationStructures = 0; + vk_physical_device_acceleration_structure_properties_khr.maxDescriptorSetUpdateAfterBindAccelerationStructures = 0; + vk_physical_device_acceleration_structure_properties_khr.minAccelerationStructureScratchOffsetAlignment = 0; + + VkPhysicalDeviceProperties2 vk_physical_device_properties_2 = {}; + vk_physical_device_properties_2.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + vk_physical_device_properties_2.pNext = &vk_physical_device_acceleration_structure_properties_khr; + vk_physical_device_properties_2.properties = {}; + + if (physical_device_driver->vkGetPhysicalDeviceProperties2 != nullptr) + { + physical_device_driver->vkGetPhysicalDeviceProperties2(physical_device->GetVkPhysicalDevice(), &vk_physical_device_properties_2); + } + else if (physical_device_driver->vkGetPhysicalDeviceProperties2KHR != nullptr) + { + physical_device_driver->vkGetPhysicalDeviceProperties2KHR(physical_device->GetVkPhysicalDevice(), &vk_physical_device_properties_2); + } + + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxGeometryCount = " << vk_physical_device_acceleration_structure_properties_khr.maxGeometryCount << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxInstanceCount = " << vk_physical_device_acceleration_structure_properties_khr.maxInstanceCount << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxPrimitiveCount = " << vk_physical_device_acceleration_structure_properties_khr.maxPrimitiveCount << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxPerStageDescriptorAccelerationStructures = " << vk_physical_device_acceleration_structure_properties_khr.maxPerStageDescriptorAccelerationStructures << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxPerStageDescriptorUpdateAfterBindAccelerationStructures = " << vk_physical_device_acceleration_structure_properties_khr.maxPerStageDescriptorUpdateAfterBindAccelerationStructures << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxDescriptorSetAccelerationStructures = " << vk_physical_device_acceleration_structure_properties_khr.maxDescriptorSetAccelerationStructures << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxDescriptorSetUpdateAfterBindAccelerationStructures = " << vk_physical_device_acceleration_structure_properties_khr.maxDescriptorSetUpdateAfterBindAccelerationStructures << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.minAccelerationStructureScratchOffsetAlignment = " << vk_physical_device_acceleration_structure_properties_khr.minAccelerationStructureScratchOffsetAlignment << std::endl; + + std::vector ray_tracing_vertexs; + for (uint32_t vertex_index = 0; vertex_index < POSITION_data.size(); vertex_index++) + { + VERTEX ray_tracing_vertex; + ray_tracing_vertex.position = POSITION_data[vertex_index]; + ray_tracing_vertex.normal = NORMAL_data[vertex_index]; + ray_tracing_vertex.texcoord = TEXCOORD_data[vertex_index]; + + ray_tracing_vertexs.push_back(ray_tracing_vertex); + } + + device_local_vertex_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS | Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, sizeof(VERTEX) * ray_tracing_vertexs.size()); + { + Turbo::Core::TBuffer *staging_vertex_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(VERTEX) * ray_tracing_vertexs.size()); + memcpy(staging_vertex_buffer->Map(), ray_tracing_vertexs.data(), sizeof(VERTEX) * ray_tracing_vertexs.size()); + staging_vertex_buffer->Unmap(); + + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + command_buffer->CmdCopyBuffer(staging_vertex_buffer, device_local_vertex_buffer, 0, 0, sizeof(VERTEX) * ray_tracing_vertexs.size()); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + delete command_pool; + delete staging_vertex_buffer; + } + + VkDeviceAddress device_local_vertex_buffer_device_address = 0; + + VkBufferDeviceAddressInfo device_local_vertex_buffer_device_address_info = {}; + device_local_vertex_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + device_local_vertex_buffer_device_address_info.pNext = nullptr; + device_local_vertex_buffer_device_address_info.buffer = device_local_vertex_buffer->GetVkBuffer(); + + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + device_local_vertex_buffer_device_address = device_driver->vkGetBufferDeviceAddress(device->GetVkDevice(), &device_local_vertex_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + device_local_vertex_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(device->GetVkDevice(), &device_local_vertex_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + device_local_vertex_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(device->GetVkDevice(), &device_local_vertex_buffer_device_address_info); + } + + if (device_local_vertex_buffer_device_address == 0) + { + throw std::runtime_error("Get ray tracing device local vertex buffer address failed"); + } + + VkDeviceOrHostAddressConstKHR vertex_data = {}; + vertex_data.deviceAddress = device_local_vertex_buffer_device_address; + + device_local_index_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_INDEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS | Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, sizeof(uint32_t) * INDICES_data.size()); + { + Turbo::Core::TBuffer *staging_index_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(uint32_t) * INDICES_data.size()); + memcpy(staging_index_buffer->Map(), INDICES_data.data(), sizeof(uint32_t) * INDICES_data.size()); + staging_index_buffer->Unmap(); + + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + command_buffer->CmdCopyBuffer(staging_index_buffer, device_local_index_buffer, 0, 0, sizeof(uint32_t) * INDICES_data.size()); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + delete command_pool; + delete staging_index_buffer; + } + + VkDeviceAddress device_local_index_buffer_device_address = 0; + + VkBufferDeviceAddressInfo device_local_index_buffer_device_address_info = {}; + device_local_index_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + device_local_index_buffer_device_address_info.pNext = nullptr; + device_local_index_buffer_device_address_info.buffer = device_local_index_buffer->GetVkBuffer(); + + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + device_local_index_buffer_device_address = device_driver->vkGetBufferDeviceAddress(device->GetVkDevice(), &device_local_index_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + device_local_index_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(device->GetVkDevice(), &device_local_index_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + device_local_index_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(device->GetVkDevice(), &device_local_index_buffer_device_address_info); + } + + if (device_local_index_buffer_device_address == 0) + { + throw std::runtime_error("Get ray tracing device local index buffer address failed"); + } + + BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS ray_tracing_bottom_level_acceleration_structure; + ray_tracing_bottom_level_acceleration_structure.vertexDeviceAddress = device_local_vertex_buffer_device_address; + ray_tracing_bottom_level_acceleration_structure.indexDeviceAddress = device_local_index_buffer_device_address; + + std::vector bottom_level_acceleration_structure_device_addresses; + bottom_level_acceleration_structure_device_addresses.push_back(ray_tracing_bottom_level_acceleration_structure); + + bottom_level_acceleration_structure_device_address_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, sizeof(BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS) * bottom_level_acceleration_structure_device_addresses.size()); + { + Turbo::Core::TBuffer *staging_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS) * bottom_level_acceleration_structure_device_addresses.size()); + memcpy(staging_buffer->Map(), bottom_level_acceleration_structure_device_addresses.data(), sizeof(BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS) * bottom_level_acceleration_structure_device_addresses.size()); + staging_buffer->Unmap(); + + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + command_buffer->CmdCopyBuffer(staging_buffer, bottom_level_acceleration_structure_device_address_buffer, 0, 0, sizeof(BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS) * bottom_level_acceleration_structure_device_addresses.size()); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + delete command_pool; + delete staging_buffer; + } + + VkDeviceOrHostAddressConstKHR index_data = {}; + index_data.deviceAddress = device_local_index_buffer_device_address; + + VkAccelerationStructureGeometryTrianglesDataKHR vk_acceleration_structure_geometry_triangles_data_khr = {}; + vk_acceleration_structure_geometry_triangles_data_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + vk_acceleration_structure_geometry_triangles_data_khr.pNext = nullptr; + vk_acceleration_structure_geometry_triangles_data_khr.vertexFormat = VkFormat::VK_FORMAT_R32G32B32_SFLOAT; + vk_acceleration_structure_geometry_triangles_data_khr.vertexData = vertex_data; + vk_acceleration_structure_geometry_triangles_data_khr.vertexStride = sizeof(VERTEX); + vk_acceleration_structure_geometry_triangles_data_khr.maxVertex = ray_tracing_vertexs.size(); + vk_acceleration_structure_geometry_triangles_data_khr.indexType = VkIndexType::VK_INDEX_TYPE_UINT32; + vk_acceleration_structure_geometry_triangles_data_khr.indexData = index_data; + vk_acceleration_structure_geometry_triangles_data_khr.transformData.deviceAddress = 0; + + VkAccelerationStructureGeometryDataKHR vk_acceleration_structure_geometry_data_khr = {}; + vk_acceleration_structure_geometry_data_khr.triangles = vk_acceleration_structure_geometry_triangles_data_khr; + + VkAccelerationStructureGeometryKHR vk_acceleration_structure_geometry_khr = {}; + vk_acceleration_structure_geometry_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + vk_acceleration_structure_geometry_khr.pNext = nullptr; + vk_acceleration_structure_geometry_khr.geometryType = VkGeometryTypeKHR::VK_GEOMETRY_TYPE_TRIANGLES_KHR; + vk_acceleration_structure_geometry_khr.geometry = vk_acceleration_structure_geometry_data_khr; + vk_acceleration_structure_geometry_khr.flags = VkGeometryFlagBitsKHR::VK_GEOMETRY_OPAQUE_BIT_KHR; + + VkAccelerationStructureBuildGeometryInfoKHR vk_acceleration_structure_build_geometry_info_khr = {}; + vk_acceleration_structure_build_geometry_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + vk_acceleration_structure_build_geometry_info_khr.pNext = nullptr; + vk_acceleration_structure_build_geometry_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + vk_acceleration_structure_build_geometry_info_khr.flags = VkBuildAccelerationStructureFlagBitsKHR::VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR | VkBuildAccelerationStructureFlagBitsKHR::VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + vk_acceleration_structure_build_geometry_info_khr.mode = VkBuildAccelerationStructureModeKHR::VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + vk_acceleration_structure_build_geometry_info_khr.srcAccelerationStructure = VK_NULL_HANDLE; + vk_acceleration_structure_build_geometry_info_khr.dstAccelerationStructure = VK_NULL_HANDLE; + vk_acceleration_structure_build_geometry_info_khr.geometryCount = 1; + vk_acceleration_structure_build_geometry_info_khr.pGeometries = &vk_acceleration_structure_geometry_khr; + vk_acceleration_structure_build_geometry_info_khr.ppGeometries = nullptr; + vk_acceleration_structure_build_geometry_info_khr.scratchData.deviceAddress = 0; + + std::vector max_primitive_counts(vk_acceleration_structure_build_geometry_info_khr.geometryCount); + for (uint32_t index = 0; index < vk_acceleration_structure_build_geometry_info_khr.geometryCount; index++) + { + // max_primitive_counts[index] = POSITION_data.size() / 3; + max_primitive_counts[index] = INDICES_data.size() / 3; + } + + std::cout << "POSITION_data.size():" << POSITION_data.size() << std::endl; + std::cout << "INDICES_data.size():" << INDICES_data.size() << std::endl; + + VkAccelerationStructureBuildSizesInfoKHR vk_acceleration_structure_build_sizes_info_khr = {}; + vk_acceleration_structure_build_sizes_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; + vk_acceleration_structure_build_sizes_info_khr.pNext = nullptr; + vk_acceleration_structure_build_sizes_info_khr.accelerationStructureSize = 0; + vk_acceleration_structure_build_sizes_info_khr.updateScratchSize = 0; + vk_acceleration_structure_build_sizes_info_khr.buildScratchSize = 0; + if (device_driver->vkGetAccelerationStructureBuildSizesKHR != nullptr) + { + device_driver->vkGetAccelerationStructureBuildSizesKHR(device->GetVkDevice(), VkAccelerationStructureBuildTypeKHR::VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &vk_acceleration_structure_build_geometry_info_khr, max_primitive_counts.data(), &vk_acceleration_structure_build_sizes_info_khr); + } + + std::cout << "Bottom Level VkAccelerationStructureBuildSizesInfoKHR.accelerationStructureSize = " << vk_acceleration_structure_build_sizes_info_khr.accelerationStructureSize << std::endl; + std::cout << "Bottom Level VkAccelerationStructureBuildSizesInfoKHR.updateScratchSize = " << vk_acceleration_structure_build_sizes_info_khr.updateScratchSize << std::endl; + std::cout << "Bottom Level VkAccelerationStructureBuildSizesInfoKHR.buildScratchSize = " << vk_acceleration_structure_build_sizes_info_khr.buildScratchSize << std::endl; + + bottom_level_acceleration_structure_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_STORAGE | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, vk_acceleration_structure_build_sizes_info_khr.accelerationStructureSize); + + // create acceleration structure + VkDevice vk_device = device->GetVkDevice(); + VkAccelerationStructureCreateInfoKHR vk_acceleration_structure_create_info_khr = {}; + vk_acceleration_structure_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + vk_acceleration_structure_create_info_khr.pNext = nullptr; + vk_acceleration_structure_create_info_khr.createFlags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + vk_acceleration_structure_create_info_khr.buffer = bottom_level_acceleration_structure_buffer->GetVkBuffer(); // 将用于存储加速结构的缓存。大小一般可以为VkAccelerationStructureCreateInfoKHR::size,usage为VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR|VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT<由于之后创建顶层加速结构需要底层加速结构的地址,所以需要VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT> + vk_acceleration_structure_create_info_khr.offset = 0; // 单位比特,相对于buffer的偏移之后存储加速结构,需要是256的倍数。 + vk_acceleration_structure_create_info_khr.size = vk_acceleration_structure_build_sizes_info_khr.accelerationStructureSize; // 该加速结构需要的大小。大小来源于vkGetAccelerationStructureBuildSizesKHR()函数中VkAccelerationStructureBuildSizesInfoKHR::accelerationStructureSize。 + vk_acceleration_structure_create_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; // 加速结构的类型:TOP,BOTTOM,GENERIC + vk_acceleration_structure_create_info_khr.deviceAddress = 0; // 如果激活使用了accelerationStructureCaptureReplay特性,该地址为加速结构要求的那个设备地址。目前为VK_NULL_HANDLE + + VkAllocationCallbacks *vk_allocation_callbacks = Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks(); + + VkResult result = device->GetDeviceDriver()->vkCreateAccelerationStructureKHR(vk_device, &vk_acceleration_structure_create_info_khr, vk_allocation_callbacks, &bottom_level_acceleration_structure_khr); + if (result != VK_SUCCESS) + { + std::cout << "Create VkAccelerationStructureKHR Failed" << std::endl; + } + + std::cout << "Create VkAccelerationStructureKHR Success" << std::endl; + + Turbo::Core::TBuffer *scratch_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, vk_acceleration_structure_build_sizes_info_khr.buildScratchSize); + + VkBufferDeviceAddressInfo scratch_buffer_device_address_info = {}; + scratch_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + scratch_buffer_device_address_info.pNext = nullptr; + scratch_buffer_device_address_info.buffer = scratch_buffer->GetVkBuffer(); + + VkDeviceAddress scratch_buffer_device_address = 0; + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddress(vk_device, &scratch_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(vk_device, &scratch_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(vk_device, &scratch_buffer_device_address_info); + } + + if (scratch_buffer_device_address != 0) + { + std::cout << "Successfully get scratch_buffer VkBuffer device local address " << std::endl; + } + + vk_acceleration_structure_build_geometry_info_khr.dstAccelerationStructure = bottom_level_acceleration_structure_khr; + vk_acceleration_structure_build_geometry_info_khr.scratchData.deviceAddress = scratch_buffer_device_address; + + VkAccelerationStructureBuildRangeInfoKHR vk_acceleration_structure_build_range_info_khr = {}; + vk_acceleration_structure_build_range_info_khr.primitiveCount = INDICES_data.size() / 3; + vk_acceleration_structure_build_range_info_khr.primitiveOffset = 0; + vk_acceleration_structure_build_range_info_khr.firstVertex = 0; + vk_acceleration_structure_build_range_info_khr.transformOffset = 0; + + std::vector vk_acceleration_structure_build_range_info_khrs; + vk_acceleration_structure_build_range_info_khrs.push_back(vk_acceleration_structure_build_range_info_khr); + + std::vector build_range_infos; // 该数组内元素个数应与 vkCmdBuildAccelerationStructuresKHR::infoCount 对应 + build_range_infos.push_back(vk_acceleration_structure_build_range_info_khrs.data()); + // TODO: compaction query pool for compact acceleration structure + { + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdBuildAccelerationStructuresKHR(command_buffer->GetVkCommandBuffer(), 1, &vk_acceleration_structure_build_geometry_info_khr, build_range_infos.data()); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + delete command_pool; + } + + // TODO: compact acceleration structure + { + VkQueryPool query_pool = VK_NULL_HANDLE; + + VkQueryPoolCreateInfo vk_query_pool_create_info = {}; + vk_query_pool_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + vk_query_pool_create_info.pNext = nullptr; + vk_query_pool_create_info.flags = 0; + vk_query_pool_create_info.queryType = VkQueryType::VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR; + vk_query_pool_create_info.queryCount = 1; + vk_query_pool_create_info.pipelineStatistics = 0; + + result = device->GetDeviceDriver()->vkCreateQueryPool(vk_device, &vk_query_pool_create_info, vk_allocation_callbacks, &query_pool); + if (result != VK_SUCCESS) + { + std::cout << "Create VkQueryPool Failed" << std::endl; + } + + std::cout << "Create VkQueryPool Success" << std::endl; + + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdResetQueryPool(command_buffer->GetVkCommandBuffer(), query_pool, 0, 1); + device->GetDeviceDriver()->vkCmdWriteAccelerationStructuresPropertiesKHR(command_buffer->GetVkCommandBuffer(), 1, &bottom_level_acceleration_structure_khr, VkQueryType::VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, query_pool, 0); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + VkDeviceSize compact_size = 0; + device->GetDeviceDriver()->vkGetQueryPoolResults(vk_device, query_pool, 0, 1, sizeof(VkDeviceSize), &compact_size, sizeof(VkDeviceSize), VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); + std::cout << "compact size:" << compact_size << std::endl; + + delete fence; + command_pool->Free(command_buffer); + + VkAccelerationStructureKHR compact_bottom_level_acceleration_structure_khr = VK_NULL_HANDLE; + + Turbo::Core::TBuffer *compact_bottom_level_acceleration_structure_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_STORAGE | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, compact_size); + + VkAccelerationStructureCreateInfoKHR compact_vk_acceleration_structure_create_info_khr = {}; + compact_vk_acceleration_structure_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + compact_vk_acceleration_structure_create_info_khr.pNext = nullptr; + compact_vk_acceleration_structure_create_info_khr.createFlags = 0; + compact_vk_acceleration_structure_create_info_khr.buffer = compact_bottom_level_acceleration_structure_buffer->GetVkBuffer(); + compact_vk_acceleration_structure_create_info_khr.offset = 0; + compact_vk_acceleration_structure_create_info_khr.size = compact_size; + compact_vk_acceleration_structure_create_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + compact_vk_acceleration_structure_create_info_khr.deviceAddress = 0; + + result = device->GetDeviceDriver()->vkCreateAccelerationStructureKHR(vk_device, &compact_vk_acceleration_structure_create_info_khr, vk_allocation_callbacks, &compact_bottom_level_acceleration_structure_khr); + if (result != VkResult::VK_SUCCESS) + { + std::cout << "vkCreateAccelerationStructureKHR create compact VkAccelerationStructureKHR Failed" << std::endl; + } + + std::cout << "vkCreateAccelerationStructureKHR create compact VkAccelerationStructureKHR Success" << std::endl; + + VkCopyAccelerationStructureInfoKHR vk_copy_acceleration_structure_info_khr = {}; + vk_copy_acceleration_structure_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR; + vk_copy_acceleration_structure_info_khr.pNext = nullptr; + vk_copy_acceleration_structure_info_khr.src = bottom_level_acceleration_structure_khr; + vk_copy_acceleration_structure_info_khr.dst = compact_bottom_level_acceleration_structure_khr; + vk_copy_acceleration_structure_info_khr.mode = VkCopyAccelerationStructureModeKHR::VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR; + + command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdCopyAccelerationStructureKHR(command_buffer->GetVkCommandBuffer(), &vk_copy_acceleration_structure_info_khr); + command_buffer->End(); + fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + delete fence; + command_pool->Free(command_buffer); + delete command_pool; + device->GetDeviceDriver()->vkDestroyQueryPool(vk_device, query_pool, vk_allocation_callbacks); + + // destroy no compact acceleration structure + device->GetDeviceDriver()->vkDestroyAccelerationStructureKHR(vk_device, bottom_level_acceleration_structure_khr, vk_allocation_callbacks); + delete bottom_level_acceleration_structure_buffer; + + // set acceleration structure value to compact version + bottom_level_acceleration_structure_khr = compact_bottom_level_acceleration_structure_khr; + bottom_level_acceleration_structure_buffer = compact_bottom_level_acceleration_structure_buffer; + } + + // Top Level Acceleration Structure + glm::mat4 acceleration_structure_model = glm::mat4(1.0f); + acceleration_structure_model = glm::rotate(acceleration_structure_model, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + VkTransformMatrixKHR vk_transform_matrix_khr = {}; + memcpy(&vk_transform_matrix_khr, &acceleration_structure_model, sizeof(VkTransformMatrixKHR)); + + VkAccelerationStructureDeviceAddressInfoKHR bottom_level_acceleration_structure_device_address_info_khr = {}; + bottom_level_acceleration_structure_device_address_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; + bottom_level_acceleration_structure_device_address_info_khr.pNext = nullptr; + bottom_level_acceleration_structure_device_address_info_khr.accelerationStructure = bottom_level_acceleration_structure_khr; + + VkDeviceAddress bottom_level_acceleration_structure_device_address = device->GetDeviceDriver()->vkGetAccelerationStructureDeviceAddressKHR(vk_device, &bottom_level_acceleration_structure_device_address_info_khr); + + VkAccelerationStructureInstanceKHR vk_acceleration_structure_instance_khr = {}; + vk_acceleration_structure_instance_khr.transform = vk_transform_matrix_khr; + vk_acceleration_structure_instance_khr.instanceCustomIndex = 0; + vk_acceleration_structure_instance_khr.mask = 0xFF; + vk_acceleration_structure_instance_khr.instanceShaderBindingTableRecordOffset = 0; + vk_acceleration_structure_instance_khr.flags = VkGeometryInstanceFlagBitsKHR::VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; + vk_acceleration_structure_instance_khr.accelerationStructureReference = bottom_level_acceleration_structure_device_address; + + { + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + + Turbo::Core::TBuffer *staging_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(VkAccelerationStructureInstanceKHR)); + void *staging_ptr = staging_buffer->Map(); + if (staging_ptr) + { + memcpy(staging_ptr, &vk_acceleration_structure_instance_khr, sizeof(VkAccelerationStructureInstanceKHR)); + } + staging_buffer->Unmap(); + + instance_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, sizeof(VkAccelerationStructureInstanceKHR)); + + command_buffer->Begin(); + command_buffer->CmdCopyBuffer(staging_buffer, instance_buffer, 0, 0, sizeof(VkAccelerationStructureInstanceKHR)); + command_buffer->End(); + + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + delete staging_buffer; + command_pool->Free(command_buffer); + delete command_pool; + } + + VkBufferDeviceAddressInfo instance_buffer_device_address_info = {}; + instance_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + instance_buffer_device_address_info.pNext = nullptr; + instance_buffer_device_address_info.buffer = instance_buffer->GetVkBuffer(); + + VkDeviceAddress instance_buffer_device_address = 0; + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + instance_buffer_device_address = device_driver->vkGetBufferDeviceAddress(vk_device, &instance_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + instance_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(vk_device, &instance_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + instance_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(vk_device, &instance_buffer_device_address_info); + } + + if (instance_buffer_device_address != 0) + { + std::cout << "Successfully get instance_buffer VkBuffer device local address " << std::endl; + } + + // Create Top Level Acceleration Structure + VkAccelerationStructureGeometryInstancesDataKHR vk_acceleration_structure_geometry_instances_data_khr = {}; + vk_acceleration_structure_geometry_instances_data_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + vk_acceleration_structure_geometry_instances_data_khr.pNext = nullptr; + vk_acceleration_structure_geometry_instances_data_khr.arrayOfPointers = VK_FALSE; + vk_acceleration_structure_geometry_instances_data_khr.data.deviceAddress = instance_buffer_device_address; + + VkAccelerationStructureGeometryKHR top_level_acceleration_structure_geometry_khr = {}; + top_level_acceleration_structure_geometry_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + top_level_acceleration_structure_geometry_khr.pNext = nullptr; + top_level_acceleration_structure_geometry_khr.geometryType = VkGeometryTypeKHR::VK_GEOMETRY_TYPE_INSTANCES_KHR; + top_level_acceleration_structure_geometry_khr.geometry.instances = vk_acceleration_structure_geometry_instances_data_khr; + top_level_acceleration_structure_geometry_khr.flags = 0; + + VkAccelerationStructureBuildGeometryInfoKHR top_level_acceleration_structure_build_geometry_info_khr = {}; + top_level_acceleration_structure_build_geometry_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + top_level_acceleration_structure_build_geometry_info_khr.pNext = nullptr; + top_level_acceleration_structure_build_geometry_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + top_level_acceleration_structure_build_geometry_info_khr.flags = VkBuildAccelerationStructureFlagBitsKHR::VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VkBuildAccelerationStructureFlagBitsKHR::VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR; + top_level_acceleration_structure_build_geometry_info_khr.mode = VkBuildAccelerationStructureModeKHR::VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + top_level_acceleration_structure_build_geometry_info_khr.srcAccelerationStructure = VK_NULL_HANDLE; + top_level_acceleration_structure_build_geometry_info_khr.dstAccelerationStructure = VK_NULL_HANDLE; + top_level_acceleration_structure_build_geometry_info_khr.geometryCount = 1; + top_level_acceleration_structure_build_geometry_info_khr.pGeometries = &top_level_acceleration_structure_geometry_khr; + top_level_acceleration_structure_build_geometry_info_khr.ppGeometries = nullptr; + top_level_acceleration_structure_build_geometry_info_khr.scratchData.deviceAddress = 0; + top_level_acceleration_structure_build_geometry_info_khr.scratchData.hostAddress = 0; + + uint32_t instance_count = 1; + VkAccelerationStructureBuildSizesInfoKHR top_level_acceleration_structure_build_sizes_info_khr = {}; + top_level_acceleration_structure_build_sizes_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; + top_level_acceleration_structure_build_sizes_info_khr.pNext = nullptr; + top_level_acceleration_structure_build_sizes_info_khr.accelerationStructureSize = 0; + top_level_acceleration_structure_build_sizes_info_khr.updateScratchSize = 0; + top_level_acceleration_structure_build_sizes_info_khr.buildScratchSize = 0; + + device->GetDeviceDriver()->vkGetAccelerationStructureBuildSizesKHR(vk_device, VkAccelerationStructureBuildTypeKHR::VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &top_level_acceleration_structure_build_geometry_info_khr, &instance_count, &top_level_acceleration_structure_build_sizes_info_khr); + + std::cout << "Top Level VkAccelerationStructureBuildSizesInfoKHR.accelerationStructureSize = " << top_level_acceleration_structure_build_sizes_info_khr.accelerationStructureSize << std::endl; + std::cout << "Top Level VkAccelerationStructureBuildSizesInfoKHR.updateScratchSize = " << top_level_acceleration_structure_build_sizes_info_khr.updateScratchSize << std::endl; + std::cout << "Top Level VkAccelerationStructureBuildSizesInfoKHR.buildScratchSize = " << top_level_acceleration_structure_build_sizes_info_khr.buildScratchSize << std::endl; + + top_level_acceleration_structure_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_STORAGE | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, top_level_acceleration_structure_build_sizes_info_khr.accelerationStructureSize); + + VkAccelerationStructureCreateInfoKHR top_level_acceleration_structure_create_info_khr = {}; + top_level_acceleration_structure_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + top_level_acceleration_structure_create_info_khr.pNext = nullptr; + top_level_acceleration_structure_create_info_khr.createFlags = 0; + top_level_acceleration_structure_create_info_khr.buffer = top_level_acceleration_structure_buffer->GetVkBuffer(); + top_level_acceleration_structure_create_info_khr.offset = 0; + top_level_acceleration_structure_create_info_khr.size = top_level_acceleration_structure_build_sizes_info_khr.accelerationStructureSize; + top_level_acceleration_structure_create_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + top_level_acceleration_structure_create_info_khr.deviceAddress = 0; + + result = device->GetDeviceDriver()->vkCreateAccelerationStructureKHR(vk_device, &top_level_acceleration_structure_create_info_khr, vk_allocation_callbacks, &top_level_acceleration_structure_khr); + if (result != VkResult::VK_SUCCESS) + { + std::cout << "vkCreateAccelerationStructureKHR create Top Level VkAccelerationStructureKHR Failed" << std::endl; + } + + std::cout << "vkCreateAccelerationStructureKHR create Top Level VkAccelerationStructureKHR Success" << std::endl; + + Turbo::Core::TBuffer *top_level_scratch_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, top_level_acceleration_structure_build_sizes_info_khr.buildScratchSize); + + VkBufferDeviceAddressInfo top_level_scratch_buffer_device_address_info = {}; + top_level_scratch_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + top_level_scratch_buffer_device_address_info.pNext = nullptr; + top_level_scratch_buffer_device_address_info.buffer = top_level_scratch_buffer->GetVkBuffer(); + + VkDeviceAddress top_level_scratch_buffer_device_address = 0; + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + top_level_scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddress(vk_device, &top_level_scratch_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + top_level_scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(vk_device, &top_level_scratch_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + top_level_scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(vk_device, &top_level_scratch_buffer_device_address_info); + } + + if (top_level_scratch_buffer_device_address != 0) + { + std::cout << "Successfully get top_level_scratch_buffer VkBuffer device local address " << std::endl; + } + + // Build Top Level Acceleration Structure + top_level_acceleration_structure_build_geometry_info_khr.dstAccelerationStructure = top_level_acceleration_structure_khr; + top_level_acceleration_structure_build_geometry_info_khr.scratchData.deviceAddress = top_level_scratch_buffer_device_address; + + VkAccelerationStructureBuildRangeInfoKHR top_level_acceleration_structure_build_range_info_khr = {}; + top_level_acceleration_structure_build_range_info_khr.primitiveCount = 1; + top_level_acceleration_structure_build_range_info_khr.primitiveOffset = 0; + top_level_acceleration_structure_build_range_info_khr.firstVertex = 0; + top_level_acceleration_structure_build_range_info_khr.transformOffset = 0; + + std::vector top_level_acceleration_structure_build_range_info_khrs; + top_level_acceleration_structure_build_range_info_khrs.push_back(top_level_acceleration_structure_build_range_info_khr); + + std::vector top_level_acceleration_structure_ppBuildRangeInfos; + top_level_acceleration_structure_ppBuildRangeInfos.push_back(top_level_acceleration_structure_build_range_info_khrs.data()); + + { + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdBuildAccelerationStructuresKHR(command_buffer->GetVkCommandBuffer(), 1, &top_level_acceleration_structure_build_geometry_info_khr, top_level_acceleration_structure_ppBuildRangeInfos.data()); + command_buffer->End(); + + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + delete command_pool; + } + + // Top Level Acceleration Structure Compact + { + VkQueryPool query_pool = VK_NULL_HANDLE; + + VkQueryPoolCreateInfo vk_query_pool_create_info = {}; + vk_query_pool_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + vk_query_pool_create_info.pNext = nullptr; + vk_query_pool_create_info.flags = 0; + vk_query_pool_create_info.queryType = VkQueryType::VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR; + vk_query_pool_create_info.queryCount = 1; + vk_query_pool_create_info.pipelineStatistics = 0; + + result = device->GetDeviceDriver()->vkCreateQueryPool(vk_device, &vk_query_pool_create_info, vk_allocation_callbacks, &query_pool); + if (result != VK_SUCCESS) + { + std::cout << "Create VkQueryPool Failed" << std::endl; + } + + std::cout << "Create VkQueryPool Success" << std::endl; + + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdResetQueryPool(command_buffer->GetVkCommandBuffer(), query_pool, 0, 1); + device->GetDeviceDriver()->vkCmdWriteAccelerationStructuresPropertiesKHR(command_buffer->GetVkCommandBuffer(), 1, &top_level_acceleration_structure_khr, VkQueryType::VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, query_pool, 0); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + VkDeviceSize compact_size = 0; + device->GetDeviceDriver()->vkGetQueryPoolResults(vk_device, query_pool, 0, 1, sizeof(VkDeviceSize), &compact_size, sizeof(VkDeviceSize), VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); + std::cout << "top level acceleration structure compact size:" << compact_size << std::endl; + + delete fence; + command_pool->Free(command_buffer); + + VkAccelerationStructureKHR compact_acceleration_structure_khr = VK_NULL_HANDLE; + + Turbo::Core::TBuffer *compact_acceleration_structure_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_STORAGE | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, compact_size); + + VkAccelerationStructureCreateInfoKHR compact_vk_acceleration_structure_create_info_khr = {}; + compact_vk_acceleration_structure_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + compact_vk_acceleration_structure_create_info_khr.pNext = nullptr; + compact_vk_acceleration_structure_create_info_khr.createFlags = 0; + compact_vk_acceleration_structure_create_info_khr.buffer = compact_acceleration_structure_buffer->GetVkBuffer(); + compact_vk_acceleration_structure_create_info_khr.offset = 0; + compact_vk_acceleration_structure_create_info_khr.size = compact_size; + compact_vk_acceleration_structure_create_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + compact_vk_acceleration_structure_create_info_khr.deviceAddress = 0; + + result = device->GetDeviceDriver()->vkCreateAccelerationStructureKHR(vk_device, &compact_vk_acceleration_structure_create_info_khr, vk_allocation_callbacks, &compact_acceleration_structure_khr); + if (result != VkResult::VK_SUCCESS) + { + std::cout << "vkCreateAccelerationStructureKHR create compact VkAccelerationStructureKHR Failed" << std::endl; + } + + std::cout << "vkCreateAccelerationStructureKHR create compact VkAccelerationStructureKHR Success" << std::endl; + + VkCopyAccelerationStructureInfoKHR vk_copy_acceleration_structure_info_khr = {}; + vk_copy_acceleration_structure_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR; + vk_copy_acceleration_structure_info_khr.pNext = nullptr; + vk_copy_acceleration_structure_info_khr.src = top_level_acceleration_structure_khr; + vk_copy_acceleration_structure_info_khr.dst = compact_acceleration_structure_khr; + vk_copy_acceleration_structure_info_khr.mode = VkCopyAccelerationStructureModeKHR::VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR; + + command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdCopyAccelerationStructureKHR(command_buffer->GetVkCommandBuffer(), &vk_copy_acceleration_structure_info_khr); + command_buffer->End(); + fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + delete fence; + command_pool->Free(command_buffer); + delete command_pool; + device->GetDeviceDriver()->vkDestroyQueryPool(vk_device, query_pool, vk_allocation_callbacks); + + // destroy no compact acceleration structure + device->GetDeviceDriver()->vkDestroyAccelerationStructureKHR(vk_device, top_level_acceleration_structure_khr, vk_allocation_callbacks); + delete top_level_acceleration_structure_buffer; + + // set acceleration structure value to compact version + top_level_acceleration_structure_khr = compact_acceleration_structure_khr; + top_level_acceleration_structure_buffer = compact_acceleration_structure_buffer; + } + + delete top_level_scratch_buffer; + delete scratch_buffer; + } + + // Ray Tracing Pipeline + Turbo::Core::TRayGenerationShader *ray_generation_shader_test = nullptr; + Turbo::Core::TMissShader *miss_shader_test = nullptr; + Turbo::Core::TClosestHitShader *closest_hit_shader_test = nullptr; + Turbo::Core::TCallableShader *callable_shader_r_test = nullptr; + Turbo::Core::TCallableShader *callable_shader_g_test = nullptr; + Turbo::Core::TCallableShader *callable_shader_b_test = nullptr; + + VkDescriptorSetLayout ray_tracing_descriptor_set_layout = VK_NULL_HANDLE; + VkDescriptorSet ray_tracing_descriptor_set = VK_NULL_HANDLE; + VkPipelineLayout ray_tracing_pipeline_layout = VK_NULL_HANDLE; + VkPipeline ray_tracing_pipeline = VK_NULL_HANDLE; + + VkStridedDeviceAddressRegionKHR ray_generation_binding_table = {}; + VkStridedDeviceAddressRegionKHR miss_binding_table = {}; + VkStridedDeviceAddressRegionKHR hit_binding_table = {}; + VkStridedDeviceAddressRegionKHR callable_binding_table = {}; + + Turbo::Core::TBuffer *sbt_buffer = nullptr; + { + VkDescriptorSetLayoutBinding vk_ray_tracing_binding_acceleration_structure = {}; + vk_ray_tracing_binding_acceleration_structure.binding = 0; + vk_ray_tracing_binding_acceleration_structure.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + vk_ray_tracing_binding_acceleration_structure.descriptorCount = 1; + vk_ray_tracing_binding_acceleration_structure.stageFlags = VkShaderStageFlagBits::VK_SHADER_STAGE_RAYGEN_BIT_KHR; + vk_ray_tracing_binding_acceleration_structure.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutBinding vk_ray_tracing_binding_storage_image = {}; + vk_ray_tracing_binding_storage_image.binding = 1; + vk_ray_tracing_binding_storage_image.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + vk_ray_tracing_binding_storage_image.descriptorCount = 1; + vk_ray_tracing_binding_storage_image.stageFlags = VkShaderStageFlagBits::VK_SHADER_STAGE_RAYGEN_BIT_KHR; + vk_ray_tracing_binding_storage_image.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutBinding vk_ray_tracing_binding_matrixs = {}; + vk_ray_tracing_binding_matrixs.binding = 2; + vk_ray_tracing_binding_matrixs.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + vk_ray_tracing_binding_matrixs.descriptorCount = 1; + vk_ray_tracing_binding_matrixs.stageFlags = VkShaderStageFlagBits::VK_SHADER_STAGE_RAYGEN_BIT_KHR; + vk_ray_tracing_binding_matrixs.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutBinding vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address = {}; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.binding = 3; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.descriptorCount = 1; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.stageFlags = VkShaderStageFlagBits::VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.pImmutableSamplers = nullptr; + + std::vector ray_tracing_descriptor_set_layout_bindings = {}; + ray_tracing_descriptor_set_layout_bindings.push_back(vk_ray_tracing_binding_acceleration_structure); + ray_tracing_descriptor_set_layout_bindings.push_back(vk_ray_tracing_binding_storage_image); + ray_tracing_descriptor_set_layout_bindings.push_back(vk_ray_tracing_binding_matrixs); + ray_tracing_descriptor_set_layout_bindings.push_back(vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address); + + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = {}; + descriptor_set_layout_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptor_set_layout_create_info.pNext = nullptr; + descriptor_set_layout_create_info.flags = 0; + descriptor_set_layout_create_info.bindingCount = ray_tracing_descriptor_set_layout_bindings.size(); + descriptor_set_layout_create_info.pBindings = ray_tracing_descriptor_set_layout_bindings.data(); + + VkAllocationCallbacks *vk_allocation_callbacks = Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks(); + VkResult ray_tracing_descriptor_set_layout_create_result = device_driver->vkCreateDescriptorSetLayout(device->GetVkDevice(), &descriptor_set_layout_create_info, vk_allocation_callbacks, &ray_tracing_descriptor_set_layout); + if (ray_tracing_descriptor_set_layout_create_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Create ray tracing descriptor set layout failed"); + } + + VkDescriptorSetAllocateInfo ray_tracing_descriptor_set_allocate_info = {}; + ray_tracing_descriptor_set_allocate_info.sType = VkStructureType::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + ray_tracing_descriptor_set_allocate_info.pNext = nullptr; + ray_tracing_descriptor_set_allocate_info.descriptorPool = descriptor_pool->GetVkDescriptorPool(); + ray_tracing_descriptor_set_allocate_info.descriptorSetCount = 1; + ray_tracing_descriptor_set_allocate_info.pSetLayouts = &ray_tracing_descriptor_set_layout; + + VkResult ray_tracing_descriptor_sets_allocate_result = device_driver->vkAllocateDescriptorSets(device->GetVkDevice(), &ray_tracing_descriptor_set_allocate_info, &ray_tracing_descriptor_set); + if (ray_tracing_descriptor_sets_allocate_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Allocate ray tracing descriptor set failed"); + } + + VkWriteDescriptorSetAccelerationStructureKHR vk_write_descriptor_set_acceleration_structure_khr = {}; + vk_write_descriptor_set_acceleration_structure_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; + vk_write_descriptor_set_acceleration_structure_khr.pNext = nullptr; + vk_write_descriptor_set_acceleration_structure_khr.accelerationStructureCount = 1; + vk_write_descriptor_set_acceleration_structure_khr.pAccelerationStructures = &top_level_acceleration_structure_khr; + + VkWriteDescriptorSet ray_tracing_write_acceleration_structure = {}; + ray_tracing_write_acceleration_structure.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_acceleration_structure.pNext = &vk_write_descriptor_set_acceleration_structure_khr; + ray_tracing_write_acceleration_structure.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_acceleration_structure.dstBinding = 0; + ray_tracing_write_acceleration_structure.dstArrayElement = 0; + ray_tracing_write_acceleration_structure.descriptorCount = 1; + ray_tracing_write_acceleration_structure.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + ray_tracing_write_acceleration_structure.pImageInfo = nullptr; + ray_tracing_write_acceleration_structure.pBufferInfo = nullptr; + ray_tracing_write_acceleration_structure.pTexelBufferView = nullptr; + + VkDescriptorImageInfo vk_descriptor_image_info = {}; + vk_descriptor_image_info.sampler = VK_NULL_HANDLE; + vk_descriptor_image_info.imageView = ray_tracing_image_view->GetVkImageView(); + vk_descriptor_image_info.imageLayout = VkImageLayout::VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet ray_tracing_write_image = {}; + ray_tracing_write_image.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_image.pNext = nullptr; + ray_tracing_write_image.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_image.dstBinding = 1; + ray_tracing_write_image.dstArrayElement = 0; + ray_tracing_write_image.descriptorCount = 1; + ray_tracing_write_image.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + ray_tracing_write_image.pImageInfo = &vk_descriptor_image_info; + ray_tracing_write_image.pBufferInfo = nullptr; + ray_tracing_write_image.pTexelBufferView = nullptr; + + VkDescriptorBufferInfo vk_descriptor_matrixs_buffer_info = {}; + vk_descriptor_matrixs_buffer_info.buffer = matrixs_buffer->GetVkBuffer(); + vk_descriptor_matrixs_buffer_info.offset = 0; + vk_descriptor_matrixs_buffer_info.range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet ray_tracing_write_matrixs = {}; + ray_tracing_write_matrixs.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_matrixs.pNext = nullptr; + ray_tracing_write_matrixs.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_matrixs.dstBinding = 2; + ray_tracing_write_matrixs.dstArrayElement = 0; + ray_tracing_write_matrixs.descriptorCount = 1; + ray_tracing_write_matrixs.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + ray_tracing_write_matrixs.pImageInfo = nullptr; + ray_tracing_write_matrixs.pBufferInfo = &vk_descriptor_matrixs_buffer_info; + ray_tracing_write_matrixs.pTexelBufferView = nullptr; + + VkDescriptorBufferInfo vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info = {}; + vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info.buffer = bottom_level_acceleration_structure_device_address_buffer->GetVkBuffer(); + vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info.offset = 0; + vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info.range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer = {}; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.pNext = nullptr; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.dstBinding = 3; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.dstArrayElement = 0; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.descriptorCount = 1; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.pImageInfo = nullptr; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.pBufferInfo = &vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.pTexelBufferView = nullptr; + + std::vector vk_write_descriptor_sets; + vk_write_descriptor_sets.push_back(ray_tracing_write_acceleration_structure); + vk_write_descriptor_sets.push_back(ray_tracing_write_image); + vk_write_descriptor_sets.push_back(ray_tracing_write_matrixs); + vk_write_descriptor_sets.push_back(ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer); + + device_driver->vkUpdateDescriptorSets(device->GetVkDevice(), vk_write_descriptor_sets.size(), vk_write_descriptor_sets.data(), 0, nullptr); + + VkPushConstantRange vk_push_constant_range = {}; + vk_push_constant_range.stageFlags = VkShaderStageFlagBits::VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + vk_push_constant_range.offset = 0; + vk_push_constant_range.size = sizeof(my_push_constants); + + VkPipelineLayoutCreateInfo ray_tracing_pipeline_layout_create_info = {}; + ray_tracing_pipeline_layout_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + ray_tracing_pipeline_layout_create_info.pNext = nullptr; + ray_tracing_pipeline_layout_create_info.flags = 0; + ray_tracing_pipeline_layout_create_info.setLayoutCount = 1; + ray_tracing_pipeline_layout_create_info.pSetLayouts = &ray_tracing_descriptor_set_layout; + ray_tracing_pipeline_layout_create_info.pushConstantRangeCount = 1; + ray_tracing_pipeline_layout_create_info.pPushConstantRanges = &vk_push_constant_range; + + VkResult ray_tracing_pipeline_layout_create_result = device_driver->vkCreatePipelineLayout(device->GetVkDevice(), &ray_tracing_pipeline_layout_create_info, vk_allocation_callbacks, &ray_tracing_pipeline_layout); + if (ray_tracing_pipeline_layout_create_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Create ray tracing pipeline layout failed"); + } + + ray_generation_shader_test = new Turbo::Core::TRayGenerationShader(device, Turbo::Core::TShaderLanguage::GLSL, RAY_GENERATION_SHADER_STR); + miss_shader_test = new Turbo::Core::TMissShader(device, Turbo::Core::TShaderLanguage::GLSL, MISS_SHADER_STR); + closest_hit_shader_test = new Turbo::Core::TClosestHitShader(device, Turbo::Core::TShaderLanguage::GLSL, CLOSEST_HIT_SHADER_STR); + callable_shader_r_test = new Turbo::Core::TCallableShader(device, Turbo::Core::TShaderLanguage::GLSL, CALLABLE_SHADER_R_STR); + callable_shader_g_test = new Turbo::Core::TCallableShader(device, Turbo::Core::TShaderLanguage::GLSL, CALLABLE_SHADER_G_STR); + callable_shader_b_test = new Turbo::Core::TCallableShader(device, Turbo::Core::TShaderLanguage::GLSL, CALLABLE_SHADER_B_STR); + + VkPipelineShaderStageCreateInfo ray_generation_shader_stage_create_info = {}; + ray_generation_shader_stage_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + ray_generation_shader_stage_create_info.pNext = nullptr; + ray_generation_shader_stage_create_info.flags = 0; + ray_generation_shader_stage_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_RAYGEN_BIT_KHR; + ray_generation_shader_stage_create_info.module = ray_generation_shader_test->GetVkShaderModule(); + ray_generation_shader_stage_create_info.pName = "main"; + ray_generation_shader_stage_create_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo miss_shader_stage_create_info = {}; + miss_shader_stage_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + miss_shader_stage_create_info.pNext = nullptr; + miss_shader_stage_create_info.flags = 0; + miss_shader_stage_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_MISS_BIT_KHR; + miss_shader_stage_create_info.module = miss_shader_test->GetVkShaderModule(); + miss_shader_stage_create_info.pName = "main"; + miss_shader_stage_create_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo closest_hit_shader_stage_create_info = {}; + closest_hit_shader_stage_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + closest_hit_shader_stage_create_info.pNext = nullptr; + closest_hit_shader_stage_create_info.flags = 0; + closest_hit_shader_stage_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + closest_hit_shader_stage_create_info.module = closest_hit_shader_test->GetVkShaderModule(); + closest_hit_shader_stage_create_info.pName = "main"; + closest_hit_shader_stage_create_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo callable_shader_stage_r_create_info = {}; + callable_shader_stage_r_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + callable_shader_stage_r_create_info.pNext = nullptr; + callable_shader_stage_r_create_info.flags = 0; + callable_shader_stage_r_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_CALLABLE_BIT_KHR; + callable_shader_stage_r_create_info.module = callable_shader_r_test->GetVkShaderModule(); + callable_shader_stage_r_create_info.pName = "main"; + callable_shader_stage_r_create_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo callable_shader_stage_g_create_info = {}; + callable_shader_stage_g_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + callable_shader_stage_g_create_info.pNext = nullptr; + callable_shader_stage_g_create_info.flags = 0; + callable_shader_stage_g_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_CALLABLE_BIT_KHR; + callable_shader_stage_g_create_info.module = callable_shader_g_test->GetVkShaderModule(); + callable_shader_stage_g_create_info.pName = "main"; + callable_shader_stage_g_create_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo callable_shader_stage_b_create_info = {}; + callable_shader_stage_b_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + callable_shader_stage_b_create_info.pNext = nullptr; + callable_shader_stage_b_create_info.flags = 0; + callable_shader_stage_b_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_CALLABLE_BIT_KHR; + callable_shader_stage_b_create_info.module = callable_shader_b_test->GetVkShaderModule(); + callable_shader_stage_b_create_info.pName = "main"; + callable_shader_stage_b_create_info.pSpecializationInfo = nullptr; + + std::vector ray_tracing_pipeline_shader_stages = {}; + ray_tracing_pipeline_shader_stages.push_back(ray_generation_shader_stage_create_info); + ray_tracing_pipeline_shader_stages.push_back(miss_shader_stage_create_info); + ray_tracing_pipeline_shader_stages.push_back(closest_hit_shader_stage_create_info); + ray_tracing_pipeline_shader_stages.push_back(callable_shader_stage_r_create_info); + ray_tracing_pipeline_shader_stages.push_back(callable_shader_stage_g_create_info); + ray_tracing_pipeline_shader_stages.push_back(callable_shader_stage_b_create_info); + + VkRayTracingShaderGroupCreateInfoKHR ray_generation_shader_group = {}; + ray_generation_shader_group.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + ray_generation_shader_group.pNext = nullptr; + ray_generation_shader_group.type = VkRayTracingShaderGroupTypeKHR::VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + ray_generation_shader_group.generalShader = 0; + ray_generation_shader_group.closestHitShader = VK_SHADER_UNUSED_KHR; + ray_generation_shader_group.anyHitShader = VK_SHADER_UNUSED_KHR; + ray_generation_shader_group.intersectionShader = VK_SHADER_UNUSED_KHR; + ray_generation_shader_group.pShaderGroupCaptureReplayHandle = nullptr; + + VkRayTracingShaderGroupCreateInfoKHR miss_shader_group = {}; + miss_shader_group.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + miss_shader_group.pNext = nullptr; + miss_shader_group.type = VkRayTracingShaderGroupTypeKHR::VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + miss_shader_group.generalShader = 1; + miss_shader_group.closestHitShader = VK_SHADER_UNUSED_KHR; + miss_shader_group.anyHitShader = VK_SHADER_UNUSED_KHR; + miss_shader_group.intersectionShader = VK_SHADER_UNUSED_KHR; + miss_shader_group.pShaderGroupCaptureReplayHandle = nullptr; + + VkRayTracingShaderGroupCreateInfoKHR close_hit_shader_group = {}; + close_hit_shader_group.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + close_hit_shader_group.pNext = nullptr; + close_hit_shader_group.type = VkRayTracingShaderGroupTypeKHR::VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; + close_hit_shader_group.generalShader = VK_SHADER_UNUSED_KHR; + close_hit_shader_group.closestHitShader = 2; + close_hit_shader_group.anyHitShader = VK_SHADER_UNUSED_KHR; + close_hit_shader_group.intersectionShader = VK_SHADER_UNUSED_KHR; + close_hit_shader_group.pShaderGroupCaptureReplayHandle = nullptr; + + VkRayTracingShaderGroupCreateInfoKHR callable_shader_r_group = {}; + callable_shader_r_group.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + callable_shader_r_group.pNext = nullptr; + callable_shader_r_group.type = VkRayTracingShaderGroupTypeKHR::VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + callable_shader_r_group.generalShader = 3; + callable_shader_r_group.closestHitShader = VK_SHADER_UNUSED_KHR; + callable_shader_r_group.anyHitShader = VK_SHADER_UNUSED_KHR; + callable_shader_r_group.intersectionShader = VK_SHADER_UNUSED_KHR; + callable_shader_r_group.pShaderGroupCaptureReplayHandle = nullptr; + + VkRayTracingShaderGroupCreateInfoKHR callable_shader_g_group = {}; + callable_shader_g_group.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + callable_shader_g_group.pNext = nullptr; + callable_shader_g_group.type = VkRayTracingShaderGroupTypeKHR::VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + callable_shader_g_group.generalShader = 4; + callable_shader_g_group.closestHitShader = VK_SHADER_UNUSED_KHR; + callable_shader_g_group.anyHitShader = VK_SHADER_UNUSED_KHR; + callable_shader_g_group.intersectionShader = VK_SHADER_UNUSED_KHR; + callable_shader_g_group.pShaderGroupCaptureReplayHandle = nullptr; + + VkRayTracingShaderGroupCreateInfoKHR callable_shader_b_group = {}; + callable_shader_b_group.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + callable_shader_b_group.pNext = nullptr; + callable_shader_b_group.type = VkRayTracingShaderGroupTypeKHR::VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + callable_shader_b_group.generalShader = 5; + callable_shader_b_group.closestHitShader = VK_SHADER_UNUSED_KHR; + callable_shader_b_group.anyHitShader = VK_SHADER_UNUSED_KHR; + callable_shader_b_group.intersectionShader = VK_SHADER_UNUSED_KHR; + callable_shader_b_group.pShaderGroupCaptureReplayHandle = nullptr; + + std::vector shader_groups = {}; + shader_groups.push_back(ray_generation_shader_group); + shader_groups.push_back(miss_shader_group); + shader_groups.push_back(close_hit_shader_group); + shader_groups.push_back(callable_shader_r_group); + shader_groups.push_back(callable_shader_g_group); + shader_groups.push_back(callable_shader_b_group); + + VkRayTracingPipelineCreateInfoKHR vk_ray_tracing_pipeline_create_info_khr = {}; + vk_ray_tracing_pipeline_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; + vk_ray_tracing_pipeline_create_info_khr.pNext = nullptr; + vk_ray_tracing_pipeline_create_info_khr.flags = 0; + vk_ray_tracing_pipeline_create_info_khr.stageCount = ray_tracing_pipeline_shader_stages.size(); + vk_ray_tracing_pipeline_create_info_khr.pStages = ray_tracing_pipeline_shader_stages.data(); + vk_ray_tracing_pipeline_create_info_khr.groupCount = shader_groups.size(); + vk_ray_tracing_pipeline_create_info_khr.pGroups = shader_groups.data(); + vk_ray_tracing_pipeline_create_info_khr.maxPipelineRayRecursionDepth = 2; + vk_ray_tracing_pipeline_create_info_khr.pLibraryInfo = nullptr; + vk_ray_tracing_pipeline_create_info_khr.pLibraryInterface = nullptr; + vk_ray_tracing_pipeline_create_info_khr.pDynamicState = nullptr; + vk_ray_tracing_pipeline_create_info_khr.layout = ray_tracing_pipeline_layout; + vk_ray_tracing_pipeline_create_info_khr.basePipelineHandle = VK_NULL_HANDLE; + vk_ray_tracing_pipeline_create_info_khr.basePipelineIndex = 0; + + VkResult create_ray_tracing_pipeline_result = device_driver->vkCreateRayTracingPipelinesKHR(device->GetVkDevice(), VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &vk_ray_tracing_pipeline_create_info_khr, vk_allocation_callbacks, &ray_tracing_pipeline); + if (create_ray_tracing_pipeline_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Create ray tracing pipeline failed"); + } + + // Shader Binding Table + VkPhysicalDeviceRayTracingPipelinePropertiesKHR vk_physical_device_ray_tracing_pipeline_properties_khr = {}; + vk_physical_device_ray_tracing_pipeline_properties_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR; + vk_physical_device_ray_tracing_pipeline_properties_khr.pNext = nullptr; + vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleSize = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayRecursionDepth = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.maxShaderGroupStride = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupBaseAlignment = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleCaptureReplaySize = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayDispatchInvocationCount = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleAlignment = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayHitAttributeSize = 0; + + VkPhysicalDeviceProperties2 vk_physical_device_properties_2 = {}; + vk_physical_device_properties_2.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + vk_physical_device_properties_2.pNext = &vk_physical_device_ray_tracing_pipeline_properties_khr; + vk_physical_device_properties_2.properties = {}; + + if (physical_device_driver->vkGetPhysicalDeviceProperties2 != nullptr) + { + physical_device_driver->vkGetPhysicalDeviceProperties2(physical_device->GetVkPhysicalDevice(), &vk_physical_device_properties_2); + } + else if (physical_device_driver->vkGetPhysicalDeviceProperties2KHR != nullptr) + { + physical_device_driver->vkGetPhysicalDeviceProperties2KHR(physical_device->GetVkPhysicalDevice(), &vk_physical_device_properties_2); + } + + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleSize:" << vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleSize << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxRayRecursionDepth:" << vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayRecursionDepth << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxShaderGroupStride:" << vk_physical_device_ray_tracing_pipeline_properties_khr.maxShaderGroupStride << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupBaseAlignment:" << vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupBaseAlignment << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleCaptureReplaySize:" << vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleCaptureReplaySize << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxRayDispatchInvocationCount:" << vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayDispatchInvocationCount << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleAlignment:" << vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleAlignment << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxRayHitAttributeSize:" << vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayHitAttributeSize << std::endl; + + uint32_t ray_generation_count = 1; + uint32_t miss_count = 1; + uint32_t hit_count = 1; + uint32_t callable_count = 3; + + uint32_t handle_count = ray_generation_count + miss_count + hit_count + callable_count; + uint32_t handle_size = vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleSize; + uint32_t shader_group_handle_alignment = vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleAlignment; + uint32_t shader_group_base_alignment = vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupBaseAlignment; + + uint32_t handle_size_aligned = Turbo::Core::TVulkanAllocator::AlignUp(handle_size, shader_group_handle_alignment); + + ray_generation_binding_table.deviceAddress = 0; + ray_generation_binding_table.stride = Turbo::Core::TVulkanAllocator::AlignUp(handle_size_aligned, shader_group_base_alignment); + ray_generation_binding_table.size = ray_generation_binding_table.stride; // The size member of pRayGenShaderBindingTable must be equal to its stride member (https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap40.html#VUID-vkCmdTraceRaysKHR-size-04023) + + miss_binding_table.deviceAddress = 0; + miss_binding_table.stride = handle_size_aligned; + miss_binding_table.size = Turbo::Core::TVulkanAllocator::AlignUp(miss_count * handle_size_aligned, shader_group_base_alignment); + + hit_binding_table.deviceAddress = 0; + hit_binding_table.stride = handle_size_aligned; + hit_binding_table.size = Turbo::Core::TVulkanAllocator::AlignUp(hit_count * handle_size_aligned, shader_group_base_alignment); + + callable_binding_table.deviceAddress = 0; + callable_binding_table.stride = handle_size_aligned; + callable_binding_table.size = Turbo::Core::TVulkanAllocator::AlignUp(callable_count * handle_size_aligned, shader_group_base_alignment); + + uint32_t data_size = handle_count * handle_size_aligned; + std::vector handles(data_size); + VkResult vk_get_ray_tracing_shader_group_handles_khr_result = device_driver->vkGetRayTracingShaderGroupHandlesKHR(device->GetVkDevice(), ray_tracing_pipeline, 0, handle_count, data_size, handles.data()); + if (vk_get_ray_tracing_shader_group_handles_khr_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Get shader group handle failed"); + } + + VkDeviceSize sbt_buffer_size = ray_generation_binding_table.size + miss_binding_table.size + hit_binding_table.size + callable_binding_table.size; + sbt_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_BINDING_TABLE, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sbt_buffer_size); + + VkBufferDeviceAddressInfo sbt_buffer_device_address_info = {}; + sbt_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + sbt_buffer_device_address_info.pNext = nullptr; + sbt_buffer_device_address_info.buffer = sbt_buffer->GetVkBuffer(); + + VkDeviceAddress sbt_buffer_device_address = 0; + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + sbt_buffer_device_address = device_driver->vkGetBufferDeviceAddress(device->GetVkDevice(), &sbt_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + sbt_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(device->GetVkDevice(), &sbt_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + sbt_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(device->GetVkDevice(), &sbt_buffer_device_address_info); + } + + if (sbt_buffer_device_address == 0) + { + throw std::runtime_error("Get shader binding table buffer address failed"); + } + + ray_generation_binding_table.deviceAddress = sbt_buffer_device_address; + miss_binding_table.deviceAddress = sbt_buffer_device_address + ray_generation_binding_table.size; + hit_binding_table.deviceAddress = sbt_buffer_device_address + ray_generation_binding_table.size + miss_binding_table.size; + callable_binding_table.deviceAddress = sbt_buffer_device_address + ray_generation_binding_table.size + miss_binding_table.size + hit_binding_table.size; + + void *sbt_buffer_point = sbt_buffer->Map(); + // ray generation + memcpy((uint8_t *)sbt_buffer_point, handles.data() + 0 * handle_size, handle_size); + // miss + memcpy((uint8_t *)sbt_buffer_point + ray_generation_binding_table.size, handles.data() + 1 * handle_size, handle_size); + // hit + memcpy((uint8_t *)sbt_buffer_point + ray_generation_binding_table.size + miss_binding_table.size, handles.data() + 2 * handle_size, handle_size); + // callable + for (uint32_t callable_index = 0; callable_index < callable_count; callable_index++) + { + memcpy((uint8_t *)sbt_buffer_point + ray_generation_binding_table.size + miss_binding_table.size + hit_binding_table.size + callable_index * callable_binding_table.stride, handles.data() + ray_generation_count * handle_size + miss_count * handle_size + hit_count * handle_size + callable_index * handle_size, handle_size); + } + // memcpy((uint8_t *)sbt_buffer_point + ray_generation_binding_table.size + miss_binding_table.size + hit_binding_table.size, handles.data() + 3 * handle_size, handle_size); + sbt_buffer->Unmap(); + } + + std::vector my_buffers; + my_buffers.push_back(my_buffer); + + std::vector matrixs_buffers; + matrixs_buffers.push_back(matrixs_buffer); + + Turbo::Core::TSubpass subpass(Turbo::Core::TPipelineType::Graphics); + subpass.AddColorAttachmentReference(0, Turbo::Core::TImageLayout::COLOR_ATTACHMENT_OPTIMAL); // swapchain color image + subpass.SetDepthStencilAttachmentReference(1, Turbo::Core::TImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); // depth image + + Turbo::Core::TSubpass subpass1(Turbo::Core::TPipelineType::Graphics); + subpass1.AddColorAttachmentReference(0, Turbo::Core::TImageLayout::COLOR_ATTACHMENT_OPTIMAL); // swapchain color image + subpass.SetDepthStencilAttachmentReference(1, Turbo::Core::TImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); // depth image + + std::vector subpasses; + subpasses.push_back(subpass); // subpass 0 + subpasses.push_back(subpass1); // subpass 1 + + Turbo::Core::TAttachment swapchain_color_attachment(swapchain_images[0]->GetFormat(), swapchain_images[0]->GetSampleCountBits(), Turbo::Core::TLoadOp::LOAD, Turbo::Core::TStoreOp::STORE, Turbo::Core::TLoadOp::DONT_CARE, Turbo::Core::TStoreOp::DONT_CARE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::PRESENT_SRC_KHR); + Turbo::Core::TAttachment depth_attachment(depth_image->GetFormat(), depth_image->GetSampleCountBits(), Turbo::Core::TLoadOp::CLEAR, Turbo::Core::TStoreOp::STORE, Turbo::Core::TLoadOp::DONT_CARE, Turbo::Core::TStoreOp::DONT_CARE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + std::vector attachemts; + attachemts.push_back(swapchain_color_attachment); + attachemts.push_back(depth_attachment); + + Turbo::Core::TRenderPass *render_pass = new Turbo::Core::TRenderPass(device, attachemts, subpasses); + + Turbo::Core::TVertexBinding position_binding(0, sizeof(POSITION), Turbo::Core::TVertexRate::VERTEX); + position_binding.AddAttribute(0, Turbo::Core::TFormatType::R32G32B32_SFLOAT, 0); // position + Turbo::Core::TVertexBinding normal_binding(1, sizeof(NORMAL), Turbo::Core::TVertexRate::VERTEX); + normal_binding.AddAttribute(1, Turbo::Core::TFormatType::R32G32B32_SFLOAT, 0); // normal + Turbo::Core::TVertexBinding texcoord_binding(2, sizeof(TEXCOORD), Turbo::Core::TVertexRate::VERTEX); + texcoord_binding.AddAttribute(2, Turbo::Core::TFormatType::R32G32_SFLOAT, 0); // texcoord/uv + Turbo::Core::TVertexBinding tangent_binding(3, sizeof(TANGENT), Turbo::Core::TVertexRate::VERTEX); + tangent_binding.AddAttribute(3, Turbo::Core::TFormatType::R32G32B32A32_SFLOAT, 0); // tangent + + std::vector vertex_bindings; + vertex_bindings.push_back(position_binding); + vertex_bindings.push_back(normal_binding); + vertex_bindings.push_back(texcoord_binding); + vertex_bindings.push_back(tangent_binding); + + Turbo::Core::TViewport viewport(0, 0, surface->GetCurrentWidth(), surface->GetCurrentHeight(), 0, 1); + Turbo::Core::TScissor scissor(0, 0, surface->GetCurrentWidth(), surface->GetCurrentHeight()); + + uint32_t patch_control_points = 3; + Turbo::Core::TPolygonMode polygon_mode = Turbo::Core::TPolygonMode::FILL; + Turbo::Core::TGraphicsPipeline *pipeline = new Turbo::Core::TGraphicsPipeline(render_pass, 0, vertex_bindings, vertex_shader, geometry_shader, fragment_shader, Turbo::Core::TTopologyType::TRIANGLE_LIST, false, false, false, polygon_mode, Turbo::Core::TCullModeBits::MODE_BACK_BIT, Turbo::Core::TFrontFace::CLOCKWISE, false, 0, 0, 0, 1, false, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, true, true, Turbo::Core::TCompareOp::LESS_OR_EQUAL, false, false, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TCompareOp::ALWAYS, 0, 0, 0, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TCompareOp::ALWAYS, 0, 0, 0, 0, 0, false, Turbo::Core::TLogicOp::NO_OP, true, Turbo::Core::TBlendFactor::SRC_ALPHA, Turbo::Core::TBlendFactor::ONE_MINUS_SRC_ALPHA, Turbo::Core::TBlendOp::ADD, Turbo::Core::TBlendFactor::ONE_MINUS_SRC_ALPHA, Turbo::Core::TBlendFactor::ZERO, Turbo::Core::TBlendOp::ADD); + + std::vector input_attachment_depths; + input_attachment_depths.push_back(depth_image_view); + + Turbo::Core::TPipelineDescriptorSet *pipeline_descriptor_set = descriptor_pool->Allocate(pipeline->GetPipelineLayout()); + pipeline_descriptor_set->BindData(0, 0, 0, matrixs_buffers); + pipeline_descriptor_set->BindData(0, 1, 0, my_buffers); + + std::vector vertex_buffers; + vertex_buffers.push_back(position_buffer); + vertex_buffers.push_back(normal_buffer); + vertex_buffers.push_back(texcoord_buffer); + vertex_buffers.push_back(tangent_buffer); + + std::vector swpachain_framebuffers; + for (Turbo::Core::TImageView *swapchain_image_view_item : swapchain_image_views) + { + std::vector image_views; + image_views.push_back(swapchain_image_view_item); + image_views.push_back(depth_image_view); + + Turbo::Core::TFramebuffer *swapchain_framebuffer = new Turbo::Core::TFramebuffer(render_pass, image_views); + swpachain_framebuffers.push_back(swapchain_framebuffer); + } + + // + ImGui::CreateContext(); + ImGuiIO &io = ImGui::GetIO(); + + ImGui::StyleColorsDark(); + + Turbo::Core::TSampler *imgui_sampler = new Turbo::Core::TSampler(device); + Turbo::Core::TShader *imgui_vertex_shader = new Turbo::Core::TShader(device, Turbo::Core::TShaderType::VERTEX, Turbo::Core::TShaderLanguage::GLSL, IMGUI_VERT_SHADER_STR); + Turbo::Core::TShader *imgui_fragment_shader = new Turbo::Core::TShader(device, Turbo::Core::TShaderType::FRAGMENT, Turbo::Core::TShaderLanguage::GLSL, IMGUI_FRAG_SHADER_STR); + + Turbo::Core::TVertexBinding imgui_vertex_binding(0, sizeof(ImDrawVert), Turbo::Core::TVertexRate::VERTEX); + imgui_vertex_binding.AddAttribute(0, Turbo::Core::TFormatType::R32G32_SFLOAT, IM_OFFSETOF(ImDrawVert, pos)); // position + imgui_vertex_binding.AddAttribute(1, Turbo::Core::TFormatType::R32G32_SFLOAT, IM_OFFSETOF(ImDrawVert, uv)); // uv + imgui_vertex_binding.AddAttribute(2, Turbo::Core::TFormatType::R8G8B8A8_UNORM, IM_OFFSETOF(ImDrawVert, col)); // color + + std::vector imgui_shaders; + imgui_shaders.push_back(imgui_vertex_shader); + imgui_shaders.push_back(imgui_fragment_shader); + + std::vector imgui_vertex_bindings; + imgui_vertex_bindings.push_back(imgui_vertex_binding); + + Turbo::Core::TGraphicsPipeline *imgui_pipeline = new Turbo::Core::TGraphicsPipeline(render_pass, 1, imgui_vertex_bindings, imgui_shaders, Turbo::Core::TTopologyType::TRIANGLE_LIST, false, false, false, Turbo::Core::TPolygonMode::FILL, Turbo::Core::TCullModeBits::MODE_BACK_BIT, Turbo::Core::TFrontFace::CLOCKWISE, false, 0, 0, 0, 1, false, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, false, false, Turbo::Core::TCompareOp::LESS_OR_EQUAL, false, false, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TCompareOp::ALWAYS, 0, 0, 0, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TCompareOp::ALWAYS, 0, 0, 0, 0, 0, false, Turbo::Core::TLogicOp::NO_OP, true, Turbo::Core::TBlendFactor::SRC_ALPHA, Turbo::Core::TBlendFactor::ONE_MINUS_SRC_ALPHA, Turbo::Core::TBlendOp::ADD, Turbo::Core::TBlendFactor::ONE_MINUS_SRC_ALPHA, Turbo::Core::TBlendFactor::ZERO, Turbo::Core::TBlendOp::ADD); + + unsigned char *imgui_font_pixels; + int imgui_font_width, imgui_font_height; + io.Fonts->GetTexDataAsRGBA32(&imgui_font_pixels, &imgui_font_width, &imgui_font_height); + size_t imgui_upload_size = imgui_font_width * imgui_font_height * 4 * sizeof(char); + + Turbo::Core::TImage *imgui_font_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::R8G8B8A8_UNORM, imgui_font_width, imgui_font_height, 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_SAMPLED | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY); + Turbo::Core::TImageView *imgui_font_image_view = new Turbo::Core::TImageView(imgui_font_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, imgui_font_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + { + Turbo::Core::TBuffer *imgui_font_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, imgui_upload_size); + void *imgui_font_ptr = imgui_font_buffer->Map(); + memcpy(imgui_font_ptr, imgui_font_pixels, imgui_upload_size); + imgui_font_buffer->Unmap(); + + Turbo::Core::TCommandBuffer *imgui_copy_command_buffer = command_pool->Allocate(); + imgui_copy_command_buffer->Begin(); + imgui_copy_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::HOST_BIT, Turbo::Core::TPipelineStageBits::TRANSFER_BIT, Turbo::Core::TAccessBits::HOST_WRITE_BIT, Turbo::Core::TAccessBits::TRANSFER_WRITE_BIT, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, imgui_font_image, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + imgui_copy_command_buffer->CmdCopyBufferToImage(imgui_font_buffer, imgui_font_image, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, 0, imgui_font_width, imgui_font_height, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 0, 1, 0, 0, 0, imgui_font_width, imgui_font_height, 1); + imgui_copy_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TRANSFER_BIT, Turbo::Core::TPipelineStageBits::FRAGMENT_SHADER_BIT, Turbo::Core::TAccessBits::TRANSFER_WRITE_BIT, Turbo::Core::TAccessBits::SHADER_READ_BIT, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, Turbo::Core::TImageLayout::SHADER_READ_ONLY_OPTIMAL, imgui_font_image, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + imgui_copy_command_buffer->End(); + + Turbo::Core::TFence *imgui_font_copy_fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, imgui_copy_command_buffer, imgui_font_copy_fence); + + imgui_font_copy_fence->WaitUntil(); + + delete imgui_font_buffer; + delete imgui_font_copy_fence; + } + + std::vector> imgui_combined_image_samplers; + imgui_combined_image_samplers.push_back(std::make_pair(imgui_font_image_view, imgui_sampler)); + + Turbo::Core::TPipelineDescriptorSet *imgui_pipeline_descriptor_set = descriptor_pool->Allocate(imgui_pipeline->GetPipelineLayout()); + imgui_pipeline_descriptor_set->BindData(0, 0, 0, imgui_combined_image_samplers); + + io.Fonts->TexID = (ImTextureID)(intptr_t)(imgui_font_image->GetVkImage()); + + Turbo::Core::TBuffer *imgui_vertex_buffer = nullptr; + Turbo::Core::TBuffer *imgui_index_buffer = nullptr; + // + + glm::vec3 camera_position = glm::vec3(1.00025, -1.50862, -2.52088); + + float horizontal_angle = 383.2; + float vertical_angle = 28; + + glm::vec2 previous_mouse_pos = glm::vec2(0, 0); + glm::vec2 current_mouse_pos = glm::vec2(0, 0); + + float angle = 0; + float _time = glfwGetTime(); + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + + void *_ptr = my_buffer->Map(); + memcpy(_ptr, &my_buffer_data, sizeof(my_buffer_data)); + my_buffer->Unmap(); + + // + uint32_t current_image_index = UINT32_MAX; + Turbo::Core::TSemaphore *wait_image_ready = new Turbo::Core::TSemaphore(device, Turbo::Core::TPipelineStageBits::COLOR_ATTACHMENT_OUTPUT_BIT); + Turbo::Core::TResult result = swapchain->AcquireNextImageUntil(wait_image_ready, nullptr, ¤t_image_index); + switch (result) + { + case Turbo::Core::TResult::SUCCESS: { + // successed get image and go on rendering + + // because we just have one command buffer, so we should reset the command buffer for each frame + // If we create command buffer for each swapchain image, we don't need to reset it each frame + + // + int window_w, window_h; + int display_w, display_h; + glfwGetWindowSize(window, &window_w, &window_h); + glfwGetFramebufferSize(window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)window_w, (float)window_h); + if (window_w > 0 && window_h > 0) + { + io.DisplayFramebufferScale = ImVec2((float)display_w / window_w, (float)display_h / window_h); + } + double current_time = glfwGetTime(); + io.DeltaTime = _time > 0.0 ? (float)(current_time - _time) : (float)(1.0f / 60.0f); + _time = current_time; + + // UpdateMousePosAndButtons + { + // Update buttons + ImGuiIO &io = ImGui::GetIO(); + for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) + { + // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(window, i) != 0; + g_MouseJustPressed[i] = false; + } + + // Update mouse position + const ImVec2 mouse_pos_backup = io.MousePos; + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + + const bool focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0; + if (focused) + { + if (io.WantSetMousePos) + { + glfwSetCursorPos(window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y); + } + else + { + double mouse_x, mouse_y; + glfwGetCursorPos(window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); + } + } + } + + // IUpdateMouseCursor + { + ImGuiIO &io = ImGui::GetIO(); + if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) + break; + + ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); + if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } + else + { + // Show OS mouse cursor + // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. + glfwSetCursor(window, g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } + } + + // UpdateKeyboard + { + ImVec2 mouse_pos = io.MousePos; + current_mouse_pos = glm::vec2(mouse_pos.x, mouse_pos.y); + glm::vec2 mouse_pos_delte = current_mouse_pos - previous_mouse_pos; + previous_mouse_pos = current_mouse_pos; + mouse_pos_delte.y = mouse_pos_delte.y; + + int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT); + if (state == GLFW_PRESS) + { + horizontal_angle += mouse_pos_delte.x * 0.2; + vertical_angle += mouse_pos_delte.y * 0.2; + + if (vertical_angle > 90) + { + vertical_angle = 90; + } + + if (vertical_angle < -90) + { + vertical_angle = -90; + } + } + + float delte_time = io.DeltaTime; + float speed = 1; + + glm::vec3 forward_axis = glm::vec3(0, 0, 1); + glm::mat4 forward_rotate_mat = glm::rotate(glm::mat4(1), glm::radians(-horizontal_angle), glm::vec3(0, 1, 0)); + forward_rotate_mat = glm::rotate(forward_rotate_mat, glm::radians(-vertical_angle), glm::vec3(1, 0, 0)); + + glm::vec3 look_forward = forward_rotate_mat * glm::vec4(forward_axis, 1.0); + look_forward = glm::normalize(look_forward); + + glm::vec3 forward_dir = look_forward; // 向前向量 + glm::vec3 up_dir = glm::vec3(0, 1, 0); // 向上向量 + glm::vec3 right_dir = glm::cross(forward_dir, up_dir); // 向右向量 + up_dir = glm::cross(right_dir, forward_dir); + + right_dir = glm::normalize(right_dir); + up_dir = glm::normalize(up_dir); + + int key_W_state = glfwGetKey(window, GLFW_KEY_W); + if (key_W_state == GLFW_PRESS) + { + // TODO: 向前 + camera_position += forward_dir * speed * delte_time; + } + + int key_A_state = glfwGetKey(window, GLFW_KEY_A); + if (key_A_state == GLFW_PRESS) + { + // TODO: 向左 + camera_position += -right_dir * speed * delte_time; + } + + int key_S_state = glfwGetKey(window, GLFW_KEY_S); + if (key_S_state == GLFW_PRESS) + { + // TODO: 向后 + camera_position += -forward_dir * speed * delte_time; + } + + int key_D_state = glfwGetKey(window, GLFW_KEY_D); + if (key_D_state == GLFW_PRESS) + { + // TODO: 向右 + camera_position += right_dir * speed * delte_time; + } + + model = glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + model = model * glm::rotate(glm::mat4(1.0f), glm::radians(angle), glm::vec3(0.0f, 0.0f, 1.0f)); + + glm::vec3 look_point = camera_position + forward_dir; + view = glm::lookAt(camera_position, look_point, up_dir); + projection = glm::perspective(glm::radians(45.0f), (float)(swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth()) / (float)(swapchain->GetHeight() <= 0 ? 1 : swapchain->GetHeight()), 0.1f, 300.0f); + + matrixs_buffer_data.m = model; + matrixs_buffer_data.v = view; + matrixs_buffer_data.p = projection; + + _ptr = matrixs_buffer->Map(); + memcpy(_ptr, &matrixs_buffer_data, sizeof(matrixs_buffer_data)); + matrixs_buffer->Unmap(); + } + + ImGui::NewFrame(); + + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("VulkanKHRRayTracingTestForCallableShader"); + ImGui::Text("W,A,S,D to move."); + ImGui::Text("Push down and drag mouse right button to rotate view."); + // ImGui::SliderFloat("angle", &angle, 0.0f, 360); + // ImGui::SliderFloat("scale", &my_buffer_data.scale, 0.03, 0.1); + ImGui::SliderInt("Callable Index", &my_push_constants.callableSBTIndex, 0, 2); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::End(); + } + // + + Turbo::Core::TViewport frame_viewport(0, 0, swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth(), swapchain->GetHeight(), 0, 1); + Turbo::Core::TScissor frame_scissor(0, 0, swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth(), swapchain->GetHeight() <= 0 ? 1 : swapchain->GetHeight()); + + std::vector frame_viewports; + frame_viewports.push_back(frame_viewport); + + std::vector frame_scissors; + frame_scissors.push_back(frame_scissor); + + command_buffer->Begin(); + + // ray tracing commands + { + VkCommandBuffer vk_command_buffer = command_buffer->GetVkCommandBuffer(); + device_driver->vkCmdBindPipeline(vk_command_buffer, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, ray_tracing_pipeline); + device_driver->vkCmdPushConstants(vk_command_buffer, ray_tracing_pipeline_layout, VkShaderStageFlagBits::VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0, sizeof(my_push_constants), &my_push_constants); + device_driver->vkCmdBindDescriptorSets(vk_command_buffer, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, ray_tracing_pipeline_layout, 0, 1, &ray_tracing_descriptor_set, 0, nullptr); + device_driver->vkCmdTraceRaysKHR(vk_command_buffer, &ray_generation_binding_table, &miss_binding_table, &hit_binding_table, &callable_binding_table, swapchain->GetWidth(), swapchain->GetHeight(), 1); + + // copy ray tracing image into color target image + VkImageBlit vk_image_blit = {}; + vk_image_blit.srcSubresource.aspectMask = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT; + vk_image_blit.srcSubresource.mipLevel = 0; + vk_image_blit.srcSubresource.baseArrayLayer = 0; + vk_image_blit.srcSubresource.layerCount = 1; + vk_image_blit.srcOffsets[0].x = 0; + vk_image_blit.srcOffsets[0].y = 0; + vk_image_blit.srcOffsets[0].z = 0; + vk_image_blit.srcOffsets[1].x = swapchain->GetWidth(); + vk_image_blit.srcOffsets[1].y = swapchain->GetHeight(); + vk_image_blit.srcOffsets[1].z = 1; + vk_image_blit.dstSubresource.aspectMask = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT; + vk_image_blit.dstSubresource.mipLevel = 0; + vk_image_blit.dstSubresource.baseArrayLayer = 0; + vk_image_blit.dstSubresource.layerCount = 1; + vk_image_blit.dstOffsets[0].x = 0; + vk_image_blit.dstOffsets[0].y = 0; + vk_image_blit.dstOffsets[0].z = 0; + vk_image_blit.dstOffsets[1].x = swapchain->GetWidth(); + vk_image_blit.dstOffsets[1].y = swapchain->GetHeight(); + vk_image_blit.dstOffsets[1].z = 1; + + command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TOP_OF_PIPE_BIT, Turbo::Core::TPipelineStageBits::TRANSFER_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::TRANSFER_WRITE_BIT, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, swpachain_framebuffers[current_image_index]->GetAttachments()[0]); + device_driver->vkCmdBlitImage(vk_command_buffer, ray_tracing_image->GetVkImage(), VkImageLayout::VK_IMAGE_LAYOUT_GENERAL, swpachain_framebuffers[current_image_index]->GetAttachments()[0]->GetImage()->GetVkImage(), VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vk_image_blit, VkFilter::VK_FILTER_LINEAR); + command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TRANSFER_BIT, Turbo::Core::TPipelineStageBits::COLOR_ATTACHMENT_OUTPUT_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::COLOR_ATTACHMENT_WRITE_BIT, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, Turbo::Core::TImageLayout::COLOR_ATTACHMENT_OPTIMAL, swpachain_framebuffers[current_image_index]->GetAttachments()[0]); + } + + command_buffer->CmdBeginRenderPass(render_pass, swpachain_framebuffers[current_image_index]); + + command_buffer->CmdSetViewport(frame_viewports); + command_buffer->CmdSetScissor(frame_scissors); + + // material_sphere + // command_buffer->CmdBindPipeline(pipeline); + // command_buffer->CmdBindPipelineDescriptorSet(pipeline_descriptor_set); + // command_buffer->CmdBindVertexBuffers(vertex_buffers); + // command_buffer->CmdSetLineWidth(1); + // command_buffer->CmdBindIndexBuffer(index_buffer); + // command_buffer->CmdDrawIndexed(indices_count, 1, 0, 0, 0); + + command_buffer->CmdNextSubpass(); + + // + ImGui::Render(); + ImDrawData *draw_data = ImGui::GetDrawData(); + const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); + + if (!is_minimized) + { + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); + int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); + if (fb_width <= 0 || fb_height <= 0) + { + break; + } + + if (draw_data->TotalVtxCount > 0) + { + size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + + if (imgui_vertex_buffer != nullptr) + { + delete imgui_vertex_buffer; + imgui_vertex_buffer = nullptr; + } + + if (imgui_index_buffer != nullptr) + { + delete imgui_index_buffer; + imgui_index_buffer = nullptr; + } + + imgui_vertex_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, vertex_size); + imgui_index_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_INDEX_BUFFER, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, index_size); + + ImDrawVert *vtx_dst = (ImDrawVert *)imgui_vertex_buffer->Map(); + ImDrawIdx *idx_dst = (ImDrawIdx *)imgui_index_buffer->Map(); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList *cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.Size; + idx_dst += cmd_list->IdxBuffer.Size; + } + imgui_vertex_buffer->Unmap(); + imgui_index_buffer->Unmap(); + + command_buffer->CmdBindPipeline(imgui_pipeline); + command_buffer->CmdBindPipelineDescriptorSet(imgui_pipeline_descriptor_set); + + std::vector imgui_vertex_buffers; + imgui_vertex_buffers.push_back(imgui_vertex_buffer); + command_buffer->CmdBindVertexBuffers(imgui_vertex_buffers); + command_buffer->CmdBindIndexBuffer(imgui_index_buffer, 0, sizeof(ImDrawIdx) == 2 ? Turbo::Core::TIndexType::UINT16 : Turbo::Core::TIndexType::UINT32); + + float scale[2]; + scale[0] = 2.0f / draw_data->DisplaySize.x; + scale[1] = 2.0f / draw_data->DisplaySize.y; + float translate[2]; + translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; + translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; + + command_buffer->CmdPushConstants(sizeof(float) * 0, sizeof(float) * 2, scale); + command_buffer->CmdPushConstants(sizeof(float) * 2, sizeof(float) * 2, translate); + + ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports + ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) + + int global_vtx_offset = 0; + int global_idx_offset = 0; + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList *cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd *pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback != NULL) + { + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + { + command_buffer->CmdBindPipeline(imgui_pipeline); + command_buffer->CmdBindPipelineDescriptorSet(imgui_pipeline_descriptor_set); + + std::vector __imgui_vertex_buffers; + __imgui_vertex_buffers.push_back(imgui_vertex_buffer); + command_buffer->CmdBindVertexBuffers(imgui_vertex_buffers); + command_buffer->CmdBindIndexBuffer(imgui_index_buffer, 0, sizeof(ImDrawIdx) == 2 ? Turbo::Core::TIndexType::UINT16 : Turbo::Core::TIndexType::UINT32); + + float __scale[2]; + __scale[0] = 2.0f / draw_data->DisplaySize.x; + __scale[1] = 2.0f / draw_data->DisplaySize.y; + float __translate[2]; + __translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; + __translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; + + command_buffer->CmdPushConstants(sizeof(float) * 0, sizeof(float) * 2, __scale); + command_buffer->CmdPushConstants(sizeof(float) * 2, sizeof(float) * 2, __translate); + } + else + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + // Project scissor/clipping rectangles into framebuffer space + ImVec4 clip_rect; + clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; + clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; + clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; + clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; + + if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) + { + // Negative offsets are illegal for vkCmdSetScissor + if (clip_rect.x < 0.0f) + clip_rect.x = 0.0f; + if (clip_rect.y < 0.0f) + clip_rect.y = 0.0f; + + // Apply scissor/clipping rectangle + VkRect2D scissor; + scissor.offset.x = (int32_t)(clip_rect.x); + scissor.offset.y = (int32_t)(clip_rect.y); + scissor.extent.width = (uint32_t)(clip_rect.z - clip_rect.x); + scissor.extent.height = (uint32_t)(clip_rect.w - clip_rect.y); + + Turbo::Core::TScissor imgui_scissor(scissor.offset.x, scissor.offset.y, scissor.extent.width, scissor.extent.height); + std::vector imgui_scissors; + imgui_scissors.push_back(imgui_scissor); + command_buffer->CmdSetScissor(imgui_scissors); + + // Draw + command_buffer->CmdDrawIndexed(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0); + } + } + } + global_idx_offset += cmd_list->IdxBuffer.Size; + global_vtx_offset += cmd_list->VtxBuffer.Size; + } + } + } + // + + command_buffer->CmdEndRenderPass(); + command_buffer->End(); + + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + std::vector wait_semaphores; + wait_semaphores.push_back(wait_image_ready); + + queue->Submit(&wait_semaphores, nullptr, command_buffer, fence); + + fence->WaitUntil(); // or you can use semaphore to wait for get higher performance + + delete fence; + + command_buffer->Reset(); // you can create an command buffer each for one swapchain image,for now just one command buffer + + Turbo::Core::TResult present_result = queue->Present(swapchain, current_image_index); + switch (present_result) + { + case Turbo::Core::TResult::MISMATCH: { + // the size of the window had changed you need to recreate swapchain + + // waite for idle + device->WaitIdle(); + + // destroy related resource + // clear old swapchain image + swapchain_images.clear(); + + // destroy swapchain image views + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + delete image_view_item; + } + + swapchain_image_views.clear(); + + // destroy depth image and view + delete depth_image_view; + delete depth_image; + + // destroy framebuffer + for (Turbo::Core::TFramebuffer *frame_buffer_item : swpachain_framebuffers) + { + delete frame_buffer_item; + } + swpachain_framebuffers.clear(); + + // destroy ray tracing image + delete ray_tracing_image_view; + delete ray_tracing_image; + + // recreate swapchain + Turbo::Extension::TSwapchain *old_swapchain = swapchain; + Turbo::Extension::TSwapchain *new_swapchain = new Turbo::Extension::TSwapchain(old_swapchain); + delete old_swapchain; + + swapchain = new_swapchain; + + // recreate swapchain image views + swapchain_images = swapchain->GetImages(); + for (Turbo::Core::TImage *swapchain_image_item : swapchain_images) + { + Turbo::Core::TImageView *swapchain_view = new Turbo::Core::TImageView(swapchain_image_item, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, Turbo::Core::TFormatType::B8G8R8A8_SRGB, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + swapchain_image_views.push_back(swapchain_view); + } + + // recreate depth image and view + depth_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::D32_SFLOAT, swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth(), swapchain->GetHeight() <= 0 ? 1 : swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_DEPTH_STENCIL_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_INPUT_ATTACHMENT, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, Turbo::Core::TImageLayout::UNDEFINED); + depth_image_view = new Turbo::Core::TImageView(depth_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, depth_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_DEPTH_BIT, 0, 1, 0, 1); + + // recreate framebuffer + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + std::vector swapchain_image_views; + swapchain_image_views.push_back(image_view_item); + swapchain_image_views.push_back(depth_image_view); + + Turbo::Core::TFramebuffer *swapchain_framebuffer = new Turbo::Core::TFramebuffer(render_pass, swapchain_image_views); + swpachain_framebuffers.push_back(swapchain_framebuffer); + } + + // recreate ray tracing image + ray_tracing_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::R32G32B32A32_SFLOAT, swapchain->GetWidth(), swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_COLOR_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_SRC | Turbo::Core::TImageUsageBits::IMAGE_STORAGE, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY); + ray_tracing_image_view = new Turbo::Core::TImageView(ray_tracing_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, ray_tracing_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + { + Turbo::Core::TCommandBuffer *change_ray_tracing_image_layout_command_buffer = command_pool->Allocate(); + + change_ray_tracing_image_layout_command_buffer->Begin(); + change_ray_tracing_image_layout_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TOP_OF_PIPE_BIT, Turbo::Core::TPipelineStageBits::BOTTOM_OF_PIPE_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::GENERAL, ray_tracing_image_view); + change_ray_tracing_image_layout_command_buffer->End(); + + Turbo::Core::TFence *change_image_layout_fence = new Turbo::Core::TFence(device); + + queue->Submit(nullptr, nullptr, change_ray_tracing_image_layout_command_buffer, change_image_layout_fence); + + change_image_layout_fence->WaitUntil(); + delete change_image_layout_fence; + + command_pool->Free(change_ray_tracing_image_layout_command_buffer); + } + + VkDescriptorImageInfo vk_descriptor_image_info = {}; + vk_descriptor_image_info.sampler = VK_NULL_HANDLE; + vk_descriptor_image_info.imageView = ray_tracing_image_view->GetVkImageView(); + vk_descriptor_image_info.imageLayout = VkImageLayout::VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet ray_tracing_write_image = {}; + ray_tracing_write_image.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_image.pNext = nullptr; + ray_tracing_write_image.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_image.dstBinding = 1; + ray_tracing_write_image.dstArrayElement = 0; + ray_tracing_write_image.descriptorCount = 1; + ray_tracing_write_image.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + ray_tracing_write_image.pImageInfo = &vk_descriptor_image_info; + ray_tracing_write_image.pBufferInfo = nullptr; + ray_tracing_write_image.pTexelBufferView = nullptr; + + std::vector vk_write_descriptor_sets; + vk_write_descriptor_sets.push_back(ray_tracing_write_image); + + device_driver->vkUpdateDescriptorSets(device->GetVkDevice(), vk_write_descriptor_sets.size(), vk_write_descriptor_sets.data(), 0, nullptr); + } + break; + default: { + // + } + break; + } + } + break; + case Turbo::Core::TResult::TIMEOUT: { + // you need to wait, or do something else + } + break; + case Turbo::Core::TResult::NOT_READY: { + // you need to wait, or do something else + } + break; + case Turbo::Core::TResult::MISMATCH: { + // the size of the window had changed you need to recreate swapchain + + // waite for idle + device->WaitIdle(); + + // destroy related resource + // clear old swapchain image + swapchain_images.clear(); + + // destroy swapchain image views + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + delete image_view_item; + } + + swapchain_image_views.clear(); + + // destroy depth image and view + delete depth_image_view; + delete depth_image; + + // destroy framebuffer + for (Turbo::Core::TFramebuffer *frame_buffer_item : swpachain_framebuffers) + { + delete frame_buffer_item; + } + swpachain_framebuffers.clear(); + + // destroy ray tracing image + delete ray_tracing_image_view; + delete ray_tracing_image; + + // recreate swapchain + Turbo::Extension::TSwapchain *old_swapchain = swapchain; + Turbo::Extension::TSwapchain *new_swapchain = new Turbo::Extension::TSwapchain(old_swapchain); + delete old_swapchain; + + swapchain = new_swapchain; + + // recreate swapchain image views + swapchain_images = swapchain->GetImages(); + for (Turbo::Core::TImage *swapchain_image_item : swapchain_images) + { + Turbo::Core::TImageView *swapchain_view = new Turbo::Core::TImageView(swapchain_image_item, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, Turbo::Core::TFormatType::B8G8R8A8_SRGB, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + swapchain_image_views.push_back(swapchain_view); + } + + // recreate depth image and view + depth_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::D32_SFLOAT, swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth(), swapchain->GetHeight() <= 0 ? 1 : swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_DEPTH_STENCIL_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_INPUT_ATTACHMENT, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, Turbo::Core::TImageLayout::UNDEFINED); + depth_image_view = new Turbo::Core::TImageView(depth_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, depth_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_DEPTH_BIT, 0, 1, 0, 1); + + // recreate framebuffer + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + std::vector swapchain_image_views; + swapchain_image_views.push_back(image_view_item); + swapchain_image_views.push_back(depth_image_view); + + Turbo::Core::TFramebuffer *swapchain_framebuffer = new Turbo::Core::TFramebuffer(render_pass, swapchain_image_views); + swpachain_framebuffers.push_back(swapchain_framebuffer); + } + + // recreate ray tracing image + ray_tracing_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::R32G32B32A32_SFLOAT, swapchain->GetWidth(), swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_COLOR_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_SRC | Turbo::Core::TImageUsageBits::IMAGE_STORAGE, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY); + ray_tracing_image_view = new Turbo::Core::TImageView(ray_tracing_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, ray_tracing_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + { + Turbo::Core::TCommandBuffer *change_ray_tracing_image_layout_command_buffer = command_pool->Allocate(); + + change_ray_tracing_image_layout_command_buffer->Begin(); + change_ray_tracing_image_layout_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TOP_OF_PIPE_BIT, Turbo::Core::TPipelineStageBits::BOTTOM_OF_PIPE_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::GENERAL, ray_tracing_image_view); + change_ray_tracing_image_layout_command_buffer->End(); + + Turbo::Core::TFence *change_image_layout_fence = new Turbo::Core::TFence(device); + + queue->Submit(nullptr, nullptr, change_ray_tracing_image_layout_command_buffer, change_image_layout_fence); + + change_image_layout_fence->WaitUntil(); + delete change_image_layout_fence; + + command_pool->Free(change_ray_tracing_image_layout_command_buffer); + } + + VkDescriptorImageInfo vk_descriptor_image_info = {}; + vk_descriptor_image_info.sampler = VK_NULL_HANDLE; + vk_descriptor_image_info.imageView = ray_tracing_image_view->GetVkImageView(); + vk_descriptor_image_info.imageLayout = VkImageLayout::VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet ray_tracing_write_image = {}; + ray_tracing_write_image.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_image.pNext = nullptr; + ray_tracing_write_image.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_image.dstBinding = 1; + ray_tracing_write_image.dstArrayElement = 0; + ray_tracing_write_image.descriptorCount = 1; + ray_tracing_write_image.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + ray_tracing_write_image.pImageInfo = &vk_descriptor_image_info; + ray_tracing_write_image.pBufferInfo = nullptr; + ray_tracing_write_image.pTexelBufferView = nullptr; + + std::vector vk_write_descriptor_sets; + vk_write_descriptor_sets.push_back(ray_tracing_write_image); + + device_driver->vkUpdateDescriptorSets(device->GetVkDevice(), vk_write_descriptor_sets.size(), vk_write_descriptor_sets.data(), 0, nullptr); + } + break; + default: { + // + } + break; + } + + delete wait_image_ready; + // + } + + if (imgui_vertex_buffer != nullptr) + { + delete imgui_vertex_buffer; + } + if (imgui_index_buffer != nullptr) + { + delete imgui_index_buffer; + } + descriptor_pool->Free(imgui_pipeline_descriptor_set); + delete imgui_font_image_view; + delete imgui_font_image; + delete imgui_pipeline; + delete imgui_vertex_shader; + delete imgui_fragment_shader; + delete imgui_sampler; + + descriptor_pool->Free(pipeline_descriptor_set); + delete pipeline; + for (Turbo::Core::TFramebuffer *framebuffer_item : swpachain_framebuffers) + { + delete framebuffer_item; + } + + delete render_pass; + + delete sbt_buffer; + + device_driver->vkDestroyPipeline(device->GetVkDevice(), ray_tracing_pipeline, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + device_driver->vkDestroyPipelineLayout(device->GetVkDevice(), ray_tracing_pipeline_layout, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + device_driver->vkFreeDescriptorSets(device->GetVkDevice(), descriptor_pool->GetVkDescriptorPool(), 1, &ray_tracing_descriptor_set); + device_driver->vkDestroyDescriptorSetLayout(device->GetVkDevice(), ray_tracing_descriptor_set_layout, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + + delete ray_generation_shader_test; + delete miss_shader_test; + delete closest_hit_shader_test; + delete callable_shader_r_test; + delete callable_shader_g_test; + delete callable_shader_b_test; + + delete descriptor_pool; + delete vertex_shader; + delete geometry_shader; + delete fragment_shader; + delete depth_image_view; + delete depth_image; + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + delete image_view_item; + } + delete index_buffer; + delete position_buffer; + delete tangent_buffer; + delete normal_buffer; + delete texcoord_buffer; + delete my_buffer; + delete matrixs_buffer; + + device->GetDeviceDriver()->vkDestroyAccelerationStructureKHR(device->GetVkDevice(), top_level_acceleration_structure_khr, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + delete top_level_acceleration_structure_buffer; + delete instance_buffer; + device->GetDeviceDriver()->vkDestroyAccelerationStructureKHR(device->GetVkDevice(), bottom_level_acceleration_structure_khr, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + delete bottom_level_acceleration_structure_buffer; + delete device_local_index_buffer; + delete device_local_vertex_buffer; + delete bottom_level_acceleration_structure_device_address_buffer; + + delete ray_tracing_image_view; + delete ray_tracing_image; + command_pool->Free(command_buffer); + delete command_pool; + delete swapchain; + delete surface; + PFN_vkDestroySurfaceKHR pfn_vk_destroy_surface_khr = Turbo::Core::TVulkanLoader::Instance()->LoadInstanceFunction(instance, "vkDestroySurfaceKHR"); + pfn_vk_destroy_surface_khr(instance->GetVkInstance(), vk_surface_khr, nullptr); + glfwTerminate(); + delete device; + delete instance; + + return 0; +} diff --git a/samples/VulkanKHRRayTracingTestForIntersectionShader.cpp b/samples/VulkanKHRRayTracingTestForIntersectionShader.cpp new file mode 100644 index 00000000..cb32e0b0 --- /dev/null +++ b/samples/VulkanKHRRayTracingTestForIntersectionShader.cpp @@ -0,0 +1,2591 @@ +#include "core/include/TDevice.h" +#include "core/include/TDeviceQueue.h" +#include "core/include/TEngine.h" +#include "core/include/TPhysicalDevice.h" +#include "core/include/TVulkanAllocator.h" + +#include "core/include/TBuffer.h" +#include "core/include/TCommandBuffer.h" +#include "core/include/TCommandBufferPool.h" +#include "core/include/TImage.h" +#include "core/include/TImageView.h" + +#include "core/include/TShader.h" + +#include "core/include/TAttachment.h" +#include "core/include/TGraphicsPipeline.h" +#include "core/include/TRenderPass.h" +#include "core/include/TSubpass.h" + +#include "core/include/TDescriptorPool.h" +#include "core/include/TDescriptorSet.h" +#include "core/include/TDescriptorSetLayout.h" +#include "core/include/TFramebuffer.h" + +#include "core/include/TFence.h" +#include "core/include/TSemaphore.h" + +#include + +#include + +#include "core/include/TSurface.h" +#include "core/include/TSwapchain.h" + +#include + +#include "core/include/TPipelineDescriptorSet.h" +#include "core/include/TSampler.h" + +#include + +#include "core/include/TVulkanLoader.h" +#define TINYGLTF_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_IMPLEMENTATION +// #define TINYGLTF_NOEXCEPTION // optional. disable exception handling. +#include + +#include + +#include + +#include + +std::string ReadTextFile(const std::string &filename) +{ + std::vector data; + + std::ifstream file; + + file.open(filename, std::ios::in); + + if (!file.is_open()) + { + throw std::runtime_error("Failed to open file: " + filename); + } + + return std::string{(std::istreambuf_iterator(file)), (std::istreambuf_iterator())}; +} + +static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {}; +static GLFWcursor *g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; + +const std::string IMGUI_VERT_SHADER_STR = ReadTextFile("../../asset/shaders/imgui.vert"); +const std::string IMGUI_FRAG_SHADER_STR = ReadTextFile("../../asset/shaders/imgui.frag"); + +const std::string VERT_SHADER_STR = ReadTextFile("../../asset/shaders/GeometryTest.vert"); +const std::string GEOM_SHADER_STR = ReadTextFile("../../asset/shaders/GeometryTest.geom"); +const std::string FRAG_SHADER_STR = ReadTextFile("../../asset/shaders/GeometryTest.frag"); + +const std::string RAY_GENERATION_SHADER_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForIntersection.rgen"); +const std::string MISS_SHADER_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForIntersection.rmiss"); +const std::string CLOSEST_HIT_SHADER_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForIntersection.rchit"); +const std::string INTERSECTION_SHADER_STR = ReadTextFile("../../asset/shaders/RayTracingKHRTestForIntersection.rint"); + +typedef struct POSITION +{ + float x; + float y; + float z; +} POSITION; + +typedef struct NORMAL +{ + float x; + float y; + float z; +} NORMAL; + +typedef struct TANGENT +{ + float x; + float y; + float z; + float w; +} TANGENT; + +typedef struct TEXCOORD +{ + float u; + float v; +} TEXCOORD; + +struct MY_BUFFER_DATA +{ + float scale; +}; + +struct MATRIXS_BUFFER_DATA +{ + glm::mat4 m; + glm::mat4 v; + glm::mat4 p; +}; + +struct VERTEX +{ + POSITION position; + NORMAL normal; + TEXCOORD texcoord; +}; + +struct BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS +{ + VkDeviceAddress vertexDeviceAddress; + VkDeviceAddress indexDeviceAddress; + VkDeviceAddress aabbsDeviceAddress; +}; + +struct RAY_TRACING_MATRIXS_BUFFER_DATA +{ + glm::mat4 v; + glm::mat4 p; +}; + +struct SPHERE +{ + glm::vec3 center; + float radius; +}; + +struct AABB +{ + glm::vec3 minimum; + glm::vec3 maximum; +}; + +int main() +{ + std::cout << "Vulkan Version:" << Turbo::Core::TVulkanLoader::Instance()->GetVulkanVersion().ToString() << std::endl; + + MY_BUFFER_DATA my_buffer_data = {}; + my_buffer_data.scale = 0.03; + + MATRIXS_BUFFER_DATA matrixs_buffer_data = {}; + + // + std::vector POSITION_data; + std::vector NORMAL_data; + std::vector TEXCOORD_data; + std::vector TANGENT_data; + std::vector INDICES_data; + { + tinygltf::Model model; + tinygltf::TinyGLTF loader; + std::string err; + std::string warn; + + bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, "../../asset/models/material_sphere_without_Yup.gltf"); + const tinygltf::Scene &scene = model.scenes[model.defaultScene]; + tinygltf::Node &node = model.nodes[scene.nodes[0]]; + tinygltf::Mesh &mesh = model.meshes[node.mesh]; + tinygltf::Primitive &primitive = mesh.primitives[0]; + int mode = primitive.mode; + int position_accesser_index = primitive.attributes["POSITION"]; + int normal_accesser_index = primitive.attributes["NORMAL"]; + int texcoord_0_accesser_index = primitive.attributes["TEXCOORD_0"]; + int tangent_accesser_index = primitive.attributes["TANGENT"]; + int indices_accesser_index = primitive.indices; + tinygltf::Accessor &position_accessor = model.accessors[position_accesser_index]; + tinygltf::Accessor &normal_accessor = model.accessors[normal_accesser_index]; + tinygltf::Accessor &texcoord_0_accessor = model.accessors[texcoord_0_accesser_index]; + tinygltf::Accessor &indices_accessor = model.accessors[indices_accesser_index]; + tinygltf::Accessor &tangent_accessor = model.accessors[tangent_accesser_index]; + + tinygltf::BufferView &position_buffer_view = model.bufferViews[position_accessor.bufferView]; + tinygltf::BufferView &normal_buffer_view = model.bufferViews[normal_accessor.bufferView]; + tinygltf::BufferView &texcoord_0_buffer_view = model.bufferViews[texcoord_0_accessor.bufferView]; + tinygltf::BufferView &indices_buffer_view = model.bufferViews[indices_accessor.bufferView]; + tinygltf::BufferView &tangent_buffer_view = model.bufferViews[tangent_accessor.bufferView]; + + int position_buffer_index = position_buffer_view.buffer; + size_t position_buffer_byteLength = position_buffer_view.byteLength; + int position_buffer_byteOffset = position_buffer_view.byteOffset; + int position_type = position_accessor.type; + + int normal_buffer_index = normal_buffer_view.buffer; + size_t normal_buffer_byteLength = normal_buffer_view.byteLength; + int normal_buffer_byteOffset = normal_buffer_view.byteOffset; + int normal_type = normal_accessor.type; + + int texcoord_0_buffer_index = texcoord_0_buffer_view.buffer; + size_t texcoord_0_buffer_byteLength = texcoord_0_buffer_view.byteLength; + int texcoord_0_buffer_byteOffset = texcoord_0_buffer_view.byteOffset; + int texcoord_0_type = texcoord_0_accessor.type; + + int indices_buffer_index = indices_buffer_view.buffer; + size_t indices_buffer_byteLength = indices_buffer_view.byteLength; + int indices_buffer_byteOffset = indices_buffer_view.byteOffset; + int indices_type = indices_accessor.type; + + int tangent_buffer_index = tangent_buffer_view.buffer; + size_t tangent_buffer_byteLength = tangent_buffer_view.byteLength; + int tangent_buffer_byteOffset = tangent_buffer_view.byteOffset; + int tangent_type = tangent_accessor.type; + + tinygltf::Buffer &position_buffer = model.buffers[position_buffer_index]; + tinygltf::Buffer &normal_buffer = model.buffers[normal_buffer_index]; + tinygltf::Buffer &texcoord_0_buffer = model.buffers[texcoord_0_buffer_index]; + tinygltf::Buffer &indices_buffer = model.buffers[indices_buffer_index]; + tinygltf::Buffer &tangent_buffer = model.buffers[tangent_buffer_index]; + + std::vector &position_data = position_buffer.data; + std::vector &normal_data = normal_buffer.data; + std::vector &texcoord_0_data = texcoord_0_buffer.data; + std::vector &indices_data = indices_buffer.data; + std::vector &tangent_data = tangent_buffer.data; + + std::vector temp_indices_data; + + POSITION_data.resize(position_buffer_byteLength / sizeof(POSITION)); + NORMAL_data.resize(normal_buffer_byteLength / sizeof(NORMAL)); + TEXCOORD_data.resize(texcoord_0_buffer_byteLength / sizeof(TEXCOORD)); + temp_indices_data.resize(indices_buffer_byteLength / sizeof(unsigned short)); + TANGENT_data.resize(tangent_buffer_byteLength / sizeof(TANGENT)); + + memcpy(POSITION_data.data(), position_data.data() + position_buffer_byteOffset, position_buffer_byteLength); + memcpy(NORMAL_data.data(), normal_data.data() + normal_buffer_byteOffset, normal_buffer_byteLength); + memcpy(TEXCOORD_data.data(), texcoord_0_data.data() + texcoord_0_buffer_byteOffset, texcoord_0_buffer_byteLength); + memcpy(temp_indices_data.data(), indices_data.data() + indices_buffer_byteOffset, indices_buffer_byteLength); + memcpy(TANGENT_data.data(), tangent_data.data() + tangent_buffer_byteOffset, tangent_buffer_byteLength); + + for (unsigned short &temp_indices_item : temp_indices_data) + { + INDICES_data.push_back(temp_indices_item); + } + } + // + + uint32_t indices_count = INDICES_data.size(); + Turbo::Core::TEngine engine; + + Turbo::Core::TLayerInfo khronos_validation; + std::vector support_layers = engine.GetInstance().GetSupportLayers(); + for (Turbo::Core::TLayerInfo &layer : support_layers) + { + if (layer.GetLayerType() == Turbo::Core::TLayerType::VK_LAYER_KHRONOS_VALIDATION) + { + khronos_validation = layer; + break; + } + } + + std::vector enable_layer; + if (khronos_validation.GetLayerType() != Turbo::Core::TLayerType::UNDEFINED) + { + enable_layer.push_back(khronos_validation); + } + + std::vector enable_instance_extensions; + std::vector instance_support_extensions = engine.GetInstance().GetSupportExtensions(); + for (Turbo::Core::TExtensionInfo &extension : instance_support_extensions) + { + if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_WIN32_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_WAYLAND_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_XCB_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_XLIB_SURFACE) + { + enable_instance_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2) + { + enable_instance_extensions.push_back(extension); + } + } + + Turbo::Core::TVersion instance_version(1, 2, 0, 0); + Turbo::Core::TInstance *instance = new Turbo::Core::TInstance(&enable_layer, &enable_instance_extensions, &instance_version); + Turbo::Core::TPhysicalDevice *physical_device = instance->GetBestPhysicalDevice(); + + Turbo::Core::TPhysicalDeviceFeatures physical_device_support_features = physical_device->GetDeviceFeatures(); + { + if (physical_device_support_features.accelerationStructure) + { + std::cout << "Support acceleration structure feature" << std::endl; + } + else + { + std::cout << "Not support acceleration structure feature" << std::endl; + } + + if (physical_device_support_features.accelerationStructureCaptureReplay) + { + std::cout << "Support acceleration structure capture replay feature" << std::endl; + } + else + { + std::cout << "Not support acceleration structure capture replay feature" << std::endl; + } + + if (physical_device_support_features.accelerationStructureHostCommands) + { + std::cout << "Support acceleration structure host commands feature" << std::endl; + } + else + { + std::cout << "Not support acceleration structure host commands feature" << std::endl; + } + + if (physical_device_support_features.accelerationStructureIndirectBuild) + { + std::cout << "Support acceleration structure indirect build feature" << std::endl; + } + else + { + std::cout << "Not support acceleration structure indirect build feature" << std::endl; + } + + if (physical_device_support_features.bufferDeviceAddress) + { + std::cout << "Support bufferDeviceAddress feature" << std::endl; + } + else + { + std::cout << "Not support bufferDeviceAddress feature" << std::endl; + } + + if (physical_device_support_features.bufferDeviceAddressCaptureReplay) + { + std::cout << "Support bufferDeviceAddressCaptureReplay feature" << std::endl; + } + else + { + std::cout << "Not support bufferDeviceAddressCaptureReplay feature" << std::endl; + } + + if (physical_device_support_features.bufferDeviceAddressMultiDevice) + { + std::cout << "Support bufferDeviceAddressMultiDevice feature" << std::endl; + } + else + { + std::cout << "Not support bufferDeviceAddressMultiDevice feature" << std::endl; + } + + if (physical_device_support_features.rayTracingPipeline) + { + std::cout << "Support ray tracing pipeline feature" << std::endl; + } + else + { + std::cout << "Not support ray tracing pipeline feature" << std::endl; + } + } + + if (!physical_device_support_features.accelerationStructure || !physical_device_support_features.rayTracingPipeline) + { + delete instance; + std::cout << "Please use a GPU which support hardware real-time ray tracing" << std::endl; + return 0; + } + + if (!glfwInit()) + return -1; + GLFWwindow *window; + int window_width = 1920 / 2.0; + int window_height = 1080 / 2.0; + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + window = glfwCreateWindow(window_width, window_height, "Turbo", NULL, NULL); + VkSurfaceKHR vk_surface_khr = VK_NULL_HANDLE; + VkInstance vk_instance = instance->GetVkInstance(); + glfwCreateWindowSurface(vk_instance, window, NULL, &vk_surface_khr); + + Turbo::Core::TPhysicalDeviceFeatures physical_device_features = {}; + physical_device_features.sampleRateShading = true; + physical_device_features.accelerationStructure = physical_device_support_features.accelerationStructure; + physical_device_features.accelerationStructureCaptureReplay = physical_device_support_features.accelerationStructureCaptureReplay; + physical_device_features.accelerationStructureHostCommands = physical_device_support_features.accelerationStructureHostCommands; + physical_device_features.accelerationStructureIndirectBuild = physical_device_support_features.accelerationStructureIndirectBuild; + physical_device_features.bufferDeviceAddress = physical_device_support_features.bufferDeviceAddress; + physical_device_features.rayTracingPipeline = physical_device_support_features.rayTracingPipeline; + + if (physical_device_support_features.geometryShader) + { + physical_device_features.geometryShader = true; + } + else + { + glfwTerminate(); + delete instance; + throw Turbo::Core::TException(Turbo::Core::TResult::UNSUPPORTED, "Not support geometry shader feature"); + } + + std::vector enable_device_extensions; + std::vector physical_device_support_extensions = physical_device->GetSupportExtensions(); + for (Turbo::Core::TExtensionInfo &extension : physical_device_support_extensions) + { + if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_SWAPCHAIN) + { + enable_device_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_ACCELERATION_STRUCTURE) + { + enable_device_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_SPIRV_1_4) + { + enable_device_extensions.push_back(extension); + } + else if (extension.GetExtensionType() == Turbo::Core::TExtensionType::VK_KHR_RAY_TRACING_PIPELINE) + { + enable_device_extensions.push_back(extension); + } + } + + Turbo::Core::TDevice *device = new Turbo::Core::TDevice(physical_device, nullptr, &enable_device_extensions, &physical_device_features); + Turbo::Core::TDeviceQueue *queue = device->GetBestGraphicsQueue(); + + Turbo::Extension::TSurface *surface = new Turbo::Extension::TSurface(device, vk_surface_khr); + uint32_t max_image_count = surface->GetMaxImageCount(); + uint32_t min_image_count = surface->GetMinImageCount(); + + uint32_t swapchain_image_count = max_image_count <= min_image_count ? min_image_count : max_image_count - 1; + + Turbo::Extension::TSwapchain *swapchain = new Turbo::Extension::TSwapchain(surface, swapchain_image_count, Turbo::Core::TFormatType::B8G8R8A8_SRGB, 1, Turbo::Core::TImageUsageBits::IMAGE_COLOR_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_SRC | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_DST, true); + + std::vector swapchain_images = swapchain->GetImages(); + + std::vector swapchain_image_views; + for (Turbo::Core::TImage *swapchain_image_item : swapchain_images) + { + Turbo::Core::TImageView *swapchain_view = new Turbo::Core::TImageView(swapchain_image_item, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, Turbo::Core::TFormatType::B8G8R8A8_SRGB, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + swapchain_image_views.push_back(swapchain_view); + } + + Turbo::Core::TCommandBufferPool *command_pool = new Turbo::Core::TCommandBufferPool(queue); + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + + glm::mat4 model = glm::mat4(1.0f); + model = glm::rotate(model, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + + glm::mat4 view = glm::mat4(1.0f); + view = glm::translate(view, glm::vec3(0.0f, 0.0f, -10.0f)); + + glm::mat4 projection = glm::mat4(1.0f); + projection = glm::perspective(glm::radians(45.0f), (float)swapchain->GetWidth() / (float)swapchain->GetHeight(), 0.1f, 100.0f); + + matrixs_buffer_data.m = model; + matrixs_buffer_data.v = view; + matrixs_buffer_data.p = projection; + + Turbo::Core::TBuffer *matrixs_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_UNIFORM_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(matrixs_buffer_data)); + void *mvp_ptr = matrixs_buffer->Map(); + memcpy(mvp_ptr, &matrixs_buffer_data, sizeof(matrixs_buffer_data)); + matrixs_buffer->Unmap(); + + Turbo::Core::TBuffer *my_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_UNIFORM_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(my_buffer_data)); + void *my_buffer_ptr = my_buffer->Map(); + memcpy(my_buffer_ptr, &my_buffer_data, sizeof(my_buffer_data)); + my_buffer->Unmap(); + + Turbo::Core::TBuffer *position_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(POSITION) * POSITION_data.size()); + void *position_buffer_ptr = position_buffer->Map(); + memcpy(position_buffer_ptr, POSITION_data.data(), sizeof(POSITION) * POSITION_data.size()); + position_buffer->Unmap(); + // POSITION_data.clear(); + + Turbo::Core::TBuffer *normal_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(NORMAL) * NORMAL_data.size()); + void *normal_buffer_ptr = normal_buffer->Map(); + memcpy(normal_buffer_ptr, NORMAL_data.data(), sizeof(NORMAL) * NORMAL_data.size()); + normal_buffer->Unmap(); + // NORMAL_data.clear(); + + Turbo::Core::TBuffer *texcoord_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(TEXCOORD) * TEXCOORD_data.size()); + void *texcoord_buffer_ptr = texcoord_buffer->Map(); + memcpy(texcoord_buffer_ptr, TEXCOORD_data.data(), sizeof(TEXCOORD) * TEXCOORD_data.size()); + texcoord_buffer->Unmap(); + // TEXCOORD_data.clear(); + + Turbo::Core::TBuffer *index_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_INDEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(uint32_t) * INDICES_data.size()); + void *index_buffer_ptr = index_buffer->Map(); + memcpy(index_buffer_ptr, INDICES_data.data(), sizeof(uint32_t) * INDICES_data.size()); + index_buffer->Unmap(); + // INDICES_data.clear(); + + Turbo::Core::TBuffer *tangent_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(TANGENT) * TANGENT_data.size()); + void *tangent_buffer_ptr = tangent_buffer->Map(); + memcpy(tangent_buffer_ptr, TANGENT_data.data(), sizeof(TANGENT) * TANGENT_data.size()); + tangent_buffer->Unmap(); + // TANGENT_data.clear(); + + Turbo::Core::TImage *depth_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::D32_SFLOAT, swapchain->GetWidth(), swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_DEPTH_STENCIL_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_INPUT_ATTACHMENT, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, Turbo::Core::TImageLayout::UNDEFINED); + Turbo::Core::TImageView *depth_image_view = new Turbo::Core::TImageView(depth_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, depth_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_DEPTH_BIT, 0, 1, 0, 1); + + Turbo::Core::TVertexShader *vertex_shader = new Turbo::Core::TVertexShader(device, Turbo::Core::TShaderLanguage::GLSL, VERT_SHADER_STR); + Turbo::Core::TGeometryShader *geometry_shader = new Turbo::Core::TGeometryShader(device, Turbo::Core::TShaderLanguage::GLSL, GEOM_SHADER_STR); + Turbo::Core::TFragmentShader *fragment_shader = new Turbo::Core::TFragmentShader(device, Turbo::Core::TShaderLanguage::GLSL, FRAG_SHADER_STR); + + // for ray tracing image + Turbo::Core::TImage *ray_tracing_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::R32G32B32A32_SFLOAT, swapchain->GetWidth(), swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_COLOR_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_SRC | Turbo::Core::TImageUsageBits::IMAGE_STORAGE, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY); + Turbo::Core::TImageView *ray_tracing_image_view = new Turbo::Core::TImageView(ray_tracing_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, ray_tracing_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + { + + Turbo::Core::TCommandBuffer *change_ray_tracing_image_layout_command_buffer = command_pool->Allocate(); + + change_ray_tracing_image_layout_command_buffer->Begin(); + change_ray_tracing_image_layout_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TOP_OF_PIPE_BIT, Turbo::Core::TPipelineStageBits::BOTTOM_OF_PIPE_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::GENERAL, ray_tracing_image_view); + change_ray_tracing_image_layout_command_buffer->End(); + + Turbo::Core::TFence *change_image_layout_fence = new Turbo::Core::TFence(device); + + queue->Submit(nullptr, nullptr, change_ray_tracing_image_layout_command_buffer, change_image_layout_fence); + + change_image_layout_fence->WaitUntil(); + delete change_image_layout_fence; + + command_pool->Free(change_ray_tracing_image_layout_command_buffer); + } + + std::vector descriptor_sizes; + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::UNIFORM_BUFFER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::COMBINED_IMAGE_SAMPLER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::SAMPLER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::SAMPLED_IMAGE, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::STORAGE_IMAGE, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::UNIFORM_TEXEL_BUFFER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::STORAGE_TEXEL_BUFFER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::STORAGE_BUFFER, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::UNIFORM_BUFFER_DYNAMIC, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::STORAGE_BUFFER_DYNAMIC, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::INPUT_ATTACHMENT, 1000)); + descriptor_sizes.push_back(Turbo::Core::TDescriptorSize(Turbo::Core::TDescriptorType::ACCELERATION_STRUCTURE, 1000)); + + Turbo::Core::TDescriptorPool *descriptor_pool = new Turbo::Core::TDescriptorPool(device, descriptor_sizes.size() * 1000, descriptor_sizes); + + const Turbo::Core::TDeviceDriver *device_driver = device->GetDeviceDriver(); + const Turbo::Core::TPhysicalDeviceDriver *physical_device_driver = physical_device->GetPhysicalDeviceDriver(); + + // Spheres and AABB + uint32_t spheres_count = 2000000; + + std::random_device seed; + std::mt19937 gen(seed()); + std::normal_distribution xzd(0.0f, 5.0f); + std::normal_distribution yd(6.0f, 3.0f); + std::uniform_real_distribution radd(0.05f, 0.2f); + + // std::vector spheres(2000000); + std::vector aabbs(spheres_count); + for (uint32_t saabb_index = 0; saabb_index < spheres_count; saabb_index++) + { + // spheres[sphere_index].center = glm::vec3(xzd(gen), yd(gen), xzd(gen)); + // spheres[sphere_index].radius = radd(gen); + glm::vec3 center = glm::vec3(xzd(gen), yd(gen), xzd(gen)); + float radius = radd(gen); + + aabbs[saabb_index].minimum = center - glm::vec3(radius /**1.414213562373*/); // center = (maximum + minimum) * 0.5; + aabbs[saabb_index].maximum = center + glm::vec3(radius /**1.414213562373*/); // radius = (maximum - minimum) * 0.5; + } + + Turbo::Core::TBuffer *aabbs_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS | Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, sizeof(AABB) * aabbs.size()); + { + Turbo::Core::TBuffer *staging_aabb_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(AABB) * aabbs.size()); + memcpy(staging_aabb_buffer->Map(), aabbs.data(), sizeof(AABB) * aabbs.size()); + staging_aabb_buffer->Unmap(); + + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + command_buffer->CmdCopyBuffer(staging_aabb_buffer, aabbs_buffer, 0, 0, sizeof(AABB) * aabbs.size()); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + delete staging_aabb_buffer; + } + + // Acceleration Structure + Turbo::Core::TBuffer *device_local_vertex_buffer = nullptr; + Turbo::Core::TBuffer *device_local_index_buffer = nullptr; + Turbo::Core::TBuffer *bottom_level_acceleration_structure_buffer = nullptr; + VkAccelerationStructureKHR bottom_level_acceleration_structure_khr = VK_NULL_HANDLE; + Turbo::Core::TBuffer *top_level_acceleration_structure_buffer = nullptr; + VkAccelerationStructureKHR top_level_acceleration_structure_khr = VK_NULL_HANDLE; + Turbo::Core::TBuffer *instance_buffer = nullptr; + + Turbo::Core::TBuffer *bottom_level_acceleration_structure_device_address_buffer = nullptr; + + { + VkPhysicalDeviceAccelerationStructurePropertiesKHR vk_physical_device_acceleration_structure_properties_khr = {}; + vk_physical_device_acceleration_structure_properties_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR; + vk_physical_device_acceleration_structure_properties_khr.pNext = nullptr; + vk_physical_device_acceleration_structure_properties_khr.maxGeometryCount = 0; + vk_physical_device_acceleration_structure_properties_khr.maxInstanceCount = 0; + vk_physical_device_acceleration_structure_properties_khr.maxPrimitiveCount = 0; + vk_physical_device_acceleration_structure_properties_khr.maxPerStageDescriptorAccelerationStructures = 0; + vk_physical_device_acceleration_structure_properties_khr.maxPerStageDescriptorUpdateAfterBindAccelerationStructures = 0; + vk_physical_device_acceleration_structure_properties_khr.maxDescriptorSetAccelerationStructures = 0; + vk_physical_device_acceleration_structure_properties_khr.maxDescriptorSetUpdateAfterBindAccelerationStructures = 0; + vk_physical_device_acceleration_structure_properties_khr.minAccelerationStructureScratchOffsetAlignment = 0; + + VkPhysicalDeviceProperties2 vk_physical_device_properties_2 = {}; + vk_physical_device_properties_2.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + vk_physical_device_properties_2.pNext = &vk_physical_device_acceleration_structure_properties_khr; + vk_physical_device_properties_2.properties = {}; + + if (physical_device_driver->vkGetPhysicalDeviceProperties2 != nullptr) + { + physical_device_driver->vkGetPhysicalDeviceProperties2(physical_device->GetVkPhysicalDevice(), &vk_physical_device_properties_2); + } + else if (physical_device_driver->vkGetPhysicalDeviceProperties2KHR != nullptr) + { + physical_device_driver->vkGetPhysicalDeviceProperties2KHR(physical_device->GetVkPhysicalDevice(), &vk_physical_device_properties_2); + } + + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxGeometryCount = " << vk_physical_device_acceleration_structure_properties_khr.maxGeometryCount << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxInstanceCount = " << vk_physical_device_acceleration_structure_properties_khr.maxInstanceCount << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxPrimitiveCount = " << vk_physical_device_acceleration_structure_properties_khr.maxPrimitiveCount << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxPerStageDescriptorAccelerationStructures = " << vk_physical_device_acceleration_structure_properties_khr.maxPerStageDescriptorAccelerationStructures << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxPerStageDescriptorUpdateAfterBindAccelerationStructures = " << vk_physical_device_acceleration_structure_properties_khr.maxPerStageDescriptorUpdateAfterBindAccelerationStructures << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxDescriptorSetAccelerationStructures = " << vk_physical_device_acceleration_structure_properties_khr.maxDescriptorSetAccelerationStructures << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.maxDescriptorSetUpdateAfterBindAccelerationStructures = " << vk_physical_device_acceleration_structure_properties_khr.maxDescriptorSetUpdateAfterBindAccelerationStructures << std::endl; + std::cout << "VkPhysicalDeviceAccelerationStructurePropertiesKHR.minAccelerationStructureScratchOffsetAlignment = " << vk_physical_device_acceleration_structure_properties_khr.minAccelerationStructureScratchOffsetAlignment << std::endl; + + std::vector ray_tracing_vertexs; + for (uint32_t vertex_index = 0; vertex_index < POSITION_data.size(); vertex_index++) + { + VERTEX ray_tracing_vertex; + ray_tracing_vertex.position = POSITION_data[vertex_index]; + ray_tracing_vertex.normal = NORMAL_data[vertex_index]; + ray_tracing_vertex.texcoord = TEXCOORD_data[vertex_index]; + + ray_tracing_vertexs.push_back(ray_tracing_vertex); + } + + device_local_vertex_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS | Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, sizeof(VERTEX) * ray_tracing_vertexs.size()); + { + Turbo::Core::TBuffer *staging_vertex_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(VERTEX) * ray_tracing_vertexs.size()); + memcpy(staging_vertex_buffer->Map(), ray_tracing_vertexs.data(), sizeof(VERTEX) * ray_tracing_vertexs.size()); + staging_vertex_buffer->Unmap(); + + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + command_buffer->CmdCopyBuffer(staging_vertex_buffer, device_local_vertex_buffer, 0, 0, sizeof(VERTEX) * ray_tracing_vertexs.size()); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + delete staging_vertex_buffer; + } + + VkDeviceAddress device_local_vertex_buffer_device_address = 0; + + VkBufferDeviceAddressInfo device_local_vertex_buffer_device_address_info = {}; + device_local_vertex_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + device_local_vertex_buffer_device_address_info.pNext = nullptr; + device_local_vertex_buffer_device_address_info.buffer = device_local_vertex_buffer->GetVkBuffer(); + + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + device_local_vertex_buffer_device_address = device_driver->vkGetBufferDeviceAddress(device->GetVkDevice(), &device_local_vertex_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + device_local_vertex_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(device->GetVkDevice(), &device_local_vertex_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + device_local_vertex_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(device->GetVkDevice(), &device_local_vertex_buffer_device_address_info); + } + + if (device_local_vertex_buffer_device_address == 0) + { + throw std::runtime_error("Get ray tracing device local vertex buffer address failed"); + } + + VkDeviceOrHostAddressConstKHR vertex_data = {}; + vertex_data.deviceAddress = device_local_vertex_buffer_device_address; + + device_local_index_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_INDEX_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS | Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, sizeof(uint32_t) * INDICES_data.size()); + { + Turbo::Core::TBuffer *staging_index_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(uint32_t) * INDICES_data.size()); + memcpy(staging_index_buffer->Map(), INDICES_data.data(), sizeof(uint32_t) * INDICES_data.size()); + staging_index_buffer->Unmap(); + + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + command_buffer->CmdCopyBuffer(staging_index_buffer, device_local_index_buffer, 0, 0, sizeof(uint32_t) * INDICES_data.size()); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + delete staging_index_buffer; + } + + VkDeviceAddress device_local_index_buffer_device_address = 0; + + VkBufferDeviceAddressInfo device_local_index_buffer_device_address_info = {}; + device_local_index_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + device_local_index_buffer_device_address_info.pNext = nullptr; + device_local_index_buffer_device_address_info.buffer = device_local_index_buffer->GetVkBuffer(); + + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + device_local_index_buffer_device_address = device_driver->vkGetBufferDeviceAddress(device->GetVkDevice(), &device_local_index_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + device_local_index_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(device->GetVkDevice(), &device_local_index_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + device_local_index_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(device->GetVkDevice(), &device_local_index_buffer_device_address_info); + } + + if (device_local_index_buffer_device_address == 0) + { + throw std::runtime_error("Get ray tracing device local index buffer address failed"); + } + + VkDeviceAddress aabbs_buffer_device_address = 0; + { + VkBufferDeviceAddressInfo aabbs_buffer_device_address_info = {}; + aabbs_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + aabbs_buffer_device_address_info.pNext = nullptr; + aabbs_buffer_device_address_info.buffer = aabbs_buffer->GetVkBuffer(); + + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + aabbs_buffer_device_address = device_driver->vkGetBufferDeviceAddress(device->GetVkDevice(), &aabbs_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + aabbs_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(device->GetVkDevice(), &aabbs_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + aabbs_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(device->GetVkDevice(), &aabbs_buffer_device_address_info); + } + + if (aabbs_buffer_device_address == 0) + { + throw std::runtime_error("Get ray tracing device local AABBs address failed"); + } + } + + BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS ray_tracing_bottom_level_acceleration_structure; + ray_tracing_bottom_level_acceleration_structure.vertexDeviceAddress = device_local_vertex_buffer_device_address; + ray_tracing_bottom_level_acceleration_structure.indexDeviceAddress = device_local_index_buffer_device_address; + ray_tracing_bottom_level_acceleration_structure.aabbsDeviceAddress = aabbs_buffer_device_address; + + std::vector bottom_level_acceleration_structure_device_addresses; + bottom_level_acceleration_structure_device_addresses.push_back(ray_tracing_bottom_level_acceleration_structure); + + bottom_level_acceleration_structure_device_address_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, sizeof(BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS) * bottom_level_acceleration_structure_device_addresses.size()); + { + Turbo::Core::TBuffer *staging_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS) * bottom_level_acceleration_structure_device_addresses.size()); + memcpy(staging_buffer->Map(), bottom_level_acceleration_structure_device_addresses.data(), sizeof(BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS) * bottom_level_acceleration_structure_device_addresses.size()); + staging_buffer->Unmap(); + + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + command_buffer->CmdCopyBuffer(staging_buffer, bottom_level_acceleration_structure_device_address_buffer, 0, 0, sizeof(BOTTOM_LEVEL_ACCELERATION_STRUCTURE_DEVICE_ADDRESS) * bottom_level_acceleration_structure_device_addresses.size()); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + delete staging_buffer; + } + + VkDeviceOrHostAddressConstKHR index_data = {}; + index_data.deviceAddress = device_local_index_buffer_device_address; + + VkAccelerationStructureGeometryAabbsDataKHR vk_acceleration_structure_geometry_aabbs_data_khr = {}; + vk_acceleration_structure_geometry_aabbs_data_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR; + vk_acceleration_structure_geometry_aabbs_data_khr.pNext = nullptr; + vk_acceleration_structure_geometry_aabbs_data_khr.data.deviceAddress = aabbs_buffer_device_address; + vk_acceleration_structure_geometry_aabbs_data_khr.stride = sizeof(AABB); + + VkAccelerationStructureGeometryTrianglesDataKHR vk_acceleration_structure_geometry_triangles_data_khr = {}; + vk_acceleration_structure_geometry_triangles_data_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + vk_acceleration_structure_geometry_triangles_data_khr.pNext = nullptr; + vk_acceleration_structure_geometry_triangles_data_khr.vertexFormat = VkFormat::VK_FORMAT_R32G32B32_SFLOAT; + vk_acceleration_structure_geometry_triangles_data_khr.vertexData = vertex_data; + vk_acceleration_structure_geometry_triangles_data_khr.vertexStride = sizeof(VERTEX); + vk_acceleration_structure_geometry_triangles_data_khr.maxVertex = ray_tracing_vertexs.size(); + vk_acceleration_structure_geometry_triangles_data_khr.indexType = VkIndexType::VK_INDEX_TYPE_UINT32; + vk_acceleration_structure_geometry_triangles_data_khr.indexData = index_data; + vk_acceleration_structure_geometry_triangles_data_khr.transformData.deviceAddress = 0; + + VkAccelerationStructureGeometryDataKHR vk_acceleration_structure_geometry_data_khr = {}; + // vk_acceleration_structure_geometry_data_khr.triangles = vk_acceleration_structure_geometry_triangles_data_khr; + vk_acceleration_structure_geometry_data_khr.aabbs = vk_acceleration_structure_geometry_aabbs_data_khr; + + VkAccelerationStructureGeometryKHR vk_acceleration_structure_geometry_khr = {}; + vk_acceleration_structure_geometry_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + vk_acceleration_structure_geometry_khr.pNext = nullptr; + // vk_acceleration_structure_geometry_khr.geometryType = VkGeometryTypeKHR::VK_GEOMETRY_TYPE_TRIANGLES_KHR; + vk_acceleration_structure_geometry_khr.geometryType = VkGeometryTypeKHR::VK_GEOMETRY_TYPE_AABBS_KHR; + vk_acceleration_structure_geometry_khr.geometry = vk_acceleration_structure_geometry_data_khr; + vk_acceleration_structure_geometry_khr.flags = VkGeometryFlagBitsKHR::VK_GEOMETRY_OPAQUE_BIT_KHR; + + VkAccelerationStructureBuildGeometryInfoKHR vk_acceleration_structure_build_geometry_info_khr = {}; + vk_acceleration_structure_build_geometry_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + vk_acceleration_structure_build_geometry_info_khr.pNext = nullptr; + vk_acceleration_structure_build_geometry_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + vk_acceleration_structure_build_geometry_info_khr.flags = VkBuildAccelerationStructureFlagBitsKHR::VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR | VkBuildAccelerationStructureFlagBitsKHR::VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + vk_acceleration_structure_build_geometry_info_khr.mode = VkBuildAccelerationStructureModeKHR::VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + vk_acceleration_structure_build_geometry_info_khr.srcAccelerationStructure = VK_NULL_HANDLE; + vk_acceleration_structure_build_geometry_info_khr.dstAccelerationStructure = VK_NULL_HANDLE; + vk_acceleration_structure_build_geometry_info_khr.geometryCount = 1; + vk_acceleration_structure_build_geometry_info_khr.pGeometries = &vk_acceleration_structure_geometry_khr; + vk_acceleration_structure_build_geometry_info_khr.ppGeometries = nullptr; + vk_acceleration_structure_build_geometry_info_khr.scratchData.deviceAddress = 0; + + std::vector max_primitive_counts(vk_acceleration_structure_build_geometry_info_khr.geometryCount); + for (uint32_t index = 0; index < vk_acceleration_structure_build_geometry_info_khr.geometryCount; index++) + { + // max_primitive_counts[index] = INDICES_data.size() / 3; + max_primitive_counts[index] = spheres_count; + } + + std::cout << "POSITION_data.size():" << POSITION_data.size() << std::endl; + std::cout << "INDICES_data.size():" << INDICES_data.size() << std::endl; + + VkAccelerationStructureBuildSizesInfoKHR vk_acceleration_structure_build_sizes_info_khr = {}; + vk_acceleration_structure_build_sizes_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; + vk_acceleration_structure_build_sizes_info_khr.pNext = nullptr; + vk_acceleration_structure_build_sizes_info_khr.accelerationStructureSize = 0; + vk_acceleration_structure_build_sizes_info_khr.updateScratchSize = 0; + vk_acceleration_structure_build_sizes_info_khr.buildScratchSize = 0; + if (device_driver->vkGetAccelerationStructureBuildSizesKHR != nullptr) + { + device_driver->vkGetAccelerationStructureBuildSizesKHR(device->GetVkDevice(), VkAccelerationStructureBuildTypeKHR::VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &vk_acceleration_structure_build_geometry_info_khr, max_primitive_counts.data(), &vk_acceleration_structure_build_sizes_info_khr); + } + + std::cout << "Bottom Level VkAccelerationStructureBuildSizesInfoKHR.accelerationStructureSize = " << vk_acceleration_structure_build_sizes_info_khr.accelerationStructureSize << std::endl; + std::cout << "Bottom Level VkAccelerationStructureBuildSizesInfoKHR.updateScratchSize = " << vk_acceleration_structure_build_sizes_info_khr.updateScratchSize << std::endl; + std::cout << "Bottom Level VkAccelerationStructureBuildSizesInfoKHR.buildScratchSize = " << vk_acceleration_structure_build_sizes_info_khr.buildScratchSize << std::endl; + + bottom_level_acceleration_structure_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_STORAGE | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, vk_acceleration_structure_build_sizes_info_khr.accelerationStructureSize); + + // create acceleration structure + VkDevice vk_device = device->GetVkDevice(); + VkAccelerationStructureCreateInfoKHR vk_acceleration_structure_create_info_khr = {}; + vk_acceleration_structure_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + vk_acceleration_structure_create_info_khr.pNext = nullptr; + vk_acceleration_structure_create_info_khr.createFlags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + vk_acceleration_structure_create_info_khr.buffer = bottom_level_acceleration_structure_buffer->GetVkBuffer(); // 将用于存储加速结构的缓存。大小一般可以为VkAccelerationStructureCreateInfoKHR::size,usage为VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR|VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT<由于之后创建顶层加速结构需要底层加速结构的地址,所以需要VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT> + vk_acceleration_structure_create_info_khr.offset = 0; // 单位比特,相对于buffer的偏移之后存储加速结构,需要是256的倍数。 + vk_acceleration_structure_create_info_khr.size = vk_acceleration_structure_build_sizes_info_khr.accelerationStructureSize; // 该加速结构需要的大小。大小来源于vkGetAccelerationStructureBuildSizesKHR()函数中VkAccelerationStructureBuildSizesInfoKHR::accelerationStructureSize。 + vk_acceleration_structure_create_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; // 加速结构的类型:TOP,BOTTOM,GENERIC + vk_acceleration_structure_create_info_khr.deviceAddress = 0; // 如果激活使用了accelerationStructureCaptureReplay特性,该地址为加速结构要求的那个设备地址。目前为VK_NULL_HANDLE + + VkAllocationCallbacks *vk_allocation_callbacks = Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks(); + VkResult result = device->GetDeviceDriver()->vkCreateAccelerationStructureKHR(vk_device, &vk_acceleration_structure_create_info_khr, vk_allocation_callbacks, &bottom_level_acceleration_structure_khr); + if (result != VK_SUCCESS) + { + std::cout << "Create VkAccelerationStructureKHR Failed" << std::endl; + } + + std::cout << "Create VkAccelerationStructureKHR Success" << std::endl; + + Turbo::Core::TBuffer *scratch_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, vk_acceleration_structure_build_sizes_info_khr.buildScratchSize); + + VkBufferDeviceAddressInfo scratch_buffer_device_address_info = {}; + scratch_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + scratch_buffer_device_address_info.pNext = nullptr; + scratch_buffer_device_address_info.buffer = scratch_buffer->GetVkBuffer(); + + VkDeviceAddress scratch_buffer_device_address = 0; + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddress(vk_device, &scratch_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(vk_device, &scratch_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(vk_device, &scratch_buffer_device_address_info); + } + + if (scratch_buffer_device_address != 0) + { + std::cout << "Successfully get scratch_buffer VkBuffer device local address " << std::endl; + } + + vk_acceleration_structure_build_geometry_info_khr.dstAccelerationStructure = bottom_level_acceleration_structure_khr; + vk_acceleration_structure_build_geometry_info_khr.scratchData.deviceAddress = scratch_buffer_device_address; + + VkAccelerationStructureBuildRangeInfoKHR vk_acceleration_structure_build_range_info_khr = {}; + // vk_acceleration_structure_build_range_info_khr.primitiveCount = INDICES_data.size() / 3; + vk_acceleration_structure_build_range_info_khr.primitiveCount = spheres_count; + vk_acceleration_structure_build_range_info_khr.primitiveOffset = 0; + vk_acceleration_structure_build_range_info_khr.firstVertex = 0; + vk_acceleration_structure_build_range_info_khr.transformOffset = 0; + + std::vector vk_acceleration_structure_build_range_info_khrs; + vk_acceleration_structure_build_range_info_khrs.push_back(vk_acceleration_structure_build_range_info_khr); + + std::vector build_range_infos; // 该数组内元素个数应与 vkCmdBuildAccelerationStructuresKHR::infoCount 对应 + build_range_infos.push_back(vk_acceleration_structure_build_range_info_khrs.data()); + // TODO: compaction query pool for compact acceleration structure + { + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdBuildAccelerationStructuresKHR(command_buffer->GetVkCommandBuffer(), 1, &vk_acceleration_structure_build_geometry_info_khr, build_range_infos.data()); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + } + + // TODO: compact acceleration structure + { + VkQueryPool query_pool = VK_NULL_HANDLE; + + VkQueryPoolCreateInfo vk_query_pool_create_info = {}; + vk_query_pool_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + vk_query_pool_create_info.pNext = nullptr; + vk_query_pool_create_info.flags = 0; + vk_query_pool_create_info.queryType = VkQueryType::VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR; + vk_query_pool_create_info.queryCount = 1; + vk_query_pool_create_info.pipelineStatistics = 0; + + result = device->GetDeviceDriver()->vkCreateQueryPool(vk_device, &vk_query_pool_create_info, vk_allocation_callbacks, &query_pool); + if (result != VK_SUCCESS) + { + std::cout << "Create VkQueryPool Failed" << std::endl; + } + + std::cout << "Create VkQueryPool Success" << std::endl; + + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdResetQueryPool(command_buffer->GetVkCommandBuffer(), query_pool, 0, 1); + device->GetDeviceDriver()->vkCmdWriteAccelerationStructuresPropertiesKHR(command_buffer->GetVkCommandBuffer(), 1, &bottom_level_acceleration_structure_khr, VkQueryType::VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, query_pool, 0); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + VkDeviceSize compact_size = 0; + device->GetDeviceDriver()->vkGetQueryPoolResults(vk_device, query_pool, 0, 1, sizeof(VkDeviceSize), &compact_size, sizeof(VkDeviceSize), VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); + std::cout << "compact size:" << compact_size << std::endl; + + delete fence; + command_pool->Free(command_buffer); + + VkAccelerationStructureKHR compact_bottom_level_acceleration_structure_khr = VK_NULL_HANDLE; + + Turbo::Core::TBuffer *compact_bottom_level_acceleration_structure_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_STORAGE | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, compact_size); + + VkAccelerationStructureCreateInfoKHR compact_vk_acceleration_structure_create_info_khr = {}; + compact_vk_acceleration_structure_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + compact_vk_acceleration_structure_create_info_khr.pNext = nullptr; + compact_vk_acceleration_structure_create_info_khr.createFlags = 0; + compact_vk_acceleration_structure_create_info_khr.buffer = compact_bottom_level_acceleration_structure_buffer->GetVkBuffer(); + compact_vk_acceleration_structure_create_info_khr.offset = 0; + compact_vk_acceleration_structure_create_info_khr.size = compact_size; + compact_vk_acceleration_structure_create_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + compact_vk_acceleration_structure_create_info_khr.deviceAddress = 0; + + result = device->GetDeviceDriver()->vkCreateAccelerationStructureKHR(vk_device, &compact_vk_acceleration_structure_create_info_khr, vk_allocation_callbacks, &compact_bottom_level_acceleration_structure_khr); + if (result != VkResult::VK_SUCCESS) + { + std::cout << "vkCreateAccelerationStructureKHR create compact VkAccelerationStructureKHR Failed" << std::endl; + } + + std::cout << "vkCreateAccelerationStructureKHR create compact VkAccelerationStructureKHR Success" << std::endl; + + VkCopyAccelerationStructureInfoKHR vk_copy_acceleration_structure_info_khr = {}; + vk_copy_acceleration_structure_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR; + vk_copy_acceleration_structure_info_khr.pNext = nullptr; + vk_copy_acceleration_structure_info_khr.src = bottom_level_acceleration_structure_khr; + vk_copy_acceleration_structure_info_khr.dst = compact_bottom_level_acceleration_structure_khr; + vk_copy_acceleration_structure_info_khr.mode = VkCopyAccelerationStructureModeKHR::VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR; + + command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdCopyAccelerationStructureKHR(command_buffer->GetVkCommandBuffer(), &vk_copy_acceleration_structure_info_khr); + command_buffer->End(); + fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + delete fence; + command_pool->Free(command_buffer); + device->GetDeviceDriver()->vkDestroyQueryPool(vk_device, query_pool, vk_allocation_callbacks); + + // destroy no compact acceleration structure + device->GetDeviceDriver()->vkDestroyAccelerationStructureKHR(vk_device, bottom_level_acceleration_structure_khr, vk_allocation_callbacks); + delete bottom_level_acceleration_structure_buffer; + + // set acceleration structure value to compact version + bottom_level_acceleration_structure_khr = compact_bottom_level_acceleration_structure_khr; + bottom_level_acceleration_structure_buffer = compact_bottom_level_acceleration_structure_buffer; + } + + // Top Level Acceleration Structure + glm::mat4 acceleration_structure_model = glm::mat4(1.0f); + //acceleration_structure_model = glm::rotate(acceleration_structure_model, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + VkTransformMatrixKHR vk_transform_matrix_khr = {}; + memcpy(&vk_transform_matrix_khr, &acceleration_structure_model, sizeof(VkTransformMatrixKHR)); + + VkAccelerationStructureDeviceAddressInfoKHR bottom_level_acceleration_structure_device_address_info_khr = {}; + bottom_level_acceleration_structure_device_address_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; + bottom_level_acceleration_structure_device_address_info_khr.pNext = nullptr; + bottom_level_acceleration_structure_device_address_info_khr.accelerationStructure = bottom_level_acceleration_structure_khr; + + VkDeviceAddress bottom_level_acceleration_structure_device_address = device->GetDeviceDriver()->vkGetAccelerationStructureDeviceAddressKHR(vk_device, &bottom_level_acceleration_structure_device_address_info_khr); + + VkAccelerationStructureInstanceKHR vk_acceleration_structure_instance_khr = {}; + vk_acceleration_structure_instance_khr.transform = vk_transform_matrix_khr; + vk_acceleration_structure_instance_khr.instanceCustomIndex = 0; + vk_acceleration_structure_instance_khr.mask = 0xFF; + vk_acceleration_structure_instance_khr.instanceShaderBindingTableRecordOffset = 0; + vk_acceleration_structure_instance_khr.flags = VkGeometryInstanceFlagBitsKHR::VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; + vk_acceleration_structure_instance_khr.accelerationStructureReference = bottom_level_acceleration_structure_device_address; + + { + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + + Turbo::Core::TBuffer *staging_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sizeof(VkAccelerationStructureInstanceKHR)); + void *staging_ptr = staging_buffer->Map(); + if (staging_ptr) + { + memcpy(staging_ptr, &vk_acceleration_structure_instance_khr, sizeof(VkAccelerationStructureInstanceKHR)); + } + staging_buffer->Unmap(); + + instance_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS | Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, sizeof(VkAccelerationStructureInstanceKHR)); + + command_buffer->Begin(); + command_buffer->CmdCopyBuffer(staging_buffer, instance_buffer, 0, 0, sizeof(VkAccelerationStructureInstanceKHR)); + command_buffer->End(); + + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + delete staging_buffer; + command_pool->Free(command_buffer); + } + + VkBufferDeviceAddressInfo instance_buffer_device_address_info = {}; + instance_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + instance_buffer_device_address_info.pNext = nullptr; + instance_buffer_device_address_info.buffer = instance_buffer->GetVkBuffer(); + + VkDeviceAddress instance_buffer_device_address = 0; + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + instance_buffer_device_address = device_driver->vkGetBufferDeviceAddress(vk_device, &instance_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + instance_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(vk_device, &instance_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + instance_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(vk_device, &instance_buffer_device_address_info); + } + + if (instance_buffer_device_address != 0) + { + std::cout << "Successfully get instance_buffer VkBuffer device local address " << std::endl; + } + + // Create Top Level Acceleration Structure + VkAccelerationStructureGeometryInstancesDataKHR vk_acceleration_structure_geometry_instances_data_khr = {}; + vk_acceleration_structure_geometry_instances_data_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + vk_acceleration_structure_geometry_instances_data_khr.pNext = nullptr; + vk_acceleration_structure_geometry_instances_data_khr.arrayOfPointers = VK_FALSE; + vk_acceleration_structure_geometry_instances_data_khr.data.deviceAddress = instance_buffer_device_address; + + VkAccelerationStructureGeometryKHR top_level_acceleration_structure_geometry_khr = {}; + top_level_acceleration_structure_geometry_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + top_level_acceleration_structure_geometry_khr.pNext = nullptr; + top_level_acceleration_structure_geometry_khr.geometryType = VkGeometryTypeKHR::VK_GEOMETRY_TYPE_INSTANCES_KHR; + top_level_acceleration_structure_geometry_khr.geometry.instances = vk_acceleration_structure_geometry_instances_data_khr; + top_level_acceleration_structure_geometry_khr.flags = 0; + + VkAccelerationStructureBuildGeometryInfoKHR top_level_acceleration_structure_build_geometry_info_khr = {}; + top_level_acceleration_structure_build_geometry_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + top_level_acceleration_structure_build_geometry_info_khr.pNext = nullptr; + top_level_acceleration_structure_build_geometry_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + top_level_acceleration_structure_build_geometry_info_khr.flags = VkBuildAccelerationStructureFlagBitsKHR::VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VkBuildAccelerationStructureFlagBitsKHR::VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR; + top_level_acceleration_structure_build_geometry_info_khr.mode = VkBuildAccelerationStructureModeKHR::VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + top_level_acceleration_structure_build_geometry_info_khr.srcAccelerationStructure = VK_NULL_HANDLE; + top_level_acceleration_structure_build_geometry_info_khr.dstAccelerationStructure = VK_NULL_HANDLE; + top_level_acceleration_structure_build_geometry_info_khr.geometryCount = 1; + top_level_acceleration_structure_build_geometry_info_khr.pGeometries = &top_level_acceleration_structure_geometry_khr; + top_level_acceleration_structure_build_geometry_info_khr.ppGeometries = nullptr; + top_level_acceleration_structure_build_geometry_info_khr.scratchData.deviceAddress = 0; + top_level_acceleration_structure_build_geometry_info_khr.scratchData.hostAddress = 0; + + uint32_t instance_count = 1; + VkAccelerationStructureBuildSizesInfoKHR top_level_acceleration_structure_build_sizes_info_khr = {}; + top_level_acceleration_structure_build_sizes_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; + top_level_acceleration_structure_build_sizes_info_khr.pNext = nullptr; + top_level_acceleration_structure_build_sizes_info_khr.accelerationStructureSize = 0; + top_level_acceleration_structure_build_sizes_info_khr.updateScratchSize = 0; + top_level_acceleration_structure_build_sizes_info_khr.buildScratchSize = 0; + + device->GetDeviceDriver()->vkGetAccelerationStructureBuildSizesKHR(vk_device, VkAccelerationStructureBuildTypeKHR::VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &top_level_acceleration_structure_build_geometry_info_khr, &instance_count, &top_level_acceleration_structure_build_sizes_info_khr); + + std::cout << "Top Level VkAccelerationStructureBuildSizesInfoKHR.accelerationStructureSize = " << top_level_acceleration_structure_build_sizes_info_khr.accelerationStructureSize << std::endl; + std::cout << "Top Level VkAccelerationStructureBuildSizesInfoKHR.updateScratchSize = " << top_level_acceleration_structure_build_sizes_info_khr.updateScratchSize << std::endl; + std::cout << "Top Level VkAccelerationStructureBuildSizesInfoKHR.buildScratchSize = " << top_level_acceleration_structure_build_sizes_info_khr.buildScratchSize << std::endl; + + top_level_acceleration_structure_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_STORAGE | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, top_level_acceleration_structure_build_sizes_info_khr.accelerationStructureSize); + + VkAccelerationStructureCreateInfoKHR top_level_acceleration_structure_create_info_khr = {}; + top_level_acceleration_structure_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + top_level_acceleration_structure_create_info_khr.pNext = nullptr; + top_level_acceleration_structure_create_info_khr.createFlags = 0; + top_level_acceleration_structure_create_info_khr.buffer = top_level_acceleration_structure_buffer->GetVkBuffer(); + top_level_acceleration_structure_create_info_khr.offset = 0; + top_level_acceleration_structure_create_info_khr.size = top_level_acceleration_structure_build_sizes_info_khr.accelerationStructureSize; + top_level_acceleration_structure_create_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + top_level_acceleration_structure_create_info_khr.deviceAddress = 0; + + result = device->GetDeviceDriver()->vkCreateAccelerationStructureKHR(vk_device, &top_level_acceleration_structure_create_info_khr, vk_allocation_callbacks, &top_level_acceleration_structure_khr); + if (result != VkResult::VK_SUCCESS) + { + std::cout << "vkCreateAccelerationStructureKHR create Top Level VkAccelerationStructureKHR Failed" << std::endl; + } + + std::cout << "vkCreateAccelerationStructureKHR create Top Level VkAccelerationStructureKHR Success" << std::endl; + + Turbo::Core::TBuffer *top_level_scratch_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_STORAGE_BUFFER | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, top_level_acceleration_structure_build_sizes_info_khr.buildScratchSize); + + VkBufferDeviceAddressInfo top_level_scratch_buffer_device_address_info = {}; + top_level_scratch_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + top_level_scratch_buffer_device_address_info.pNext = nullptr; + top_level_scratch_buffer_device_address_info.buffer = top_level_scratch_buffer->GetVkBuffer(); + + VkDeviceAddress top_level_scratch_buffer_device_address = 0; + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + top_level_scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddress(vk_device, &top_level_scratch_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + top_level_scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(vk_device, &top_level_scratch_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + top_level_scratch_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(vk_device, &top_level_scratch_buffer_device_address_info); + } + + if (top_level_scratch_buffer_device_address != 0) + { + std::cout << "Successfully get top_level_scratch_buffer VkBuffer device local address " << std::endl; + } + + // Build Top Level Acceleration Structure + top_level_acceleration_structure_build_geometry_info_khr.dstAccelerationStructure = top_level_acceleration_structure_khr; + top_level_acceleration_structure_build_geometry_info_khr.scratchData.deviceAddress = top_level_scratch_buffer_device_address; + + VkAccelerationStructureBuildRangeInfoKHR top_level_acceleration_structure_build_range_info_khr = {}; + top_level_acceleration_structure_build_range_info_khr.primitiveCount = 1; + top_level_acceleration_structure_build_range_info_khr.primitiveOffset = 0; + top_level_acceleration_structure_build_range_info_khr.firstVertex = 0; + top_level_acceleration_structure_build_range_info_khr.transformOffset = 0; + + std::vector top_level_acceleration_structure_build_range_info_khrs; + top_level_acceleration_structure_build_range_info_khrs.push_back(top_level_acceleration_structure_build_range_info_khr); + + std::vector top_level_acceleration_structure_ppBuildRangeInfos; + top_level_acceleration_structure_ppBuildRangeInfos.push_back(top_level_acceleration_structure_build_range_info_khrs.data()); + + { + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdBuildAccelerationStructuresKHR(command_buffer->GetVkCommandBuffer(), 1, &top_level_acceleration_structure_build_geometry_info_khr, top_level_acceleration_structure_ppBuildRangeInfos.data()); + command_buffer->End(); + + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + delete fence; + command_pool->Free(command_buffer); + } + + // Top Level Acceleration Structure Compact + { + VkQueryPool query_pool = VK_NULL_HANDLE; + + VkQueryPoolCreateInfo vk_query_pool_create_info = {}; + vk_query_pool_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + vk_query_pool_create_info.pNext = nullptr; + vk_query_pool_create_info.flags = 0; + vk_query_pool_create_info.queryType = VkQueryType::VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR; + vk_query_pool_create_info.queryCount = 1; + vk_query_pool_create_info.pipelineStatistics = 0; + + result = device->GetDeviceDriver()->vkCreateQueryPool(vk_device, &vk_query_pool_create_info, vk_allocation_callbacks, &query_pool); + if (result != VK_SUCCESS) + { + std::cout << "Create VkQueryPool Failed" << std::endl; + } + + std::cout << "Create VkQueryPool Success" << std::endl; + + Turbo::Core::TCommandBuffer *command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdResetQueryPool(command_buffer->GetVkCommandBuffer(), query_pool, 0, 1); + device->GetDeviceDriver()->vkCmdWriteAccelerationStructuresPropertiesKHR(command_buffer->GetVkCommandBuffer(), 1, &top_level_acceleration_structure_khr, VkQueryType::VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, query_pool, 0); + command_buffer->End(); + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + + VkDeviceSize compact_size = 0; + device->GetDeviceDriver()->vkGetQueryPoolResults(vk_device, query_pool, 0, 1, sizeof(VkDeviceSize), &compact_size, sizeof(VkDeviceSize), VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); + std::cout << "top level acceleration structure compact size:" << compact_size << std::endl; + + delete fence; + command_pool->Free(command_buffer); + + VkAccelerationStructureKHR compact_acceleration_structure_khr = VK_NULL_HANDLE; + + Turbo::Core::TBuffer *compact_acceleration_structure_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_ACCELERATION_STRUCTURE_STORAGE | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, compact_size); + + VkAccelerationStructureCreateInfoKHR compact_vk_acceleration_structure_create_info_khr = {}; + compact_vk_acceleration_structure_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + compact_vk_acceleration_structure_create_info_khr.pNext = nullptr; + compact_vk_acceleration_structure_create_info_khr.createFlags = 0; + compact_vk_acceleration_structure_create_info_khr.buffer = compact_acceleration_structure_buffer->GetVkBuffer(); + compact_vk_acceleration_structure_create_info_khr.offset = 0; + compact_vk_acceleration_structure_create_info_khr.size = compact_size; + compact_vk_acceleration_structure_create_info_khr.type = VkAccelerationStructureTypeKHR::VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + compact_vk_acceleration_structure_create_info_khr.deviceAddress = 0; + + result = device->GetDeviceDriver()->vkCreateAccelerationStructureKHR(vk_device, &compact_vk_acceleration_structure_create_info_khr, vk_allocation_callbacks, &compact_acceleration_structure_khr); + if (result != VkResult::VK_SUCCESS) + { + std::cout << "vkCreateAccelerationStructureKHR create compact VkAccelerationStructureKHR Failed" << std::endl; + } + + std::cout << "vkCreateAccelerationStructureKHR create compact VkAccelerationStructureKHR Success" << std::endl; + + VkCopyAccelerationStructureInfoKHR vk_copy_acceleration_structure_info_khr = {}; + vk_copy_acceleration_structure_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR; + vk_copy_acceleration_structure_info_khr.pNext = nullptr; + vk_copy_acceleration_structure_info_khr.src = top_level_acceleration_structure_khr; + vk_copy_acceleration_structure_info_khr.dst = compact_acceleration_structure_khr; + vk_copy_acceleration_structure_info_khr.mode = VkCopyAccelerationStructureModeKHR::VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR; + + command_buffer = command_pool->Allocate(); + command_buffer->Begin(); + device->GetDeviceDriver()->vkCmdCopyAccelerationStructureKHR(command_buffer->GetVkCommandBuffer(), &vk_copy_acceleration_structure_info_khr); + command_buffer->End(); + fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, command_buffer, fence); + fence->WaitUntil(); + delete fence; + command_pool->Free(command_buffer); + device->GetDeviceDriver()->vkDestroyQueryPool(vk_device, query_pool, vk_allocation_callbacks); + + // destroy no compact acceleration structure + device->GetDeviceDriver()->vkDestroyAccelerationStructureKHR(vk_device, top_level_acceleration_structure_khr, vk_allocation_callbacks); + delete top_level_acceleration_structure_buffer; + + // set acceleration structure value to compact version + top_level_acceleration_structure_khr = compact_acceleration_structure_khr; + top_level_acceleration_structure_buffer = compact_acceleration_structure_buffer; + } + + delete top_level_scratch_buffer; + delete scratch_buffer; + } + + // Ray Tracing Pipeline + Turbo::Core::TRayGenerationShader *ray_generation_shader_test = nullptr; + Turbo::Core::TMissShader *miss_shader_test = nullptr; + Turbo::Core::TClosestHitShader *closest_hit_shader_test = nullptr; + + Turbo::Core::TIntersectionShader *intersection_shader_test = nullptr; + + VkDescriptorSetLayout ray_tracing_descriptor_set_layout = VK_NULL_HANDLE; + VkDescriptorSet ray_tracing_descriptor_set = VK_NULL_HANDLE; + VkPipelineLayout ray_tracing_pipeline_layout = VK_NULL_HANDLE; + VkPipeline ray_tracing_pipeline = VK_NULL_HANDLE; + + VkStridedDeviceAddressRegionKHR ray_generation_binding_table = {}; + VkStridedDeviceAddressRegionKHR miss_binding_table = {}; + VkStridedDeviceAddressRegionKHR closest_hit_binding_table = {}; + VkStridedDeviceAddressRegionKHR callable_binding_table = {}; /*Not used but need statement because vkCmdTraceRaysKHR(..., const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, ...) must be a valid pointer to a valid VkStridedDeviceAddressRegionKHR structure */ + + Turbo::Core::TBuffer *sbt_buffer = nullptr; + + { + VkDescriptorSetLayoutBinding vk_ray_tracing_binding_acceleration_structure = {}; + vk_ray_tracing_binding_acceleration_structure.binding = 0; + vk_ray_tracing_binding_acceleration_structure.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + vk_ray_tracing_binding_acceleration_structure.descriptorCount = 1; + vk_ray_tracing_binding_acceleration_structure.stageFlags = VkShaderStageFlagBits::VK_SHADER_STAGE_RAYGEN_BIT_KHR; + vk_ray_tracing_binding_acceleration_structure.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutBinding vk_ray_tracing_binding_storage_image = {}; + vk_ray_tracing_binding_storage_image.binding = 1; + vk_ray_tracing_binding_storage_image.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + vk_ray_tracing_binding_storage_image.descriptorCount = 1; + vk_ray_tracing_binding_storage_image.stageFlags = VkShaderStageFlagBits::VK_SHADER_STAGE_RAYGEN_BIT_KHR; + vk_ray_tracing_binding_storage_image.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutBinding vk_ray_tracing_binding_matrixs = {}; + vk_ray_tracing_binding_matrixs.binding = 2; + vk_ray_tracing_binding_matrixs.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + vk_ray_tracing_binding_matrixs.descriptorCount = 1; + vk_ray_tracing_binding_matrixs.stageFlags = VkShaderStageFlagBits::VK_SHADER_STAGE_RAYGEN_BIT_KHR; + vk_ray_tracing_binding_matrixs.pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutBinding vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address = {}; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.binding = 3; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.descriptorCount = 1; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.stageFlags = VkShaderStageFlagBits::VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VkShaderStageFlagBits::VK_SHADER_STAGE_INTERSECTION_BIT_KHR; + vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address.pImmutableSamplers = nullptr; + + std::vector ray_tracing_descriptor_set_layout_bindings = {}; + ray_tracing_descriptor_set_layout_bindings.push_back(vk_ray_tracing_binding_acceleration_structure); + ray_tracing_descriptor_set_layout_bindings.push_back(vk_ray_tracing_binding_storage_image); + ray_tracing_descriptor_set_layout_bindings.push_back(vk_ray_tracing_binding_matrixs); + ray_tracing_descriptor_set_layout_bindings.push_back(vk_ray_tracing_binding_bottom_level_acceleration_structure_device_address); + + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = {}; + descriptor_set_layout_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptor_set_layout_create_info.pNext = nullptr; + descriptor_set_layout_create_info.flags = 0; + descriptor_set_layout_create_info.bindingCount = ray_tracing_descriptor_set_layout_bindings.size(); + descriptor_set_layout_create_info.pBindings = ray_tracing_descriptor_set_layout_bindings.data(); + + VkAllocationCallbacks *vk_allocation_callbacks = Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks(); + VkResult ray_tracing_descriptor_set_layout_create_result = device_driver->vkCreateDescriptorSetLayout(device->GetVkDevice(), &descriptor_set_layout_create_info, vk_allocation_callbacks, &ray_tracing_descriptor_set_layout); + if (ray_tracing_descriptor_set_layout_create_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Create ray tracing descriptor set layout failed"); + } + + VkDescriptorSetAllocateInfo ray_tracing_descriptor_set_allocate_info = {}; + ray_tracing_descriptor_set_allocate_info.sType = VkStructureType::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + ray_tracing_descriptor_set_allocate_info.pNext = nullptr; + ray_tracing_descriptor_set_allocate_info.descriptorPool = descriptor_pool->GetVkDescriptorPool(); + ray_tracing_descriptor_set_allocate_info.descriptorSetCount = 1; + ray_tracing_descriptor_set_allocate_info.pSetLayouts = &ray_tracing_descriptor_set_layout; + + VkResult ray_tracing_descriptor_sets_allocate_result = device_driver->vkAllocateDescriptorSets(device->GetVkDevice(), &ray_tracing_descriptor_set_allocate_info, &ray_tracing_descriptor_set); + if (ray_tracing_descriptor_sets_allocate_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Allocate ray tracing descriptor set failed"); + } + + VkWriteDescriptorSetAccelerationStructureKHR vk_write_descriptor_set_acceleration_structure_khr = {}; + vk_write_descriptor_set_acceleration_structure_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; + vk_write_descriptor_set_acceleration_structure_khr.pNext = nullptr; + vk_write_descriptor_set_acceleration_structure_khr.accelerationStructureCount = 1; + vk_write_descriptor_set_acceleration_structure_khr.pAccelerationStructures = &top_level_acceleration_structure_khr; + + VkWriteDescriptorSet ray_tracing_write_acceleration_structure = {}; + ray_tracing_write_acceleration_structure.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_acceleration_structure.pNext = &vk_write_descriptor_set_acceleration_structure_khr; + ray_tracing_write_acceleration_structure.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_acceleration_structure.dstBinding = 0; + ray_tracing_write_acceleration_structure.dstArrayElement = 0; + ray_tracing_write_acceleration_structure.descriptorCount = 1; + ray_tracing_write_acceleration_structure.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + ray_tracing_write_acceleration_structure.pImageInfo = nullptr; + ray_tracing_write_acceleration_structure.pBufferInfo = nullptr; + ray_tracing_write_acceleration_structure.pTexelBufferView = nullptr; + + VkDescriptorImageInfo vk_descriptor_image_info = {}; + vk_descriptor_image_info.sampler = VK_NULL_HANDLE; + vk_descriptor_image_info.imageView = ray_tracing_image_view->GetVkImageView(); + vk_descriptor_image_info.imageLayout = VkImageLayout::VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet ray_tracing_write_image = {}; + ray_tracing_write_image.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_image.pNext = nullptr; + ray_tracing_write_image.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_image.dstBinding = 1; + ray_tracing_write_image.dstArrayElement = 0; + ray_tracing_write_image.descriptorCount = 1; + ray_tracing_write_image.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + ray_tracing_write_image.pImageInfo = &vk_descriptor_image_info; + ray_tracing_write_image.pBufferInfo = nullptr; + ray_tracing_write_image.pTexelBufferView = nullptr; + + VkDescriptorBufferInfo vk_descriptor_matrixs_buffer_info = {}; + vk_descriptor_matrixs_buffer_info.buffer = matrixs_buffer->GetVkBuffer(); + vk_descriptor_matrixs_buffer_info.offset = 0; + vk_descriptor_matrixs_buffer_info.range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet ray_tracing_write_matrixs = {}; + ray_tracing_write_matrixs.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_matrixs.pNext = nullptr; + ray_tracing_write_matrixs.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_matrixs.dstBinding = 2; + ray_tracing_write_matrixs.dstArrayElement = 0; + ray_tracing_write_matrixs.descriptorCount = 1; + ray_tracing_write_matrixs.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + ray_tracing_write_matrixs.pImageInfo = nullptr; + ray_tracing_write_matrixs.pBufferInfo = &vk_descriptor_matrixs_buffer_info; + ray_tracing_write_matrixs.pTexelBufferView = nullptr; + + VkDescriptorBufferInfo vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info = {}; + vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info.buffer = bottom_level_acceleration_structure_device_address_buffer->GetVkBuffer(); + vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info.offset = 0; + vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info.range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer = {}; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.pNext = nullptr; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.dstBinding = 3; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.dstArrayElement = 0; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.descriptorCount = 1; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.pImageInfo = nullptr; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.pBufferInfo = &vk_descriptor_bottom_level_acceleration_structure_device_address_buffer_info; + ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer.pTexelBufferView = nullptr; + + std::vector vk_write_descriptor_sets; + vk_write_descriptor_sets.push_back(ray_tracing_write_acceleration_structure); + vk_write_descriptor_sets.push_back(ray_tracing_write_image); + vk_write_descriptor_sets.push_back(ray_tracing_write_matrixs); + vk_write_descriptor_sets.push_back(ray_tracing_write_bottom_level_acceleration_structure_device_address_buffer); + + device_driver->vkUpdateDescriptorSets(device->GetVkDevice(), vk_write_descriptor_sets.size(), vk_write_descriptor_sets.data(), 0, nullptr); + + VkPipelineLayoutCreateInfo ray_tracing_pipeline_layout_create_info = {}; + ray_tracing_pipeline_layout_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + ray_tracing_pipeline_layout_create_info.pNext = nullptr; + ray_tracing_pipeline_layout_create_info.flags = 0; + ray_tracing_pipeline_layout_create_info.setLayoutCount = 1; + ray_tracing_pipeline_layout_create_info.pSetLayouts = &ray_tracing_descriptor_set_layout; + ray_tracing_pipeline_layout_create_info.pushConstantRangeCount = 0; + ray_tracing_pipeline_layout_create_info.pPushConstantRanges = nullptr; + + VkResult ray_tracing_pipeline_layout_create_result = device_driver->vkCreatePipelineLayout(device->GetVkDevice(), &ray_tracing_pipeline_layout_create_info, vk_allocation_callbacks, &ray_tracing_pipeline_layout); + if (ray_tracing_pipeline_layout_create_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Create ray tracing pipeline layout failed"); + } + + ray_generation_shader_test = new Turbo::Core::TRayGenerationShader(device, Turbo::Core::TShaderLanguage::GLSL, RAY_GENERATION_SHADER_STR); + miss_shader_test = new Turbo::Core::TMissShader(device, Turbo::Core::TShaderLanguage::GLSL, MISS_SHADER_STR); + closest_hit_shader_test = new Turbo::Core::TClosestHitShader(device, Turbo::Core::TShaderLanguage::GLSL, CLOSEST_HIT_SHADER_STR); + intersection_shader_test = new Turbo::Core::TIntersectionShader(device, Turbo::Core::TShaderLanguage::GLSL, INTERSECTION_SHADER_STR); + + VkPipelineShaderStageCreateInfo ray_generation_shader_stage_create_info = {}; + ray_generation_shader_stage_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + ray_generation_shader_stage_create_info.pNext = nullptr; + ray_generation_shader_stage_create_info.flags = 0; + ray_generation_shader_stage_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_RAYGEN_BIT_KHR; + ray_generation_shader_stage_create_info.module = ray_generation_shader_test->GetVkShaderModule(); + ray_generation_shader_stage_create_info.pName = "main"; + ray_generation_shader_stage_create_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo miss_shader_stage_create_info = {}; + miss_shader_stage_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + miss_shader_stage_create_info.pNext = nullptr; + miss_shader_stage_create_info.flags = 0; + miss_shader_stage_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_MISS_BIT_KHR; + miss_shader_stage_create_info.module = miss_shader_test->GetVkShaderModule(); + miss_shader_stage_create_info.pName = "main"; + miss_shader_stage_create_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo closest_hit_shader_stage_create_info = {}; + closest_hit_shader_stage_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + closest_hit_shader_stage_create_info.pNext = nullptr; + closest_hit_shader_stage_create_info.flags = 0; + closest_hit_shader_stage_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + closest_hit_shader_stage_create_info.module = closest_hit_shader_test->GetVkShaderModule(); + closest_hit_shader_stage_create_info.pName = "main"; + closest_hit_shader_stage_create_info.pSpecializationInfo = nullptr; + + VkPipelineShaderStageCreateInfo intersection_shader_stage_create_info = {}; + intersection_shader_stage_create_info.sType = VkStructureType::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + intersection_shader_stage_create_info.pNext = nullptr; + intersection_shader_stage_create_info.flags = 0; + intersection_shader_stage_create_info.stage = VkShaderStageFlagBits::VK_SHADER_STAGE_INTERSECTION_BIT_KHR; + intersection_shader_stage_create_info.module = intersection_shader_test->GetVkShaderModule(); + intersection_shader_stage_create_info.pName = "main"; + intersection_shader_stage_create_info.pSpecializationInfo = nullptr; + + std::vector ray_tracing_pipeline_shader_stages = {}; + ray_tracing_pipeline_shader_stages.push_back(ray_generation_shader_stage_create_info); + ray_tracing_pipeline_shader_stages.push_back(miss_shader_stage_create_info); + ray_tracing_pipeline_shader_stages.push_back(closest_hit_shader_stage_create_info); + ray_tracing_pipeline_shader_stages.push_back(intersection_shader_stage_create_info); + + VkRayTracingShaderGroupCreateInfoKHR ray_generation_shader_group = {}; + ray_generation_shader_group.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + ray_generation_shader_group.pNext = nullptr; + ray_generation_shader_group.type = VkRayTracingShaderGroupTypeKHR::VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + ray_generation_shader_group.generalShader = 0; + ray_generation_shader_group.closestHitShader = VK_SHADER_UNUSED_KHR; + ray_generation_shader_group.anyHitShader = VK_SHADER_UNUSED_KHR; + ray_generation_shader_group.intersectionShader = VK_SHADER_UNUSED_KHR; + ray_generation_shader_group.pShaderGroupCaptureReplayHandle = nullptr; + + VkRayTracingShaderGroupCreateInfoKHR miss_shader_group = {}; + miss_shader_group.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + miss_shader_group.pNext = nullptr; + miss_shader_group.type = VkRayTracingShaderGroupTypeKHR::VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + miss_shader_group.generalShader = 1; + miss_shader_group.closestHitShader = VK_SHADER_UNUSED_KHR; + miss_shader_group.anyHitShader = VK_SHADER_UNUSED_KHR; + miss_shader_group.intersectionShader = VK_SHADER_UNUSED_KHR; + miss_shader_group.pShaderGroupCaptureReplayHandle = nullptr; + + VkRayTracingShaderGroupCreateInfoKHR hit_shader_group = {}; + hit_shader_group.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + hit_shader_group.pNext = nullptr; + hit_shader_group.type = VkRayTracingShaderGroupTypeKHR::VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; + hit_shader_group.generalShader = VK_SHADER_UNUSED_KHR; + hit_shader_group.closestHitShader = 2; + hit_shader_group.anyHitShader = VK_SHADER_UNUSED_KHR; + hit_shader_group.intersectionShader = 3; + hit_shader_group.pShaderGroupCaptureReplayHandle = nullptr; + + std::vector shader_groups = {}; + shader_groups.push_back(ray_generation_shader_group); + shader_groups.push_back(miss_shader_group); + shader_groups.push_back(hit_shader_group); + + VkRayTracingPipelineCreateInfoKHR vk_ray_tracing_pipeline_create_info_khr = {}; + vk_ray_tracing_pipeline_create_info_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; + vk_ray_tracing_pipeline_create_info_khr.pNext = nullptr; + vk_ray_tracing_pipeline_create_info_khr.flags = 0; + vk_ray_tracing_pipeline_create_info_khr.stageCount = ray_tracing_pipeline_shader_stages.size(); + vk_ray_tracing_pipeline_create_info_khr.pStages = ray_tracing_pipeline_shader_stages.data(); + vk_ray_tracing_pipeline_create_info_khr.groupCount = shader_groups.size(); + vk_ray_tracing_pipeline_create_info_khr.pGroups = shader_groups.data(); + vk_ray_tracing_pipeline_create_info_khr.maxPipelineRayRecursionDepth = 2; + vk_ray_tracing_pipeline_create_info_khr.pLibraryInfo = nullptr; + vk_ray_tracing_pipeline_create_info_khr.pLibraryInterface = nullptr; + vk_ray_tracing_pipeline_create_info_khr.pDynamicState = nullptr; + vk_ray_tracing_pipeline_create_info_khr.layout = ray_tracing_pipeline_layout; + vk_ray_tracing_pipeline_create_info_khr.basePipelineHandle = VK_NULL_HANDLE; + vk_ray_tracing_pipeline_create_info_khr.basePipelineIndex = 0; + + VkResult create_ray_tracing_pipeline_result = device_driver->vkCreateRayTracingPipelinesKHR(device->GetVkDevice(), VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &vk_ray_tracing_pipeline_create_info_khr, vk_allocation_callbacks, &ray_tracing_pipeline); + if (create_ray_tracing_pipeline_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Create ray tracing pipeline failed"); + } + + // Shader Binding Table + VkPhysicalDeviceRayTracingPipelinePropertiesKHR vk_physical_device_ray_tracing_pipeline_properties_khr = {}; + vk_physical_device_ray_tracing_pipeline_properties_khr.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR; + vk_physical_device_ray_tracing_pipeline_properties_khr.pNext = nullptr; + vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleSize = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayRecursionDepth = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.maxShaderGroupStride = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupBaseAlignment = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleCaptureReplaySize = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayDispatchInvocationCount = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleAlignment = 0; + vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayHitAttributeSize = 0; + + VkPhysicalDeviceProperties2 vk_physical_device_properties_2 = {}; + vk_physical_device_properties_2.sType = VkStructureType::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + vk_physical_device_properties_2.pNext = &vk_physical_device_ray_tracing_pipeline_properties_khr; + vk_physical_device_properties_2.properties = {}; + + if (physical_device_driver->vkGetPhysicalDeviceProperties2 != nullptr) + { + physical_device_driver->vkGetPhysicalDeviceProperties2(physical_device->GetVkPhysicalDevice(), &vk_physical_device_properties_2); + } + else if (physical_device_driver->vkGetPhysicalDeviceProperties2KHR != nullptr) + { + physical_device_driver->vkGetPhysicalDeviceProperties2KHR(physical_device->GetVkPhysicalDevice(), &vk_physical_device_properties_2); + } + + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleSize:" << vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleSize << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxRayRecursionDepth:" << vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayRecursionDepth << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxShaderGroupStride:" << vk_physical_device_ray_tracing_pipeline_properties_khr.maxShaderGroupStride << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupBaseAlignment:" << vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupBaseAlignment << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleCaptureReplaySize:" << vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleCaptureReplaySize << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxRayDispatchInvocationCount:" << vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayDispatchInvocationCount << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleAlignment:" << vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleAlignment << std::endl; + std::cout << "VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxRayHitAttributeSize:" << vk_physical_device_ray_tracing_pipeline_properties_khr.maxRayHitAttributeSize << std::endl; + + uint32_t ray_generation_count = 1; + uint32_t miss_count = 1; + uint32_t hit_count = 1; + + uint32_t handle_count = ray_generation_count + miss_count + hit_count; + uint32_t handle_size = vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleSize; + uint32_t shader_group_handle_alignment = vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupHandleAlignment; + uint32_t shader_group_base_alignment = vk_physical_device_ray_tracing_pipeline_properties_khr.shaderGroupBaseAlignment; + + uint32_t handle_size_aligned = Turbo::Core::TVulkanAllocator::AlignUp(handle_size, shader_group_handle_alignment); + + ray_generation_binding_table.deviceAddress = 0; + ray_generation_binding_table.stride = Turbo::Core::TVulkanAllocator::AlignUp(handle_size_aligned, shader_group_base_alignment); + ray_generation_binding_table.size = ray_generation_binding_table.stride; // The size member of pRayGenShaderBindingTable must be equal to its stride member (https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap40.html#VUID-vkCmdTraceRaysKHR-size-04023) + + miss_binding_table.deviceAddress = 0; + miss_binding_table.stride = handle_size_aligned; + miss_binding_table.size = Turbo::Core::TVulkanAllocator::AlignUp(miss_count * handle_size_aligned, shader_group_base_alignment); + + closest_hit_binding_table.deviceAddress = 0; + closest_hit_binding_table.stride = handle_size_aligned; + closest_hit_binding_table.size = Turbo::Core::TVulkanAllocator::AlignUp(hit_count * handle_size_aligned, shader_group_base_alignment); + + uint32_t data_size = handle_count * handle_size_aligned; + std::vector handles(data_size); + + VkResult vk_get_ray_tracing_shader_group_handles_khr_result = device_driver->vkGetRayTracingShaderGroupHandlesKHR(device->GetVkDevice(), ray_tracing_pipeline, 0, handle_count, data_size, handles.data()); + if (vk_get_ray_tracing_shader_group_handles_khr_result != VkResult::VK_SUCCESS) + { + throw std::runtime_error("Get shader group handle failed"); + } + + VkDeviceSize sbt_buffer_size = ray_generation_binding_table.size + miss_binding_table.size + closest_hit_binding_table.size; + sbt_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_DEVICE_ADDRESS | Turbo::Core::TBufferUsageBits::BUFFER_SHADER_BINDING_TABLE, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, sbt_buffer_size); + + VkBufferDeviceAddressInfo sbt_buffer_device_address_info = {}; + sbt_buffer_device_address_info.sType = VkStructureType::VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + sbt_buffer_device_address_info.pNext = nullptr; + sbt_buffer_device_address_info.buffer = sbt_buffer->GetVkBuffer(); + + VkDeviceAddress sbt_buffer_device_address = 0; + if (device_driver->vkGetBufferDeviceAddress != nullptr) + { + sbt_buffer_device_address = device_driver->vkGetBufferDeviceAddress(device->GetVkDevice(), &sbt_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressKHR != nullptr) + { + sbt_buffer_device_address = device_driver->vkGetBufferDeviceAddressKHR(device->GetVkDevice(), &sbt_buffer_device_address_info); + } + else if (device_driver->vkGetBufferDeviceAddressEXT != nullptr) + { + sbt_buffer_device_address = device_driver->vkGetBufferDeviceAddressEXT(device->GetVkDevice(), &sbt_buffer_device_address_info); + } + + if (sbt_buffer_device_address == 0) + { + throw std::runtime_error("Get shader binding table buffer address failed"); + } + + ray_generation_binding_table.deviceAddress = sbt_buffer_device_address; + miss_binding_table.deviceAddress = sbt_buffer_device_address + ray_generation_binding_table.size; + closest_hit_binding_table.deviceAddress = sbt_buffer_device_address + ray_generation_binding_table.size + miss_binding_table.size; + + void *sbt_buffer_point = sbt_buffer->Map(); + // ray generation + memcpy((uint8_t *)sbt_buffer_point, handles.data() + 0 * handle_size, handle_size); + // miss + memcpy((uint8_t *)sbt_buffer_point + ray_generation_binding_table.size, handles.data() + 1 * handle_size, handle_size); + // closest_hit + memcpy((uint8_t *)sbt_buffer_point + ray_generation_binding_table.size + miss_binding_table.size, handles.data() + 2 * handle_size, handle_size); + sbt_buffer->Unmap(); + } + + std::vector my_buffers; + my_buffers.push_back(my_buffer); + + std::vector matrixs_buffers; + matrixs_buffers.push_back(matrixs_buffer); + + Turbo::Core::TSubpass subpass(Turbo::Core::TPipelineType::Graphics); + subpass.AddColorAttachmentReference(0, Turbo::Core::TImageLayout::COLOR_ATTACHMENT_OPTIMAL); // swapchain color image + subpass.SetDepthStencilAttachmentReference(1, Turbo::Core::TImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); // depth image + + Turbo::Core::TSubpass subpass1(Turbo::Core::TPipelineType::Graphics); + subpass1.AddColorAttachmentReference(0, Turbo::Core::TImageLayout::COLOR_ATTACHMENT_OPTIMAL); // swapchain color image + subpass.SetDepthStencilAttachmentReference(1, Turbo::Core::TImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); // depth image + + std::vector subpasses; + subpasses.push_back(subpass); // subpass 0 + subpasses.push_back(subpass1); // subpass 1 + + Turbo::Core::TAttachment swapchain_color_attachment(swapchain_images[0]->GetFormat(), swapchain_images[0]->GetSampleCountBits(), Turbo::Core::TLoadOp::LOAD, Turbo::Core::TStoreOp::STORE, Turbo::Core::TLoadOp::DONT_CARE, Turbo::Core::TStoreOp::DONT_CARE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::PRESENT_SRC_KHR); + Turbo::Core::TAttachment depth_attachment(depth_image->GetFormat(), depth_image->GetSampleCountBits(), Turbo::Core::TLoadOp::CLEAR, Turbo::Core::TStoreOp::STORE, Turbo::Core::TLoadOp::DONT_CARE, Turbo::Core::TStoreOp::DONT_CARE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + std::vector attachemts; + attachemts.push_back(swapchain_color_attachment); + attachemts.push_back(depth_attachment); + + Turbo::Core::TRenderPass *render_pass = new Turbo::Core::TRenderPass(device, attachemts, subpasses); + + Turbo::Core::TVertexBinding position_binding(0, sizeof(POSITION), Turbo::Core::TVertexRate::VERTEX); + position_binding.AddAttribute(0, Turbo::Core::TFormatType::R32G32B32_SFLOAT, 0); // position + Turbo::Core::TVertexBinding normal_binding(1, sizeof(NORMAL), Turbo::Core::TVertexRate::VERTEX); + normal_binding.AddAttribute(1, Turbo::Core::TFormatType::R32G32B32_SFLOAT, 0); // normal + Turbo::Core::TVertexBinding texcoord_binding(2, sizeof(TEXCOORD), Turbo::Core::TVertexRate::VERTEX); + texcoord_binding.AddAttribute(2, Turbo::Core::TFormatType::R32G32_SFLOAT, 0); // texcoord/uv + Turbo::Core::TVertexBinding tangent_binding(3, sizeof(TANGENT), Turbo::Core::TVertexRate::VERTEX); + tangent_binding.AddAttribute(3, Turbo::Core::TFormatType::R32G32B32A32_SFLOAT, 0); // tangent + + std::vector vertex_bindings; + vertex_bindings.push_back(position_binding); + vertex_bindings.push_back(normal_binding); + vertex_bindings.push_back(texcoord_binding); + vertex_bindings.push_back(tangent_binding); + + Turbo::Core::TViewport viewport(0, 0, surface->GetCurrentWidth(), surface->GetCurrentHeight(), 0, 1); + Turbo::Core::TScissor scissor(0, 0, surface->GetCurrentWidth(), surface->GetCurrentHeight()); + + uint32_t patch_control_points = 3; + Turbo::Core::TPolygonMode polygon_mode = Turbo::Core::TPolygonMode::FILL; + Turbo::Core::TGraphicsPipeline *pipeline = new Turbo::Core::TGraphicsPipeline(render_pass, 0, vertex_bindings, vertex_shader, geometry_shader, fragment_shader, Turbo::Core::TTopologyType::TRIANGLE_LIST, false, false, false, polygon_mode, Turbo::Core::TCullModeBits::MODE_BACK_BIT, Turbo::Core::TFrontFace::CLOCKWISE, false, 0, 0, 0, 1, false, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, true, true, Turbo::Core::TCompareOp::LESS_OR_EQUAL, false, false, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TCompareOp::ALWAYS, 0, 0, 0, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TCompareOp::ALWAYS, 0, 0, 0, 0, 0, false, Turbo::Core::TLogicOp::NO_OP, true, Turbo::Core::TBlendFactor::SRC_ALPHA, Turbo::Core::TBlendFactor::ONE_MINUS_SRC_ALPHA, Turbo::Core::TBlendOp::ADD, Turbo::Core::TBlendFactor::ONE_MINUS_SRC_ALPHA, Turbo::Core::TBlendFactor::ZERO, Turbo::Core::TBlendOp::ADD); + + std::vector input_attachment_depths; + input_attachment_depths.push_back(depth_image_view); + + Turbo::Core::TPipelineDescriptorSet *pipeline_descriptor_set = descriptor_pool->Allocate(pipeline->GetPipelineLayout()); + pipeline_descriptor_set->BindData(0, 0, 0, matrixs_buffers); + pipeline_descriptor_set->BindData(0, 1, 0, my_buffers); + + std::vector vertex_buffers; + vertex_buffers.push_back(position_buffer); + vertex_buffers.push_back(normal_buffer); + vertex_buffers.push_back(texcoord_buffer); + vertex_buffers.push_back(tangent_buffer); + + std::vector swpachain_framebuffers; + for (Turbo::Core::TImageView *swapchain_image_view_item : swapchain_image_views) + { + std::vector image_views; + image_views.push_back(swapchain_image_view_item); + image_views.push_back(depth_image_view); + + Turbo::Core::TFramebuffer *swapchain_framebuffer = new Turbo::Core::TFramebuffer(render_pass, image_views); + swpachain_framebuffers.push_back(swapchain_framebuffer); + } + + // + ImGui::CreateContext(); + ImGuiIO &io = ImGui::GetIO(); + + ImGui::StyleColorsDark(); + + Turbo::Core::TSampler *imgui_sampler = new Turbo::Core::TSampler(device); + Turbo::Core::TShader *imgui_vertex_shader = new Turbo::Core::TShader(device, Turbo::Core::TShaderType::VERTEX, Turbo::Core::TShaderLanguage::GLSL, IMGUI_VERT_SHADER_STR); + Turbo::Core::TShader *imgui_fragment_shader = new Turbo::Core::TShader(device, Turbo::Core::TShaderType::FRAGMENT, Turbo::Core::TShaderLanguage::GLSL, IMGUI_FRAG_SHADER_STR); + + Turbo::Core::TVertexBinding imgui_vertex_binding(0, sizeof(ImDrawVert), Turbo::Core::TVertexRate::VERTEX); + imgui_vertex_binding.AddAttribute(0, Turbo::Core::TFormatType::R32G32_SFLOAT, IM_OFFSETOF(ImDrawVert, pos)); // position + imgui_vertex_binding.AddAttribute(1, Turbo::Core::TFormatType::R32G32_SFLOAT, IM_OFFSETOF(ImDrawVert, uv)); // uv + imgui_vertex_binding.AddAttribute(2, Turbo::Core::TFormatType::R8G8B8A8_UNORM, IM_OFFSETOF(ImDrawVert, col)); // color + + std::vector imgui_shaders; + imgui_shaders.push_back(imgui_vertex_shader); + imgui_shaders.push_back(imgui_fragment_shader); + + std::vector imgui_vertex_bindings; + imgui_vertex_bindings.push_back(imgui_vertex_binding); + + Turbo::Core::TGraphicsPipeline *imgui_pipeline = new Turbo::Core::TGraphicsPipeline(render_pass, 1, imgui_vertex_bindings, imgui_shaders, Turbo::Core::TTopologyType::TRIANGLE_LIST, false, false, false, Turbo::Core::TPolygonMode::FILL, Turbo::Core::TCullModeBits::MODE_BACK_BIT, Turbo::Core::TFrontFace::CLOCKWISE, false, 0, 0, 0, 1, false, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, false, false, Turbo::Core::TCompareOp::LESS_OR_EQUAL, false, false, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TCompareOp::ALWAYS, 0, 0, 0, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TStencilOp::KEEP, Turbo::Core::TCompareOp::ALWAYS, 0, 0, 0, 0, 0, false, Turbo::Core::TLogicOp::NO_OP, true, Turbo::Core::TBlendFactor::SRC_ALPHA, Turbo::Core::TBlendFactor::ONE_MINUS_SRC_ALPHA, Turbo::Core::TBlendOp::ADD, Turbo::Core::TBlendFactor::ONE_MINUS_SRC_ALPHA, Turbo::Core::TBlendFactor::ZERO, Turbo::Core::TBlendOp::ADD); + + unsigned char *imgui_font_pixels; + int imgui_font_width, imgui_font_height; + io.Fonts->GetTexDataAsRGBA32(&imgui_font_pixels, &imgui_font_width, &imgui_font_height); + size_t imgui_upload_size = imgui_font_width * imgui_font_height * 4 * sizeof(char); + + Turbo::Core::TImage *imgui_font_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::R8G8B8A8_UNORM, imgui_font_width, imgui_font_height, 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_SAMPLED | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_DST, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY); + Turbo::Core::TImageView *imgui_font_image_view = new Turbo::Core::TImageView(imgui_font_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, imgui_font_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + { + Turbo::Core::TBuffer *imgui_font_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_TRANSFER_SRC, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, imgui_upload_size); + void *imgui_font_ptr = imgui_font_buffer->Map(); + memcpy(imgui_font_ptr, imgui_font_pixels, imgui_upload_size); + imgui_font_buffer->Unmap(); + + Turbo::Core::TCommandBuffer *imgui_copy_command_buffer = command_pool->Allocate(); + imgui_copy_command_buffer->Begin(); + imgui_copy_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::HOST_BIT, Turbo::Core::TPipelineStageBits::TRANSFER_BIT, Turbo::Core::TAccessBits::HOST_WRITE_BIT, Turbo::Core::TAccessBits::TRANSFER_WRITE_BIT, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, imgui_font_image, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + imgui_copy_command_buffer->CmdCopyBufferToImage(imgui_font_buffer, imgui_font_image, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, 0, imgui_font_width, imgui_font_height, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 0, 1, 0, 0, 0, imgui_font_width, imgui_font_height, 1); + imgui_copy_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TRANSFER_BIT, Turbo::Core::TPipelineStageBits::FRAGMENT_SHADER_BIT, Turbo::Core::TAccessBits::TRANSFER_WRITE_BIT, Turbo::Core::TAccessBits::SHADER_READ_BIT, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, Turbo::Core::TImageLayout::SHADER_READ_ONLY_OPTIMAL, imgui_font_image, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + imgui_copy_command_buffer->End(); + + Turbo::Core::TFence *imgui_font_copy_fence = new Turbo::Core::TFence(device); + queue->Submit(nullptr, nullptr, imgui_copy_command_buffer, imgui_font_copy_fence); + + imgui_font_copy_fence->WaitUntil(); + + delete imgui_font_buffer; + delete imgui_font_copy_fence; + } + + std::vector> imgui_combined_image_samplers; + imgui_combined_image_samplers.push_back(std::make_pair(imgui_font_image_view, imgui_sampler)); + + Turbo::Core::TPipelineDescriptorSet *imgui_pipeline_descriptor_set = descriptor_pool->Allocate(imgui_pipeline->GetPipelineLayout()); + imgui_pipeline_descriptor_set->BindData(0, 0, 0, imgui_combined_image_samplers); + + io.Fonts->TexID = (ImTextureID)(intptr_t)(imgui_font_image->GetVkImage()); + + Turbo::Core::TBuffer *imgui_vertex_buffer = nullptr; + Turbo::Core::TBuffer *imgui_index_buffer = nullptr; + // + + glm::vec3 camera_position = glm::vec3(1.00025, -1.50862, -2.52088); + + float horizontal_angle = 383.2; + float vertical_angle = 28; + + glm::vec2 previous_mouse_pos = glm::vec2(0, 0); + glm::vec2 current_mouse_pos = glm::vec2(0, 0); + + float angle = 0; + float _time = glfwGetTime(); + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + + void *_ptr = my_buffer->Map(); + memcpy(_ptr, &my_buffer_data, sizeof(my_buffer_data)); + my_buffer->Unmap(); + + // + uint32_t current_image_index = UINT32_MAX; + Turbo::Core::TSemaphore *wait_image_ready = new Turbo::Core::TSemaphore(device, Turbo::Core::TPipelineStageBits::COLOR_ATTACHMENT_OUTPUT_BIT); + Turbo::Core::TResult result = swapchain->AcquireNextImageUntil(wait_image_ready, nullptr, ¤t_image_index); + switch (result) + { + case Turbo::Core::TResult::SUCCESS: { + // successed get image and go on rendering + + // because we just have one command buffer, so we should reset the command buffer for each frame + // If we create command buffer for each swapchain image, we don't need to reset it each frame + + // + int window_w, window_h; + int display_w, display_h; + glfwGetWindowSize(window, &window_w, &window_h); + glfwGetFramebufferSize(window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)window_w, (float)window_h); + if (window_w > 0 && window_h > 0) + { + io.DisplayFramebufferScale = ImVec2((float)display_w / window_w, (float)display_h / window_h); + } + double current_time = glfwGetTime(); + io.DeltaTime = _time > 0.0 ? (float)(current_time - _time) : (float)(1.0f / 60.0f); + _time = current_time; + + // UpdateMousePosAndButtons + { + // Update buttons + ImGuiIO &io = ImGui::GetIO(); + for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) + { + // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(window, i) != 0; + g_MouseJustPressed[i] = false; + } + + // Update mouse position + const ImVec2 mouse_pos_backup = io.MousePos; + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + + const bool focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0; + if (focused) + { + if (io.WantSetMousePos) + { + glfwSetCursorPos(window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y); + } + else + { + double mouse_x, mouse_y; + glfwGetCursorPos(window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); + } + } + } + + // IUpdateMouseCursor + { + ImGuiIO &io = ImGui::GetIO(); + if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) + break; + + ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); + if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } + else + { + // Show OS mouse cursor + // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. + glfwSetCursor(window, g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } + } + + // UpdateKeyboard + { + ImVec2 mouse_pos = io.MousePos; + current_mouse_pos = glm::vec2(mouse_pos.x, mouse_pos.y); + glm::vec2 mouse_pos_delte = current_mouse_pos - previous_mouse_pos; + previous_mouse_pos = current_mouse_pos; + mouse_pos_delte.y = mouse_pos_delte.y; + + int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT); + if (state == GLFW_PRESS) + { + horizontal_angle += mouse_pos_delte.x * 0.2; + vertical_angle += mouse_pos_delte.y * 0.2; + + if (vertical_angle > 90) + { + vertical_angle = 90; + } + + if (vertical_angle < -90) + { + vertical_angle = -90; + } + } + + float delte_time = io.DeltaTime; + float speed = 1; + + glm::vec3 forward_axis = glm::vec3(0, 0, 1); + glm::mat4 forward_rotate_mat = glm::rotate(glm::mat4(1), glm::radians(-horizontal_angle), glm::vec3(0, 1, 0)); + forward_rotate_mat = glm::rotate(forward_rotate_mat, glm::radians(-vertical_angle), glm::vec3(1, 0, 0)); + + glm::vec3 look_forward = forward_rotate_mat * glm::vec4(forward_axis, 1.0); + look_forward = glm::normalize(look_forward); + + glm::vec3 forward_dir = look_forward; // 向前向量 + glm::vec3 up_dir = glm::vec3(0, 1, 0); // 向上向量 + glm::vec3 right_dir = glm::cross(forward_dir, up_dir); // 向右向量 + up_dir = glm::cross(right_dir, forward_dir); + + right_dir = glm::normalize(right_dir); + up_dir = glm::normalize(up_dir); + + int key_W_state = glfwGetKey(window, GLFW_KEY_W); + if (key_W_state == GLFW_PRESS) + { + // TODO: 向前 + camera_position += forward_dir * speed * delte_time; + } + + int key_A_state = glfwGetKey(window, GLFW_KEY_A); + if (key_A_state == GLFW_PRESS) + { + // TODO: 向左 + camera_position += -right_dir * speed * delte_time; + } + + int key_S_state = glfwGetKey(window, GLFW_KEY_S); + if (key_S_state == GLFW_PRESS) + { + // TODO: 向后 + camera_position += -forward_dir * speed * delte_time; + } + + int key_D_state = glfwGetKey(window, GLFW_KEY_D); + if (key_D_state == GLFW_PRESS) + { + // TODO: 向右 + camera_position += right_dir * speed * delte_time; + } + + model = glm::rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + model = model * glm::rotate(glm::mat4(1.0f), glm::radians(angle), glm::vec3(0.0f, 0.0f, 1.0f)); + + glm::vec3 look_point = camera_position + forward_dir; + view = glm::lookAt(camera_position, look_point, up_dir); + projection = glm::perspective(glm::radians(45.0f), (float)(swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth()) / (float)(swapchain->GetHeight() <= 0 ? 1 : swapchain->GetHeight()), 0.1f, 300.0f); + + matrixs_buffer_data.m = model; + matrixs_buffer_data.v = view; + matrixs_buffer_data.p = projection; + + _ptr = matrixs_buffer->Map(); + memcpy(_ptr, &matrixs_buffer_data, sizeof(matrixs_buffer_data)); + matrixs_buffer->Unmap(); + } + + ImGui::NewFrame(); + + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("VulkanKHRRayTracingTestForIntersectionShader"); + ImGui::Text("W,A,S,D to move."); + ImGui::Text("Push down and drag mouse right button to rotate view."); + ImGui::SliderFloat("angle", &angle, 0.0f, 360); + ImGui::SliderFloat("scale", &my_buffer_data.scale, 0.03, 0.1); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::End(); + } + // + + Turbo::Core::TViewport frame_viewport(0, 0, swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth(), swapchain->GetHeight(), 0, 1); + Turbo::Core::TScissor frame_scissor(0, 0, swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth(), swapchain->GetHeight() <= 0 ? 1 : swapchain->GetHeight()); + + std::vector frame_viewports; + frame_viewports.push_back(frame_viewport); + + std::vector frame_scissors; + frame_scissors.push_back(frame_scissor); + + command_buffer->Begin(); + + // ray tracing commands + { + VkCommandBuffer vk_command_buffer = command_buffer->GetVkCommandBuffer(); + device_driver->vkCmdBindPipeline(vk_command_buffer, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, ray_tracing_pipeline); + device_driver->vkCmdBindDescriptorSets(vk_command_buffer, VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, ray_tracing_pipeline_layout, 0, 1, &ray_tracing_descriptor_set, 0, nullptr); + device_driver->vkCmdTraceRaysKHR(vk_command_buffer, &ray_generation_binding_table, &miss_binding_table, &closest_hit_binding_table, &callable_binding_table, swapchain->GetWidth(), swapchain->GetHeight(), 1); + + // copy ray tracing image into color target image + VkImageBlit vk_image_blit = {}; + vk_image_blit.srcSubresource.aspectMask = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT; + vk_image_blit.srcSubresource.mipLevel = 0; + vk_image_blit.srcSubresource.baseArrayLayer = 0; + vk_image_blit.srcSubresource.layerCount = 1; + vk_image_blit.srcOffsets[0].x = 0; + vk_image_blit.srcOffsets[0].y = 0; + vk_image_blit.srcOffsets[0].z = 0; + vk_image_blit.srcOffsets[1].x = swapchain->GetWidth(); + vk_image_blit.srcOffsets[1].y = swapchain->GetHeight(); + vk_image_blit.srcOffsets[1].z = 1; + vk_image_blit.dstSubresource.aspectMask = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT; + vk_image_blit.dstSubresource.mipLevel = 0; + vk_image_blit.dstSubresource.baseArrayLayer = 0; + vk_image_blit.dstSubresource.layerCount = 1; + vk_image_blit.dstOffsets[0].x = 0; + vk_image_blit.dstOffsets[0].y = 0; + vk_image_blit.dstOffsets[0].z = 0; + vk_image_blit.dstOffsets[1].x = swapchain->GetWidth(); + vk_image_blit.dstOffsets[1].y = swapchain->GetHeight(); + vk_image_blit.dstOffsets[1].z = 1; + + command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TOP_OF_PIPE_BIT, Turbo::Core::TPipelineStageBits::TRANSFER_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::TRANSFER_WRITE_BIT, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, swpachain_framebuffers[current_image_index]->GetAttachments()[0]); + device_driver->vkCmdBlitImage(vk_command_buffer, ray_tracing_image->GetVkImage(), VkImageLayout::VK_IMAGE_LAYOUT_GENERAL, swpachain_framebuffers[current_image_index]->GetAttachments()[0]->GetImage()->GetVkImage(), VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vk_image_blit, VkFilter::VK_FILTER_LINEAR); + command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TRANSFER_BIT, Turbo::Core::TPipelineStageBits::COLOR_ATTACHMENT_OUTPUT_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::COLOR_ATTACHMENT_WRITE_BIT, Turbo::Core::TImageLayout::TRANSFER_DST_OPTIMAL, Turbo::Core::TImageLayout::COLOR_ATTACHMENT_OPTIMAL, swpachain_framebuffers[current_image_index]->GetAttachments()[0]); + } + + command_buffer->CmdBeginRenderPass(render_pass, swpachain_framebuffers[current_image_index]); + + command_buffer->CmdSetViewport(frame_viewports); + command_buffer->CmdSetScissor(frame_scissors); + + // material_sphere + // command_buffer->CmdBindPipeline(pipeline); + // command_buffer->CmdBindPipelineDescriptorSet(pipeline_descriptor_set); + // command_buffer->CmdBindVertexBuffers(vertex_buffers); + // command_buffer->CmdSetLineWidth(1); + // command_buffer->CmdBindIndexBuffer(index_buffer); + // command_buffer->CmdDrawIndexed(indices_count, 1, 0, 0, 0); + + command_buffer->CmdNextSubpass(); + + // + ImGui::Render(); + ImDrawData *draw_data = ImGui::GetDrawData(); + const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); + + if (!is_minimized) + { + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); + int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); + if (fb_width <= 0 || fb_height <= 0) + { + break; + } + + if (draw_data->TotalVtxCount > 0) + { + size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + + if (imgui_vertex_buffer != nullptr) + { + delete imgui_vertex_buffer; + imgui_vertex_buffer = nullptr; + } + + if (imgui_index_buffer != nullptr) + { + delete imgui_index_buffer; + imgui_index_buffer = nullptr; + } + + imgui_vertex_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_VERTEX_BUFFER, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, vertex_size); + imgui_index_buffer = new Turbo::Core::TBuffer(device, 0, Turbo::Core::TBufferUsageBits::BUFFER_INDEX_BUFFER, Turbo::Core::TMemoryFlagsBits::HOST_ACCESS_SEQUENTIAL_WRITE, index_size); + + ImDrawVert *vtx_dst = (ImDrawVert *)imgui_vertex_buffer->Map(); + ImDrawIdx *idx_dst = (ImDrawIdx *)imgui_index_buffer->Map(); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList *cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.Size; + idx_dst += cmd_list->IdxBuffer.Size; + } + imgui_vertex_buffer->Unmap(); + imgui_index_buffer->Unmap(); + + command_buffer->CmdBindPipeline(imgui_pipeline); + command_buffer->CmdBindPipelineDescriptorSet(imgui_pipeline_descriptor_set); + + std::vector imgui_vertex_buffers; + imgui_vertex_buffers.push_back(imgui_vertex_buffer); + command_buffer->CmdBindVertexBuffers(imgui_vertex_buffers); + command_buffer->CmdBindIndexBuffer(imgui_index_buffer, 0, sizeof(ImDrawIdx) == 2 ? Turbo::Core::TIndexType::UINT16 : Turbo::Core::TIndexType::UINT32); + + float scale[2]; + scale[0] = 2.0f / draw_data->DisplaySize.x; + scale[1] = 2.0f / draw_data->DisplaySize.y; + float translate[2]; + translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; + translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; + + command_buffer->CmdPushConstants(sizeof(float) * 0, sizeof(float) * 2, scale); + command_buffer->CmdPushConstants(sizeof(float) * 2, sizeof(float) * 2, translate); + + ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports + ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) + + int global_vtx_offset = 0; + int global_idx_offset = 0; + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList *cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd *pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback != NULL) + { + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + { + command_buffer->CmdBindPipeline(imgui_pipeline); + command_buffer->CmdBindPipelineDescriptorSet(imgui_pipeline_descriptor_set); + + std::vector __imgui_vertex_buffers; + __imgui_vertex_buffers.push_back(imgui_vertex_buffer); + command_buffer->CmdBindVertexBuffers(imgui_vertex_buffers); + command_buffer->CmdBindIndexBuffer(imgui_index_buffer, 0, sizeof(ImDrawIdx) == 2 ? Turbo::Core::TIndexType::UINT16 : Turbo::Core::TIndexType::UINT32); + + float __scale[2]; + __scale[0] = 2.0f / draw_data->DisplaySize.x; + __scale[1] = 2.0f / draw_data->DisplaySize.y; + float __translate[2]; + __translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; + __translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; + + command_buffer->CmdPushConstants(sizeof(float) * 0, sizeof(float) * 2, __scale); + command_buffer->CmdPushConstants(sizeof(float) * 2, sizeof(float) * 2, __translate); + } + else + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + // Project scissor/clipping rectangles into framebuffer space + ImVec4 clip_rect; + clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; + clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; + clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; + clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; + + if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) + { + // Negative offsets are illegal for vkCmdSetScissor + if (clip_rect.x < 0.0f) + clip_rect.x = 0.0f; + if (clip_rect.y < 0.0f) + clip_rect.y = 0.0f; + + // Apply scissor/clipping rectangle + VkRect2D scissor; + scissor.offset.x = (int32_t)(clip_rect.x); + scissor.offset.y = (int32_t)(clip_rect.y); + scissor.extent.width = (uint32_t)(clip_rect.z - clip_rect.x); + scissor.extent.height = (uint32_t)(clip_rect.w - clip_rect.y); + + Turbo::Core::TScissor imgui_scissor(scissor.offset.x, scissor.offset.y, scissor.extent.width, scissor.extent.height); + std::vector imgui_scissors; + imgui_scissors.push_back(imgui_scissor); + command_buffer->CmdSetScissor(imgui_scissors); + + // Draw + command_buffer->CmdDrawIndexed(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0); + } + } + } + global_idx_offset += cmd_list->IdxBuffer.Size; + global_vtx_offset += cmd_list->VtxBuffer.Size; + } + } + } + // + + command_buffer->CmdEndRenderPass(); + command_buffer->End(); + + Turbo::Core::TFence *fence = new Turbo::Core::TFence(device); + std::vector wait_semaphores; + wait_semaphores.push_back(wait_image_ready); + + queue->Submit(&wait_semaphores, nullptr, command_buffer, fence); + + fence->WaitUntil(); // or you can use semaphore to wait for get higher performance + + delete fence; + + command_buffer->Reset(); // you can create an command buffer each for one swapchain image,for now just one command buffer + + Turbo::Core::TResult present_result = queue->Present(swapchain, current_image_index); + switch (present_result) + { + case Turbo::Core::TResult::MISMATCH: { + // the size of the window had changed you need to recreate swapchain + + // waite for idle + device->WaitIdle(); + + // destroy related resource + // clear old swapchain image + swapchain_images.clear(); + + // destroy swapchain image views + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + delete image_view_item; + } + + swapchain_image_views.clear(); + + // destroy depth image and view + delete depth_image_view; + delete depth_image; + + // destroy framebuffer + for (Turbo::Core::TFramebuffer *frame_buffer_item : swpachain_framebuffers) + { + delete frame_buffer_item; + } + swpachain_framebuffers.clear(); + + // destroy ray tracing image + delete ray_tracing_image_view; + delete ray_tracing_image; + + // recreate swapchain + Turbo::Extension::TSwapchain *old_swapchain = swapchain; + Turbo::Extension::TSwapchain *new_swapchain = new Turbo::Extension::TSwapchain(old_swapchain); + delete old_swapchain; + + swapchain = new_swapchain; + + // recreate swapchain image views + swapchain_images = swapchain->GetImages(); + for (Turbo::Core::TImage *swapchain_image_item : swapchain_images) + { + Turbo::Core::TImageView *swapchain_view = new Turbo::Core::TImageView(swapchain_image_item, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, Turbo::Core::TFormatType::B8G8R8A8_SRGB, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + swapchain_image_views.push_back(swapchain_view); + } + + // recreate depth image and view + depth_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::D32_SFLOAT, swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth(), swapchain->GetHeight() <= 0 ? 1 : swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_DEPTH_STENCIL_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_INPUT_ATTACHMENT, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, Turbo::Core::TImageLayout::UNDEFINED); + depth_image_view = new Turbo::Core::TImageView(depth_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, depth_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_DEPTH_BIT, 0, 1, 0, 1); + + // recreate framebuffer + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + std::vector swapchain_image_views; + swapchain_image_views.push_back(image_view_item); + swapchain_image_views.push_back(depth_image_view); + + Turbo::Core::TFramebuffer *swapchain_framebuffer = new Turbo::Core::TFramebuffer(render_pass, swapchain_image_views); + swpachain_framebuffers.push_back(swapchain_framebuffer); + } + + // recreate ray tracing image + ray_tracing_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::R32G32B32A32_SFLOAT, swapchain->GetWidth(), swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_COLOR_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_SRC | Turbo::Core::TImageUsageBits::IMAGE_STORAGE, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY); + ray_tracing_image_view = new Turbo::Core::TImageView(ray_tracing_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, ray_tracing_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + { + Turbo::Core::TCommandBuffer *change_ray_tracing_image_layout_command_buffer = command_pool->Allocate(); + + change_ray_tracing_image_layout_command_buffer->Begin(); + change_ray_tracing_image_layout_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TOP_OF_PIPE_BIT, Turbo::Core::TPipelineStageBits::BOTTOM_OF_PIPE_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::GENERAL, ray_tracing_image_view); + change_ray_tracing_image_layout_command_buffer->End(); + + Turbo::Core::TFence *change_image_layout_fence = new Turbo::Core::TFence(device); + + queue->Submit(nullptr, nullptr, change_ray_tracing_image_layout_command_buffer, change_image_layout_fence); + + change_image_layout_fence->WaitUntil(); + delete change_image_layout_fence; + + command_pool->Free(change_ray_tracing_image_layout_command_buffer); + } + + VkDescriptorImageInfo vk_descriptor_image_info = {}; + vk_descriptor_image_info.sampler = VK_NULL_HANDLE; + vk_descriptor_image_info.imageView = ray_tracing_image_view->GetVkImageView(); + vk_descriptor_image_info.imageLayout = VkImageLayout::VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet ray_tracing_write_image = {}; + ray_tracing_write_image.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_image.pNext = nullptr; + ray_tracing_write_image.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_image.dstBinding = 1; + ray_tracing_write_image.dstArrayElement = 0; + ray_tracing_write_image.descriptorCount = 1; + ray_tracing_write_image.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + ray_tracing_write_image.pImageInfo = &vk_descriptor_image_info; + ray_tracing_write_image.pBufferInfo = nullptr; + ray_tracing_write_image.pTexelBufferView = nullptr; + + std::vector vk_write_descriptor_sets; + vk_write_descriptor_sets.push_back(ray_tracing_write_image); + + device_driver->vkUpdateDescriptorSets(device->GetVkDevice(), vk_write_descriptor_sets.size(), vk_write_descriptor_sets.data(), 0, nullptr); + } + break; + default: { + // + } + break; + } + } + break; + case Turbo::Core::TResult::TIMEOUT: { + // you need to wait, or do something else + } + break; + case Turbo::Core::TResult::NOT_READY: { + // you need to wait, or do something else + } + break; + case Turbo::Core::TResult::MISMATCH: { + // the size of the window had changed you need to recreate swapchain + + // waite for idle + device->WaitIdle(); + + // destroy related resource + // clear old swapchain image + swapchain_images.clear(); + + // destroy swapchain image views + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + delete image_view_item; + } + + swapchain_image_views.clear(); + + // destroy depth image and view + delete depth_image_view; + delete depth_image; + + // destroy framebuffer + for (Turbo::Core::TFramebuffer *frame_buffer_item : swpachain_framebuffers) + { + delete frame_buffer_item; + } + swpachain_framebuffers.clear(); + + // destroy ray tracing image + delete ray_tracing_image_view; + delete ray_tracing_image; + + // recreate swapchain + Turbo::Extension::TSwapchain *old_swapchain = swapchain; + Turbo::Extension::TSwapchain *new_swapchain = new Turbo::Extension::TSwapchain(old_swapchain); + delete old_swapchain; + + swapchain = new_swapchain; + + // recreate swapchain image views + swapchain_images = swapchain->GetImages(); + for (Turbo::Core::TImage *swapchain_image_item : swapchain_images) + { + Turbo::Core::TImageView *swapchain_view = new Turbo::Core::TImageView(swapchain_image_item, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, Turbo::Core::TFormatType::B8G8R8A8_SRGB, Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + swapchain_image_views.push_back(swapchain_view); + } + + // recreate depth image and view + depth_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::D32_SFLOAT, swapchain->GetWidth() <= 0 ? 1 : swapchain->GetWidth(), swapchain->GetHeight() <= 0 ? 1 : swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_DEPTH_STENCIL_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_INPUT_ATTACHMENT, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY, Turbo::Core::TImageLayout::UNDEFINED); + depth_image_view = new Turbo::Core::TImageView(depth_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, depth_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_DEPTH_BIT, 0, 1, 0, 1); + + // recreate framebuffer + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + std::vector swapchain_image_views; + swapchain_image_views.push_back(image_view_item); + swapchain_image_views.push_back(depth_image_view); + + Turbo::Core::TFramebuffer *swapchain_framebuffer = new Turbo::Core::TFramebuffer(render_pass, swapchain_image_views); + swpachain_framebuffers.push_back(swapchain_framebuffer); + } + + // recreate ray tracing image + ray_tracing_image = new Turbo::Core::TImage(device, 0, Turbo::Core::TImageType::DIMENSION_2D, Turbo::Core::TFormatType::R32G32B32A32_SFLOAT, swapchain->GetWidth(), swapchain->GetHeight(), 1, 1, 1, Turbo::Core::TSampleCountBits::SAMPLE_1_BIT, Turbo::Core::TImageTiling::OPTIMAL, Turbo::Core::TImageUsageBits::IMAGE_COLOR_ATTACHMENT | Turbo::Core::TImageUsageBits::IMAGE_TRANSFER_SRC | Turbo::Core::TImageUsageBits::IMAGE_STORAGE, Turbo::Core::TMemoryFlagsBits::DEDICATED_MEMORY); + ray_tracing_image_view = new Turbo::Core::TImageView(ray_tracing_image, Turbo::Core::TImageViewType::IMAGE_VIEW_2D, ray_tracing_image->GetFormat(), Turbo::Core::TImageAspectBits::ASPECT_COLOR_BIT, 0, 1, 0, 1); + { + Turbo::Core::TCommandBuffer *change_ray_tracing_image_layout_command_buffer = command_pool->Allocate(); + + change_ray_tracing_image_layout_command_buffer->Begin(); + change_ray_tracing_image_layout_command_buffer->CmdTransformImageLayout(Turbo::Core::TPipelineStageBits::TOP_OF_PIPE_BIT, Turbo::Core::TPipelineStageBits::BOTTOM_OF_PIPE_BIT, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TAccessBits::ACCESS_NONE, Turbo::Core::TImageLayout::UNDEFINED, Turbo::Core::TImageLayout::GENERAL, ray_tracing_image_view); + change_ray_tracing_image_layout_command_buffer->End(); + + Turbo::Core::TFence *change_image_layout_fence = new Turbo::Core::TFence(device); + + queue->Submit(nullptr, nullptr, change_ray_tracing_image_layout_command_buffer, change_image_layout_fence); + + change_image_layout_fence->WaitUntil(); + delete change_image_layout_fence; + + command_pool->Free(change_ray_tracing_image_layout_command_buffer); + } + + VkDescriptorImageInfo vk_descriptor_image_info = {}; + vk_descriptor_image_info.sampler = VK_NULL_HANDLE; + vk_descriptor_image_info.imageView = ray_tracing_image_view->GetVkImageView(); + vk_descriptor_image_info.imageLayout = VkImageLayout::VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet ray_tracing_write_image = {}; + ray_tracing_write_image.sType = VkStructureType::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + ray_tracing_write_image.pNext = nullptr; + ray_tracing_write_image.dstSet = ray_tracing_descriptor_set; + ray_tracing_write_image.dstBinding = 1; + ray_tracing_write_image.dstArrayElement = 0; + ray_tracing_write_image.descriptorCount = 1; + ray_tracing_write_image.descriptorType = VkDescriptorType::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + ray_tracing_write_image.pImageInfo = &vk_descriptor_image_info; + ray_tracing_write_image.pBufferInfo = nullptr; + ray_tracing_write_image.pTexelBufferView = nullptr; + + std::vector vk_write_descriptor_sets; + vk_write_descriptor_sets.push_back(ray_tracing_write_image); + + device_driver->vkUpdateDescriptorSets(device->GetVkDevice(), vk_write_descriptor_sets.size(), vk_write_descriptor_sets.data(), 0, nullptr); + } + break; + default: { + // + } + break; + } + + delete wait_image_ready; + // + } + + if (imgui_vertex_buffer != nullptr) + { + delete imgui_vertex_buffer; + } + if (imgui_index_buffer != nullptr) + { + delete imgui_index_buffer; + } + descriptor_pool->Free(imgui_pipeline_descriptor_set); + delete imgui_font_image_view; + delete imgui_font_image; + delete imgui_pipeline; + delete imgui_vertex_shader; + delete imgui_fragment_shader; + delete imgui_sampler; + + descriptor_pool->Free(pipeline_descriptor_set); + delete pipeline; + for (Turbo::Core::TFramebuffer *framebuffer_item : swpachain_framebuffers) + { + delete framebuffer_item; + } + + delete render_pass; + + delete sbt_buffer; + + device_driver->vkDestroyPipeline(device->GetVkDevice(), ray_tracing_pipeline, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + device_driver->vkDestroyPipelineLayout(device->GetVkDevice(), ray_tracing_pipeline_layout, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + device_driver->vkFreeDescriptorSets(device->GetVkDevice(), descriptor_pool->GetVkDescriptorPool(), 1, &ray_tracing_descriptor_set); + device_driver->vkDestroyDescriptorSetLayout(device->GetVkDevice(), ray_tracing_descriptor_set_layout, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + + delete ray_generation_shader_test; + delete miss_shader_test; + delete closest_hit_shader_test; + delete intersection_shader_test; + + delete descriptor_pool; + delete vertex_shader; + delete geometry_shader; + delete fragment_shader; + delete depth_image_view; + delete depth_image; + for (Turbo::Core::TImageView *image_view_item : swapchain_image_views) + { + delete image_view_item; + } + delete index_buffer; + delete position_buffer; + delete tangent_buffer; + delete normal_buffer; + delete texcoord_buffer; + delete my_buffer; + delete matrixs_buffer; + + delete aabbs_buffer; + + device->GetDeviceDriver()->vkDestroyAccelerationStructureKHR(device->GetVkDevice(), top_level_acceleration_structure_khr, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + delete top_level_acceleration_structure_buffer; + delete instance_buffer; + device->GetDeviceDriver()->vkDestroyAccelerationStructureKHR(device->GetVkDevice(), bottom_level_acceleration_structure_khr, Turbo::Core::TVulkanAllocator::Instance()->GetVkAllocationCallbacks()); + delete bottom_level_acceleration_structure_buffer; + delete device_local_index_buffer; + delete device_local_vertex_buffer; + delete bottom_level_acceleration_structure_device_address_buffer; + + delete ray_tracing_image_view; + delete ray_tracing_image; + command_pool->Free(command_buffer); + delete command_pool; + delete swapchain; + delete surface; + PFN_vkDestroySurfaceKHR pfn_vk_destroy_surface_khr = Turbo::Core::TVulkanLoader::Instance()->LoadInstanceFunction(instance, "vkDestroySurfaceKHR"); + pfn_vk_destroy_surface_khr(instance->GetVkInstance(), vk_surface_khr, nullptr); + glfwTerminate(); + delete device; + delete instance; + + return 0; +} diff --git a/samples/VulkanTest.cpp b/samples/VulkanTest.cpp index 306015f2..82be8a81 100644 --- a/samples/VulkanTest.cpp +++ b/samples/VulkanTest.cpp @@ -1,5 +1,7 @@ +#include "core/include/TException.h" #include "core/include/TInstance.h" #include + // #include #if defined(_WIN16) || defined(_WIN32) || defined(_WIN64) #include @@ -138,7 +140,7 @@ int main() HMODULE library = LoadLibraryA("vulkan-1.dll"); if (!library) { - throw std::exception("Can not found vulkan-1.dll"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "Can not found vulkan-1.dll"); } vk_GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)(void (*)(void))GetProcAddress(library, "vkGetInstanceProcAddr"); @@ -195,7 +197,7 @@ int main() VkResult result = vk_CreateInstance(&vk_instance_create_info, &vk_allocation_callbacks, &vk_instance); if (result != VkResult::VK_SUCCESS) { - throw std::exception("vkCreateInstance failed"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "vkCreateInstance failed"); } else { @@ -234,14 +236,14 @@ int main() result = vk_EnumeratePhysicalDevices(vk_instance, &physcial_device_count, nullptr); if (result != VkResult::VK_SUCCESS) { - throw std::exception("vkEnumeratePhysicalDevices get count failed"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "vkEnumeratePhysicalDevices get count failed"); } std::vector physcail_devices(physcial_device_count); result = vk_EnumeratePhysicalDevices(vk_instance, &physcial_device_count, physcail_devices.data()); if (result != VkResult::VK_SUCCESS) { - throw std::exception("vkEnumeratePhysicalDevices failed"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "vkEnumeratePhysicalDevices failed"); } VkPhysicalDevice target_physical_device = VK_NULL_HANDLE; @@ -266,7 +268,7 @@ int main() if (target_physical_device == VK_NULL_HANDLE) { - throw std::exception("Not found suitable GPU"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "Not found suitable GPU"); } else { @@ -317,7 +319,7 @@ int main() result = vk_CreateDevice(target_physical_device, &vk_device_create_info, nullptr, &vk_device); if (result != VkResult::VK_SUCCESS) { - throw std::exception("vkCreateDevice failed"); + throw Turbo::Core::TException(Turbo::Core::TResult::FAIL, "vkCreateDevice failed"); } std::cout << "vkCreateDevice success" << std::endl; diff --git a/thirdparty/KTX-Software b/thirdparty/KTX-Software index d7255fe7..9c223d95 160000 --- a/thirdparty/KTX-Software +++ b/thirdparty/KTX-Software @@ -1 +1 @@ -Subproject commit d7255fe73cd53b856731ceb9f2c279181d0dbbca +Subproject commit 9c223d9500f7ea734e493aef99e8ff766aa75676