From c5119193ffaedf4ac94fecfb434a3292a4746259 Mon Sep 17 00:00:00 2001 From: ladevieq Date: Sun, 26 Sep 2021 23:57:26 +0200 Subject: Refactor gltf loading and triangles attributes --- include/aabb.hpp | 24 ++----- include/gltf.hpp | 10 ++- include/scene.hpp | 20 +++++- include/triangle.hpp | 21 ++---- include/vk-api.hpp | 1 - include/vk-renderer.hpp | 25 +++---- shaders/compute.comp | 67 ++++++++++++++---- shaders/include/brdf.h | 99 +++++++++++++++++++++++++++ shaders/include/color_utils.h | 26 +++++++ shaders/include/math.h | 45 ++++++++++++ shaders/include/rand.h | 12 ++++ shaders/include/ray.h | 155 ++++++++++++++++++++++++++++++++++++++++++ shaders/tonemapping.comp | 4 +- shaders/ui.frag | 2 +- shaders/ui.vert | 2 +- src/gltf.cpp | 34 ++++----- src/main.cpp | 63 ++++++++--------- src/scene.cpp | 51 ++++++++++++-- src/vk-api.cpp | 14 ++-- src/vk-renderer.cpp | 89 +++++------------------- 20 files changed, 550 insertions(+), 214 deletions(-) create mode 100644 shaders/include/brdf.h create mode 100644 shaders/include/color_utils.h create mode 100644 shaders/include/math.h create mode 100644 shaders/include/rand.h create mode 100644 shaders/include/ray.h diff --git a/include/aabb.hpp b/include/aabb.hpp index 5f819db..475c04e 100644 --- a/include/aabb.hpp +++ b/include/aabb.hpp @@ -12,22 +12,15 @@ class aabb { aabb(vec3 &min_point, vec3 &max_point): minimum(min_point), maximum(max_point) {} aabb(vec3 &position, float radius): minimum(position - vec3(radius)), maximum(position + vec3(radius)) {} aabb(triangle &tri) { - auto &v1 = tri.v1.position; - auto &v2 = tri.v2.position; - auto &v3 = tri.v3.position; - - // minimum.x = fmin(fmin(v1.x, v2.x), v3.x); - // minimum.y = fmin(fmin(v1.y, v2.y), v3.y); - // minimum.z = fmin(fmin(v1.z, v2.z), v3.z); + auto &v1 = tri.p1; + auto &v2 = tri.p2; + auto &v3 = tri.p3; + // TODO: Use vector 3 functions minimum.v[0] = fmin(fmin(v1.v[0], v2.v[0]), v3.v[0]); minimum.v[1] = fmin(fmin(v1.v[1], v2.v[1]), v3.v[1]); minimum.v[2] = fmin(fmin(v1.v[2], v2.v[2]), v3.v[2]); - // maximum.x = fmax(fmax(v1.x, v2.x), v3.x); - // maximum.y = fmax(fmax(v1.y, v2.y), v3.y); - // maximum.z = fmax(fmax(v1.z, v2.z), v3.z); - maximum.v[0] = fmax(fmax(v1.v[0], v2.v[0]), v3.v[0]); maximum.v[1] = fmax(fmax(v1.v[1], v2.v[1]), v3.v[1]); maximum.v[2] = fmax(fmax(v1.v[2], v2.v[2]), v3.v[2]); @@ -46,14 +39,6 @@ class aabb { int32_t maximum_axis() { vec3 diag = diagonal(); - // if (diag.x > diag.y && diag.x > diag.z) { - // return 0; - // } else if (diag.y > diag.z) { - // return 1; - // } else { - // return 2; - // } - if (diag.v[0] > diag.v[1] && diag.v[0] > diag.v[2]) { return 0; } else if (diag.v[1] > diag.v[2]) { @@ -73,7 +58,6 @@ class aabb { float surface_area() { auto diag = diagonal(); - // return 2.f * (diag.x * diag.y + diag.x * diag.z + diag.y * diag.z); return 2.f * (diag.v[0] * diag.v[1] + diag.v[0] * diag.v[2] + diag.v[1] * diag.v[2]); } diff --git a/include/gltf.hpp b/include/gltf.hpp index 0a63ba6..7df5e7a 100644 --- a/include/gltf.hpp +++ b/include/gltf.hpp @@ -16,14 +16,18 @@ using json = nlohmann::json; struct mesh_part { std::vector indices; - std::vector positions; - std::vector normals; - std::vector uvs; + std::vector positions; + std::vector normals; + std::vector uvs; material mat; + uint32_t triangles_count = 0; + uint32_t vertices_count = 0; }; struct mesh { std::vector parts; + uint32_t triangles_count = 0; + uint32_t vertices_count = 0; }; struct node { diff --git a/include/scene.hpp b/include/scene.hpp index 82ffb3d..2c945d4 100644 --- a/include/scene.hpp +++ b/include/scene.hpp @@ -34,11 +34,27 @@ class scene { public: scene(camera cam, uint32_t width, uint32_t height, vkrenderer &renderer); + void* scene_buffer_ptr() { + return scene_buffer.alloc_info.pMappedData; + } + metadata meta; // Geometry & BVH - // std::vector spheres; - std::vector triangles; + std::vector indices; + std::vector positions; + std::vector normals; + std::vector uvs; + std::vector materials; + + Buffer scene_buffer; + Buffer indices_buffer; + Buffer positions_buffer; + Buffer normals_buffer; + Buffer uvs_buffer; + Buffer bvh_buffer; + Buffer materials_buffer; + std::vector packed_nodes; }; diff --git a/include/triangle.hpp b/include/triangle.hpp index 5a62aec..4d3550b 100644 --- a/include/triangle.hpp +++ b/include/triangle.hpp @@ -1,28 +1,21 @@ #ifndef __TRIANGLE_HPP_ #define __TRIANGLE_HPP_ -#include "material.hpp" - -struct vertex { - vec3 position; - vec3 normal; - vec3 uv; -}; +#include "vec3.hpp" struct triangle { triangle() = default; - triangle(vertex v1, vertex v2, vertex v3, material mat) - : v1(v1), v2(v2), v3(v3), mat(mat) + triangle(vec3 p1, vec3 p2, vec3 p3) + : p1(p1), p2(p2), p3(p3) {} vec3 center() { - return (v1.position + v2.position + v3.position) / 3.f; + return (p1 + p2 + p3) / 3.f; } - vertex v1; - vertex v2; - vertex v3; - material mat; + vec3 p1; + vec3 p2; + vec3 p3; }; #endif // !__TRIANGLE_HPP_ diff --git a/include/vk-api.hpp b/include/vk-api.hpp index 8612e00..7953817 100644 --- a/include/vk-api.hpp +++ b/include/vk-api.hpp @@ -49,7 +49,6 @@ struct global_descriptor { VkPipelineLayout pipeline_layout; VkDescriptorSet set; - // TODO: Use constant here std::vector index_pool[3]; global_descriptor() { diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp index 78d7028..dada742 100644 --- a/include/vk-renderer.hpp +++ b/include/vk-renderer.hpp @@ -27,24 +27,18 @@ class vkrenderer { void recreate_swapchain(); - void create_scene_buffer(size_t size); - - void create_geometry_buffer(size_t size); - - void create_bvh_buffer(size_t size); - - inline void* scene_buffer_ptr() { - return scene_buffer.alloc_info.pMappedData; - } - - void update_geometry_buffer(void* data); - - void update_bvh_buffer(void* data); - void update_image(image img, void* data, size_t size); vkapi api; + VkDeviceAddress scene_buffer_addr; + VkDeviceAddress indices_buffer_addr; + VkDeviceAddress positions_buffer_addr; + VkDeviceAddress normals_buffer_addr; + VkDeviceAddress uvs_buffer_addr; + VkDeviceAddress bvh_buffer_addr; + VkDeviceAddress materials_buffer_addr; + private: void handle_swapchain_result(VkResult function_result); @@ -62,9 +56,6 @@ class vkrenderer { Pipeline compute_pipeline; - Buffer scene_buffer; - Buffer geometry_buffer; - Buffer bvh_buffer; Buffer staging_buffer; diff --git a/shaders/compute.comp b/shaders/compute.comp index 015ef1e..2663592 100644 --- a/shaders/compute.comp +++ b/shaders/compute.comp @@ -6,12 +6,6 @@ #extension GL_EXT_buffer_reference : require #extension GL_EXT_nonuniform_qualifier : require -const float PI = 3.141592653589793f; -const float TWO_PI = PI * 2.0f; - -const uint DIFFUSE = 1; -const uint SPECULAR = 2; - #include "math.h" #include "color_utils.h" #include "rand.h" @@ -52,7 +46,6 @@ struct triangle { vertex v1; vertex v2; vertex v3; - material mat; }; struct camera { @@ -91,9 +84,24 @@ layout(buffer_reference) readonly buffer scene_metadata { int downscale_factor; }; -layout(buffer_reference) readonly buffer primitives_array { - // sphere[] spheres; - triangle triangles[]; +layout(buffer_reference) readonly buffer indices_array { + uint indices[]; +}; + +layout(buffer_reference) readonly buffer positions_array { + float positions[]; +}; + +layout(buffer_reference) readonly buffer normals_array { + float normals[]; +}; + +layout(buffer_reference) readonly buffer uvs_array { + float uvs[]; +}; + +layout(buffer_reference) readonly buffer materials_array { + material materials[]; }; layout(buffer_reference) readonly buffer nodes_array { @@ -106,8 +114,12 @@ layout(set = 0, binding = 2, rgba32f) uniform image2D images[]; layout(push_constant) uniform buffers { scene_metadata scene; - primitives_array geometry; nodes_array bvh; + indices_array indices_arr; + positions_array positions_arr; + normals_array normals_arr; + uvs_array uvs_arr; + materials_array materials_arr; uint output_image_index; uint accumulation_image_index; uint padding[2]; @@ -128,12 +140,36 @@ vec3 ray_color(ray r, uint seed) { - // TODO: Interpolation function - triangle tri = bufs.geometry.triangles[info.id]; + // TODO: Interpolation function & indices decoding function + uint id1 = bufs.indices_arr.indices[info.id * 3] & 0x00ffffff; + uint id2 = bufs.indices_arr.indices[info.id * 3 + 1] & 0x00ffffff; + uint id3 = bufs.indices_arr.indices[info.id * 3 + 2] & 0x00ffffff; + uint mat_id = (bufs.indices_arr.indices[info.id * 3] & 0xff000000) >> 8 + | (bufs.indices_arr.indices[info.id * 3 + 1] & 0xff000000) >> 16 + | (bufs.indices_arr.indices[info.id * 3 + 2] & 0xff000000) >> 24; + + vec3 p1 = vec3(bufs.positions_arr.positions[id1 * 3], bufs.positions_arr.positions[id1 * 3 + 1], bufs.positions_arr.positions[id1 * 3 + 2]); + vec3 p2 = vec3(bufs.positions_arr.positions[id2 * 3], bufs.positions_arr.positions[id2 * 3 + 1], bufs.positions_arr.positions[id2 * 3 + 2]); + vec3 p3 = vec3(bufs.positions_arr.positions[id3 * 3], bufs.positions_arr.positions[id3 * 3 + 1], bufs.positions_arr.positions[id3 * 3 + 2]); + + vec3 n1 = vec3(bufs.normals_arr.normals[id1 * 3], bufs.normals_arr.normals[id1 * 3 + 1], bufs.normals_arr.normals[id1 * 3 + 2]); + vec3 n2 = vec3(bufs.normals_arr.normals[id2 * 3], bufs.normals_arr.normals[id2 * 3 + 1], bufs.normals_arr.normals[id2 * 3 + 2]); + vec3 n3 = vec3(bufs.normals_arr.normals[id3 * 3], bufs.normals_arr.normals[id3 * 3 + 1], bufs.normals_arr.normals[id3 * 3 + 2]); + + vec2 uv1 = vec2(bufs.uvs_arr.uvs[id1 * 2], bufs.uvs_arr.uvs[id1 * 2 + 1]); + vec2 uv2 = vec2(bufs.uvs_arr.uvs[id2 * 2], bufs.uvs_arr.uvs[id2 * 2 + 1]); + vec2 uv3 = vec2(bufs.uvs_arr.uvs[id3 * 2], bufs.uvs_arr.uvs[id3 * 2 + 1]); + + vertex v1 = vertex(p1, n1, uv1); + vertex v2 = vertex(p2, n2, uv2); + vertex v3 = vertex(p3, n3, uv3); + + triangle tri = triangle(v1, v2, v3); + info.shading_normal = normalize(tri.v1.normal * info.barycentrics.x + tri.v2.normal * info.barycentrics.y + tri.v3.normal * info.barycentrics.z); info.uv = tri.v1.uv * info.barycentrics.x + tri.v2.uv * info.barycentrics.y + tri.v3.uv * info.barycentrics.z; - material mat = tri.mat; + material mat = bufs.materials_arr.materials[mat_id]; info.color = srgb_to_linear(texture( sampler2D( textures[nonuniformEXT(mat.base_color_texture.texture_id)], @@ -149,12 +185,13 @@ vec3 ray_color(ray r, uint seed) { + if (dot(info.geometry_normal, v) < 0.f) info.geometry_normal = -info.geometry_normal; if (dot(info.geometry_normal, info.shading_normal) < 0.0f) info.shading_normal = -info.shading_normal; uint brdf_type; - if (mat.metalness == 1.f && mat.metalness == 0.f) { + if (info.metalness_roughness.x == 1.f && info.metalness_roughness.y == 0.f) { brdf_type = SPECULAR; } else { float brdf_probability = get_brdf_probability(info.color, info.metalness_roughness.x, -r.direction, info.shading_normal); diff --git a/shaders/include/brdf.h b/shaders/include/brdf.h new file mode 100644 index 0000000..cafe289 --- /dev/null +++ b/shaders/include/brdf.h @@ -0,0 +1,99 @@ +// Specifies minimal reflectance for dielectrics (when metalness is zero) +// Nothing has lower reflectance than 2%, but we use 4% to have consistent results with UE4, Frostbite, et al. +#define MIN_DIELECTRICS_F0 0.04f + +const uint DIFFUSE = 1; +const uint SPECULAR = 2; + +// Samples a microfacet normal for the GGX distribution using VNDF method. +// Source: "Sampling the GGX Distribution of Visible Normals" by Heitz +// See also https://hal.inria.fr/hal-00996995v1/document and http://jcgt.org/published/0007/04/01/ +// Random variables 'u' must be in <0;1) interval +// PDF is 'G1(NdotV) * D' +vec3 sample_GGXVNDF(vec3 Ve, vec2 alpha2D, uint seed) { + // Section 3.2: transforming the view direction to the hemisphere configuration + vec3 Vh = normalize(vec3(alpha2D.x * Ve.x, alpha2D.y * Ve.y, Ve.z)); + + // Section 4.1: orthonormal basis (with special case if cross product is zero) + float lensq = Vh.x * Vh.x + Vh.y * Vh.y; + vec3 T1 = lensq > 0.0f ? vec3(-Vh.y, Vh.x, 0.0f) * inversesqrt(lensq) : vec3(1.0f, 0.0f, 0.0f); + vec3 T2 = cross(Vh, T1); + + // Section 4.2: parameterization of the projected area + float r = sqrt(rand(seed)); + float phi = TWO_PI * rand(seed); + float t1 = r * cos(phi); + float t2 = r * sin(phi); + float s = 0.5f * (1.0f + Vh.z); + t2 = mix(sqrt(1.0f - t1 * t1), t2, s); + + // Section 4.3: reprojection onto hemisphere + vec3 Nh = t1 * T1 + t2 * T2 + sqrt(max(0.0f, 1.0f - t1 * t1 - t2 * t2)) * Vh; + + // Section 3.4: transforming the normal back to the ellipsoid configuration + return normalize(vec3(alpha2D.x * Nh.x, alpha2D.y * Nh.y, max(0.0f, Nh.z))); +} + +// Smith G1 term (masking function) further optimized for GGX distribution (by substituting G_a into G1_GGX) +float Smith_G1_GGX(float alpha, float NdotS, float alpha_squared, float NdotS_squared) { + return 2.0f / (sqrt(((alpha_squared * (1.0f - NdotS_squared)) + NdotS_squared) / NdotS_squared) + 1.0f); +} + +// Weight for the reflection ray sampled from GGX distribution using VNDF method +float specular_sample_weight_GGXVNDF(float alpha, float alpha_squared, float NdotL, float NdotV, float HdotL, float NdotH) { +#if USE_HEIGHT_CORRELATED_G2 + return Smith_G2_Over_G1_Height_Correlated(alpha, alpha_squared, NdotL, NdotV); +#else + return Smith_G1_GGX(alpha, NdotL, alpha_squared, NdotL * NdotL); +#endif +} + +vec3 base_color_to_specular_F0(vec3 base_color, float metalness) { + return mix(vec3(MIN_DIELECTRICS_F0), base_color, metalness); +} + +vec3 base_color_to_diffuse_reflectance(vec3 base_color, float metalness) { + return base_color * (1.0f - metalness); +} + +// Schlick's approximation to Fresnel term +// f90 should be 1.0, except for the trick used by Schuler (see 'shadowed_F90' function) +vec3 eval_fresnel_schlick(vec3 f0, float f90, float NdotS) { + return f0 + (f90 - f0) * pow(1.0f - NdotS, 5.0f); +} + +vec3 eval_fresnel(vec3 f0, float f90, float NdotS) { + // Default is Schlick's approximation + return eval_fresnel_schlick(f0, f90, NdotS); +} + +// Attenuates F90 for very low F0 values +// Source: "An efficient and Physically Plausible Real-Time Shading Model" in ShaderX7 by Schuler +// Also see section "Overbright highlights" in Hoffman's 2010 "Crafting Physically Motivated Shading Models for Game Development" for discussion +// IMPORTANT: Note that when F0 is calculated using metalness, it's value is never less than MIN_DIELECTRICS_F0, and therefore, +// this adjustment has no effect. To be effective, F0 must be authored separately, or calculated in different way. See main text for discussion. +float shadowed_F90(vec3 F0) { + // This scaler value is somewhat arbitrary, Schuler used 60 in his article. In here, we derive it from MIN_DIELECTRICS_F0 so + // that it takes effect for any reflectance lower than least reflective dielectrics + //const float t = 60.0f; + const float t = (1.f / MIN_DIELECTRICS_F0); + return min(1.f, t * luminance(F0)); +} + +float get_brdf_probability(vec3 color, float metalness, vec3 view, vec3 shading_normal) { + // Evaluate Fresnel term using the shading normal + // Note: we use the shading normal instead of the microfacet normal (half-vector) for Fresnel term here. That's suboptimal for rough surfaces at grazing angles, but half-vector is yet unknown at this point + vec3 specular_F0 = vec3(luminance(base_color_to_specular_F0(color, metalness))); + float diffuse_reflectance = luminance(base_color_to_diffuse_reflectance(color, metalness)); + float fresnel = clamp(luminance(eval_fresnel(specular_F0, shadowed_F90(specular_F0), max(0.0f, dot(view, shading_normal)))), 0.0, 1.0); + + // Approximate relative contribution of BRDFs using the Fresnel term + float specular = fresnel; + float diffuse = diffuse_reflectance * (1.0f - fresnel); //< If diffuse term is weighted by Fresnel, apply it here as well + + // Return probability of selecting specular BRDF over diffuse BRDF + float p = (specular / max(0.0001f, (specular + diffuse))); + + // Clamp probability to avoid undersampling of less prominent BRDF + return clamp(p, 0.1f, 0.9f); +} diff --git a/shaders/include/color_utils.h b/shaders/include/color_utils.h new file mode 100644 index 0000000..11c2d9e --- /dev/null +++ b/shaders/include/color_utils.h @@ -0,0 +1,26 @@ +vec3 linear_to_srgb(vec3 color) +{ + color = clamp(color, 0.0f, 1.0f); + + return mix( + pow(color, vec3(1.0f / 2.4f)) * 1.055f - 0.055f, + color * 12.92f, + less_than(color, 0.0031308f) + ); +} + +vec3 srgb_to_linear(vec3 color) +{ + color = clamp(color, 0.0f, 1.0f); + + return mix( + pow(((color + 0.055f) / 1.055f), vec3(2.4f)), + color / 12.92f, + less_than(color, 0.04045f) + ); +} + +float luminance(vec3 rgb) +{ + return dot(rgb, vec3(0.2126f, 0.7152f, 0.0722f)); +} diff --git a/shaders/include/math.h b/shaders/include/math.h new file mode 100644 index 0000000..cc4e2f4 --- /dev/null +++ b/shaders/include/math.h @@ -0,0 +1,45 @@ +const float PI = 3.141592653589793f; +const float TWO_PI = PI * 2.0f; + +vec3 less_than(vec3 vec, float value) +{ + return vec3( + (vec.x < value) ? 1.0f : 0.0f, + (vec.y < value) ? 1.0f : 0.0f, + (vec.z < value) ? 1.0f : 0.0f); +} + +vec3 sample_hemisphere(vec2 randoms) { + float radius = sqrt(randoms[0]); + float theta = 2.0 * PI * randoms[1]; + + return vec3(cos(theta) * radius, sin(theta) * radius, sqrt(1 - randoms[0])); +} + +vec2 disk_vec(vec2 randoms) { + float z = randoms[0] * 2.0 - 1.0; + float a = 2.0 * PI * randoms[1]; + float r = sqrt(1.0 - z * z); + + return vec2(cos(a) * r, sin(a) * r); +} + +// Calculates rotation quaternion from axis vector to the vector (0, 0, 1) +// Input vector must be normalized! +vec4 rotation_to_z_axis(vec3 axis) { + // Handle special case when axis is exact or near opposite of (0, 0, 1) + if (axis.z < -0.99999f) return vec4(1.0f, 0.0f, 0.0f, 0.0f); + + return normalize(vec4(axis.y, -axis.x, 0.0f, 1.0f + axis.z)); +} + +vec4 invert_rotation(vec4 q) { + return vec4(-q.xyz, q.w); +} + +// Optimized point rotation using quaternion +// Source: https://gamedev.stackexchange.com/questions/28395/rotating-vector3-by-a-quaternion +vec3 rotate_point(vec4 q, vec3 v) { + const vec3 q_axis = q.xyz; + return 2.0f * dot(q_axis, v) * q_axis + (q.w * q.w - dot(q_axis, q_axis)) * v + 2.0f * q.w * cross(q_axis, v); +} diff --git a/shaders/include/rand.h b/shaders/include/rand.h new file mode 100644 index 0000000..e1f8b27 --- /dev/null +++ b/shaders/include/rand.h @@ -0,0 +1,12 @@ +uint pcg_hash(inout uint seed) +{ + uint state = seed; + seed *= 747796405u + 2891336453u; + uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + return (word >> 22u) ^ word; +} + +float rand(inout uint seed) +{ + return float(pcg_hash(seed)) / 4294967296.0; +} diff --git a/shaders/include/ray.h b/shaders/include/ray.h new file mode 100644 index 0000000..38e5c16 --- /dev/null +++ b/shaders/include/ray.h @@ -0,0 +1,155 @@ +struct ray { + vec3 origin; + vec3 direction; + float min_t; + float max_t; +}; + +vec3 at(ray r, float t) { + return r.origin + r.direction * t; +} + +struct hit_info { + vec3 point; + vec3 barycentrics; + vec3 geometry_normal; + vec3 shading_normal; + vec3 color; + vec2 metalness_roughness; + vec2 uv; + float t; + uint id; +}; + +bool hit_aabb(vec3 minimum, vec3 maximum, ray r) { + const vec3 invdir = 1.0 / r.direction; + const vec3 f = (maximum.xyz - r.origin.xyz) * invdir; + const vec3 n = (minimum.xyz - r.origin.xyz) * invdir; + + const vec3 tmax = max(f, n); + const vec3 tmin = min(f, n); + + const float t1 = min(min(tmax.x, min(tmax.y, tmax.z)), r.max_t); + const float t0 = max(max(max(tmin.x, max(tmin.y, tmin.z)), r.min_t), 0.0f); + + return t1 >= t0; +} + +uint hit_aabbs(ray r) { + uint hit_count = 0; + int id = 0; + + while(id != -1) { + if (bufs.bvh.nodes[id].primitive_id != -1) { + // triangle tri = bufs.geometry.triangles[bufs.bvh.nodes[id].primitive_id]; + // vec3 minimum = min(tri.v1.position, min(tri.v2.position, tri.v3.position)).xyz; + // vec3 maximum = max(tri.v1.position, max(tri.v2.position, tri.v3.position)).xyz; + + // if (hit_aabb(minimum, maximum, r)) { + // hit_count++; + // } + id = bufs.bvh.nodes[id].next_id; + } else if (hit_aabb(bufs.bvh.nodes[id].min, bufs.bvh.nodes[id].max, r)) { + hit_count++; + id++; + } else { + id = bufs.bvh.nodes[id].next_id; + } + } + + return hit_count; +} + +bool hit_sphere(sphere s, ray r, out hit_info info) { + vec3 origin_center = r.origin - s.position.xyz; + + float a = dot(r.direction, r.direction); + float half_b = dot(r.direction, origin_center); + float c = dot(origin_center, origin_center) - s.radius * s.radius; + float discriminant = half_b * half_b - a * c; + + if (discriminant < 0) { + return false; + } + + float sqrt_discriminant = sqrt(discriminant); + float root = (-half_b - sqrt_discriminant) / a; + if (root < r.min_t || root > r.max_t) { + root = (-half_b + sqrt_discriminant) / a; + + if (root < r.min_t || root > r.max_t) { + return false; + } + } + + info.t = root; + // info.point = at(r, info.t); + + // vec3 outward_normal = (info.point - s.position.xyz) / s.radius; + // bool front_face = dot(outward_normal, r.direction) < 0.0; + // info.normal = front_face ? outward_normal : -outward_normal; + + return true; +} + +bool hit_triangle(uint id, ray r, out hit_info info) { + uint id1 = bufs.indices_arr.indices[id * 3] & 0x00ffffff; + uint id2 = bufs.indices_arr.indices[id * 3 + 1] & 0x00ffffff; + uint id3 = bufs.indices_arr.indices[id * 3 + 2] & 0x00ffffff; + + vec3 p1 = vec3(bufs.positions_arr.positions[id1 * 3], bufs.positions_arr.positions[id1 * 3 + 1], bufs.positions_arr.positions[id1 * 3 + 2]); + vec3 p2 = vec3(bufs.positions_arr.positions[id2 * 3], bufs.positions_arr.positions[id2 * 3 + 1], bufs.positions_arr.positions[id2 * 3 + 2]); + vec3 p3 = vec3(bufs.positions_arr.positions[id3 * 3], bufs.positions_arr.positions[id3 * 3 + 1], bufs.positions_arr.positions[id3 * 3 + 2]); + + vec3 v2v1 = p2 - p1; + vec3 v3v1 = p3 - p1; + + vec3 originv1 = r.origin - p1; + vec3 normal = cross(v2v1, v3v1); + vec3 q = cross(originv1, r.direction); + float d = 1.0 / dot(r.direction, normal); + float u = d * dot(-q, v3v1); + float v = d * dot(q, v2v1); + float t = d * dot(-normal, originv1); + + if (u < 0.0 || u > 1.0 || v < 0.0 || u + v > 1.0 || t < r.min_t || t > r.max_t) { + return false; + } + + info.t = t; + info.barycentrics = vec3(1 - u - v, u, v); + info.geometry_normal = normalize(normal); + info.id = id; + + return true; +} + +bool hit_node(ray r, out hit_info info) { + hit_info temp_info; + bool hit = false; + int id = 0; + + while(id != -1) { + // Leafs + if (bufs.bvh.nodes[id].primitive_id != -1) { + // if (hit_sphere(bufs.geometry.spheres[bufs.bvh.nodes[id].primitive_id], r, temp_info)) { + // info = temp_info; + // r.max_t = temp_info.t; + // hit = true; + // } + if (hit_triangle(bufs.bvh.nodes[id].primitive_id, r, temp_info)) { + info = temp_info; + r.max_t = temp_info.t; + hit = true; + } + id = bufs.bvh.nodes[id].next_id; + } else if (hit_aabb(bufs.bvh.nodes[id].min, bufs.bvh.nodes[id].max, r)) { + id++; + } else { + id = bufs.bvh.nodes[id].next_id; + } + } + + info.point = at(r, info.t); + return hit; +} diff --git a/shaders/tonemapping.comp b/shaders/tonemapping.comp index 660327d..35a7a13 100644 --- a/shaders/tonemapping.comp +++ b/shaders/tonemapping.comp @@ -12,8 +12,8 @@ layout(set = 0, binding = 2, rgba32f) uniform image2D images[]; layout(push_constant) uniform constants { scene_metadata scene; - uint output_image_index; - uint accumulation_image_index; + layout(offset = 56) uint output_image_index; + layout(offset = 60) uint accumulation_image_index; } consts; void main() { diff --git a/shaders/ui.frag b/shaders/ui.frag index c4e0150..dd0fdd4 100644 --- a/shaders/ui.frag +++ b/shaders/ui.frag @@ -11,7 +11,7 @@ layout(set = 0, binding = 0) uniform sampler samplers[]; layout(set = 0, binding = 1) uniform texture2D textures[]; layout(push_constant) uniform constants { - layout(offset = 56) uint texture_index; + layout(offset = 96) uint texture_index; uint sampler_index; } consts; diff --git a/shaders/ui.vert b/shaders/ui.vert index dd71ef6..a9f0670 100644 --- a/shaders/ui.vert +++ b/shaders/ui.vert @@ -12,7 +12,7 @@ layout(buffer_reference) readonly buffer vertices { }; layout(push_constant) uniform constants { - layout(offset = 32) vertices vertex_buffer; + layout(offset = 64) vertices vertex_buffer; vec2 scale; vec2 translate; } consts; diff --git a/src/gltf.cpp b/src/gltf.cpp index bfd7522..61c68ac 100644 --- a/src/gltf.cpp +++ b/src/gltf.cpp @@ -8,8 +8,6 @@ #include "utils.hpp" -const vec3 scale (0.00800000037997961); - node gltf::load(std::filesystem::path &path, std::string &filename, vkrenderer &renderer) { std::fstream f(path / filename); json gltf_json; @@ -73,7 +71,10 @@ std::vector gltf::load_meshes(json &gltf_json, std::vector()]; + part.vertices_count = part.positions.size() / 3; + part.triangles_count = part.indices.size() / 3; return std::move(part); } diff --git a/src/main.cpp b/src/main.cpp index 287b0eb..06c351c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,17 +63,14 @@ int main() { vkrenderer renderer { wnd }; auto main_scene = scene(cam, width, height, renderer); - // vkrenderer renderer { wnd, sizeof(main_scene.meta), sizeof(main_scene.spheres[0]) * main_scene.spheres.size(), sizeof(main_scene.packed_nodes[0]) * main_scene.packed_nodes.size() }; - renderer.create_scene_buffer(sizeof(main_scene.meta)); - renderer.create_geometry_buffer(sizeof(main_scene.triangles[0]) * main_scene.triangles.size()); - renderer.create_bvh_buffer(sizeof(main_scene.packed_nodes[0]) * main_scene.packed_nodes.size()); - - // Upload scene content - std::memcpy(renderer.scene_buffer_ptr(), &main_scene.meta, sizeof(main_scene.meta)); - renderer.update_geometry_buffer(main_scene.triangles.data()); - // renderer.update_geometry_buffer(main_scene.spheres.data()); - renderer.update_bvh_buffer(main_scene.packed_nodes.data()); + renderer.scene_buffer_addr = main_scene.scene_buffer.device_address; + renderer.indices_buffer_addr = main_scene.indices_buffer.device_address; + renderer.positions_buffer_addr = main_scene.positions_buffer.device_address; + renderer.normals_buffer_addr = main_scene.normals_buffer.device_address; + renderer.uvs_buffer_addr = main_scene.uvs_buffer.device_address; + renderer.materials_buffer_addr = main_scene.materials_buffer.device_address; + renderer.bvh_buffer_addr = main_scene.bvh_buffer.device_address; auto can_render = true; @@ -101,8 +98,8 @@ int main() { width = event.width; height = event.height; - ((scene*) renderer.scene_buffer_ptr())->meta.width = width; - ((scene*) renderer.scene_buffer_ptr())->meta.height = height; + ((scene*) main_scene.scene_buffer_ptr())->meta.width = width; + ((scene*) main_scene.scene_buffer_ptr())->meta.height = height; io.DisplaySize.x = (float)width; io.DisplaySize.y = (float)height; @@ -112,8 +109,8 @@ int main() { } else { can_render = true; renderer.recreate_swapchain(); - ((scene*) renderer.scene_buffer_ptr())->meta.cam.set_aspect_ratio((float)event.width / (float)event.height); - ((scene*) renderer.scene_buffer_ptr())->meta.sample_index = 0; + ((scene*) main_scene.scene_buffer_ptr())->meta.cam.set_aspect_ratio((float)event.width / (float)event.height); + ((scene*) main_scene.scene_buffer_ptr())->meta.sample_index = 0; } reset_accumulation = true; @@ -121,7 +118,7 @@ int main() { break; } case EVENT_TYPES::KEY_PRESS: { - auto move_speed = 0.01f * delta_time; + auto move_speed = 1.f * delta_time; if (wnd.keyboard[KEYS::LSHIFT] || wnd.keyboard[KEYS::RSHIFT]) { move_speed *= 10.f; } @@ -130,44 +127,44 @@ int main() { switch (event.key) { case KEYS::W: { - move_vec = ((scene*) renderer.scene_buffer_ptr())->meta.cam.forward * move_speed; + move_vec = ((scene*) main_scene.scene_buffer_ptr())->meta.cam.forward * move_speed; break; } case KEYS::S: { - move_vec = -((scene*) renderer.scene_buffer_ptr())->meta.cam.forward * move_speed; + move_vec = -((scene*) main_scene.scene_buffer_ptr())->meta.cam.forward * move_speed; break; } case KEYS::D: { - move_vec = ((scene*) renderer.scene_buffer_ptr())->meta.cam.right * move_speed; + move_vec = ((scene*) main_scene.scene_buffer_ptr())->meta.cam.right * move_speed; break; } case KEYS::A: { - move_vec = -((scene*) renderer.scene_buffer_ptr())->meta.cam.right * move_speed; + move_vec = -((scene*) main_scene.scene_buffer_ptr())->meta.cam.right * move_speed; break; } case KEYS::E: { - ((scene*) renderer.scene_buffer_ptr())->meta.cam.rotate_y(0.001f * delta_time); + ((scene*) main_scene.scene_buffer_ptr())->meta.cam.rotate_y(0.001f * delta_time); reset_accumulation = true; break; } case KEYS::Q: { - ((scene*) renderer.scene_buffer_ptr())->meta.cam.rotate_y(-0.001f * delta_time); + ((scene*) main_scene.scene_buffer_ptr())->meta.cam.rotate_y(-0.001f * delta_time); reset_accumulation = true; break; } case KEYS::SPACE: { - move_vec = ((scene*) renderer.scene_buffer_ptr())->meta.cam.up * move_speed; + move_vec = ((scene*) main_scene.scene_buffer_ptr())->meta.cam.up * move_speed; break; } case KEYS::LCTRL: { - move_vec = -((scene*) renderer.scene_buffer_ptr())->meta.cam.up * move_speed; + move_vec = -((scene*) main_scene.scene_buffer_ptr())->meta.cam.up * move_speed; break; } default: break; } - ((scene*) renderer.scene_buffer_ptr())->meta.cam.move(move_vec); + ((scene*) main_scene.scene_buffer_ptr())->meta.cam.move(move_vec); if (!move_vec.near_zero()) { reset_accumulation = true; @@ -216,19 +213,19 @@ int main() { ImGui::Text("frame per second %u\n", static_cast(1000.f / delta_time)); ImGui::Text("frame time %f ms\n", delta_time); - ImGui::Text("frame count %u\n", ((scene*) renderer.scene_buffer_ptr())->meta.sample_index); + ImGui::Text("frame count %u\n", ((scene*) main_scene.scene_buffer_ptr())->meta.sample_index); - if (ImGui::Checkbox("depth of field", (bool*)&((scene*) renderer.scene_buffer_ptr())->meta.enable_dof)) { + if (ImGui::Checkbox("depth of field", (bool*)&((scene*) main_scene.scene_buffer_ptr())->meta.enable_dof)) { reset_accumulation = true; } - ImGui::SliderInt("max bounces", (int32_t*)&((scene*) renderer.scene_buffer_ptr())->meta.max_bounce, 1, 250); - ImGui::SliderInt("min bounces", (int32_t*)&((scene*) renderer.scene_buffer_ptr())->meta.min_bounce, 1, ((scene*) renderer.scene_buffer_ptr())->meta.max_bounce); - if (ImGui::SliderInt("downscale factor", (int32_t*)&((scene*) renderer.scene_buffer_ptr())->meta.downscale_factor, 1, 32)) { + ImGui::SliderInt("max bounces", (int32_t*)&((scene*) main_scene.scene_buffer_ptr())->meta.max_bounce, 1, 250); + ImGui::SliderInt("min bounces", (int32_t*)&((scene*) main_scene.scene_buffer_ptr())->meta.min_bounce, 1, ((scene*) main_scene.scene_buffer_ptr())->meta.max_bounce); + if (ImGui::SliderInt("downscale factor", (int32_t*)&((scene*) main_scene.scene_buffer_ptr())->meta.downscale_factor, 1, 32)) { reset_accumulation = true; } - if (ImGui::Checkbox("debug bvh", (bool*)&((scene*) renderer.scene_buffer_ptr())->meta.debug_bvh)) { + if (ImGui::Checkbox("debug bvh", (bool*)&((scene*) main_scene.scene_buffer_ptr())->meta.debug_bvh)) { reset_accumulation = true; } @@ -246,14 +243,14 @@ int main() { renderer.begin_frame(); if (reset_accumulation) { - ((scene*) renderer.scene_buffer_ptr())->meta.sample_index = 0; + ((scene*) main_scene.scene_buffer_ptr())->meta.sample_index = 0; renderer.reset_accumulation(); } - float scale = (float)((scene*) renderer.scene_buffer_ptr())->meta.downscale_factor; + float scale = (float)((scene*) main_scene.scene_buffer_ptr())->meta.downscale_factor; renderer.compute(width / scale, height / scale); - ((scene*) renderer.scene_buffer_ptr())->meta.sample_index++; + ((scene*) main_scene.scene_buffer_ptr())->meta.sample_index++; renderer.ui(); diff --git a/src/scene.cpp b/src/scene.cpp index d162b3a..9caed7b 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -66,6 +66,9 @@ scene::scene(camera cam, uint32_t width, uint32_t height, vkrenderer &renderer) // auto sponza_filename = std::string("Sponza.gltf"); // auto root_node = gltf::load(sponza_path, sponza_filename, renderer); + std::vector triangles; + auto triangles_offset = 0; + auto vertices_offset = 0; std::queue nodes_to_load {}; nodes_to_load.push(root_node); @@ -74,18 +77,37 @@ scene::scene(camera cam, uint32_t width, uint32_t height, vkrenderer &renderer) if (node.mesh) { auto &mesh = node.mesh.value(); + + indices.resize(indices.size() + mesh.triangles_count * 3); + positions.resize(positions.size() + mesh.vertices_count * 3); + normals.resize(normals.size() + mesh.vertices_count * 3); + uvs.resize(uvs.size() + mesh.vertices_count * 2); + + for (auto& mesh_part: mesh.parts) { + std::memcpy(positions.data() + vertices_offset * 3, mesh_part.positions.data(), mesh_part.positions.size() * sizeof(float)); + std::memcpy(normals.data() + vertices_offset * 3, mesh_part.normals.data(), mesh_part.normals.size() * sizeof(float)); + std::memcpy(uvs.data() + vertices_offset * 2, mesh_part.uvs.data(), mesh_part.uvs.size() * sizeof(float)); + for (size_t i = 0; i < mesh_part.indices.size(); i += 3) { auto i1 = mesh_part.indices[i]; auto i2 = mesh_part.indices[i + 1]; auto i3 = mesh_part.indices[i + 2]; - auto v1 = vertex { .position = mesh_part.positions[i1], .normal = mesh_part.normals[i1], .uv = mesh_part.uvs[i1] }; - auto v2 = vertex { .position = mesh_part.positions[i2], .normal = mesh_part.normals[i2], .uv = mesh_part.uvs[i2] }; - auto v3 = vertex { .position = mesh_part.positions[i3], .normal = mesh_part.normals[i3], .uv = mesh_part.uvs[i3] }; + auto p1 = vec3(mesh_part.positions[i1 * 3], mesh_part.positions[i1 * 3 + 1], mesh_part.positions[i1 * 3 + 2]); + auto p2 = vec3(mesh_part.positions[i2 * 3], mesh_part.positions[i2 * 3 + 1], mesh_part.positions[i2 * 3 + 2]); + auto p3 = vec3(mesh_part.positions[i3 * 3], mesh_part.positions[i3 * 3 + 1], mesh_part.positions[i3 * 3 + 2]); - triangles.emplace_back(v1, v2, v3, mesh_part.mat); + indices[triangles_offset * 3 + i] = (i1 + vertices_offset) | (0xff000000 & (materials.size() << 8)); + indices[triangles_offset * 3 + i + 1] = (i2 + vertices_offset) | (0xff000000 & (materials.size() << 16)); + indices[triangles_offset * 3 + i + 2] = (i3 + vertices_offset) | (0xff000000 & (materials.size() << 24)); + + triangles.emplace_back(p1, p2, p3); + materials.push_back(mesh_part.mat); } + + triangles_offset += mesh_part.triangles_count; + vertices_offset += mesh_part.vertices_count; } } @@ -100,4 +122,25 @@ scene::scene(camera cam, uint32_t width, uint32_t height, vkrenderer &renderer) bvh builder(triangles, packed_nodes); // bvh builder(spheres, packed_nodes); + + scene_buffer = renderer.api.create_buffer(sizeof(meta), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + std::memcpy(scene_buffer.alloc_info.pMappedData, &meta, sizeof(meta)); + + indices_buffer = renderer.api.create_buffer(indices.size() * sizeof(indices[0]), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + std::memcpy(indices_buffer.alloc_info.pMappedData, indices.data(), indices.size() * sizeof(indices[0])); + + positions_buffer = renderer.api.create_buffer(positions.size() * sizeof(positions[0]), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + std::memcpy(positions_buffer.alloc_info.pMappedData, positions.data(), positions.size() * sizeof(positions[0])); + + normals_buffer = renderer.api.create_buffer(normals.size() * sizeof(normals[0]), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + std::memcpy(normals_buffer.alloc_info.pMappedData, normals.data(), normals.size() * sizeof(normals[0])); + + uvs_buffer = renderer.api.create_buffer(uvs.size() * sizeof(uvs[0]), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + std::memcpy(uvs_buffer.alloc_info.pMappedData, uvs.data(), uvs.size() * sizeof(uvs[0])); + + bvh_buffer = renderer.api.create_buffer(packed_nodes.size() * sizeof(packed_nodes[0]), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + std::memcpy(bvh_buffer.alloc_info.pMappedData, packed_nodes.data(), packed_nodes.size() * sizeof(packed_nodes[0])); + + materials_buffer = renderer.api.create_buffer(materials.size() * sizeof(materials[0]), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + std::memcpy(materials_buffer.alloc_info.pMappedData, materials.data(), materials.size() * sizeof(materials[0])); } diff --git a/src/vk-api.cpp b/src/vk-api.cpp index efcd073..3391246 100644 --- a/src/vk-api.cpp +++ b/src/vk-api.cpp @@ -98,17 +98,17 @@ vkapi::vkapi() { { .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, .offset = 0, - .size = 32, + .size = 64, }, { .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - .offset = 32, - .size = 24, + .offset = 64, + .size = 32, }, { .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - .offset = 56, - .size = 8, + .offset = 96, + .size = 32, }, }; @@ -159,13 +159,13 @@ Buffer vkapi::create_buffer(size_t data_size, VkBufferUsageFlags buffer_usage, V VKRESULT(vmaCreateBuffer(context.allocator, &buffer_info, &alloc_create_info, &buffer.handle, &buffer.alloc, &buffer.alloc_info)) - buffer.size = data_size; - VkBufferDeviceAddressInfo buffer_device_address_info = {}; buffer_device_address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; buffer_device_address_info.pNext = VK_NULL_HANDLE; buffer_device_address_info.buffer = buffer.handle; + buffer.size = data_size; + buffer.device_address = vkGetBufferDeviceAddress(context.device, &buffer_device_address_info); return std::move(buffer); diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp index 4ac1cd0..ba5f017 100644 --- a/src/vk-renderer.cpp +++ b/src/vk-renderer.cpp @@ -143,9 +143,6 @@ vkrenderer::vkrenderer(window& wnd) { vkrenderer::~vkrenderer() { VKRESULT(vkWaitForFences(api.context.device, submission_fences.size(), submission_fences.data(), VK_TRUE, UINT64_MAX)) - api.destroy_buffer(scene_buffer); - api.destroy_buffer(geometry_buffer); - api.destroy_buffer(bvh_buffer); api.destroy_buffer(staging_buffer); api.destroy_fences(submission_fences); api.destroy_semaphores(execution_semaphores); @@ -267,12 +264,12 @@ void vkrenderer::ui() { -1.f - draw_data->DisplayPos.x * (2.f / draw_data->DisplaySize.x), -1.f - draw_data->DisplayPos.y * (2.f / draw_data->DisplaySize.y), }; - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 32, 8, (void*)&ui_vertex_buffers[virtual_frame_index].device_address); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 40, 8, (void*)&scale); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 48, 8, (void*)&translate); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 64, 8, (void*)&ui_vertex_buffers[virtual_frame_index].device_address); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 72, 8, (void*)&scale); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 80, 8, (void*)&translate); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 56, 4, (void*)&ui_texture.bindless_sampled_index); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 60, 4, (void*)&ui_texture_sampler.bindless_index); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 96, 4, (void*)&ui_texture.bindless_sampled_index); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 100, 4, (void*)&ui_texture_sampler.bindless_index); off_t vertex_buffer_offset = 0; off_t index_buffer_offset = 0; @@ -304,19 +301,23 @@ void vkrenderer::ui() { void vkrenderer::compute(uint32_t width, uint32_t height) { auto cmd_buf = command_buffers[virtual_frame_index]; - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 8, (void*)&scene_buffer.device_address); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 8, 8, (void*)&geometry_buffer.device_address); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 16, 8, (void*)&bvh_buffer.device_address); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 24, 4, (void*)&accumulation_images[0].bindless_storage_index); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 28, 4, (void*)&accumulation_images[1].bindless_storage_index); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 8, (void*)&scene_buffer_addr); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 8, 8, (void*)&bvh_buffer_addr); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 16, 8, (void*)&indices_buffer_addr); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 24, 8, (void*)&positions_buffer_addr); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 32, 8, (void*)&normals_buffer_addr); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 40, 8, (void*)&uvs_buffer_addr); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 48, 8, (void*)&materials_buffer_addr); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 56, 4, (void*)&accumulation_images[0].bindless_storage_index); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 60, 4, (void*)&accumulation_images[1].bindless_storage_index); api.run_compute_pipeline(cmd_buf, compute_pipeline, (width / 8) + 1, (height / 8) + 1, 1); api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, swapchain.images[swapchain_image_index]); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 8, (void*)&scene_buffer.device_address); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 8, 4, (void*)&swapchain.images[swapchain_image_index].bindless_storage_index); - vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 12, 4, (void*)&accumulation_images[0].bindless_storage_index); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 8, (void*)&scene_buffer_addr); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 56, 4, (void*)&swapchain.images[swapchain_image_index].bindless_storage_index); + vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 60, 4, (void*)&accumulation_images[0].bindless_storage_index); api.run_compute_pipeline(cmd_buf, tonemapping_pipeline, (width / 8) + 1, (height / 8) + 1, 1); } @@ -405,62 +406,6 @@ void vkrenderer::handle_swapchain_result(VkResult function_result) { } } - -void vkrenderer::create_scene_buffer(size_t size) { - scene_buffer = api.create_buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); -} - -void vkrenderer::create_geometry_buffer(size_t size) { - geometry_buffer = api.create_buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); -} - -void vkrenderer::create_bvh_buffer(size_t size) { - bvh_buffer = api.create_buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); -} - -// TODO: Integrate into the API so that we no longer have to wait for the fence -void vkrenderer::update_geometry_buffer(void* data) { - VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX)) - VKRESULT(vkResetFences(api.context.device, 1, &submission_fences[virtual_frame_index])) - - auto cmd_buf = command_buffers[virtual_frame_index]; - api.start_record(cmd_buf); - - auto staging_buffer = api.create_buffer(geometry_buffer.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - std::memcpy(staging_buffer.alloc_info.pMappedData, data, staging_buffer.size); - - api.copy_buffer(cmd_buf, staging_buffer, geometry_buffer, staging_buffer.size); - - api.end_record(cmd_buf); - - api.submit(cmd_buf, VK_NULL_HANDLE, VK_NULL_HANDLE, submission_fences[virtual_frame_index]); - - VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX)) - - api.destroy_buffer(staging_buffer); -} - -void vkrenderer::update_bvh_buffer(void* data) { - VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX)) - VKRESULT(vkResetFences(api.context.device, 1, &submission_fences[virtual_frame_index])) - - auto cmd_buf = command_buffers[virtual_frame_index]; - api.start_record(cmd_buf); - - auto staging_buffer = api.create_buffer(bvh_buffer.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - std::memcpy(staging_buffer.alloc_info.pMappedData, data, staging_buffer.size); - - api.copy_buffer(cmd_buf, staging_buffer, bvh_buffer, staging_buffer.size); - - api.end_record(cmd_buf); - - api.submit(cmd_buf, VK_NULL_HANDLE, VK_NULL_HANDLE, submission_fences[virtual_frame_index]); - - VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX)) - - api.destroy_buffer(staging_buffer); -} - void vkrenderer::update_image(image img, void* data, size_t size) { if (staging_buffer.size < size) { api.destroy_buffer(staging_buffer); -- cgit v1.3