aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bvh.cpp9
-rw-r--r--src/camera.cpp1
-rw-r--r--src/gltf.cpp542
-rw-r--r--src/mesh.cpp4
-rw-r--r--src/scene.cpp160
-rw-r--r--src/utils.cpp92
-rw-r--r--src/vec3.cpp19
-rw-r--r--src/vulkan-loader.cpp4
-rw-r--r--src/window.cpp113
9 files changed, 550 insertions, 394 deletions
diff --git a/src/bvh.cpp b/src/bvh.cpp
index 8e62a93..9362504 100644
--- a/src/bvh.cpp
+++ b/src/bvh.cpp
@@ -1,11 +1,5 @@
#include "bvh.hpp"
-#include <cassert>
-
-#include <algorithm>
-#include <cstdint>
-#include <cstdio>
-
// bvh::bvh(std::vector<sphere>& spheres, std::vector<packed_bvh_node>& packed_nodes)
// :spheres(spheres) {
// packed_nodes.resize(2 * spheres.size() - 1);
@@ -48,6 +42,7 @@
bvh::bvh(std::vector<triangle>& triangles, std::vector<packed_bvh_node>& packed_nodes)
:triangles(triangles) {
+ BEGIN_MARKER(GENERATE_BVH);
assert(!triangles.empty());
packed_nodes.resize(2 * triangles.size() - 1);
@@ -84,6 +79,8 @@ bvh::bvh(std::vector<triangle>& triangles, std::vector<packed_bvh_node>& packed_
node.next_id = temp_nodes[old_node.next_id].df_id;
}
}
+
+ END_MARKER(GENERATE_BVH);
}
//-------------------------
diff --git a/src/camera.cpp b/src/camera.cpp
index 4c63630..8139c5b 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -1,5 +1,4 @@
#include "camera.hpp"
-#include "utils.hpp"
camera::camera(
point3 position,
diff --git a/src/gltf.cpp b/src/gltf.cpp
index 4cdfdce..2ddf16a 100644
--- a/src/gltf.cpp
+++ b/src/gltf.cpp
@@ -1,145 +1,177 @@
#include "gltf.hpp"
-#include <execution>
-#include <fstream>
+using namespace simdjson;
-#ifndef API_TEST
-#define STB_IMAGE_IMPLEMENTATION
-#endif
-#include <stb_image.h>
+ondemand::object root;
-#include "utils.hpp"
-#ifdef API_TEST
-#include "vk-device-types.hpp"
-#include "vk-device.hpp"
-#include "vk-command-buffer.hpp"
-#include <vk_mem_alloc.h>
-#else
-#include "vk-renderer.hpp"
-#endif
+struct accessor {
+ u32 view_index = 0U;
+ u32 count = 0U;
+ u32 component_type = 0U;
+ std::string_view type;
+};
-gltf::gltf(const std::filesystem::path& filepath) {
- auto parent_path = filepath.parent_path();
- std::fstream f{ filepath };
+struct buffer_view {
+ u32 buffer_index = 0U;
+ u32 length = 0U;
+ u32 offset = 0U;
+};
- if (!f.is_open()) {
- OutputDebugStringA("failed to open!");
- }
-
- f >> gltf_json;
+// component types
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
- auto& scene = gltf_json["scenes"][0];
+#define SCALAR 0x5343414C4152
+#define VEC2 0x56454332
+#define VEC3 0x56454333
+#define VEC4 0x56454334
- auto& gltf_buffers = gltf_json["buffers"];
- auto buffer_count = gltf_buffers.size();
- buffers.resize(gltf_buffers.size());
- for (auto buffer_index{ 0U }; buffer_index < buffer_count; buffer_index++) {
- auto buffer_path = parent_path / gltf_buffers[buffer_index]["uri"].get<std::string>();
- buffers[buffer_index] = read_file(buffer_path.string().c_str());
+static u32 accessor_type_to_component_count(std::string_view& type) {
+ if (strncmp("SCALAR", type.data(), type.size()) == 0) {
+ return 1U;
+ } else if (strncmp("VEC2", type.data(), type.size()) == 0) {
+ return 2U;
+ } else if (strncmp("VEC3", type.data(), type.size()) == 0) {
+ return 3U;
+ } else if (strncmp("VEC4", type.data(), type.size()) == 0) {
+ return 4U;
}
+ assert(false);
+ return 0U;
+}
- load_textures(parent_path);
- load_materials();
-
- load_meshes();
-
- auto& root_children = scene["nodes"];
- size_t root_children_count = scene["nodes"].size();
- root_node.children.resize(root_children_count);
-
- for (size_t child_index = 0; child_index < root_children_count; child_index++) {
- load_node(root_children[child_index].get<uint32_t>(), root_node.children[child_index]);
+static u32 component_type_size(u32 type) {
+ switch (type) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ return 1U;
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ return 2U;
+ case GL_FLOAT:
+ case GL_FIXED:
+ return 4U;
+ default: assert(false);
}
-
- f.close();
+ return 0U;
}
-void gltf::load_node(uint32_t index, node& parent) {
- const auto& gltf_node = gltf_json["nodes"][index];
+static Mesh::submesh load_primitive(ondemand::object& primitive, std::vector<struct buffer>& buffers, std::vector<struct accessor>& accessors, std::vector<struct buffer_view>& buffer_views) {
+ Mesh::submesh submesh;
+
+ // indices
+ {
+ u32 indices_id = primitive["indices"].get_uint32();
+ struct accessor& accessor = accessors[indices_id];
- if (gltf_node.contains("children")) {
- const auto& children = gltf_node["children"];
- uint32_t children_count = gltf_node["children"];
- parent.children.resize(children_count);
+ struct buffer_view& view = buffer_views[accessor.view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
- for (size_t child_index = 0; child_index < children_count; child_index++) {
- load_node(children[child_index].get<uint32_t>(), parent.children[child_index]);
- }
- }
+ submesh.indices = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
- if (gltf_node.contains("mesh")) {
- parent.mesh = &meshes[gltf_node["mesh"].get<uint32_t>()];
+ submesh.index_count = accessor.count;
}
-}
-void gltf::load_meshes() {
- const auto& gltf_meshes = gltf_json["meshes"];
- auto meshes_count = gltf_meshes.size();
- meshes.resize(meshes_count);
+ // positions
+ {
+ u32 pos_id = primitive["attributes"]["POSITION"].get_uint32();
+ struct accessor& accessor = accessors[pos_id];
- for (size_t mesh_index = 0; mesh_index < meshes_count; mesh_index++) {
- auto& mesh = meshes[mesh_index];
- const auto& primitives = gltf_meshes[mesh_index]["primitives"];
+ struct buffer_view& view = buffer_views[accessor.view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
- for (const auto& primitive : primitives) {
- auto& material = materials[primitive["material"].get<uint32_t>()];
- mesh.add_submesh(load_primitive(primitive), material);
- }
+ submesh.attributes[ATTRIBUTE_TYPE::POSITION] = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
- Mesh::register_mesh(mesh);
+ submesh.vertex_count = accessor.count;
}
-}
-Mesh::submesh gltf::load_primitive(const json& primitive) {
- Mesh::submesh submesh;
+ u32 normal_index = 0U;
+ if (!primitive["attributes"]["NORMAL"].get(normal_index)) {
+ struct accessor& accessor = accessors[normal_index];
+ u32 view_index = accessor.view_index;
- submesh.indices = load_attribute(primitive["indices"]);
- submesh.attributes[ATTRIBUTE_TYPE::POSITION] = load_attribute(primitive["attributes"]["POSITION"]);
+ struct buffer_view& view = buffer_views[view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
- if (primitive["attributes"].contains("NORMAL")) {
- submesh.attributes[ATTRIBUTE_TYPE::NORMAL] = load_attribute(primitive["attributes"]["NORMAL"]);
+ submesh.attributes[ATTRIBUTE_TYPE::NORMAL] = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
}
- if (primitive["attributes"].contains("TEXCOORD_0")) {
- submesh.attributes[ATTRIBUTE_TYPE::UV_0] = load_attribute(primitive["attributes"]["TEXCOORD_0"]);
- }
+ u32 texcoord_index = 0U;
+ if (!primitive["attributes"]["TEXCOORD_0"].get(texcoord_index)) {
+ struct accessor& accessor = accessors[texcoord_index];
+ u32 view_index = accessor.view_index;
- submesh.index_count = gltf_json["accessors"][primitive["indices"].get<uint32_t>()]["count"].get<uint32_t>();
- submesh.vertex_count = gltf_json["accessors"][primitive["attributes"]["POSITION"].get<uint32_t>()]["count"].get<uint32_t>();
+ struct buffer_view& view = buffer_views[view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
+
+ submesh.attributes[ATTRIBUTE_TYPE::UV_0] = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
+ }
return submesh;
}
-Mesh::attribute gltf::load_attribute(uint32_t accessor_index) {
- auto view_index = gltf_json["accessors"][accessor_index]["bufferView"].get<uint32_t>();
- const auto& view = gltf_json["bufferViews"][view_index];
- auto offset = view["byteOffset"].get<off_t>();
- auto& buffer = buffers[view["buffer"].get<uint32_t>()];
+static void load_textures(char* path, std::vector<handle<device_texture>>& textures, std::vector<struct buffer>& buffers, std::vector<struct buffer_view>& buffer_views, bool is_glb) {
+ ondemand::array gltf_images = root["images"];
+ std::vector<raw_image> images(gltf_images.count_elements());
+ size_t path_len = strlen(path);
+ char path_buffer[2048] = { 0U };
+ strncpy(path_buffer, path, path_len);
+ BEGIN_MARKER(LOAD_TEXTURES);
+ u32 image_index = 0U;
+ for (ondemand::object gltf_image : gltf_images) {
+ if (is_glb) {
+ // TODO: consider mimeType
+ struct buffer_view& view = buffer_views[gltf_image["bufferView"]];
+ struct buffer& buffer = buffers[view.buffer_index];
- return {
- &buffer[offset],
- view["byteLength"].get<size_t>()
- };
-}
+ raw_image& image = images[image_index++];
-void gltf::load_textures(const std::filesystem::path& path) {
- const auto& gltf_images = gltf_json["images"];
- auto images_count = gltf_images.size();
- std::vector<raw_image> images{ images_count };
+ image.data = stbi_load_from_memory(&buffer.bytes[view.offset], view.length, &image.width, &image.height, &image.channels, 4);
- std::vector<size_t> v(images_count);
- std::iota(v.begin(), v.end(), 0);
+ } else {
+ std::string_view uri_view = gltf_image["uri"];
+ strncpy(path_buffer + path_len, uri_view.data(), uri_view.length());
+ path_buffer[path_len + uri_view.length()] = '\0';
- const auto& gltf_textures = gltf_json["textures"];
- auto textures_count = gltf_textures.size();
- textures.resize(textures_count);
+ raw_image& image = images[image_index++];
+ image.data = stbi_load(path_buffer, &image.width, &image.height, &image.channels, 4);
+ }
+ }
+ END_MARKER(LOAD_TEXTURES);
-#ifdef API_TEST
- auto& device = vkdevice::get_render_device();
+ // ondemand::array gltf_samplers = root["samplers"];
+ // std::vector<handle<device_sampler>> samplers(gltf_samplers.count_elements());
+
+ // auto sampler = device.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
+ // for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
+ // samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
+ // }
+
+ vkdevice& device = vkdevice::get();
constexpr auto buffers_count = 2U;
- auto total_size = images_count * 4096U * 4096 * sizeof(uint32_t);
- auto buffer_size = total_size / 32U;
+ auto total_size = images.size() * 4096U * 4096 * sizeof(uint32_t);
+ // TODO: Fix nasty stuff going on
+ // Crash on buffer destruction
+ // Load wrong images
+ // auto buffer_size = total_size / 32U;
+ auto buffer_size = total_size / 2U;
handle<device_buffer> staging_buffers_handle[buffers_count] = {
device.create_buffer({
@@ -156,46 +188,28 @@ void gltf::load_textures(const std::filesystem::path& path) {
}),
};
+ // TODO: Create a proper upload heap
+ BEGIN_MARKER(UPLOAD_TEXTURES);
graphics_command_buffer command_buffers[buffers_count];
device.allocate_command_buffers(command_buffers, buffers_count, QueueType::GRAPHICS, "upload_buffer");
auto buffer_index = 0U;
auto command_buffer = command_buffers[buffer_index];
auto buffer_handle = staging_buffers_handle[buffer_index];
- auto buffer = device.get_buffer(buffer_handle);
+ device_buffer& buffer = device.get_buffer(buffer_handle);
command_buffer.start();
-#endif // API_TEST
-
- std::for_each(std::execution::par, v.begin(), v.end(), [&](const size_t image_index) {
- const auto& gltf_image = gltf_images[image_index];
- auto filepath = (path / gltf_image["uri"].get<std::string>()).string();
- auto& image = images[image_index];
- image.data = stbi_load(filepath.c_str(), &image.width, &image.height, &image.channels, 4);
- });
-
- // const auto &gltf_samplers = gltf_json["samplers"];
- // auto samplers_count = gltf_samplers.size();
- // std::vector<Sampler *> samplers{samplers_count};
-
-#ifdef API_TEST
- const auto &gltf_samplers = gltf_json["samplers"];
- auto samplers_count = gltf_samplers.size();
- std::vector<handle<device_sampler>> samplers{samplers_count};
-
- // auto sampler = device.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
- // samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // }
- for (size_t texture_index = 0; texture_index < textures_count; texture_index++) {
- auto gltf_texture = gltf_textures[texture_index];
- auto& image = images[gltf_texture["source"].get<uint32_t>()];
+ ondemand::array gltf_textures = root["textures"];
+ textures.resize(gltf_textures.count_elements());
+ u32 texture_index = 0U;
+ for (ondemand::object gltf_texture: gltf_textures) {
+ raw_image& image = images[gltf_texture["source"]];
// if (gltf_texture.contains("sampler")) {
- // auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
+ // u32 sampler_index = gltf_texture["sampler"].get_uint32();
// sampler = samplers[sampler_index];
// }
- auto texture = device.create_texture({
+ handle<device_texture> texture = device.create_texture({
.width = static_cast<uint32_t>(image.width),
.height = static_cast<uint32_t>(image.height),
.usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
@@ -203,105 +217,247 @@ void gltf::load_textures(const std::filesystem::path& path) {
.type = VK_IMAGE_TYPE_2D,
});
- uint64_t size = image.width * image.height * sizeof(uint32_t);
- auto offset = buffer.offset;
- if (offset + size > buffer_size) {
+ u32 size = image.width * image.height * sizeof(uint32_t);
+ if (buffer.allocated_size + size > buffer.size) {
command_buffer.stop();
- device.submit(&command_buffer, 1 );
+ device.submit(&command_buffer, 1);
- buffer_index = (++buffer_index) % buffers_count;
+ buffer_index = (buffer_index + 1U) % buffers_count;
command_buffer = command_buffers[buffer_index];
buffer_handle = staging_buffers_handle[buffer_index];
buffer = device.get_buffer(buffer_handle);
buffer.reset();
- device.wait();
+ // TODO: Remove the wait
+ // device.wait();
command_buffer.start();
- offset = 0U;
}
- void* ptr = buffer.allocate(size);
- memcpy(ptr, image.data, size);
+ memcpy(buffer.allocate(size), image.data, size);
command_buffer.barrier(texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- command_buffer.copy(buffer_handle, texture, static_cast<VkDeviceSize>(offset));
+ command_buffer.copy(buffer_handle, texture, static_cast<VkDeviceSize>(buffer.offset));
command_buffer.barrier(texture, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
- textures[texture_index] = texture;
+ textures[texture_index++] = texture;
}
- command_buffer.stop();
- device.submit(&command_buffer, 1);
+ if (buffer.allocated_size > 0U) {
+ command_buffer.stop();
+ device.submit(&command_buffer, 1);
+ }
device.wait();
device.destroy_buffer(staging_buffers_handle[0]);
device.destroy_buffer(staging_buffers_handle[1]);
-#else
- Sampler* sampler = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
- // samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // }
+ END_MARKER(UPLOAD_TEXTURES);
+}
- for (size_t texture_index = 0; texture_index < textures_count; texture_index++) {
- auto gltf_texture = gltf_textures[texture_index];
+static void load_materials(std::vector<material>& materials, std::vector<handle<device_texture>>& textures) {
+ ondemand::array gltf_materials = root["materials"];
+ materials.resize(gltf_materials.count_elements());
- auto& image = images[gltf_texture["source"].get<uint32_t>()];
- // if (gltf_texture.contains("sampler")) {
- // auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
- // sampler = samplers[sampler_index];
- // }
+ u32 material_index = 0U;
+ for (ondemand::object object: gltf_materials) {
+ material& material = materials[material_index++];
+ material.base_color = vec3(1.f);
+ material.metalness = 1.f;
+ material.roughness = 1.f;
- auto* texture = vkrenderer::create_2d_texture(static_cast<uint32_t>(image.width), static_cast<uint32_t>(image.height), VK_FORMAT_R8G8B8A8_UNORM, sampler);
+ ondemand::object pbr_params;
+ if (!object["pbrMetallicRoughness"].get(pbr_params)) {
+ ondemand::array base_color;
+ if (!pbr_params["baseColorFactor"].get(base_color)) {
+ u32 id = 0U;
+ for (double val : base_color) {
+ material.base_color.arr[id++] = static_cast<float>(val);
+ }
+ }
- texture->update(image.data);
+ ondemand::object base_color_texture;
+ if (!pbr_params["baseColorTexture"].get(base_color_texture)) {
+ material.base_color_texture = textures[base_color_texture["index"]];
+ }
- textures[texture_index] = texture;
+ pbr_params["metallicFactor"].get(material.metalness);
+ pbr_params["roughnessFactor"].get(material.roughness);
+
+ ondemand::object metallic_roughness_texture;
+ if (!pbr_params["metallicRoughnessTexture"].get(metallic_roughness_texture)) {
+ material.metallic_roughness_texture = textures[metallic_roughness_texture["index"]];
+ }
+ }
}
-#endif
}
-void gltf::load_materials() {
- const auto& gltf_materials = gltf_json["materials"];
- auto materials_count = gltf_materials.size();
- materials.resize(materials_count);
+gltf::gltf(const char* filepath) {
+ BEGIN_MARKER(LOAD_GLTF);
- for (size_t material_index = 0; material_index < materials_count; material_index++) {
- const auto& gltf_material = gltf_materials[material_index];
- auto& material = materials[material_index];
+ ondemand::parser parser;
+ padded_string json;
+ ondemand::document doc;
- if (gltf_material.contains("pbrMetallicRoughness")) {
- const auto& pbr_params = gltf_material["pbrMetallicRoughness"];
+ const char* ext = PathFindExtensionA(filepath);
- if (pbr_params.contains("baseColorFactor")) {
- const auto& base_color = pbr_params["baseColorFactor"];
- material.base_color.set<0>(base_color[0].get<float>());
- material.base_color.set<1>(base_color[1].get<float>());
- material.base_color.set<2>(base_color[2].get<float>());
- material.base_color.arr[3] = base_color[3].get<float>(); // Since we use a vec3 for colors we are not allowed toset fourth value with set<3>
- } else {
- material.base_color = vec3(1.f);
- }
+ char buffer_path[2048U] = { 0U };
+ char* filename = nullptr;
+ GetFullPathNameA( filepath, 2048U, buffer_path, &filename);
+ size_t parent_dir_len = filename - buffer_path;
- if (pbr_params.contains("baseColorTexture")) {
- auto base_color_index = pbr_params["baseColorTexture"]["index"].get<uint32_t>();
- material.base_color_texture = textures[base_color_index];
- }
+ // TODO: Remove
+ is_glb = strcmp(ext, ".glb") == 0;
+
+ if (is_glb) {
+ size_t filesize = 0U;
+ size_t read = 0U;
+ u8* glb_buffer = read_file(filepath, &filesize);
+ header = (struct glb_header*)glb_buffer;
+ assert(filesize == header->length);
+ // assert(header->magic == (u32)"glTF");
+
+ read += sizeof(*header);
+ chunks.push_back((struct glb_chunk*)(header + 1));
+ read += offsetof(struct glb_chunk, data) + chunks.back()->length;
+ while (read != header->length) {
+ chunks.push_back((struct glb_chunk*)(glb_buffer + read));
+ read += offsetof(struct glb_chunk, data) + chunks.back()->length;
+ }
+
+ doc = parser.iterate((const char*)&chunks[0]->data[0U], chunks[0]->length, filesize);
+ root = doc;
+
+ ondemand::array gltf_buffers = root["buffers"];
+ assert(gltf_buffers.count_elements() == chunks.size() - 1U);
+ buffers.resize(gltf_buffers.count_elements());
+ u32 buffer_index = 0U;
+ for (u32 chunk_index = 1U; chunk_index < chunks.size(); chunk_index++) {
+ buffers[buffer_index++] = buffer {
+ .bytes = chunks[chunk_index]->data,
+ .size = chunks[chunk_index]->length,
+ };
+ }
+ } else {
+ json = padded_string::load(filepath);
+ doc = parser.iterate(json);
+ root = doc;
- if (pbr_params.contains("metallicFactor")) {
- material.metalness = pbr_params["metallicFactor"].get<float>();
- } else {
- material.metalness = 1.0;
+ {
+ ondemand::array gltf_buffers = root["buffers"];
+ buffers.resize(gltf_buffers.count_elements());
+ u32 buffer_index = 0U;
+ for (ondemand::object value: gltf_buffers) {
+ std::string_view uri_view = value["uri"];
+ strncpy(buffer_path + parent_dir_len, uri_view.data(), uri_view.length());
+ buffer_path[parent_dir_len + uri_view.length()] = '\0';
+
+ size_t file_size = 0U;
+ uint8_t* bytes = read_file(buffer_path, &file_size);
+ buffers[buffer_index++] = {
+ .bytes = bytes,
+ .size = file_size,
+ };
}
+ }
+ }
+
+
+ std::vector<struct accessor> accessors;
+ {
+ ondemand::array gltf_accessors = root["accessors"];
+ accessors.resize(gltf_accessors.count_elements());
+ u32 accessor_index = 0U;
+ for (ondemand::object value: gltf_accessors) {
+ struct accessor& accessor = accessors[accessor_index++];
+ value["bufferView"].get(accessor.view_index);
+ value["count"].get(accessor.count);
+ value["type"].get(accessor.type);
+ value["componentType"].get(accessor.component_type);
+ }
+ }
+
+ std::vector<struct buffer_view> buffer_views;
+ {
+ ondemand::array gltf_views = root["bufferViews"];
+ buffer_views.resize(gltf_views.count_elements());
+ u32 view_index = 0U;
+ for (ondemand::object value: gltf_views) {
+ struct buffer_view& view = buffer_views[view_index++];
+ value["buffer"].get(view.buffer_index);
+ value["byteLength"].get(view.length);
+ value["byteOffset"].get(view.offset);
+ }
+ }
+
- if (pbr_params.contains("roughnessFactor")) {
- material.roughness = pbr_params["roughnessFactor"].get<float>();
- } else {
- material.roughness = 1.0;
+ {
+ ondemand::array gltf_nodes = root["nodes"];
+ nodes.resize(gltf_nodes.count_elements());
+
+ u32 node_index = 0U;
+ for (ondemand::object gltf_node: gltf_nodes) {
+ struct node& node = nodes[node_index++];
+
+ ondemand::array gltf_children;
+ if (!gltf_node["children"].get(gltf_children)) {
+ node.children.resize(gltf_children.count_elements());
+
+ u32 child_index = 0U;
+ for (auto child : gltf_children) {
+ node.children[child_index++] = child.get_uint32();
+ }
}
- if (pbr_params.contains("metallicRoughnessTexture")) {
- auto metallic_roughness_index = pbr_params["metallicRoughnessTexture"]["index"].get<uint32_t>();
- material.metallic_roughness_texture = textures[metallic_roughness_index];
+ node.mesh = UINT32_MAX;
+ gltf_node["mesh"].get(node.mesh);
+ }
+ }
+
+
+ // root nodes
+ {
+ u32 scene_index = root["scene"].get_uint32();
+ ondemand::array gltf_scene_nodes = root["scenes"].at(scene_index)["nodes"];
+ root_nodes.resize(gltf_scene_nodes.count_elements());
+
+ u32 index = 0U;
+ for (auto node_index: gltf_scene_nodes) {
+ root_nodes[index++] = node_index.get_uint32();
+ }
+ }
+
+ buffer_path[parent_dir_len] = '\0';
+ load_textures(buffer_path, textures, buffers, buffer_views, is_glb);
+ load_materials(materials, textures);
+
+ // meshes
+ {
+ ondemand::array gltf_meshes = root["meshes"];
+ meshes.resize(gltf_meshes.count_elements());
+
+ u32 mesh_index = 0U;
+ for (ondemand::object gltf_mesh: gltf_meshes) {
+ Mesh& mesh = meshes[mesh_index++];
+ ondemand::array gltf_primitives = gltf_mesh["primitives"];
+
+ for (ondemand::object primitive : gltf_primitives) {
+ material& material = materials[primitive["material"]];
+ mesh.add_submesh(load_primitive(primitive, buffers, accessors, buffer_views), material);
}
+
+ Mesh::register_mesh(mesh);
}
}
+
+ END_MARKER(LOAD_GLTF);
+}
+
+void gltf::deinit() {
+ for (handle<device_texture> handle: textures) {
+ vkdevice::get().destroy_texture(handle);
+ }
+
+ for (struct buffer& buffer: buffers) {
+ free(buffer.bytes);
+ }
+
+ free(header);
}
diff --git a/src/mesh.cpp b/src/mesh.cpp
index 3863ca8..cbfe392 100644
--- a/src/mesh.cpp
+++ b/src/mesh.cpp
@@ -1,6 +1,6 @@
#include "mesh.hpp"
-static std::vector<Mesh> meshes {};
+static std::vector<Mesh> registered_meshes {};
void Mesh::add_submesh(const submesh& submesh, material& material) {
submeshes.emplace_back(
@@ -42,5 +42,5 @@ void Mesh::add_submesh(const submesh& submesh, material& material) {
}
void Mesh::register_mesh(const Mesh& mesh) {
- meshes.push_back(mesh);
+ registered_meshes.push_back(mesh);
}
diff --git a/src/scene.cpp b/src/scene.cpp
index 9d6b981..9369eae 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -1,17 +1,5 @@
#include "scene.hpp"
-
-#include <cstdint>
-#include <queue>
-
-#ifdef API_TEST
-#include <vk_mem_alloc.h>
-#else
-#include "vk-renderer.hpp"
-#endif // API_TEST
-
-#include "gltf.hpp"
-#include "bvh.hpp"
-// #include "material.hpp"
+#include "mesh.hpp"
// void scene::random_scene() {
// material ground_material = { { 0.5, 0.5, 0.5 } };
@@ -63,15 +51,19 @@
// }
-scene::metadata::metadata(const camera &cam, uint32_t width, uint32_t height)
+metadata::metadata(const camera &cam, uint32_t width, uint32_t height)
: cam(cam), width(width), height(height) {}
scene::scene(const camera& cam, uint32_t width, uint32_t height)
- :meta(cam, width, height){
+ // :model("../models/sponza/Sponza.gltf"), meta(cam, width, height) {
+ // :model("../models/BistroInterior/BistroInterior.gltf"), meta(cam, width, height) {
+ // :model("../models/BistroExterior/BistroExterior.gltf"), meta(cam, width, height) {
+ // :model("../models/sponza-avif-hi.glb"), meta(cam, width, height) {
+ // :model("../models/main_sponza/NewSponza_Main_glTF_003.gltf"), meta(cam, width, height) {
+ // :model("../models/pkg_a_curtains/NewSponza_Curtains_glTF.gltf"), meta(cam, width, height) {
+ :model("../models/sponza.glb"), meta(cam, width, height) {
-#ifdef API_TEST
- auto& device = vkdevice::get_render_device();
-#endif
+ auto& device = vkdevice::get();
// Geometry & BVH
std::vector<uint32_t> indices;
@@ -81,51 +73,50 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
std::vector<gpu_material> materials;
std::vector<packed_bvh_node> packed_nodes;
- // auto root_node = gltf::load("../models/BistroInterior", "BistroInterior.gltf");
- auto gltf_model = gltf("../models/sponza/Sponza.gltf");
-
std::vector<triangle> triangles;
- size_t triangles_offset = 0;
- size_t vertices_offset = 0;
- std::queue<node> nodes_to_load {};
- nodes_to_load.push(gltf_model.root_node);
+ u32 triangles_offset = 0U;
+ u32 vertices_offset = 0U;
+ u32 positions_count = 0U;
+ u32 normals_count = 0U;
+ u32 uvs_count = 0U;
+ std::vector<u32> nodes_to_load = model.root_nodes;
- while(!nodes_to_load.empty()) {
- auto &node = nodes_to_load.front();
+ for (u32 cur_node_index = 0U; cur_node_index < nodes_to_load.size(); cur_node_index++) {
+ struct node &node = model.nodes[nodes_to_load[cur_node_index]];
- if (node.mesh != nullptr) {
- const auto* mesh = node.mesh;
- const auto& mesh_positions = mesh->get_attribute(ATTRIBUTE_TYPE::POSITION);
- const auto& mesh_normals = mesh->get_attribute(ATTRIBUTE_TYPE::NORMAL);
- const auto& mesh_uvs_0 = mesh->get_attribute(ATTRIBUTE_TYPE::UV_0);
- const auto& mesh_indices = mesh->get_indices();
+ if (node.mesh != UINT32_MAX) {
+ const Mesh& mesh = model.meshes[node.mesh];
+ const auto& mesh_positions = mesh.get_attribute(ATTRIBUTE_TYPE::POSITION);
+ const auto& mesh_normals = mesh.get_attribute(ATTRIBUTE_TYPE::NORMAL);
+ const auto& mesh_uvs_0 = mesh.get_attribute(ATTRIBUTE_TYPE::UV_0);
+ const auto& mesh_indices = mesh.get_indices();
- indices.resize(indices.size() + mesh_indices.size());
- positions.resize(vertices_offset + mesh_positions.size());
- normals.resize(vertices_offset + mesh_normals.size());
- uvs.resize(vertices_offset + mesh_uvs_0.size());
+ indices.resize(indices.size() + mesh_indices.size());
+ positions.resize(positions_count + mesh_positions.size());
+ normals.resize(normals_count + mesh_normals.size());
+ uvs.resize(uvs_count + mesh_uvs_0.size());
std::memcpy(
- positions.data() + vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::POSITION),
+ positions.data() + positions_count,
mesh_positions.data(),
- mesh_positions.size() * sizeof(float)
+ mesh_positions.size() * sizeof(mesh_positions[0U])
);
std::memcpy(
- normals.data() + vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::NORMAL),
+ normals.data() + normals_count,
mesh_normals.data(),
- mesh_normals.size() * sizeof(float)
+ mesh_normals.size() * sizeof(mesh_normals[0U])
);
std::memcpy(
- uvs.data() + vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::UV_0),
+ uvs.data() + uvs_count,
mesh_uvs_0.data(),
- mesh_uvs_0.size() * sizeof(float)
+ mesh_uvs_0.size() * sizeof(mesh_uvs_0[0U])
);
auto index_offset { 0U };
// Add offset to indices in order to have absolute indices
- for (const auto& submesh: mesh->get_submeshes()) {
+ for (const auto& submesh: mesh.get_submeshes()) {
auto vertex_offset = vertices_offset + submesh.vertex_offset;
const auto& material = submesh.material;
@@ -151,9 +142,6 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
indices[triangle_offset + 2] = static_cast<uint32_t>((submesh_level_index_3 + vertex_offset) | (0xff000000 & (materials.size() << 24)));
}
-// const auto& albedo_image = vkrenderer::api.get_image(material.base_color_texture->device_image);
-// const auto& albedo_sampler = vkrenderer::api.get_sampler(material.base_color_texture->sampler->device_sampler);
-
auto& mat = materials.emplace_back(gpu_material {
.base_color = material.base_color,
// .albedo_texture_id = albedo_image.bindless_sampled_index,
@@ -162,7 +150,6 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.roughness = material.roughness
});
-#ifdef API_TEST
if (material.base_color_texture.id != handle<device_texture>::invalid_id) {
mat.albedo_texture_id = device.get_texture(material.base_color_texture).get_sampled_index();
// mat.albedo_texture_sampler_id = device.get_sampler(0);
@@ -172,28 +159,18 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
mat.metallic_roughness_texture_id = device.get_texture(material.metallic_roughness_texture).get_sampled_index();
// mat.metallic_roughness_texture_sampler_id = device.get_sampler(0);
}
-#else
- if (material.metallic_roughness_texture != nullptr) {
- // auto& gpu_material = materials.back();
-// const auto& metallic_roughness_image = vkrenderer::api.get_image(material.metallic_roughness_texture->device_image);
-// const auto& metallic_roughness_sampler = vkrenderer::api.get_sampler(material.metallic_roughness_texture->sampler->device_sampler);
-
-// gpu_material.metallic_roughness_texture_id = metallic_roughness_image.bindless_sampled_index;
-// gpu_material.metallic_roughness_texture_sampler_id = metallic_roughness_sampler.bindless_index;
- }
-#endif
-
}
- triangles_offset += mesh->triangle_count();
- vertices_offset += mesh->vertices_count();
+ triangles_offset += mesh.triangle_count();
+ vertices_offset += mesh.vertices_count();
+ positions_count = vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::POSITION);
+ normals_count = vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::NORMAL);
+ uvs_count = vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::UV_0);
}
- for (auto &new_node: node.children) {
- nodes_to_load.push(new_node);
+ for (u32 child_index: node.children) {
+ nodes_to_load.push_back(child_index);
}
-
- nodes_to_load.pop();
}
// random_scene();
@@ -201,28 +178,13 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
bvh builder(triangles, packed_nodes);
// bvh builder(spheres, packed_nodes);
-#ifdef API_TEST
- {
- scene_buffer_handle = device.create_buffer({
- .size = sizeof(meta) * 3U,
- .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
- .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
- });
-
- const auto& scene_buffer = device.get_buffer(scene_buffer_handle);
- uint8_t* ptr = static_cast<uint8_t*>(scene_buffer.mapped_ptr);
- memcpy(static_cast<void*>(ptr), &meta, sizeof(meta));
- memcpy(static_cast<void*>(ptr + sizeof(meta)), &meta, sizeof(meta));
- memcpy(static_cast<void*>(ptr + sizeof(meta) * 2U), &meta, sizeof(meta));
- }
-
{
indices_buffer_handle = device.create_buffer({
.size = indices.size() * sizeof(indices[0]),
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "indices",
});
const auto& indices_buffer = device.get_buffer(indices_buffer_handle);
void* ptr = indices_buffer.mapped_ptr;
@@ -235,6 +197,7 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "positions",
});
const auto& positions_buffer = device.get_buffer(positions_buffer_handle);
void* ptr = positions_buffer.mapped_ptr;
@@ -247,6 +210,7 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "normals",
});
const auto& normals_buffer = device.get_buffer(normals_buffer_handle);
void* ptr = normals_buffer.mapped_ptr;
@@ -259,6 +223,7 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "uvs",
});
const auto& uvs_buffer = device.get_buffer(uvs_buffer_handle);
void* ptr = uvs_buffer.mapped_ptr;
@@ -271,6 +236,7 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "bvh",
});
const auto& bvh_buffer = device.get_buffer(bvh_buffer_handle);
void* ptr = bvh_buffer.mapped_ptr;
@@ -283,33 +249,21 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "materials",
});
const auto& materials_buffer = device.get_buffer(materials_buffer_handle);
void* ptr = materials_buffer.mapped_ptr;
memcpy(ptr, materials.data(), materials.size() * sizeof(materials[0]));
}
-#else
- scene_buffer = vkrenderer::create_buffer(sizeof(meta) * vkrenderer::virtual_frames_count);
- scene_buffer->write(&meta, 0, sizeof(meta));
- scene_buffer->write(&meta, sizeof(meta), sizeof(meta));
- scene_buffer->write(&meta, sizeof(meta) * 2, sizeof(meta));
-
- indices_buffer = vkrenderer::create_buffer(indices.size() * sizeof(indices[0]));
- indices_buffer->write(indices.data(), 0, indices.size() * sizeof(indices[0]));
-
- positions_buffer = vkrenderer::create_buffer(positions.size() * sizeof(positions[0]));
- positions_buffer->write(positions.data(), 0, positions.size() * sizeof(positions[0]));
-
- normals_buffer = vkrenderer::create_buffer(normals.size() * sizeof(normals[0]));
- normals_buffer->write(normals.data(), 0, normals.size() * sizeof(normals[0]));
-
- uvs_buffer = vkrenderer::create_buffer(uvs.size() * sizeof(uvs[0]));
- uvs_buffer->write(uvs.data(), 0, uvs.size() * sizeof(uvs[0]));
+}
- bvh_buffer = vkrenderer::create_buffer(packed_nodes.size() * sizeof(packed_nodes[0]));
- bvh_buffer->write(packed_nodes.data(), 0, packed_nodes.size() * sizeof(packed_nodes[0]));
+void scene::deinit() {
+ vkdevice::get().destroy_buffer(indices_buffer_handle);
+ vkdevice::get().destroy_buffer(positions_buffer_handle);
+ vkdevice::get().destroy_buffer(normals_buffer_handle);
+ vkdevice::get().destroy_buffer(uvs_buffer_handle);
+ vkdevice::get().destroy_buffer(bvh_buffer_handle);
+ vkdevice::get().destroy_buffer(materials_buffer_handle);
- materials_buffer = vkrenderer::create_buffer(materials.size() * sizeof(materials[0]));
- materials_buffer->write(materials.data(), 0, materials.size() * sizeof(materials[0]));
-#endif // API_TEST
+ model.deinit();
}
diff --git a/src/utils.cpp b/src/utils.cpp
index ffe50b3..4c383db 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -1,54 +1,46 @@
#include "utils.hpp"
-#if defined(WINDOWS)
-#include <windows.h>
-#endif
-
-#include <filesystem>
-#include <iostream>
+#include <unordered_map>
-std::vector<uint8_t> read_file(const char* path) {
-#if defined(WINDOWS)
- FILE* f = nullptr;
- errno_t err = fopen_s(&f, path, "rb");
+uint8_t* read_file(const char* path, size_t* size) {
+#if _WIN32
+ HANDLE f = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (err != 0) {
- std::cerr << "Cannot open file !" << std::endl;
- return {};
+ if (f == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "Cannot open file !\n");
+ return nullptr;
}
-#elif defined(LINUX)
+#elif LINUX
FILE* f = fopen(path, "rb");
if (!f) {
- std::cerr << "Cannot open file !" << std::endl;
+ fprintf(stderr, "Cannot open file !\n");
return {};
}
#endif
- if (fseek(f, 0, SEEK_END) != 0) {
- return {};
+ LARGE_INTEGER file_size = { .QuadPart = 0ULL };
+ if (!GetFileSizeEx(f, &file_size)) {
+ return nullptr;
}
+ *size = file_size.LowPart;
- std::vector<uint8_t> file_content(ftell(f));
+ void* content = malloc(*size);
- if (fseek(f, 0, SEEK_SET) != 0) {
- return {};
- }
-
- if (fread(file_content.data(), sizeof(uint8_t), file_content.size(), f) != file_content.size()) {
- std::cerr << "Reading file content failed" << std::endl;
- return {};
+ DWORD bread = 0U;
+ if (!ReadFile(f, content, static_cast<DWORD>(*size), &bread, NULL) || bread != *size) {
+ fprintf(stderr, "Reading file content failed\n");
+ return nullptr;
}
- fclose(f);
+ CloseHandle(f);
- return file_content;
+ return (uint8_t*)content;
}
-
-#ifdef WINDOWS
+#if _WIN32
void log_last_error() {
- auto error_code = GetLastError();
+ DWORD error_code = GetLastError();
const char* error_message = nullptr;
FormatMessageA(
@@ -63,29 +55,49 @@ void log_last_error() {
nullptr
);
- std::cerr << error_message << std::endl;
+ fprintf(stderr, "%s\n", error_message);
}
-bool watcher::watch_file(const char* filepath, watcher::func callback) {
+struct watch_data {
+ HANDLE dir_handle;
+ OVERLAPPED overlapped;
+ DWORD buffer[512];
+};
+
+static std::unordered_map<const char*, func> callbacks;
+static std::unordered_map<const char*, watch_data> watched_dirs;
+
+bool watch_file(const char* filepath, func callback) {
DWORD attrib = GetFileAttributes(filepath);
if (attrib == INVALID_FILE_ATTRIBUTES)
return false;
- std::filesystem::path path(filepath);
- if (!watcher::watch_dir(path.parent_path().string().c_str()))
+ size_t buffer_size = 2048U;
+ char* fullpath = static_cast<char*>(malloc(buffer_size));
+ char* filename = nullptr;
+ GetFullPathNameA( filepath, 2028, fullpath, &filename);
+
+ size_t dir_len = filename - fullpath;
+ char* parent_dir = static_cast<char*>(malloc(dir_len));
+ strncpy(parent_dir, fullpath, dir_len);
+
+ free(fullpath);
+
+ if (!watch_dir(parent_dir)) {
return false;
+ }
- auto [_, is_inserted] = watcher::callbacks.emplace(filepath, callback);
+ auto [_, is_inserted] = callbacks.emplace(filepath, callback);
return is_inserted;
}
-bool watcher::watch_dir(const char* dir_path) {
+bool watch_dir(const char* dir_path) {
DWORD attrib = GetFileAttributes(dir_path);
if (attrib == INVALID_FILE_ATTRIBUTES || (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0U )
return false;
- if (watcher::watched_dirs.find(dir_path) != watcher::watched_dirs.end())
+ if (watched_dirs.find(dir_path) != watched_dirs.end())
return true;
HANDLE dir_handle = CreateFileA(
@@ -103,7 +115,7 @@ bool watcher::watch_dir(const char* dir_path) {
return false;
}
- auto [dir, _] = watcher::watched_dirs.emplace(dir_path, watch_data{ .dir_handle = dir_handle, .overlapped{}, .buffer{} });
+ auto [dir, _] = watched_dirs.emplace(dir_path, watch_data{ .dir_handle = dir_handle, .overlapped{}, .buffer{} });
if (FAILED(ReadDirectoryChangesW(dir_handle, dir->second.buffer, sizeof(watch_data::buffer), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, nullptr, &dir->second.overlapped, nullptr))) {
log_last_error();
@@ -113,8 +125,8 @@ bool watcher::watch_dir(const char* dir_path) {
return true;
}
-void watcher::pull_changes() {
- for (auto& dir : watcher::watched_dirs) {
+void pull_changes() {
+ for (auto& dir : watched_dirs) {
auto& watch_data = dir.second;
if (!HasOverlappedIoCompleted(&watch_data.overlapped))
continue;
diff --git a/src/vec3.cpp b/src/vec3.cpp
index 3167bc2..414ee73 100644
--- a/src/vec3.cpp
+++ b/src/vec3.cpp
@@ -1,10 +1,8 @@
-#include <cmath>
-#include <cassert.>
-#include <smmintrin.h>
-
-#include "utils.hpp"
#include "vec3.hpp"
+// #include <smmintrin.h>
+// #include <xmmintrin.h>
+
vec3::vec3() : v(_mm_setzero_ps()) {}
vec3::vec3(float x) : v(_mm_set1_ps(x)) {}
@@ -122,7 +120,16 @@ bool vec3::near_zero() const {
float v0 = fabs(static_cast<float>(_mm_extract_ps(v, 0)));
float v1 = fabs(static_cast<float>(_mm_extract_ps(v, 1)));
float v2 = fabs(static_cast<float>(_mm_extract_ps(v, 2)));
- return (v0 < EPSILON) && (v1 < EPSILON) && (v2 < EPSILON);
+ return (v0 < FLT_EPSILON) && (v1 < FLT_EPSILON) && (v2 < FLT_EPSILON);
+}
+
+bool vec3::is_zero() const {
+ // __m128 e = _mm_set1_ps(EPSILON);
+ // _mm_cmplt_ps(_mm_andnot_ps(_mm_set1_ps(-0.0f), v), e);
+ float v0 = fabs(static_cast<float>(_mm_extract_ps(v, 0)));
+ float v1 = fabs(static_cast<float>(_mm_extract_ps(v, 1)));
+ float v2 = fabs(static_cast<float>(_mm_extract_ps(v, 2)));
+ return (v0 == 0.f) && (v1 == 0.f) && (v2 == 0.f);
}
void vec3::print() const {
diff --git a/src/vulkan-loader.cpp b/src/vulkan-loader.cpp
index c799f17..399b566 100644
--- a/src/vulkan-loader.cpp
+++ b/src/vulkan-loader.cpp
@@ -1,8 +1,6 @@
#include "vulkan-loader.hpp"
-#include <cassert>
-
-#if defined(WINDOWS)
+#if defined(_WIN32)
// extern "C" void* GetProcAddress(HMODULE, const char*);
// extern "C" HMODULE LoadLibraryA(const char*);
HMODULE vulkanLibrary = LoadLibraryA("vulkan-1.dll");
diff --git a/src/window.cpp b/src/window.cpp
index 7ba3bc0..38c9765 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -1,6 +1,5 @@
#include "window.hpp"
-
#ifdef LINUX
#include <iostream>
@@ -169,10 +168,23 @@ void window::poll_events() {
}
}
-#elif defined(WINDOWS)
-#include <windowsx.h>
+#elif _WIN32
+#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
-#include "utils.hpp"
+HCURSOR window::cursors[CURSOR_TYPE::MAX_CURSOR] = {
+ LoadCursorA(NULL, IDC_ARROW),
+ LoadCursorA(NULL, IDC_IBEAM),
+ LoadCursorA(NULL, IDC_SIZEALL),
+ LoadCursorA(NULL, IDC_SIZENS),
+ LoadCursorA(NULL, IDC_SIZEWE),
+ LoadCursorA(NULL, IDC_SIZENESW),
+ LoadCursorA(NULL, IDC_SIZENWSE),
+ LoadCursorA(NULL, IDC_HAND),
+ LoadCursorA(NULL, IDC_WAIT),
+ LoadCursorA(NULL, IDC_APPSTARTING),
+ LoadCursorA(NULL, IDC_NO),
+};
LRESULT CALLBACK window::window_procedure(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) {
window* win = nullptr;
@@ -250,29 +262,27 @@ void window::message_loop() {
MSG msg {};
while(true) {
- // Generate keydown events pressed keys
- for (size_t virtual_key { KEYS::LSHIFT }; virtual_key < KEYS::MAX_KEYS; virtual_key++) {
- if (keyboard[virtual_key]) {
- events.push_back({
- .data {
- .key = (KEYS)virtual_key,
- },
- .type = EVENT_TYPES::KEY_PRESS,
- });
- }
- }
-
-
while (PeekMessageA(&msg, nullptr, 0, 0, PM_REMOVE) != 0) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
+ for (u32 key_index = 0U; key_index <= KEY::MAX_KEY; key_index++) {
+ events.push_back(event {
+ .data {
+ .key = (KEY)key_index,
+ },
+ .type = keyboard[key_index] ? EVENT_TYPE::KEY_DOWN : EVENT_TYPE::KEY_UP,
+ });
+ }
+
SwitchToFiber(main_fiber);
}
}
void window::poll_events() {
+ events.clear();
+
SwitchToFiber(message_loop_fiber);
}
@@ -281,7 +291,10 @@ LRESULT window::message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lpar
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT: {
- events.push_back({ .data {}, .type = EVENT_TYPES::QUIT });
+ events.push_back({
+ .data {},
+ .type = EVENT_TYPE::QUIT
+ });
isOpen = false;
break;
}
@@ -296,86 +309,90 @@ LRESULT window::message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lpar
.height = height,
},
},
- .type = EVENT_TYPES::RESIZE
+ .type = EVENT_TYPE::RESIZE
});
break;
}
case WM_KEYDOWN: {
- keyboard[wparam] = true;
-
events.push_back({
.data {
- .key = (KEYS)wparam,
+ .key = (KEY)wparam,
},
- .type = EVENT_TYPES::KEY_PRESS,
+ .type = EVENT_TYPE::KEY_PRESS,
});
+ keyboard[wparam] = true;
break;
}
case WM_KEYUP: {
- keyboard[wparam] = false;
-
events.push_back({
.data {
- .key = (KEYS)wparam,
+ .key = (KEY)wparam,
},
- .type = EVENT_TYPES::KEY_RELEASE,
+ .type = EVENT_TYPE::KEY_RELEASE,
});
+ keyboard[wparam] = false;
break;
}
case WM_LBUTTONDOWN: {
+ mouse[BUTTON::LEFT] = true;
events.push_back({
.data {
- .button = BUTTONS::LEFT,
+ .button = BUTTON::LEFT,
},
- .type = EVENT_TYPES::BUTTON_PRESS,
+ .type = EVENT_TYPE::BUTTON_PRESS,
});
break;
}
case WM_LBUTTONUP: {
+ mouse[BUTTON::LEFT] = false;
events.push_back({
.data {
- .button = BUTTONS::LEFT,
+ .button = BUTTON::LEFT,
},
- .type = EVENT_TYPES::BUTTON_RELEASE,
+ .type = EVENT_TYPE::BUTTON_RELEASE,
});
break;
}
case WM_RBUTTONDOWN: {
+ mouse[BUTTON::RIGHT] = true;
events.push_back({
.data {
- .button = BUTTONS::RIGHT,
+ .button = BUTTON::RIGHT,
},
- .type = EVENT_TYPES::BUTTON_PRESS,
+ .type = EVENT_TYPE::BUTTON_PRESS,
});
break;
}
case WM_RBUTTONUP: {
+ mouse[BUTTON::RIGHT] = false;
events.push_back({
.data {
- .button = BUTTONS::RIGHT,
+ .button = BUTTON::RIGHT,
},
- .type = EVENT_TYPES::BUTTON_RELEASE,
+ .type = EVENT_TYPE::BUTTON_RELEASE,
});
break;
}
case WM_MBUTTONDOWN: {
+ mouse[BUTTON::MIDDLE] = true;
events.push_back({
.data {
- .button = BUTTONS::MIDDLE,
+ .button = BUTTON::MIDDLE,
},
- .type = EVENT_TYPES::BUTTON_PRESS,
+ .type = EVENT_TYPE::BUTTON_PRESS,
});
break;
}
case WM_MBUTTONUP: {
+ mouse[BUTTON::MIDDLE] = false;
events.push_back({
.data {
- .button = BUTTONS::MIDDLE,
+ .button = BUTTON::MIDDLE,
},
- .type = EVENT_TYPES::BUTTON_RELEASE,
+ .type = EVENT_TYPE::BUTTON_RELEASE,
});
break;
}
@@ -387,7 +404,19 @@ LRESULT window::message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lpar
.y = GET_Y_LPARAM(lparam),
},
},
- .type = EVENT_TYPES::MOUSE_MOVE,
+ .type = EVENT_TYPE::MOUSE_MOVE,
+ });
+ break;
+ }
+ case WM_MOUSEWHEEL: {
+ events.push_back({
+ .data {
+ .delta {
+ .x = 0,
+ .y = GET_WHEEL_DELTA_WPARAM(wparam) / WHEEL_DELTA,
+ },
+ },
+ .type = EVENT_TYPE::MOUSE_WHEEL,
});
break;
}
@@ -400,6 +429,10 @@ LRESULT window::message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lpar
return 0;
}
+
+void window::set_cursor(enum CURSOR_TYPE type) {
+ SetCursor(window::cursors[type]);
+}
#elif defined(MACOS)
window::window(uint32_t width, uint32_t height) {
}