diff --git a/config/Sources.cmake b/config/Sources.cmake index 54bb3485ed975669668d987787975f019aa6358b..7ae106e2538c66179ab1ed50408551c43b785bc3 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -21,6 +21,8 @@ set(vkcv_sources ${vkcv_include}/vkcv/Buffer.hpp + ${vkcv_include}/vkcv/PushConstants.hpp + ${vkcv_include}/vkcv/BufferManager.hpp ${vkcv_source}/vkcv/BufferManager.cpp diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index cbbe1e908cdb74891ab9bfe4416c03e487e76b26..cd3676f45bf0891de97ab88ff74cdd980f6920da 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -223,9 +223,9 @@ namespace vkcv Multisampling multisampling = Multisampling::None); [[nodiscard]] - const uint32_t getImageWidth(ImageHandle imageHandle); + uint32_t getImageWidth(ImageHandle imageHandle); [[nodiscard]] - const uint32_t getImageHeight(ImageHandle imageHandle); + uint32_t getImageHeight(ImageHandle imageHandle); /** TODO: * @param setDescriptions @@ -246,7 +246,7 @@ namespace vkcv const CommandStreamHandle cmdStreamHandle, const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, - const PushConstantData &pushConstantData, + const PushConstants &pushConstants, const std::vector<DrawcallInfo> &drawcalls, const std::vector<ImageHandle> &renderTargets); @@ -255,7 +255,7 @@ namespace vkcv PipelineHandle computePipeline, const uint32_t dispatchCount[3], const std::vector<DescriptorSetUsage> &descriptorSetUsages, - const PushConstantData& pushConstantData); + const PushConstants& pushConstants); /** * @brief end recording and present image diff --git a/include/vkcv/DescriptorConfig.hpp b/include/vkcv/DescriptorConfig.hpp index c6d0dfd1bc60988afb8b6a9326a8d50d8a4ea32e..776322e6270431f9fa52fd7c3cb4551e5b4bf752 100644 --- a/include/vkcv/DescriptorConfig.hpp +++ b/include/vkcv/DescriptorConfig.hpp @@ -11,6 +11,7 @@ namespace vkcv { vk::DescriptorSet vulkanHandle; vk::DescriptorSetLayout layout; + size_t poolIndex; }; /* diff --git a/include/vkcv/DrawcallRecording.hpp b/include/vkcv/DrawcallRecording.hpp index 9f162a499a38d5633703f70eec8a8682e3328d72..572fc2b6b51735bdcd7eb77c1dd9d4a3482a1640 100644 --- a/include/vkcv/DrawcallRecording.hpp +++ b/include/vkcv/DrawcallRecording.hpp @@ -2,6 +2,7 @@ #include <vulkan/vulkan.hpp> #include <vkcv/Handles.hpp> #include <vkcv/DescriptorConfig.hpp> +#include <vkcv/PushConstants.hpp> namespace vkcv { struct VertexBufferBinding { @@ -29,13 +30,6 @@ namespace vkcv { size_t indexCount; }; - struct PushConstantData { - inline PushConstantData(void* data, size_t sizePerDrawcall) : data(data), sizePerDrawcall(sizePerDrawcall) {} - - void* data; - size_t sizePerDrawcall; - }; - struct DrawcallInfo { inline DrawcallInfo(const Mesh& mesh, const std::vector<DescriptorSetUsage>& descriptorSets, const uint32_t instanceCount = 1) : mesh(mesh), descriptorSets(descriptorSets), instanceCount(instanceCount){} @@ -49,7 +43,7 @@ namespace vkcv { const DrawcallInfo &drawcall, vk::CommandBuffer cmdBuffer, vk::PipelineLayout pipelineLayout, - const PushConstantData &pushConstantData, + const PushConstants &pushConstants, const size_t drawcallIndex); } \ No newline at end of file diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp index 85ab2b81e2718b3890ba361c988d5db0e40e84c7..3fca76f70315c0e08e404d7acd8c2010a3501c24 100644 --- a/include/vkcv/Image.hpp +++ b/include/vkcv/Image.hpp @@ -31,21 +31,21 @@ namespace vkcv { uint32_t getDepth() const; [[nodiscard]] - vkcv::ImageHandle getHandle() const; + const vkcv::ImageHandle& getHandle() const; [[nodiscard]] uint32_t getMipCount() const; void switchLayout(vk::ImageLayout newLayout); - void fill(void* data, size_t size = SIZE_MAX); + void fill(const void* data, size_t size = SIZE_MAX); void generateMipChainImmediate(); void recordMipChainGeneration(const vkcv::CommandStreamHandle& cmdStream); private: // TODO: const qualifier removed, very hacky!!! // Else you cannot recreate an image. Pls fix. ImageManager* m_manager; - ImageHandle m_handle; + ImageHandle m_handle; Image(ImageManager* manager, const ImageHandle& handle); diff --git a/include/vkcv/Logger.hpp b/include/vkcv/Logger.hpp index d484711f642506926b1281a830fb2c9caf8240a2..1ae0f211e1a3255d624cf78985b0797e9d90c634 100644 --- a/include/vkcv/Logger.hpp +++ b/include/vkcv/Logger.hpp @@ -5,6 +5,7 @@ namespace vkcv { enum class LogLevel { + RAW_INFO, INFO, WARNING, ERROR @@ -12,6 +13,7 @@ namespace vkcv { constexpr auto getLogOutput(LogLevel level) { switch (level) { + case LogLevel::RAW_INFO: case LogLevel::INFO: return stdout; default: @@ -21,6 +23,7 @@ namespace vkcv { constexpr const char* getLogName(LogLevel level) { switch (level) { + case LogLevel::RAW_INFO: case LogLevel::INFO: return "INFO"; case LogLevel::WARNING: @@ -41,24 +44,33 @@ namespace vkcv { #define __PRETTY_FUNCTION__ __FUNCSIG__ #endif -#define vkcv_log(level, ...) { \ - char output_message [ \ - VKCV_DEBUG_MESSAGE_LEN \ - ]; \ - snprintf( \ - output_message, \ - VKCV_DEBUG_MESSAGE_LEN, \ - __VA_ARGS__ \ - ); \ - fprintf( \ - getLogOutput(level), \ - "[%s]: %s [%s, line %d: %s]\n", \ - vkcv::getLogName(level), \ - output_message, \ - __FILE__, \ - __LINE__, \ - __PRETTY_FUNCTION__ \ - ); \ +#define vkcv_log(level, ...) { \ + char output_message [ \ + VKCV_DEBUG_MESSAGE_LEN \ + ]; \ + snprintf( \ + output_message, \ + VKCV_DEBUG_MESSAGE_LEN, \ + __VA_ARGS__ \ + ); \ + if (level != vkcv::LogLevel::RAW_INFO) { \ + fprintf( \ + getLogOutput(level), \ + "[%s]: %s [%s, line %d: %s]\n", \ + vkcv::getLogName(level), \ + output_message, \ + __FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__ \ + ); \ + } else { \ + fprintf( \ + getLogOutput(level), \ + "[%s]: %s\n", \ + vkcv::getLogName(level), \ + output_message \ + ); \ + } \ } #else diff --git a/include/vkcv/PushConstants.hpp b/include/vkcv/PushConstants.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d974fbe6241daf948b13929305fb24aff5ec06f5 --- /dev/null +++ b/include/vkcv/PushConstants.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include <vector> +#include <vulkan/vulkan.hpp> + +#include "Logger.hpp" + +namespace vkcv { + + class PushConstants { + private: + std::vector<uint8_t> m_data; + size_t m_sizePerDrawcall; + + public: + template<typename T> + PushConstants() : PushConstants(sizeof(T)) {} + + explicit PushConstants(size_t sizePerDrawcall) : + m_data(), + m_sizePerDrawcall(sizePerDrawcall) {} + + PushConstants(const PushConstants& other) = default; + PushConstants(PushConstants&& other) = default; + + ~PushConstants() = default; + + PushConstants& operator=(const PushConstants& other) = default; + PushConstants& operator=(PushConstants&& other) = default; + + [[nodiscard]] + size_t getSizePerDrawcall() const { + return m_sizePerDrawcall; + } + + [[nodiscard]] + size_t getFullSize() const { + return m_data.size(); + } + + [[nodiscard]] + size_t getDrawcallCount() const { + return (m_data.size() / m_sizePerDrawcall); + } + + void clear() { + m_data.clear(); + } + + template<typename T = uint8_t> + bool appendDrawcall(const T& value) { + if (sizeof(T) != m_sizePerDrawcall) { + vkcv_log(LogLevel::WARNING, "Size (%lu) of value does not match the specified size per drawcall (%lu)", + sizeof(value), m_sizePerDrawcall); + return false; + } + + const size_t offset = m_data.size(); + m_data.resize(offset + sizeof(value)); + std::memcpy(m_data.data() + offset, &value, sizeof(value)); + return true; + } + + template<typename T = uint8_t> + T& getDrawcall(size_t index) { + const size_t offset = (index * m_sizePerDrawcall); + return *reinterpret_cast<T*>(m_data.data() + offset); + } + + template<typename T = uint8_t> + const T& getDrawcall(size_t index) const { + const size_t offset = (index * m_sizePerDrawcall); + return *reinterpret_cast<const T*>(m_data.data() + offset); + } + + [[nodiscard]] + const void* getDrawcallData(size_t index) const { + const size_t offset = (index * m_sizePerDrawcall); + return reinterpret_cast<const void*>(m_data.data() + offset); + } + + [[nodiscard]] + const void* getData() const { + if (m_data.empty()) { + return nullptr; + } else { + return m_data.data(); + } + } + + }; + +} diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 28b2184b2a83515a514f1428733bcf8cf1499633..802200ad5deb76decbb75e30e1fbd14bff3b7e3b 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,8 +1,9 @@ # Add new modules here: add_subdirectory(asset_loader) -add_subdirectory(material) add_subdirectory(camera) add_subdirectory(gui) +add_subdirectory(material) +add_subdirectory(scene) add_subdirectory(shader_compiler) add_subdirectory(testing) diff --git a/modules/camera/include/vkcv/camera/Camera.hpp b/modules/camera/include/vkcv/camera/Camera.hpp index 9d85df7dce6d043630fd9d39287cace8530dbd6a..8a8c5df5d74cf1402bd8810172657ba77ddb2d56 100644 --- a/modules/camera/include/vkcv/camera/Camera.hpp +++ b/modules/camera/include/vkcv/camera/Camera.hpp @@ -3,6 +3,8 @@ #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_access.hpp> +#include <glm/vec3.hpp> +#include <glm/mat4x4.hpp> namespace vkcv::camera { @@ -20,9 +22,6 @@ namespace vkcv::camera { glm::vec3 m_up; glm::vec3 m_position; glm::vec3 m_center; - - float m_pitch; - float m_yaw; /** * @brief Sets the view matrix of the camera to @p view @@ -75,7 +74,7 @@ namespace vkcv::camera { * @brief Gets the current projection of the camera * @return The current projection matrix */ - glm::mat4 getProjection() const; + const glm::mat4& getProjection() const; /** * @brief Gets the model-view-projection matrix of the camera with y-axis-correction applied @@ -156,6 +155,20 @@ namespace vkcv::camera { * @param[in] center The new center point. */ void setCenter(const glm::vec3& center); + + /** + * @brief Gets the angles of the camera. + * @param[out] pitch The pitch value in radians + * @param[out] yaw The yaw value in radians + */ + void getAngles(float& pitch, float& yaw); + + /** + * @brief Sets the angles of the camera. + * @param pitch The new pitch value in radians + * @param yaw The new yaw value in radians + */ + void setAngles(float pitch, float yaw); /** * @brief Gets the pitch value of the camera in degrees. diff --git a/modules/camera/include/vkcv/camera/TrackballCameraController.hpp b/modules/camera/include/vkcv/camera/TrackballCameraController.hpp index 4166bda9f6cb62e4c8f1b650557b00c6ec94b2a1..20336f7a10644c73e451c5106f37545e84eb27f7 100644 --- a/modules/camera/include/vkcv/camera/TrackballCameraController.hpp +++ b/modules/camera/include/vkcv/camera/TrackballCameraController.hpp @@ -14,6 +14,8 @@ namespace vkcv::camera { float m_cameraSpeed; float m_scrollSensitivity; float m_radius; + float m_pitch; + float m_yaw; /** * @brief Updates the current radius of @p camera in respect to the @p offset. diff --git a/modules/camera/src/vkcv/camera/Camera.cpp b/modules/camera/src/vkcv/camera/Camera.cpp index 3541b1a5bc1253c6b0f2b044d757341855a5e900..87d09aa9a6e3e7dc80d5de9a95f3e1e3b72e9205 100644 --- a/modules/camera/src/vkcv/camera/Camera.cpp +++ b/modules/camera/src/vkcv/camera/Camera.cpp @@ -10,8 +10,6 @@ namespace vkcv::camera { glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f) ); - - setFront(glm::normalize(m_center - m_position)); } Camera::~Camera() = default; @@ -44,20 +42,20 @@ namespace vkcv::camera { 0.0f, 0.0f, 0.0f, 1.0f ); - glm::mat4 Camera::getProjection() const { - return y_correction * m_projection; + const glm::mat4& Camera::getProjection() const { + return m_projection; } void Camera::setProjection(const glm::mat4& projection) { - m_projection = glm::inverse(y_correction) * projection; + m_projection = y_correction * projection; } glm::mat4 Camera::getMVP() const { - return y_correction * m_projection * m_view; + return m_projection * m_view; } float Camera::getFov() const { - const float tanHalfFovy = 1.0f / m_projection[1][1]; + const float tanHalfFovy = -1.0f / m_projection[1][1]; float halfFovy = std::atan(tanHalfFovy); if (halfFovy < 0) { @@ -73,7 +71,7 @@ namespace vkcv::camera { float Camera::getRatio() const { const float aspectProduct = 1.0f / m_projection[0][0]; - const float tanHalfFovy = 1.0f / m_projection[1][1]; + const float tanHalfFovy = -1.0f / m_projection[1][1]; return aspectProduct / tanHalfFovy; } @@ -93,16 +91,11 @@ namespace vkcv::camera { } glm::vec3 Camera::getFront() const { - glm::vec3 direction; - direction.x = std::sin(glm::radians(m_yaw)) * std::cos(glm::radians(m_pitch)); - direction.y = std::sin(glm::radians(m_pitch)); - direction.z = std::cos(glm::radians(m_yaw)) * std::cos(glm::radians(m_pitch)); - return glm::normalize(direction); + return glm::normalize(m_center - m_position); } void Camera::setFront(const glm::vec3 &front) { - m_pitch = std::atan2(front.y, std::sqrt(front.x * front.x + front.z * front.z)); - m_yaw = std::atan2(front.x, front.z); + setCenter(m_position + front); } const glm::vec3& Camera::getPosition() const { @@ -128,21 +121,47 @@ namespace vkcv::camera { void Camera::setUp(const glm::vec3 &up) { lookAt(m_position, m_center, up); } - - float Camera::getPitch() const { - return m_pitch; + + void Camera::getAngles(float& pitch, float& yaw) { + const auto front = getFront(); + + pitch = std::atan2(front[1], std::sqrt( + front[0] * front[0] + front[2] * front[2] + )); + + yaw = std::atan2(front[0], front[2]); + } + + void Camera::setAngles(float pitch, float yaw) { + float cosPitch = std::cos(pitch); + + setFront(glm::vec3( + std::sin(yaw) * cosPitch, + std::sin(pitch), + std::cos(yaw) * cosPitch + )); + } + + float Camera::getPitch() const { + const auto front = getFront(); + + return glm::degrees(std::atan2(front[1], std::sqrt( + front[0] * front[0] + front[2] * front[2] + ))); } void Camera::setPitch(float pitch) { - m_pitch = pitch; + setAngles(glm::radians(pitch), glm::radians(getYaw())); } float Camera::getYaw() const { - return m_yaw; + const auto front = getFront(); + + return glm::degrees(std::atan2(front[0], front[2])); } void Camera::setYaw(float yaw) { - m_yaw = yaw; + setAngles(glm::radians(getPitch()), glm::radians(yaw)); } } \ No newline at end of file diff --git a/modules/camera/src/vkcv/camera/PilotCameraController.cpp b/modules/camera/src/vkcv/camera/PilotCameraController.cpp index 5460858ab48d81252787b3c0141dd72982faca7d..28ef7c6943428078589047497fc2d3b44fde5fd7 100644 --- a/modules/camera/src/vkcv/camera/PilotCameraController.cpp +++ b/modules/camera/src/vkcv/camera/PilotCameraController.cpp @@ -50,12 +50,11 @@ namespace vkcv::camera { } // handle yaw rotation - float yaw = camera.getYaw() + static_cast<float>(xOffset); - yaw += 360.0f * (yaw < -180.0f) - 360.0f * (yaw > 180.0f); + float yaw = camera.getYaw() + static_cast<float>(xOffset) * m_cameraSpeed; camera.setYaw(yaw); // handle pitch rotation - float pitch = camera.getPitch() - static_cast<float>(yOffset); + float pitch = camera.getPitch() - static_cast<float>(yOffset) * m_cameraSpeed; pitch = glm::clamp(pitch, -89.0f, 89.0f); camera.setPitch(pitch); } diff --git a/modules/camera/src/vkcv/camera/TrackballCameraController.cpp b/modules/camera/src/vkcv/camera/TrackballCameraController.cpp index cdd66cdb7fdd650d5112fe7bb4738f1fcded7783..b149a168f061125c08103ba63fcd7a97fa13ccc3 100644 --- a/modules/camera/src/vkcv/camera/TrackballCameraController.cpp +++ b/modules/camera/src/vkcv/camera/TrackballCameraController.cpp @@ -8,6 +8,8 @@ namespace vkcv::camera { m_radius = 3.0f; m_cameraSpeed = 2.5f; m_scrollSensitivity = 0.2f; + m_pitch = 0.0f; + m_yaw = 0.0f; } void TrackballCameraController::setRadius(const float radius) { @@ -21,14 +23,10 @@ namespace vkcv::camera { } // handle yaw rotation - float yaw = camera.getYaw() + static_cast<float>(xOffset) * m_cameraSpeed; - yaw += 360.0f * (yaw < 0.0f) - 360.0f * (yaw > 360.0f); - camera.setYaw(yaw); + m_yaw = m_yaw + static_cast<float>(xOffset) * m_cameraSpeed; // handle pitch rotation - float pitch = camera.getPitch() + static_cast<float>(yOffset) * m_cameraSpeed; - pitch += 360.0f * (pitch < 0.0f) - 360.0f * (pitch > 360.0f); - camera.setPitch(pitch); + m_pitch = m_pitch + static_cast<float>(yOffset) * m_cameraSpeed; } void TrackballCameraController::updateRadius(double offset, Camera &camera) { @@ -44,14 +42,11 @@ namespace vkcv::camera { } void TrackballCameraController::updateCamera(double deltaTime, Camera &camera) { - float yaw = camera.getYaw(); - float pitch = camera.getPitch(); - const glm::vec3 yAxis = glm::vec3(0.0f, 1.0f, 0.0f); const glm::vec3 xAxis = glm::vec3(1.0f, 0.0f, 0.0f); - const glm::mat4 rotationY = glm::rotate(glm::mat4(1.0f), glm::radians(yaw), yAxis); - const glm::mat4 rotationX = glm::rotate(rotationY, -glm::radians(pitch), xAxis); + const glm::mat4 rotationY = glm::rotate(glm::mat4(1.0f), glm::radians(m_yaw), yAxis); + const glm::mat4 rotationX = glm::rotate(rotationY, -glm::radians(m_pitch), xAxis); const glm::vec3 translation = glm::vec3( rotationX * glm::vec4(0.0f, 0.0f, m_radius, 0.0f) ); diff --git a/modules/material/CMakeLists.txt b/modules/material/CMakeLists.txt index d5b654cc6d00ce77d93b4666f48b7a5097e674b3..ed3804531d36f9850bbb5d334e4fed9b43d92434 100644 --- a/modules/material/CMakeLists.txt +++ b/modules/material/CMakeLists.txt @@ -12,8 +12,6 @@ set(vkcv_material_include ${PROJECT_SOURCE_DIR}/include) set(vkcv_material_sources ${vkcv_material_include}/vkcv/material/Material.hpp ${vkcv_material_source}/vkcv/material/Material.cpp - ${vkcv_material_include}/vkcv/material/PBRMaterial.hpp - ${vkcv_material_source}/vkcv/material/PBRMaterial.cpp ) # adding source files to the module diff --git a/modules/material/include/vkcv/material/Material.hpp b/modules/material/include/vkcv/material/Material.hpp index 00b492072fa4ef8b7b41f70202d515ee4ac828fa..9b54d99828eca3738fed9ff1c4078ca9f87eaefa 100644 --- a/modules/material/include/vkcv/material/Material.hpp +++ b/modules/material/include/vkcv/material/Material.hpp @@ -1,14 +1,70 @@ #pragma once + +#include <vector> + +#include <vkcv/Core.hpp> #include <vkcv/Handles.hpp> namespace vkcv::material { - + + enum class MaterialType { + PBR_MATERIAL = 1, + + UNKNOWN = 0 + }; + class Material { private: + struct Texture { + ImageHandle m_Image; + SamplerHandle m_Sampler; + std::vector<float> m_Factors; + }; + + MaterialType m_Type; + DescriptorSetHandle m_DescriptorSet; + std::vector<Texture> m_Textures; + public: - const DescriptorSetHandle m_DescriptorSetHandle; - protected: - Material(const DescriptorSetHandle& setHandle); + Material(); + ~Material() = default; + + Material(const Material& other) = default; + Material(Material&& other) = default; + + Material& operator=(const Material& other) = default; + Material& operator=(Material&& other) = default; + + [[nodiscard]] + MaterialType getType() const; + + [[nodiscard]] + const DescriptorSetHandle& getDescriptorSet() const; + + explicit operator bool() const; + + bool operator!() const; + + static const std::vector<DescriptorBinding>& getDescriptorBindings(MaterialType type); + + static Material createPBR(Core &core, + const ImageHandle &colorImg, + const SamplerHandle &colorSmp, + const ImageHandle &normalImg, + const SamplerHandle &normalSmp, + const ImageHandle &metRoughImg, + const SamplerHandle &metRoughSmp, + const ImageHandle &occlusionImg, + const SamplerHandle &occlusionSmp, + const ImageHandle &emissiveImg, + const SamplerHandle &emissiveSmp, + const float baseColorFactor [4], + float metallicFactor, + float roughnessFactor, + float normalScale, + float occlusionStrength, + const float emissiveFactor [3]); + }; } diff --git a/modules/material/include/vkcv/material/PBRMaterial.hpp b/modules/material/include/vkcv/material/PBRMaterial.hpp deleted file mode 100644 index 09a5214b0e748a09ef8caefe5bf2b1a69ecbd8e1..0000000000000000000000000000000000000000 --- a/modules/material/include/vkcv/material/PBRMaterial.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include <vector> - -#include <vkcv/DescriptorConfig.hpp> -#include <vkcv/Core.hpp> - - -#include "Material.hpp" - -namespace vkcv::material -{ - class PBRMaterial : Material - { - private: - struct vec3 { - float x, y, z; - }; - struct vec4 { - float x, y, z, a; - }; - PBRMaterial(const ImageHandle& colorImg, - const SamplerHandle& colorSmp, - const ImageHandle& normalImg, - const SamplerHandle& normalSmp, - const ImageHandle& metRoughImg, - const SamplerHandle& metRoughSmp, - const ImageHandle& occlusionImg, - const SamplerHandle& occlusionSmp, - const ImageHandle& emissiveImg, - const SamplerHandle& emissiveSmp, - const DescriptorSetHandle& setHandle, - vec4 baseColorFactor, - float metallicFactor, - float roughnessFactor, - float normalScale, - float occlusionStrength, - vec3 emissiveFactor) noexcept; - - - public: - PBRMaterial() = delete; - - const ImageHandle m_ColorTexture; - const SamplerHandle m_ColorSampler; - - const ImageHandle m_NormalTexture; - const SamplerHandle m_NormalSampler; - - const ImageHandle m_MetRoughTexture; - const SamplerHandle m_MetRoughSampler; - - const ImageHandle m_OcclusionTexture; - const SamplerHandle m_OcclusionSampler; - - const ImageHandle m_EmissiveTexture; - const SamplerHandle m_EmissiveSampler; - - // - const vec4 m_BaseColorFactor; - const float m_MetallicFactor; - const float m_RoughnessFactor; - const float m_NormalScale; - const float m_OcclusionStrength; - const vec3 m_EmissiveFactor; - - /* - * Returns the material's necessary descriptor bindings which serves as its descriptor layout - * The binding is in the following order: - * 0 - diffuse texture - * 1 - diffuse sampler - * 2 - normal texture - * 3 - normal sampler - * 4 - metallic roughness texture - * 5 - metallic roughness sampler - * 6 - occlusion texture - * 7 - occlusion sampler - * 8 - emissive texture - * 9 - emissive sampler - */ - static std::vector<DescriptorBinding> getDescriptorBindings() noexcept; - - static PBRMaterial create( - vkcv::Core* core, - ImageHandle &colorImg, - SamplerHandle &colorSmp, - ImageHandle &normalImg, - SamplerHandle &normalSmp, - ImageHandle &metRoughImg, - SamplerHandle &metRoughSmp, - ImageHandle &occlusionImg, - SamplerHandle &occlusionSmp, - ImageHandle &emissiveImg, - SamplerHandle &emissiveSmp, - vec4 baseColorFactor, - float metallicFactor, - float roughnessFactor, - float normalScale, - float occlusionStrength, - vec3 emissiveFactor); - - }; -} \ No newline at end of file diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp index 9168bcfbf924e9868ceaaff74aef5d3c6b99739c..409db0b9dd83f91b6a2afbb48d74933ab1a483fc 100644 --- a/modules/material/src/vkcv/material/Material.cpp +++ b/modules/material/src/vkcv/material/Material.cpp @@ -2,11 +2,185 @@ #include "vkcv/material/Material.hpp" namespace vkcv::material { + + Material::Material() { + m_Type = MaterialType::UNKNOWN; + } - //TODO - - Material::Material(const DescriptorSetHandle& setHandle) : m_DescriptorSetHandle(setHandle) + MaterialType Material::getType() const { + return m_Type; + } + + const DescriptorSetHandle & Material::getDescriptorSet() const { + return m_DescriptorSet; + } + + Material::operator bool() const { + return (m_Type != MaterialType::UNKNOWN); + } + + bool Material::operator!() const { + return (m_Type == MaterialType::UNKNOWN); + } + + const std::vector<DescriptorBinding>& Material::getDescriptorBindings(MaterialType type) { + static std::vector<DescriptorBinding> pbr_bindings; + static std::vector<DescriptorBinding> default_bindings; + + switch (type) { + case MaterialType::PBR_MATERIAL: + if (pbr_bindings.empty()) { + pbr_bindings.emplace_back(0, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + pbr_bindings.emplace_back(1, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + pbr_bindings.emplace_back(2, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + pbr_bindings.emplace_back(3, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + pbr_bindings.emplace_back(4, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + pbr_bindings.emplace_back(5, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + pbr_bindings.emplace_back(6, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + pbr_bindings.emplace_back(7, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + pbr_bindings.emplace_back(8, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + pbr_bindings.emplace_back(9, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + } + + return pbr_bindings; + default: + return default_bindings; + } + } + + static void fillImage(Image& image, float data [4]) { + std::vector<float> vec (image.getWidth() * image.getHeight() * image.getDepth() * 4); + + for (size_t i = 0; i < vec.size(); i++) { + vec[i] = data[i % 4]; + } + + image.fill(data); + } + + Material Material::createPBR(Core &core, + const ImageHandle &colorImg, const SamplerHandle &colorSmp, + const ImageHandle &normalImg, const SamplerHandle &normalSmp, + const ImageHandle &metRoughImg, const SamplerHandle &metRoughSmp, + const ImageHandle &occlusionImg, const SamplerHandle &occlusionSmp, + const ImageHandle &emissiveImg, const SamplerHandle &emissiveSmp, + const float baseColorFactor [4], + float metallicFactor, + float roughnessFactor, + float normalScale, + float occlusionStrength, + const float emissiveFactor [3]) { + ImageHandle images [5] = { + colorImg, normalImg, metRoughImg, occlusionImg, emissiveImg + }; + + SamplerHandle samplers [5] = { + colorSmp, normalSmp, metRoughSmp, occlusionSmp, emissiveSmp + }; + + if (!colorImg) { + vkcv::Image defaultColor = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2); + float colorData [4] = { 228, 51, 255, 1 }; + fillImage(defaultColor, colorData); + images[0] = defaultColor.getHandle(); + } + + if (!normalImg) { + vkcv::Image defaultNormal = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2); + float normalData [4] = { 0, 0, 1, 0 }; + fillImage(defaultNormal, normalData); + images[1] = defaultNormal.getHandle(); + } + + if (!metRoughImg) { + vkcv::Image defaultRough = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2); + float roughData [4] = { 228, 51, 255, 1 }; + fillImage(defaultRough, roughData); + images[2] = defaultRough.getHandle(); + } + + if (!occlusionImg) { + vkcv::Image defaultOcclusion = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2); + float occlusionData [4] = { 228, 51, 255, 1 }; + fillImage(defaultOcclusion, occlusionData); + images[3] = defaultOcclusion.getHandle(); + } + + if (!emissiveImg) { + vkcv::Image defaultEmissive = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2); + float emissiveData [4] = { 0, 0, 0, 1 }; + fillImage(defaultEmissive, emissiveData); + images[4] = defaultEmissive.getHandle(); + } + + if (!colorSmp) { + samplers[0] = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + + if (!normalSmp) { + samplers[1] = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + + if (!metRoughSmp) { + samplers[2] = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + + if (!occlusionSmp) { + samplers[3] = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + + if (!emissiveSmp) { + samplers[4] = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + + Material material; + material.m_Type = MaterialType::PBR_MATERIAL; + + const auto& bindings = getDescriptorBindings(material.m_Type); + material.m_DescriptorSet = core.createDescriptorSet(bindings);; + + material.m_Textures.reserve(bindings.size()); + material.m_Textures.push_back({ images[0], samplers[0], std::vector<float>(baseColorFactor, baseColorFactor+4) }); + material.m_Textures.push_back({ images[1], samplers[1], { normalScale } }); + material.m_Textures.push_back({ images[2], samplers[2], { metallicFactor, roughnessFactor } }); + material.m_Textures.push_back({ images[3], samplers[3], { occlusionStrength } }); + material.m_Textures.push_back({ images[4], samplers[4], std::vector<float>(emissiveFactor, emissiveFactor+3) }); + + vkcv::DescriptorWrites setWrites; + + for (size_t i = 0; i < material.m_Textures.size(); i++) { + setWrites.sampledImageWrites.emplace_back(i * 2, material.m_Textures[i].m_Image); + setWrites.samplerWrites.emplace_back(i * 2 + 1, material.m_Textures[i].m_Sampler); + } + + core.writeDescriptorSet(material.m_DescriptorSet, setWrites); + return material; } } diff --git a/modules/material/src/vkcv/material/PBRMaterial.cpp b/modules/material/src/vkcv/material/PBRMaterial.cpp deleted file mode 100644 index d27e755c06a39e369d22efc997a0b411d067c132..0000000000000000000000000000000000000000 --- a/modules/material/src/vkcv/material/PBRMaterial.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include "vkcv/material/PBRMaterial.hpp" - - -namespace vkcv::material -{ - PBRMaterial::PBRMaterial( - const ImageHandle& colorImg, - const SamplerHandle& colorSmp, - const ImageHandle& normalImg, - const SamplerHandle& normalSmp, - const ImageHandle& metRoughImg, - const SamplerHandle& metRoughSmp, - const ImageHandle& occlusionImg, - const SamplerHandle& occlusionSmp, - const ImageHandle& emissiveImg, - const SamplerHandle& emissiveSmp, - const DescriptorSetHandle& setHandle, - vec4 baseColorFactor, - float metallicFactor, - float roughnessFactor, - float normalScale, - float occlusionStrength, - vec3 emissiveFactor) noexcept : - m_ColorTexture(colorImg), - m_ColorSampler(colorSmp), - m_NormalTexture(normalImg), - m_NormalSampler(normalSmp), - m_MetRoughTexture(metRoughImg), - m_MetRoughSampler(metRoughSmp), - m_OcclusionTexture(occlusionImg), - m_OcclusionSampler(occlusionSmp), - m_EmissiveTexture(emissiveImg), - m_EmissiveSampler(emissiveSmp), - Material(setHandle), - m_BaseColorFactor(baseColorFactor), - m_MetallicFactor(metallicFactor), - m_RoughnessFactor(roughnessFactor), - m_NormalScale(normalScale), - m_OcclusionStrength(occlusionStrength), - m_EmissiveFactor(emissiveFactor) - { - } - - std::vector<DescriptorBinding> PBRMaterial::getDescriptorBindings() noexcept - { - static std::vector<DescriptorBinding> bindings; - - if (bindings.empty()) { - bindings.emplace_back(0, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); - bindings.emplace_back(1, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); - bindings.emplace_back(2, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); - bindings.emplace_back(3, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); - bindings.emplace_back(4, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); - bindings.emplace_back(5, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); - bindings.emplace_back(6, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); - bindings.emplace_back(7, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); - bindings.emplace_back(8, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); - bindings.emplace_back(9, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); - } - - return bindings; - } - - PBRMaterial PBRMaterial::create( - vkcv::Core* core, - ImageHandle& colorImg, - SamplerHandle& colorSmp, - ImageHandle& normalImg, - SamplerHandle& normalSmp, - ImageHandle& metRoughImg, - SamplerHandle& metRoughSmp, - ImageHandle& occlusionImg, - SamplerHandle& occlusionSmp, - ImageHandle& emissiveImg, - SamplerHandle& emissiveSmp, - vec4 baseColorFactor, - float metallicFactor, - float roughnessFactor, - float normalScale, - float occlusionStrength, - vec3 emissiveFactor) - { - //Test if Images and samplers valid, if not use default - if (!colorImg) { - vkcv::Image defaultColor = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); - vec4 colorData{ 228, 51, 255,1 }; - defaultColor.fill(&colorData); - colorImg = defaultColor.getHandle(); - } - if (!normalImg) { - vkcv::Image defaultNormal = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); - vec4 normalData{ 0, 0, 1,0 }; - defaultNormal.fill(&normalData); - normalImg = defaultNormal.getHandle(); - } - if (!metRoughImg) { - vkcv::Image defaultRough = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); - vec4 roughData{ 228, 51, 255,1 }; - defaultRough.fill(&roughData); - metRoughImg = defaultRough.getHandle(); - } - if (!occlusionImg) { - vkcv::Image defaultOcclusion = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); - vec4 occlusionData{ 228, 51, 255,1 }; - defaultOcclusion.fill(&occlusionData); - occlusionImg = defaultOcclusion.getHandle(); - } - if (!emissiveImg) { - vkcv::Image defaultEmissive = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); - vec4 emissiveData{ 0, 0, 0,1 }; - defaultEmissive.fill(&emissiveData); - emissiveImg = defaultEmissive.getHandle(); - } - if (!colorSmp) { - colorSmp = core->createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - } - if (!normalSmp) { - normalSmp = core->createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - } - if (!metRoughSmp) { - metRoughSmp = core->createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - } - if (!occlusionSmp) { - occlusionSmp = core->createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - } - if (!emissiveSmp) { - emissiveSmp = core->createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - } - - - - //create descriptorset - vkcv::DescriptorSetHandle descriptorSetHandle = core->createDescriptorSet(getDescriptorBindings()); - //writes - vkcv::DescriptorWrites setWrites; - setWrites.sampledImageWrites = { - vkcv::SampledImageDescriptorWrite(0, colorImg), - vkcv::SampledImageDescriptorWrite(2, normalImg), - vkcv::SampledImageDescriptorWrite(4, metRoughImg), - vkcv::SampledImageDescriptorWrite(6, occlusionImg), - vkcv::SampledImageDescriptorWrite(8, emissiveImg) }; - setWrites.samplerWrites = { - vkcv::SamplerDescriptorWrite(1, colorSmp), - vkcv::SamplerDescriptorWrite(3, normalSmp), - vkcv::SamplerDescriptorWrite(5, metRoughSmp), - vkcv::SamplerDescriptorWrite(7, occlusionSmp), - vkcv::SamplerDescriptorWrite(9, emissiveSmp) }; - core->writeDescriptorSet(descriptorSetHandle, setWrites); - - return PBRMaterial( - colorImg, - colorSmp, - normalImg, - normalSmp, - metRoughImg, - metRoughSmp, - occlusionImg, - occlusionSmp, - emissiveImg, - emissiveSmp, - descriptorSetHandle, - baseColorFactor, - metallicFactor, - roughnessFactor, - normalScale, - occlusionStrength, - emissiveFactor); - } -} \ No newline at end of file diff --git a/modules/scene/CMakeLists.txt b/modules/scene/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9aa76883a260d26aa6f46d6dabdc8206e4dad387 --- /dev/null +++ b/modules/scene/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.16) +project(vkcv_scene) + +# setting c++ standard for the module +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(vkcv_scene_source ${PROJECT_SOURCE_DIR}/src) +set(vkcv_scene_include ${PROJECT_SOURCE_DIR}/include) + +# Add source and header files to the module +set(vkcv_scene_sources + ${vkcv_scene_include}/vkcv/scene/Bounds.hpp + ${vkcv_scene_source}/vkcv/scene/Bounds.cpp + + ${vkcv_scene_source}/vkcv/scene/Frustum.hpp + ${vkcv_scene_source}/vkcv/scene/Frustum.cpp + + ${vkcv_scene_include}/vkcv/scene/MeshPart.hpp + ${vkcv_scene_source}/vkcv/scene/MeshPart.cpp + + ${vkcv_scene_include}/vkcv/scene/Mesh.hpp + ${vkcv_scene_source}/vkcv/scene/Mesh.cpp + + ${vkcv_scene_include}/vkcv/scene/Node.hpp + ${vkcv_scene_source}/vkcv/scene/Node.cpp + + ${vkcv_scene_include}/vkcv/scene/Scene.hpp + ${vkcv_scene_source}/vkcv/scene/Scene.cpp +) + +# adding source files to the module +add_library(vkcv_scene STATIC ${vkcv_scene_sources}) + +# link the required libraries to the module +target_link_libraries(vkcv_scene vkcv) + +# including headers of dependencies and the VkCV framework +target_include_directories(vkcv_scene SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_material_include} ${vkcv_camera_include}) + +# add the own include directory for public headers +target_include_directories(vkcv_scene BEFORE PUBLIC ${vkcv_scene_include}) + +# linking with libraries from all dependencies and the VkCV framework +target_link_libraries(vkcv_scene vkcv vkcv_asset_loader vkcv_material vkcv_camera) \ No newline at end of file diff --git a/modules/scene/include/vkcv/scene/Bounds.hpp b/modules/scene/include/vkcv/scene/Bounds.hpp new file mode 100644 index 0000000000000000000000000000000000000000..07cdf88828d786982b0fe8e7919d543557794c42 --- /dev/null +++ b/modules/scene/include/vkcv/scene/Bounds.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include <array> +#include <iostream> +#include <glm/vec3.hpp> + +namespace vkcv::scene { + + class Bounds { + private: + glm::vec3 m_min; + glm::vec3 m_max; + + public: + Bounds(); + Bounds(const glm::vec3& min, const glm::vec3& max); + ~Bounds() = default; + + Bounds(const Bounds& other) = default; + Bounds(Bounds&& other) = default; + + Bounds& operator=(const Bounds& other) = default; + Bounds& operator=(Bounds&& other) = default; + + void setMin(const glm::vec3& min); + + [[nodiscard]] + const glm::vec3& getMin() const; + + void setMax(const glm::vec3& max); + + [[nodiscard]] + const glm::vec3& getMax() const; + + void setCenter(const glm::vec3& center); + + [[nodiscard]] + glm::vec3 getCenter() const; + + void setSize(const glm::vec3& size); + + [[nodiscard]] + glm::vec3 getSize() const; + + [[nodiscard]] + std::array<glm::vec3, 8> getCorners() const; + + void extend(const glm::vec3& point); + + [[nodiscard]] + bool contains(const glm::vec3& point) const; + + [[nodiscard]] + bool contains(const Bounds& other) const; + + [[nodiscard]] + bool intersects(const Bounds& other) const; + + [[nodiscard]] + explicit operator bool() const; + + [[nodiscard]] + bool operator!() const; + + }; + + std::ostream& operator << (std::ostream& out, const Bounds& bounds); + +} diff --git a/modules/scene/include/vkcv/scene/Mesh.hpp b/modules/scene/include/vkcv/scene/Mesh.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bc82af4bfabed5e8bfc286bc53cd7b89791726fc --- /dev/null +++ b/modules/scene/include/vkcv/scene/Mesh.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include <glm/mat4x4.hpp> + +#include <vkcv/camera/Camera.hpp> + +#include "MeshPart.hpp" + +namespace vkcv::scene { + + typedef typename event_function<const glm::mat4&, const glm::mat4&, PushConstants&, vkcv::DrawcallInfo&>::type RecordMeshDrawcallFunction; + + class Node; + + class Mesh { + friend class Node; + + private: + Scene& m_scene; + std::vector<MeshPart> m_parts; + std::vector<DrawcallInfo> m_drawcalls; + glm::mat4 m_transform; + Bounds m_bounds; + + explicit Mesh(Scene& scene); + + void load(const asset::Scene& scene, + const asset::Mesh& mesh); + + void recordDrawcalls(const glm::mat4& viewProjection, + PushConstants& pushConstants, + std::vector<DrawcallInfo>& drawcalls, + const RecordMeshDrawcallFunction& record); + + [[nodiscard]] + size_t getDrawcallCount() const; + + public: + ~Mesh(); + + Mesh(const Mesh& other) = default; + Mesh(Mesh&& other) = default; + + Mesh& operator=(const Mesh& other); + Mesh& operator=(Mesh&& other) noexcept; + + [[nodiscard]] + const Bounds& getBounds() const; + + }; + +} diff --git a/modules/scene/include/vkcv/scene/MeshPart.hpp b/modules/scene/include/vkcv/scene/MeshPart.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0d3467c6b57fcece69eb6f0c609c604fb99907d2 --- /dev/null +++ b/modules/scene/include/vkcv/scene/MeshPart.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include <vector> + +#include <vkcv/Buffer.hpp> +#include <vkcv/asset/asset_loader.hpp> +#include <vkcv/material/Material.hpp> + +#include "Bounds.hpp" + +namespace vkcv::scene { + + class Scene; + class Mesh; + + class MeshPart { + friend class Mesh; + + private: + Scene& m_scene; + BufferHandle m_vertices; + std::vector<VertexBufferBinding> m_vertexBindings; + BufferHandle m_indices; + size_t m_indexCount; + Bounds m_bounds; + size_t m_materialIndex; + + explicit MeshPart(Scene& scene); + + void load(const asset::Scene& scene, + const asset::VertexGroup& vertexGroup, + std::vector<DrawcallInfo>& drawcalls); + + public: + ~MeshPart(); + + MeshPart(const MeshPart& other); + MeshPart(MeshPart&& other); + + MeshPart& operator=(const MeshPart& other); + MeshPart& operator=(MeshPart&& other) noexcept; + + [[nodiscard]] + const material::Material& getMaterial() const; + + [[nodiscard]] + const Bounds& getBounds() const; + + explicit operator bool() const; + bool operator!() const; + + }; + +} diff --git a/modules/scene/include/vkcv/scene/Node.hpp b/modules/scene/include/vkcv/scene/Node.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1fcca5b9cbecf1064070d7737d008d2b108371db --- /dev/null +++ b/modules/scene/include/vkcv/scene/Node.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include <vector> + +#include <vkcv/camera/Camera.hpp> + +#include "Bounds.hpp" +#include "Mesh.hpp" + +namespace vkcv::scene { + + class Scene; + + class Node { + friend class Scene; + + private: + Scene& m_scene; + + std::vector<Mesh> m_meshes; + std::vector<Node> m_nodes; + Bounds m_bounds; + + explicit Node(Scene& scene); + + void addMesh(const Mesh& mesh); + + void loadMesh(const asset::Scene& asset_scene, const asset::Mesh& asset_mesh); + + void recordDrawcalls(const glm::mat4& viewProjection, + PushConstants& pushConstants, + std::vector<DrawcallInfo>& drawcalls, + const RecordMeshDrawcallFunction& record); + + void splitMeshesToSubNodes(size_t maxMeshesPerNode); + + [[nodiscard]] + size_t getDrawcallCount() const; + + size_t addNode(); + + Node& getNode(size_t index); + + [[nodiscard]] + const Node& getNode(size_t index) const; + + public: + ~Node(); + + Node(const Node& other) = default; + Node(Node&& other) = default; + + Node& operator=(const Node& other); + Node& operator=(Node&& other) noexcept; + + [[nodiscard]] + const Bounds& getBounds() const; + + }; + +} diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp new file mode 100644 index 0000000000000000000000000000000000000000..429c0bcf729f9afb7dd76cdd58c54931862e1a4a --- /dev/null +++ b/modules/scene/include/vkcv/scene/Scene.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include <filesystem> +#include <mutex> + +#include <vkcv/Core.hpp> +#include <vkcv/Event.hpp> +#include <vkcv/camera/Camera.hpp> +#include <vkcv/material/Material.hpp> + +#include "Node.hpp" + +namespace vkcv::scene { + + class Scene { + friend class MeshPart; + + private: + struct Material { + size_t m_usages; + material::Material m_data; + }; + + Core* m_core; + + std::vector<Material> m_materials; + std::vector<Node> m_nodes; + + explicit Scene(Core* core); + + size_t addNode(); + + Node& getNode(size_t index); + + const Node& getNode(size_t index) const; + + void increaseMaterialUsage(size_t index); + + void decreaseMaterialUsage(size_t index); + + void loadMaterial(size_t index, const asset::Scene& scene, + const asset::Material& material); + + public: + ~Scene(); + + Scene(const Scene& other); + Scene(Scene&& other) noexcept; + + Scene& operator=(const Scene& other); + Scene& operator=(Scene&& other) noexcept; + + size_t getMaterialCount() const; + + [[nodiscard]] + const material::Material& getMaterial(size_t index) const; + + void recordDrawcalls(CommandStreamHandle &cmdStream, + const camera::Camera &camera, + const PassHandle &pass, + const PipelineHandle &pipeline, + size_t pushConstantsSizePerDrawcall, + const RecordMeshDrawcallFunction &record, + const std::vector<ImageHandle> &renderTargets); + + static Scene create(Core& core); + + static Scene load(Core& core, const std::filesystem::path &path); + + }; + +} \ No newline at end of file diff --git a/modules/scene/src/vkcv/scene/Bounds.cpp b/modules/scene/src/vkcv/scene/Bounds.cpp new file mode 100644 index 0000000000000000000000000000000000000000..731d81e928deae4c27f5c857de5b94dc3180888b --- /dev/null +++ b/modules/scene/src/vkcv/scene/Bounds.cpp @@ -0,0 +1,126 @@ + +#include "vkcv/scene/Bounds.hpp" + +namespace vkcv::scene { + + Bounds::Bounds() : + m_min(glm::vec3(0)), + m_max(glm::vec3(0)) {} + + Bounds::Bounds(const glm::vec3 &min, const glm::vec3 &max) : + m_min(min), + m_max(max) + {} + + void Bounds::setMin(const glm::vec3 &min) { + m_min = min; + } + + const glm::vec3 & Bounds::getMin() const { + return m_min; + } + + void Bounds::setMax(const glm::vec3 &max) { + m_max = max; + } + + const glm::vec3 & Bounds::getMax() const { + return m_max; + } + + void Bounds::setCenter(const glm::vec3 ¢er) { + const glm::vec3 size = getSize(); + m_min = center - size / 2.0f; + m_max = center + size / 2.0f; + } + + glm::vec3 Bounds::getCenter() const { + return (m_min + m_max) / 2.0f; + } + + void Bounds::setSize(const glm::vec3 &size) { + const glm::vec3 center = getCenter(); + m_min = center - size / 2.0f; + m_max = center + size / 2.0f; + } + + glm::vec3 Bounds::getSize() const { + return (m_max - m_min); + } + + std::array<glm::vec3, 8> Bounds::getCorners() const { + return { + m_min, + glm::vec3(m_min[0], m_min[1], m_max[2]), + glm::vec3(m_min[0], m_max[1], m_min[2]), + glm::vec3(m_min[0], m_max[1], m_max[2]), + glm::vec3(m_max[0], m_min[1], m_min[2]), + glm::vec3(m_max[0], m_min[1], m_max[2]), + glm::vec3(m_max[0], m_max[1], m_min[2]), + m_max + }; + } + + void Bounds::extend(const glm::vec3 &point) { + m_min = glm::vec3( + std::min(m_min[0], point[0]), + std::min(m_min[1], point[1]), + std::min(m_min[2], point[2]) + ); + + m_max = glm::vec3( + std::max(m_max[0], point[0]), + std::max(m_max[1], point[1]), + std::max(m_max[2], point[2]) + ); + } + + bool Bounds::contains(const glm::vec3 &point) const { + return ( + (point[0] >= m_min[0]) && (point[0] <= m_max[0]) && + (point[1] >= m_min[1]) && (point[1] <= m_max[1]) && + (point[2] >= m_min[2]) && (point[2] <= m_max[2]) + ); + } + + bool Bounds::contains(const Bounds &other) const { + return ( + (other.m_min[0] >= m_min[0]) && (other.m_max[0] <= m_max[0]) && + (other.m_min[1] >= m_min[1]) && (other.m_max[1] <= m_max[1]) && + (other.m_min[2] >= m_min[2]) && (other.m_max[2] <= m_max[2]) + ); + } + + bool Bounds::intersects(const Bounds &other) const { + return ( + (other.m_max[0] >= m_min[0]) && (other.m_min[0] <= m_max[0]) && + (other.m_max[1] >= m_min[1]) && (other.m_min[1] <= m_max[1]) && + (other.m_max[2] >= m_min[2]) && (other.m_min[2] <= m_max[2]) + ); + } + + Bounds::operator bool() const { + return ( + (m_min[0] <= m_max[0]) && + (m_min[1] <= m_max[1]) && + (m_min[2] <= m_max[2]) + ); + } + + bool Bounds::operator!() const { + return ( + (m_min[0] > m_max[0]) || + (m_min[1] > m_max[1]) || + (m_min[2] > m_max[2]) + ); + } + + std::ostream& operator << (std::ostream& out, const Bounds& bounds) { + const auto& min = bounds.getMin(); + const auto& max = bounds.getMax(); + + return out << "[Bounds: (" << min[0] << ", " << min[1] << ", " << min[2] << ") (" + << max[0] << ", " << max[1] << ", " << max[2] << ") ]"; + } + +} diff --git a/modules/scene/src/vkcv/scene/Frustum.cpp b/modules/scene/src/vkcv/scene/Frustum.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c800bb1e4baf4d0feef33c073740fb211da7bf63 --- /dev/null +++ b/modules/scene/src/vkcv/scene/Frustum.cpp @@ -0,0 +1,73 @@ + +#include "Frustum.hpp" + +namespace vkcv::scene { + + static glm::vec3 transformPoint(const glm::mat4& transform, const glm::vec3& point, bool* negative_w) { + const glm::vec4 position = transform * glm::vec4(point, 1.0f); + + + /* + * We divide by the absolute of the 4th coorditnate because + * clipping is weird and points have to move to the other + * side of the camera. + * + * We also need to collect if the 4th coordinate was negative + * to know if all corners are behind the camera. So these can + * be culled as well + */ + if (negative_w) { + const float perspective = std::abs(position[3]); + + *negative_w &= (position[3] < 0.0f); + + return glm::vec3( + position[0] / perspective, + position[1] / perspective, + position[2] / perspective + ); + } else { + return glm::vec3( + position[0], + position[1], + position[2] + ); + } + } + + Bounds transformBounds(const glm::mat4& transform, const Bounds& bounds, bool* negative_w) { + const auto corners = bounds.getCorners(); + + if (negative_w) { + *negative_w = true; + } + + auto projected = transformPoint(transform, corners[0], negative_w); + + Bounds result (projected, projected); + + for (size_t j = 1; j < corners.size(); j++) { + projected = transformPoint(transform, corners[j], negative_w); + result.extend(projected); + } + + return result; + } + + bool checkFrustum(const glm::mat4& transform, const Bounds& bounds) { + static Bounds frustum ( + glm::vec3(-1.0f, -1.0f, -0.0f), + glm::vec3(+1.0f, +1.0f, +1.0f) + ); + + bool negative_w; + auto box = transformBounds(transform, bounds, &negative_w); + + if (negative_w) { + return false; + } else { + return box.intersects(frustum); + } + } + +} diff --git a/modules/scene/src/vkcv/scene/Frustum.hpp b/modules/scene/src/vkcv/scene/Frustum.hpp new file mode 100644 index 0000000000000000000000000000000000000000..de3917575a9aed32459e6403fab1d6d8fe131b0a --- /dev/null +++ b/modules/scene/src/vkcv/scene/Frustum.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include <glm/mat4x4.hpp> +#include "vkcv/scene/Bounds.hpp" + +namespace vkcv::scene { + + Bounds transformBounds(const glm::mat4& transform, const Bounds& bounds, bool* negative_w = nullptr); + + bool checkFrustum(const glm::mat4& transform, const Bounds& bounds); + +} diff --git a/modules/scene/src/vkcv/scene/Mesh.cpp b/modules/scene/src/vkcv/scene/Mesh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53fb81713ed7e14049a21cb91c771d67f2f7086c --- /dev/null +++ b/modules/scene/src/vkcv/scene/Mesh.cpp @@ -0,0 +1,132 @@ + +#include "vkcv/scene/Mesh.hpp" +#include "vkcv/scene/Scene.hpp" +#include "Frustum.hpp" + +namespace vkcv::scene { + + Mesh::Mesh(Scene& scene) : + m_scene(scene) {} + + static glm::mat4 arrayTo4x4Matrix(const std::array<float,16>& array){ + glm::mat4 matrix; + + for (int i = 0; i < 4; i++){ + for (int j = 0; j < 4; j++){ + matrix[i][j] = array[j * 4 + i]; + } + } + + return matrix; + } + + void Mesh::load(const asset::Scene &scene, const asset::Mesh &mesh) { + m_parts.clear(); + m_drawcalls.clear(); + + m_transform = arrayTo4x4Matrix(mesh.modelMatrix); + + for (const auto& vertexGroupIndex : mesh.vertexGroups) { + if ((vertexGroupIndex < 0) || (vertexGroupIndex >= scene.vertexGroups.size())) { + continue; + } + + MeshPart part (m_scene); + part.load(scene, scene.vertexGroups[vertexGroupIndex], m_drawcalls); + + if (!part) { + continue; + } + + auto bounds = transformBounds(m_transform, part.getBounds()); + + if (m_parts.empty()) { + m_bounds = bounds; + } else { + m_bounds.extend(bounds.getMin()); + m_bounds.extend(bounds.getMax()); + } + + m_parts.push_back(part); + } + } + + Mesh::~Mesh() { + m_drawcalls.clear(); + m_parts.clear(); + } + + Mesh &Mesh::operator=(const Mesh &other) { + if (&other == this) { + return *this; + } + + m_parts.resize(other.m_parts.size(), MeshPart(m_scene)); + + for (size_t i = 0; i < m_parts.size(); i++) { + m_parts[i] = other.m_parts[i]; + } + + m_drawcalls = std::vector<DrawcallInfo>(other.m_drawcalls); + m_transform = other.m_transform; + m_bounds = other.m_bounds; + + return *this; + } + + Mesh &Mesh::operator=(Mesh &&other) noexcept { + m_parts.resize(other.m_parts.size(), MeshPart(m_scene)); + + for (size_t i = 0; i < m_parts.size(); i++) { + m_parts[i] = std::move(other.m_parts[i]); + } + + m_drawcalls = std::move(other.m_drawcalls); + m_transform = other.m_transform; + m_bounds = other.m_bounds; + + return *this; + } + + void Mesh::recordDrawcalls(const glm::mat4& viewProjection, + PushConstants& pushConstants, + std::vector<DrawcallInfo>& drawcalls, + const RecordMeshDrawcallFunction& record) { + const glm::mat4 transform = viewProjection * m_transform; + + if (!checkFrustum(viewProjection, m_bounds)) { + return; + } + + if (m_drawcalls.size() == 1) { + drawcalls.push_back(m_drawcalls[0]); + + if (record) { + record(transform, m_transform, pushConstants, drawcalls.back()); + } + } else { + for (size_t i = 0; i < m_parts.size(); i++) { + const MeshPart& part = m_parts[i]; + + if (!checkFrustum(transform, part.getBounds())) { + continue; + } + + drawcalls.push_back(m_drawcalls[i]); + + if (record) { + record(transform, m_transform, pushConstants, drawcalls.back()); + } + } + } + } + + size_t Mesh::getDrawcallCount() const { + return m_drawcalls.size(); + } + + const Bounds& Mesh::getBounds() const { + return m_bounds; + } + +} diff --git a/modules/scene/src/vkcv/scene/MeshPart.cpp b/modules/scene/src/vkcv/scene/MeshPart.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46e79897719d5422151ec31837a41f7e58324a71 --- /dev/null +++ b/modules/scene/src/vkcv/scene/MeshPart.cpp @@ -0,0 +1,158 @@ + +#include "vkcv/scene/MeshPart.hpp" +#include "vkcv/scene/Scene.hpp" + +namespace vkcv::scene { + + MeshPart::MeshPart(Scene& scene) : + m_scene(scene), + m_vertices(), + m_vertexBindings(), + m_indices(), + m_indexCount(0), + m_bounds(), + m_materialIndex(std::numeric_limits<size_t>::max()) {} + + void MeshPart::load(const asset::Scene& scene, + const asset::VertexGroup &vertexGroup, + std::vector<DrawcallInfo>& drawcalls) { + Core& core = *(m_scene.m_core); + + auto vertexBuffer = core.createBuffer<uint8_t>( + BufferType::VERTEX, vertexGroup.vertexBuffer.data.size() + ); + + vertexBuffer.fill(vertexGroup.vertexBuffer.data); + m_vertices = vertexBuffer.getHandle(); + + auto attributes = vertexGroup.vertexBuffer.attributes; + + std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { + return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); + }); + + for (const auto& attribute : attributes) { + m_vertexBindings.emplace_back(attribute.offset, vertexBuffer.getVulkanHandle()); + } + + auto indexBuffer = core.createBuffer<uint8_t>( + BufferType::INDEX, vertexGroup.indexBuffer.data.size() + ); + + indexBuffer.fill(vertexGroup.indexBuffer.data); + m_indices = indexBuffer.getHandle(); + m_indexCount = vertexGroup.numIndices; + + m_bounds.setMin(glm::vec3( + vertexGroup.min.x, + vertexGroup.min.y, + vertexGroup.min.z + )); + + m_bounds.setMax(glm::vec3( + vertexGroup.max.x, + vertexGroup.max.y, + vertexGroup.max.z + )); + + if ((vertexGroup.materialIndex >= 0) && + (vertexGroup.materialIndex < scene.materials.size())) { + m_materialIndex = vertexGroup.materialIndex; + + if (!getMaterial()) { + m_scene.loadMaterial(m_materialIndex, scene, scene.materials[vertexGroup.materialIndex]); + } + + m_scene.increaseMaterialUsage(m_materialIndex); + } else { + m_materialIndex = std::numeric_limits<size_t>::max(); + } + + if (*this) { + const auto& material = getMaterial(); + const auto& descriptorSet = core.getDescriptorSet(material.getDescriptorSet()); + + drawcalls.push_back(DrawcallInfo( + vkcv::Mesh(m_vertexBindings, indexBuffer.getVulkanHandle(), m_indexCount), + { DescriptorSetUsage(0, descriptorSet.vulkanHandle) } + )); + } + } + + MeshPart::~MeshPart() { + m_scene.decreaseMaterialUsage(m_materialIndex); + } + + MeshPart::MeshPart(const MeshPart &other) : + m_scene(other.m_scene), + m_vertices(other.m_vertices), + m_vertexBindings(other.m_vertexBindings), + m_indices(other.m_indices), + m_indexCount(other.m_indexCount), + m_bounds(other.m_bounds), + m_materialIndex(other.m_materialIndex) { + m_scene.increaseMaterialUsage(m_materialIndex); + } + + MeshPart::MeshPart(MeshPart &&other) : + m_scene(other.m_scene), + m_vertices(other.m_vertices), + m_vertexBindings(other.m_vertexBindings), + m_indices(other.m_indices), + m_indexCount(other.m_indexCount), + m_bounds(other.m_bounds), + m_materialIndex(other.m_materialIndex) { + m_scene.increaseMaterialUsage(m_materialIndex); + } + + MeshPart &MeshPart::operator=(const MeshPart &other) { + if (&other == this) { + return *this; + } + + m_vertices = other.m_vertices; + m_vertexBindings = other.m_vertexBindings; + m_indices = other.m_indices; + m_indexCount = other.m_indexCount; + m_bounds = other.m_bounds; + m_materialIndex = other.m_materialIndex; + + return *this; + } + + MeshPart &MeshPart::operator=(MeshPart &&other) noexcept { + m_vertices = other.m_vertices; + m_vertexBindings = other.m_vertexBindings; + m_indices = other.m_indices; + m_indexCount = other.m_indexCount; + m_bounds = other.m_bounds; + m_materialIndex = other.m_materialIndex; + + return *this; + } + + const material::Material & MeshPart::getMaterial() const { + return m_scene.getMaterial(m_materialIndex); + } + + MeshPart::operator bool() const { + return ( + (getMaterial()) && + (m_vertices) && + (m_indices) + ); + } + + bool MeshPart::operator!() const { + return ( + (!getMaterial()) || + (!m_vertices) || + (!m_indices) + ); + } + + const Bounds &MeshPart::getBounds() const { + return m_bounds; + } + +} diff --git a/modules/scene/src/vkcv/scene/Node.cpp b/modules/scene/src/vkcv/scene/Node.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32230099b2f693362bab69d8172a4dee56c4e304 --- /dev/null +++ b/modules/scene/src/vkcv/scene/Node.cpp @@ -0,0 +1,189 @@ + +#include "vkcv/scene/Node.hpp" +#include "vkcv/scene/Scene.hpp" +#include "Frustum.hpp" + +#include <algorithm> + +namespace vkcv::scene { + + Node::Node(Scene& scene) : + m_scene(scene), + m_meshes(), + m_nodes(), + m_bounds() {} + + Node::~Node() { + m_nodes.clear(); + m_meshes.clear(); + } + + Node &Node::operator=(const Node &other) { + if (&other == this) { + return *this; + } + + m_meshes.resize(other.m_meshes.size(), Mesh(m_scene)); + + for (size_t i = 0; i < m_meshes.size(); i++) { + m_meshes[i] = other.m_meshes[i]; + } + + m_nodes.resize(other.m_nodes.size(), Node(m_scene)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = other.m_nodes[i]; + } + + m_bounds = other.m_bounds; + + return *this; + } + + Node &Node::operator=(Node &&other) noexcept { + m_meshes.resize(other.m_meshes.size(), Mesh(m_scene)); + + for (size_t i = 0; i < m_meshes.size(); i++) { + m_meshes[i] = std::move(other.m_meshes[i]); + } + + m_nodes.resize(other.m_nodes.size(), Node(m_scene)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = std::move(other.m_nodes[i]); + } + + m_bounds = other.m_bounds; + + return *this; + } + + void Node::addMesh(const Mesh& mesh) { + if (m_meshes.empty()) { + m_bounds = mesh.getBounds(); + } else { + m_bounds.extend(mesh.getBounds().getMin()); + m_bounds.extend(mesh.getBounds().getMax()); + } + + m_meshes.push_back(mesh); + } + + void Node::loadMesh(const asset::Scene &asset_scene, const asset::Mesh &asset_mesh) { + Mesh mesh (m_scene); + mesh.load(asset_scene, asset_mesh); + addMesh(mesh); + } + + size_t Node::addNode() { + const Node node (m_scene); + const size_t index = m_nodes.size(); + m_nodes.push_back(node); + return index; + } + + Node& Node::getNode(size_t index) { + return m_nodes[index]; + } + + const Node& Node::getNode(size_t index) const { + return m_nodes[index]; + } + + void Node::recordDrawcalls(const glm::mat4& viewProjection, + PushConstants& pushConstants, + std::vector<DrawcallInfo>& drawcalls, + const RecordMeshDrawcallFunction& record) { + if (!checkFrustum(viewProjection, m_bounds)) { + return; + } + + for (auto& mesh : m_meshes) { + mesh.recordDrawcalls(viewProjection, pushConstants, drawcalls, record); + } + + for (auto& node : m_nodes) { + node.recordDrawcalls(viewProjection, pushConstants, drawcalls, record); + } + } + + void Node::splitMeshesToSubNodes(size_t maxMeshesPerNode) { + if (m_meshes.size() <= maxMeshesPerNode) { + return; + } + + const auto split = m_bounds.getCenter(); + int axis = 0; + + const auto size = m_bounds.getSize(); + + if (size[1] > size[0]) { + if (size[2] > size[1]) { + axis = 2; + } else { + axis = 1; + } + } else + if (size[2] > size[0]) { + axis = 2; + } + + std::vector<size_t> left_meshes; + std::vector<size_t> right_meshes; + + for (size_t i = 0; i < m_meshes.size(); i++) { + const auto& bounds = m_meshes[i].getBounds(); + + if (bounds.getMax()[axis] <= split[axis]) { + left_meshes.push_back(i); + } else + if (bounds.getMin()[axis] >= split[axis]) { + right_meshes.push_back(i); + } + } + + if ((left_meshes.empty()) || (right_meshes.empty())) { + return; + } + + const size_t left = addNode(); + const size_t right = addNode(); + + for (size_t i : left_meshes) { + getNode(left).addMesh(m_meshes[i]); + } + + for (size_t i : right_meshes) { + getNode(right).addMesh(m_meshes[i]); + left_meshes.push_back(i); + } + + std::sort(left_meshes.begin(), left_meshes.end(), std::greater()); + + for (size_t i : left_meshes) { + m_meshes.erase(m_meshes.begin() + static_cast<long>(i)); + } + + getNode(left).splitMeshesToSubNodes(maxMeshesPerNode); + getNode(right).splitMeshesToSubNodes(maxMeshesPerNode); + } + + size_t Node::getDrawcallCount() const { + size_t count = 0; + + for (auto& mesh : m_meshes) { + count += mesh.getDrawcallCount(); + } + + for (auto& node : m_nodes) { + count += node.getDrawcallCount(); + } + + return count; + } + + const Bounds& Node::getBounds() const { + return m_bounds; + } + +} diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b050f67ff352296db6155247beebbb5682e542c2 --- /dev/null +++ b/modules/scene/src/vkcv/scene/Scene.cpp @@ -0,0 +1,273 @@ + +#include "vkcv/scene/Scene.hpp" + +#include <vkcv/Logger.hpp> +#include <vkcv/asset/asset_loader.hpp> + +namespace vkcv::scene { + + Scene::Scene(Core* core) : + m_core(core), + m_materials(), + m_nodes() {} + + Scene::~Scene() { + m_nodes.clear(); + m_materials.clear(); + } + + Scene::Scene(const Scene &other) : + m_core(other.m_core), + m_materials(other.m_materials), + m_nodes() { + m_nodes.resize(other.m_nodes.size(), Node(*this)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = other.m_nodes[i]; + } + } + + Scene::Scene(Scene &&other) noexcept : + m_core(other.m_core), + m_materials(other.m_materials), + m_nodes() { + m_nodes.resize(other.m_nodes.size(), Node(*this)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = std::move(other.m_nodes[i]); + } + } + + Scene &Scene::operator=(const Scene &other) { + if (&other == this) { + return *this; + } + + m_core = other.m_core; + m_materials = std::vector<Material>(other.m_materials); + + m_nodes.resize(other.m_nodes.size(), Node(*this)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = other.m_nodes[i]; + } + + return *this; + } + + Scene &Scene::operator=(Scene &&other) noexcept { + m_core = other.m_core; + m_materials = std::move(other.m_materials); + + m_nodes.resize(other.m_nodes.size(), Node(*this)); + + for (size_t i = 0; i < m_nodes.size(); i++) { + m_nodes[i] = std::move(other.m_nodes[i]); + } + + return *this; + } + + size_t Scene::addNode() { + const Node node (*this); + const size_t index = m_nodes.size(); + m_nodes.push_back(node); + return index; + } + + Node& Scene::getNode(size_t index) { + return m_nodes[index]; + } + + const Node& Scene::getNode(size_t index) const { + return m_nodes[index]; + } + + void Scene::increaseMaterialUsage(size_t index) { + if (index < m_materials.size()) { + m_materials[index].m_usages++; + } + } + + void Scene::decreaseMaterialUsage(size_t index) { + if ((index < m_materials.size()) && (m_materials[index].m_usages > 0)) { + m_materials[index].m_usages--; + } + } + + size_t Scene::getMaterialCount() const { + return m_materials.size(); + } + + const material::Material & Scene::getMaterial(size_t index) const { + static material::Material noMaterial; + + if (index >= m_materials.size()) { + return noMaterial; + } + + return m_materials[index].m_data; + } + + void Scene::recordDrawcalls(CommandStreamHandle &cmdStream, + const camera::Camera &camera, + const PassHandle &pass, + const PipelineHandle &pipeline, + size_t pushConstantsSizePerDrawcall, + const RecordMeshDrawcallFunction &record, + const std::vector<ImageHandle> &renderTargets) { + PushConstants pushConstants (pushConstantsSizePerDrawcall); + std::vector<DrawcallInfo> drawcalls; + size_t count = 0; + + const glm::mat4 viewProjection = camera.getMVP(); + + for (auto& node : m_nodes) { + count += node.getDrawcallCount(); + node.recordDrawcalls(viewProjection, pushConstants, drawcalls, record); + } + + vkcv_log(LogLevel::RAW_INFO, "Frustum culling: %lu / %lu", drawcalls.size(), count); + + m_core->recordDrawcallsToCmdStream( + cmdStream, + pass, + pipeline, + pushConstants, + drawcalls, + renderTargets + ); + } + + Scene Scene::create(Core& core) { + return Scene(&core); + } + + static void loadImage(Core& core, const asset::Scene& asset_scene, + const asset::Texture& asset_texture, + const vk::Format& format, + ImageHandle& image, SamplerHandle& sampler) { + asset::Sampler* asset_sampler = nullptr; + + if ((asset_texture.sampler >= 0) && (asset_texture.sampler < asset_scene.samplers.size())) { + //asset_sampler = &(asset_scene.samplers[asset_texture.sampler]); // TODO + } + + Image img = core.createImage(format, asset_texture.w, asset_texture.h); + img.fill(asset_texture.data.data()); + image = img.getHandle(); + + if (asset_sampler) { + //sampler = core.createSampler(asset_sampler) // TODO + } else { + sampler = core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + } + + void Scene::loadMaterial(size_t index, const asset::Scene& scene, + const asset::Material& material) { + if (index >= m_materials.size()) { + return; + } + + ImageHandle diffuseImg; + SamplerHandle diffuseSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + ImageHandle normalImg; + SamplerHandle normalSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + ImageHandle metalRoughImg; + SamplerHandle metalRoughSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + ImageHandle occlusionImg; + SamplerHandle occlusionSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + ImageHandle emissionImg; + SamplerHandle emissionSmp; + + if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) { + loadImage(*m_core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb, + diffuseImg,diffuseSmp); + } + + const float colorFactors [4] = { + material.baseColorFactor.r, + material.baseColorFactor.g, + material.baseColorFactor.b, + material.baseColorFactor.a + }; + + const float emissionFactors[4] = { + material.emissiveFactor.r, + material.emissiveFactor.g, + material.emissiveFactor.b + }; + + m_materials[index].m_data = material::Material::createPBR( + *m_core, + diffuseImg, diffuseSmp, + normalImg, normalSmp, + metalRoughImg, metalRoughSmp, + occlusionImg, occlusionSmp, + emissionImg, emissionSmp, + colorFactors, + material.normalScale, + material.metallicFactor, + material.roughnessFactor, + material.occlusionStrength, + emissionFactors + ); + } + + Scene Scene::load(Core& core, const std::filesystem::path &path) { + asset::Scene asset_scene; + + if (!asset::loadScene(path.string(), asset_scene)) { + vkcv_log(LogLevel::WARNING, "Scene could not be loaded") + return create(core); + } + + Scene scene = create(core); + + for (const auto& material : asset_scene.materials) { + scene.m_materials.push_back({ + 0, material::Material() + }); + } + + const size_t root = scene.addNode(); + + for (const auto& mesh : asset_scene.meshes) { + scene.getNode(root).loadMesh(asset_scene, mesh); + } + + scene.getNode(root).splitMeshesToSubNodes(128); + return scene; + } + +} diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt index 1c6e3afe2347f6ef8ea8a62be7acbe0ea750497d..4196d55d99db115641f0a23cf5d7445bc70e52fe 100644 --- a/projects/CMakeLists.txt +++ b/projects/CMakeLists.txt @@ -1,8 +1,7 @@ # Add new projects/examples here: -add_subdirectory(bloom) add_subdirectory(first_triangle) add_subdirectory(first_mesh) -add_subdirectory(particle_simulation) add_subdirectory(first_scene) +add_subdirectory(particle_simulation) add_subdirectory(voxelization) diff --git a/projects/bloom/.gitignore b/projects/bloom/.gitignore deleted file mode 100644 index 3643183e0628e666abab193e1dd1d92c1774ac61..0000000000000000000000000000000000000000 --- a/projects/bloom/.gitignore +++ /dev/null @@ -1 +0,0 @@ -bloom \ No newline at end of file diff --git a/projects/bloom/CMakeLists.txt b/projects/bloom/CMakeLists.txt deleted file mode 100644 index 8171938e7cb430aacce5562af44f628c11c97c54..0000000000000000000000000000000000000000 --- a/projects/bloom/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -cmake_minimum_required(VERSION 3.16) -project(bloom) - -# setting c++ standard for the project -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# this should fix the execution path to load local files from the project -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - -# adding source files to the project -add_executable(bloom src/main.cpp) - -target_sources(bloom PRIVATE - src/BloomAndFlares.cpp - src/BloomAndFlares.hpp) - -# this should fix the execution path to load local files from the project (for MSVC) -if(MSVC) - set_target_properties(bloom PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set_target_properties(bloom PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - # in addition to setting the output directory, the working directory has to be set - # by default visual studio sets the working directory to the build directory, when using the debugger - set_target_properties(bloom PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -endif() - -# including headers of dependencies and the VkCV framework -target_include_directories(bloom SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include}) - -# linking with libraries from all dependencies and the VkCV framework -target_link_libraries(bloom vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera vkcv_shader_compiler) diff --git a/projects/bloom/resources/Sponza/Sponza.bin b/projects/bloom/resources/Sponza/Sponza.bin deleted file mode 100644 index cfedd26ca5a67b6d0a47d44d13a75e14a141717a..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/Sponza.bin +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4b809f7a17687dc99e6f41ca1ea32c06eded8779bf34d16f1f565d750b0ffd68 -size 6347696 diff --git a/projects/bloom/resources/Sponza/Sponza.gltf b/projects/bloom/resources/Sponza/Sponza.gltf deleted file mode 100644 index 172ea07e21c94465211c860cd805355704cef230..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/Sponza.gltf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5cc0ecad5c4694088ff820e663619c370421afc1323ac487406e8e9b4735d787 -size 713962 diff --git a/projects/bloom/resources/Sponza/background.png b/projects/bloom/resources/Sponza/background.png deleted file mode 100644 index b64def129da38f4e23d89e21b4af1039008a4327..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/background.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f5b5f900ff8ed83a31750ec8e428b5b91273794ddcbfc4e4b8a6a7e781f8c686 -size 1417666 diff --git a/projects/bloom/resources/Sponza/chain_texture.png b/projects/bloom/resources/Sponza/chain_texture.png deleted file mode 100644 index c1e1768cff78e0614ad707eca8602a4c4edab5e5..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/chain_texture.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d8362cfd472880daeaea37439326a4651d1338680ae69bb2513fc6b17c8de7d4 -size 490895 diff --git a/projects/bloom/resources/Sponza/lion.png b/projects/bloom/resources/Sponza/lion.png deleted file mode 100644 index c49c7f0ed31e762e19284d0d3624fbc47664e56b..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/lion.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9f882f746c3a9cd51a9c6eedc1189b97668721d91a3fe49232036e789912c652 -size 2088728 diff --git a/projects/bloom/resources/Sponza/spnza_bricks_a_diff.png b/projects/bloom/resources/Sponza/spnza_bricks_a_diff.png deleted file mode 100644 index cde4c7a6511e9a5f03c63ad996437fcdba3ce2df..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/spnza_bricks_a_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b94219c2f5f943f3f4715c74e7d1038bf0ab3b3b3216a758eaee67f875df0851 -size 1928829 diff --git a/projects/bloom/resources/Sponza/sponza_arch_diff.png b/projects/bloom/resources/Sponza/sponza_arch_diff.png deleted file mode 100644 index bcd9bda2918d226039f9e2d03902d377b706fab6..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_arch_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c0df2c8a01b2843b1c792b494f7173cdbc4f834840fc2177af3e5d690fceda57 -size 1596151 diff --git a/projects/bloom/resources/Sponza/sponza_ceiling_a_diff.png b/projects/bloom/resources/Sponza/sponza_ceiling_a_diff.png deleted file mode 100644 index 59de631ffac4414cabf69b2dc794c46fc187d6cb..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_ceiling_a_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ab6c187a81aa68f4eba30119e17fce2e4882a9ec320f70c90482dbe9da82b1c6 -size 1872074 diff --git a/projects/bloom/resources/Sponza/sponza_column_a_diff.png b/projects/bloom/resources/Sponza/sponza_column_a_diff.png deleted file mode 100644 index 01a82432d3f9939bbefe850bdb900f1ff9a3f6db..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_column_a_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2c291507e2808bb83e160ab4b020689817df273baad3713a9ad19ac15fac6826 -size 1840992 diff --git a/projects/bloom/resources/Sponza/sponza_column_b_diff.png b/projects/bloom/resources/Sponza/sponza_column_b_diff.png deleted file mode 100644 index 10a660cce2a5a9b8997772c746058ce23e7d45d7..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_column_b_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2820b0267c4289c6cedbb42721792a57ef244ec2d0935941011c2a7d3fe88a9b -size 2170433 diff --git a/projects/bloom/resources/Sponza/sponza_column_c_diff.png b/projects/bloom/resources/Sponza/sponza_column_c_diff.png deleted file mode 100644 index bc46fd979044a938d3adca7601689e71504e48bf..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_column_c_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a0bc993ff59865468ef4530798930c7dfefb07482d71db45bc2a520986b27735 -size 2066950 diff --git a/projects/bloom/resources/Sponza/sponza_curtain_blue_diff.png b/projects/bloom/resources/Sponza/sponza_curtain_blue_diff.png deleted file mode 100644 index 384c8c2c051160d530eb3ac8b05c9c60752a2d2b..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_curtain_blue_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b85c6bb3cd5105f48d3812ec8e7a1068521ce69e917300d79e136e19d45422fb -size 9510905 diff --git a/projects/bloom/resources/Sponza/sponza_curtain_diff.png b/projects/bloom/resources/Sponza/sponza_curtain_diff.png deleted file mode 100644 index af842e9f5fe18c1f609875e00899a6770fa4488b..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_curtain_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:563c56bdbbee395a6ef7f0c51c8ac9223c162e517b4cdba0d4654e8de27c98d8 -size 9189263 diff --git a/projects/bloom/resources/Sponza/sponza_curtain_green_diff.png b/projects/bloom/resources/Sponza/sponza_curtain_green_diff.png deleted file mode 100644 index 6c9b6391a199407637fa71033d79fb58b8b4f0d7..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_curtain_green_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:238fe1c7f481388d1c1d578c2da8d411b99e8f0030ab62060a306db333124476 -size 8785458 diff --git a/projects/bloom/resources/Sponza/sponza_details_diff.png b/projects/bloom/resources/Sponza/sponza_details_diff.png deleted file mode 100644 index 12656686362c3e0a297e060491f33bd7351551f9..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_details_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cb1223b3bb82f8757e7df25a6891f1239cdd7ec59990340e952fb2d6b7ea570c -size 1522643 diff --git a/projects/bloom/resources/Sponza/sponza_fabric_blue_diff.png b/projects/bloom/resources/Sponza/sponza_fabric_blue_diff.png deleted file mode 100644 index 879d16ef84722a4fc13e83a771778de326e4bc54..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_fabric_blue_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:467d290bf5d4b2a017da140ba9e244ed8a8a9be5418a9ac9bcb4ad572ae2d7ab -size 2229440 diff --git a/projects/bloom/resources/Sponza/sponza_fabric_diff.png b/projects/bloom/resources/Sponza/sponza_fabric_diff.png deleted file mode 100644 index 3311287a219d2148620b87fe428fea071688d051..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_fabric_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1594f59cc2848db26add47361f4e665e3d8afa147760ed915d839fea42b20287 -size 2267382 diff --git a/projects/bloom/resources/Sponza/sponza_fabric_green_diff.png b/projects/bloom/resources/Sponza/sponza_fabric_green_diff.png deleted file mode 100644 index de110f369004388dae4cd5067c63428db3a07834..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_fabric_green_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:902b87faab221173bf370cea7c74cb9060b4d870ac6316b190dafded1cb12993 -size 2258220 diff --git a/projects/bloom/resources/Sponza/sponza_flagpole_diff.png b/projects/bloom/resources/Sponza/sponza_flagpole_diff.png deleted file mode 100644 index 5f6e0812a0df80346318baa3cb50a6888afc58f8..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_flagpole_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bfffb62e770959c725d0f3db6dc7dbdd46a380ec55ef884dab94d44ca017b438 -size 1425673 diff --git a/projects/bloom/resources/Sponza/sponza_floor_a_diff.png b/projects/bloom/resources/Sponza/sponza_floor_a_diff.png deleted file mode 100644 index 788ed764f79ba724f04a2d603076a5b85013e188..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_floor_a_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a16f9230fa91f9f31dfca6216ce205f1ef132d44f3b012fbf6efc0fba69770ab -size 1996838 diff --git a/projects/bloom/resources/Sponza/sponza_roof_diff.png b/projects/bloom/resources/Sponza/sponza_roof_diff.png deleted file mode 100644 index c5b84261fdd1cc776a94b3ce398c7806b895f9a3..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_roof_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7fc412138c20da19f8173e53545e771f4652558dff624d4dc67143e40efe562b -size 2320533 diff --git a/projects/bloom/resources/Sponza/sponza_thorn_diff.png b/projects/bloom/resources/Sponza/sponza_thorn_diff.png deleted file mode 100644 index 7a9142674a7d4a6f94a48c5152cf0300743b597a..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/sponza_thorn_diff.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a73a17c883cd0d0d67cfda2dc4118400a916366c05b9a5ac465f0c8b30fd9c8e -size 635001 diff --git a/projects/bloom/resources/Sponza/vase_dif.png b/projects/bloom/resources/Sponza/vase_dif.png deleted file mode 100644 index 61236a81cb324af8797b05099cd264cefe189e56..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/vase_dif.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:53d06f52bf9e59df4cf00237707cca76c4f692bda61a62b06a30d321311d6dd9 -size 1842101 diff --git a/projects/bloom/resources/Sponza/vase_hanging.png b/projects/bloom/resources/Sponza/vase_hanging.png deleted file mode 100644 index 36a3cee71d8213225090c74f8c0dce33b9d44378..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/vase_hanging.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a9d10b4f27a3c9a78d5bac882fdd4b6a6987c262f48fa490670fe5e235951e31 -size 1432804 diff --git a/projects/bloom/resources/Sponza/vase_plant.png b/projects/bloom/resources/Sponza/vase_plant.png deleted file mode 100644 index 7ad95e702e229f1ebd803e5203a266d15f2c07b9..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/vase_plant.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d2087371ff02212fb7014b6daefa191cf5676d2227193fff261a5d02f554cb8e -size 998089 diff --git a/projects/bloom/resources/Sponza/vase_round.png b/projects/bloom/resources/Sponza/vase_round.png deleted file mode 100644 index c17953abc000c44b8991e23c136c2b67348f3d1b..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/Sponza/vase_round.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aa23d48d492d5d4ada2ddb27d1ef22952b214e6eb3b301c65f9d88442723d20a -size 1871399 diff --git a/projects/bloom/resources/shaders/comp.spv b/projects/bloom/resources/shaders/comp.spv deleted file mode 100644 index 85c7e74cfc0a89917bf6dd1a7ec449368274c1d3..0000000000000000000000000000000000000000 Binary files a/projects/bloom/resources/shaders/comp.spv and /dev/null differ diff --git a/projects/bloom/resources/shaders/composite.comp b/projects/bloom/resources/shaders/composite.comp deleted file mode 100644 index 190bed0657d70e0217bf654820d0b2b2c58f12c2..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/composite.comp +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -layout(set=0, binding=0) uniform texture2D blurImage; -layout(set=0, binding=1) uniform texture2D lensImage; -layout(set=0, binding=2) uniform sampler linearSampler; -layout(set=0, binding=3, r11f_g11f_b10f) uniform image2D colorBuffer; - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - - -void main() -{ - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(colorBuffer)))){ - return; - } - - ivec2 pixel_coord = ivec2(gl_GlobalInvocationID.xy); - vec2 pixel_size = vec2(1.0f) / textureSize(sampler2D(blurImage, linearSampler), 0); - vec2 UV = pixel_coord.xy * pixel_size; - - vec4 composite_color = vec4(0.0f); - - vec3 blur_color = texture(sampler2D(blurImage, linearSampler), UV).rgb; - vec3 lens_color = texture(sampler2D(lensImage, linearSampler), UV).rgb; - vec3 main_color = imageLoad(colorBuffer, pixel_coord).rgb; - - // composite blur and lens features - float bloom_weight = 0.25f; - float lens_weight = 0.25f; - float main_weight = 1 - (bloom_weight + lens_weight); - - composite_color.rgb = blur_color * bloom_weight + - lens_color * lens_weight + - main_color * main_weight; - - imageStore(colorBuffer, pixel_coord, composite_color); -} \ No newline at end of file diff --git a/projects/bloom/resources/shaders/downsample.comp b/projects/bloom/resources/shaders/downsample.comp deleted file mode 100644 index 2ab00c7c92798769153634f3479c5b7f3fb61d94..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/downsample.comp +++ /dev/null @@ -1,76 +0,0 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -layout(set=0, binding=0) uniform texture2D inBlurImage; -layout(set=0, binding=1) uniform sampler inImageSampler; -layout(set=0, binding=2, r11f_g11f_b10f) uniform writeonly image2D outBlurImage; - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - - -void main() -{ - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outBlurImage)))){ - return; - } - - ivec2 pixel_coord = ivec2(gl_GlobalInvocationID.xy); - vec2 pixel_size = vec2(1.0f) / imageSize(outBlurImage); - vec2 UV = pixel_coord.xy * pixel_size; - vec2 UV_offset = UV + 0.5f * pixel_size; - - vec2 color_fetches[13] = { - // center neighbourhood (RED) - vec2(-1, 1), // LT - vec2(-1, -1), // LB - vec2( 1, -1), // RB - vec2( 1, 1), // RT - - vec2(-2, 2), // LT - vec2( 0, 2), // CT - vec2( 2, 2), // RT - - vec2(0 ,-2), // LC - vec2(0 , 0), // CC - vec2(2, 0), // CR - - vec2(-2, -2), // LB - vec2(0 , -2), // CB - vec2(2 , -2) // RB - }; - - float color_weights[13] = { - // 0.5f - 1.f/8.f, - 1.f/8.f, - 1.f/8.f, - 1.f/8.f, - - // 0.125f - 1.f/32.f, - 1.f/16.f, - 1.f/32.f, - - // 0.25f - 1.f/16.f, - 1.f/8.f, - 1.f/16.f, - - // 0.125f - 1.f/32.f, - 1.f/16.f, - 1.f/32.f - }; - - vec3 sampled_color = vec3(0.0f); - - for(uint i = 0; i < 13; i++) - { - vec2 color_fetch = UV_offset + color_fetches[i] * pixel_size; - vec3 color = texture(sampler2D(inBlurImage, inImageSampler), color_fetch).rgb; - color *= color_weights[i]; - sampled_color += color; - } - - imageStore(outBlurImage, pixel_coord, vec4(sampled_color, 1.f)); -} \ No newline at end of file diff --git a/projects/bloom/resources/shaders/gammaCorrection.comp b/projects/bloom/resources/shaders/gammaCorrection.comp deleted file mode 100644 index f89ad167c846cca8e80f69d33eda83bd6ed00d46..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/gammaCorrection.comp +++ /dev/null @@ -1,20 +0,0 @@ -#version 440 - -layout(set=0, binding=0, r11f_g11f_b10f) uniform image2D inImage; -layout(set=0, binding=1, rgba8) uniform image2D outImage; - - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -void main(){ - - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(inImage)))){ - return; - } - ivec2 uv = ivec2(gl_GlobalInvocationID.xy); - vec3 linearColor = imageLoad(inImage, uv).rgb; - // cheap Reinhard tone mapping - linearColor = linearColor/(linearColor + 1.0f); - vec3 gammaCorrected = pow(linearColor, vec3(1.f / 2.2f)); - imageStore(outImage, uv, vec4(gammaCorrected, 0.f)); -} \ No newline at end of file diff --git a/projects/bloom/resources/shaders/lensFlares.comp b/projects/bloom/resources/shaders/lensFlares.comp deleted file mode 100644 index ce27d8850b709f61332d467914ddc944dc63109f..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/lensFlares.comp +++ /dev/null @@ -1,109 +0,0 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -layout(set=0, binding=0) uniform texture2D blurBuffer; -layout(set=0, binding=1) uniform sampler linearSampler; -layout(set=0, binding=2, r11f_g11f_b10f) uniform image2D lensBuffer; - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -vec3 sampleColorChromaticAberration(vec2 _uv) -{ - vec2 toCenter = (vec2(0.5) - _uv); - - vec3 colorScales = vec3(-1, 0, 1); - float aberrationScale = 0.1; - vec3 scaleFactors = colorScales * aberrationScale; - - float r = texture(sampler2D(blurBuffer, linearSampler), _uv + toCenter * scaleFactors.r).r; - float g = texture(sampler2D(blurBuffer, linearSampler), _uv + toCenter * scaleFactors.g).g; - float b = texture(sampler2D(blurBuffer, linearSampler), _uv + toCenter * scaleFactors.b).b; - return vec3(r, g, b); -} - -// _uv assumed to be flipped UV coordinates! -vec3 ghost_vectors(vec2 _uv) -{ - vec2 ghost_vec = (vec2(0.5f) - _uv); - - const uint c_ghost_count = 64; - const float c_ghost_spacing = length(ghost_vec) / c_ghost_count; - - ghost_vec *= c_ghost_spacing; - - vec3 ret_color = vec3(0.0f); - - for (uint i = 0; i < c_ghost_count; ++i) - { - // sample scene color - vec2 s_uv = fract(_uv + ghost_vec * vec2(i)); - vec3 s = sampleColorChromaticAberration(s_uv); - - // tint/weight - float d = distance(s_uv, vec2(0.5)); - float weight = 1.0f - smoothstep(0.0f, 0.75f, d); - s *= weight; - - ret_color += s; - } - - ret_color /= c_ghost_count; - return ret_color; -} - -vec3 halo(vec2 _uv) -{ - const float c_aspect_ratio = float(imageSize(lensBuffer).x) / float(imageSize(lensBuffer).y); - const float c_radius = 0.6f; - const float c_halo_thickness = 0.1f; - - vec2 halo_vec = vec2(0.5) - _uv; - //halo_vec.x /= c_aspect_ratio; - halo_vec = normalize(halo_vec); - //halo_vec.x *= c_aspect_ratio; - - - //vec2 w_uv = (_uv - vec2(0.5, 0.0)) * vec2(c_aspect_ratio, 1.0) + vec2(0.5, 0.0); - vec2 w_uv = _uv; - float d = distance(w_uv, vec2(0.5)); // distance to center - - float distance_to_halo = abs(d - c_radius); - - float halo_weight = 0.0f; - if(abs(d - c_radius) <= c_halo_thickness) - { - float distance_to_border = c_halo_thickness - distance_to_halo; - halo_weight = distance_to_border / c_halo_thickness; - - //halo_weight = clamp((halo_weight / 0.4f), 0.0f, 1.0f); - halo_weight = pow(halo_weight, 2.0f); - - - //halo_weight = 1.0f; - } - - return sampleColorChromaticAberration(_uv + halo_vec) * halo_weight; -} - - - -void main() -{ - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(lensBuffer)))){ - return; - } - - ivec2 pixel_coord = ivec2(gl_GlobalInvocationID.xy); - vec2 pixel_size = vec2(1.0f) / imageSize(lensBuffer); - vec2 UV = pixel_coord.xy * pixel_size; - - vec2 flipped_UV = vec2(1.0f) - UV; - - vec3 color = vec3(0.0f); - - color += ghost_vectors(flipped_UV); - color += halo(UV); - color *= 0.5f; - - imageStore(lensBuffer, pixel_coord, vec4(color, 0.0f)); -} \ No newline at end of file diff --git a/projects/bloom/resources/shaders/perMeshResources.inc b/projects/bloom/resources/shaders/perMeshResources.inc deleted file mode 100644 index 95e4fb7c27009965659d14a9c72acfec950c37e3..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/perMeshResources.inc +++ /dev/null @@ -1,2 +0,0 @@ -layout(set=1, binding=0) uniform texture2D albedoTexture; -layout(set=1, binding=1) uniform sampler textureSampler; \ No newline at end of file diff --git a/projects/bloom/resources/shaders/shader.frag b/projects/bloom/resources/shaders/shader.frag deleted file mode 100644 index 3e95b4508f112c1ed9aa4a7050a98fa789dccd09..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/shader.frag +++ /dev/null @@ -1,45 +0,0 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable -#extension GL_GOOGLE_include_directive : enable - -#include "perMeshResources.inc" - -layout(location = 0) in vec3 passNormal; -layout(location = 1) in vec2 passUV; -layout(location = 2) in vec3 passPos; - -layout(location = 0) out vec3 outColor; - -layout(set=0, binding=0) uniform sunBuffer { - vec3 L; float padding; - mat4 lightMatrix; -}; -layout(set=0, binding=1) uniform texture2D shadowMap; -layout(set=0, binding=2) uniform sampler shadowMapSampler; - -float shadowTest(vec3 worldPos){ - vec4 lightPos = lightMatrix * vec4(worldPos, 1); - lightPos /= lightPos.w; - lightPos.xy = lightPos.xy * 0.5 + 0.5; - - if(any(lessThan(lightPos.xy, vec2(0))) || any(greaterThan(lightPos.xy, vec2(1)))){ - return 1; - } - - lightPos.z = clamp(lightPos.z, 0, 1); - - float shadowMapSample = texture(sampler2D(shadowMap, shadowMapSampler), lightPos.xy).r; - float bias = 0.01f; - shadowMapSample += bias; - return shadowMapSample < lightPos.z ? 0 : 1; -} - -void main() { - vec3 N = normalize(passNormal); - vec3 sunColor = vec3(10); - vec3 sun = sunColor * clamp(dot(N, L), 0, 1); - sun *= shadowTest(passPos); - vec3 ambient = vec3(0.05); - vec3 albedo = texture(sampler2D(albedoTexture, textureSampler), passUV).rgb; - outColor = albedo * (sun + ambient); -} \ No newline at end of file diff --git a/projects/bloom/resources/shaders/shader.vert b/projects/bloom/resources/shaders/shader.vert deleted file mode 100644 index 926f86af2860cb57c44d2d5ee78712b6ae155e5c..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/shader.vert +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -layout(location = 0) in vec3 inPosition; -layout(location = 1) in vec3 inNormal; -layout(location = 2) in vec2 inUV; - -layout(location = 0) out vec3 passNormal; -layout(location = 1) out vec2 passUV; -layout(location = 2) out vec3 passPos; - -layout( push_constant ) uniform constants{ - mat4 mvp; - mat4 model; -}; - -void main() { - gl_Position = mvp * vec4(inPosition, 1.0); - passNormal = mat3(model) * inNormal; // assuming no weird stuff like shearing or non-uniform scaling - passUV = inUV; - passPos = (model * vec4(inPosition, 1)).xyz; -} \ No newline at end of file diff --git a/projects/bloom/resources/shaders/shadow.frag b/projects/bloom/resources/shaders/shadow.frag deleted file mode 100644 index 848f853f556660b4900b5db7fb6fc98d57c1cd5b..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/shadow.frag +++ /dev/null @@ -1,6 +0,0 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -void main() { - -} \ No newline at end of file diff --git a/projects/bloom/resources/shaders/shadow.vert b/projects/bloom/resources/shaders/shadow.vert deleted file mode 100644 index e0f41d42d575fa64fedbfa04adf89ac0f4aeebe8..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/shadow.vert +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -layout(location = 0) in vec3 inPosition; - -layout( push_constant ) uniform constants{ - mat4 mvp; -}; - -void main() { - gl_Position = mvp * vec4(inPosition, 1.0); -} \ No newline at end of file diff --git a/projects/bloom/resources/shaders/upsample.comp b/projects/bloom/resources/shaders/upsample.comp deleted file mode 100644 index 0ddeedb5b5af9e476dc19012fed6430544006c0e..0000000000000000000000000000000000000000 --- a/projects/bloom/resources/shaders/upsample.comp +++ /dev/null @@ -1,45 +0,0 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -layout(set=0, binding=0) uniform texture2D inUpsampleImage; -layout(set=0, binding=1) uniform sampler inImageSampler; -layout(set=0, binding=2, r11f_g11f_b10f) uniform image2D outUpsampleImage; - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -void main() -{ - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outUpsampleImage)))){ - return; - } - - - ivec2 pixel_coord = ivec2(gl_GlobalInvocationID.xy); - vec2 pixel_size = vec2(1.0f) / imageSize(outUpsampleImage); - vec2 UV = pixel_coord.xy * pixel_size; - - const float gauss_kernel[3] = {1.f, 2.f, 1.f}; - const float gauss_weight = 16.f; - - vec3 sampled_color = vec3(0.f); - - for(int i = -1; i <= 1; i++) - { - for(int j = -1; j <= 1; j++) - { - vec2 sample_location = UV + vec2(j, i) * pixel_size; - vec3 color = texture(sampler2D(inUpsampleImage, inImageSampler), sample_location).rgb; - color *= gauss_kernel[j+1]; - color *= gauss_kernel[i+1]; - color /= gauss_weight; - - sampled_color += color; - } - } - - //vec3 prev_color = imageLoad(outUpsampleImage, pixel_coord).rgb; - //float bloomRimStrength = 0.75f; // adjust this to change strength of bloom - //sampled_color = mix(prev_color, sampled_color, bloomRimStrength); - - imageStore(outUpsampleImage, pixel_coord, vec4(sampled_color, 1.f)); -} \ No newline at end of file diff --git a/projects/bloom/src/BloomAndFlares.cpp b/projects/bloom/src/BloomAndFlares.cpp deleted file mode 100644 index 6f26db9de0f2c8334b6dd7e5dd6cf4b6f48baedc..0000000000000000000000000000000000000000 --- a/projects/bloom/src/BloomAndFlares.cpp +++ /dev/null @@ -1,274 +0,0 @@ -#include "BloomAndFlares.hpp" -#include <vkcv/shader/GLSLCompiler.hpp> - -BloomAndFlares::BloomAndFlares( - vkcv::Core *p_Core, - vk::Format colorBufferFormat, - uint32_t width, - uint32_t height) : - - p_Core(p_Core), - m_ColorBufferFormat(colorBufferFormat), - m_Width(width), - m_Height(height), - m_LinearSampler(p_Core->createSampler(vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::CLAMP_TO_EDGE)), - m_Blur(p_Core->createImage(colorBufferFormat, width, height, 1, true, true, false)), - m_LensFeatures(p_Core->createImage(colorBufferFormat, width, height, 1, false, true, false)) -{ - vkcv::shader::GLSLCompiler compiler; - - // DOWNSAMPLE - vkcv::ShaderProgram dsProg; - compiler.compile(vkcv::ShaderStage::COMPUTE, - "resources/shaders/downsample.comp", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) - { - dsProg.addShader(shaderStage, path); - }); - for(uint32_t mipLevel = 0; mipLevel < m_Blur.getMipCount(); mipLevel++) - { - m_DownsampleDescSets.push_back( - p_Core->createDescriptorSet(dsProg.getReflectedDescriptors()[0])); - } - m_DownsamplePipe = p_Core->createComputePipeline( - dsProg, { p_Core->getDescriptorSet(m_DownsampleDescSets[0]).layout }); - - // UPSAMPLE - vkcv::ShaderProgram usProg; - compiler.compile(vkcv::ShaderStage::COMPUTE, - "resources/shaders/upsample.comp", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) - { - usProg.addShader(shaderStage, path); - }); - for(uint32_t mipLevel = 0; mipLevel < m_Blur.getMipCount(); mipLevel++) - { - m_UpsampleDescSets.push_back( - p_Core->createDescriptorSet(usProg.getReflectedDescriptors()[0])); - } - m_UpsamplePipe = p_Core->createComputePipeline( - usProg, { p_Core->getDescriptorSet(m_UpsampleDescSets[0]).layout }); - - // LENS FEATURES - vkcv::ShaderProgram lensProg; - compiler.compile(vkcv::ShaderStage::COMPUTE, - "resources/shaders/lensFlares.comp", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) - { - lensProg.addShader(shaderStage, path); - }); - m_LensFlareDescSet = p_Core->createDescriptorSet(lensProg.getReflectedDescriptors()[0]); - m_LensFlarePipe = p_Core->createComputePipeline( - lensProg, { p_Core->getDescriptorSet(m_LensFlareDescSet).layout }); - - // COMPOSITE - vkcv::ShaderProgram compProg; - compiler.compile(vkcv::ShaderStage::COMPUTE, - "resources/shaders/composite.comp", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) - { - compProg.addShader(shaderStage, path); - }); - m_CompositeDescSet = p_Core->createDescriptorSet(compProg.getReflectedDescriptors()[0]); - m_CompositePipe = p_Core->createComputePipeline( - compProg, { p_Core->getDescriptorSet(m_CompositeDescSet).layout }); -} - -void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStream, - const vkcv::ImageHandle &colorAttachment) -{ - auto dispatchCountX = static_cast<float>(m_Width) / 8.0f; - auto dispatchCountY = static_cast<float>(m_Height) / 8.0f; - // blur dispatch - uint32_t initialDispatchCount[3] = { - static_cast<uint32_t>(glm::ceil(dispatchCountX)), - static_cast<uint32_t>(glm::ceil(dispatchCountY)), - 1 - }; - - // downsample dispatch of original color attachment - p_Core->prepareImageForSampling(cmdStream, colorAttachment); - p_Core->prepareImageForStorage(cmdStream, m_Blur.getHandle()); - - vkcv::DescriptorWrites initialDownsampleWrites; - initialDownsampleWrites.sampledImageWrites = {vkcv::SampledImageDescriptorWrite(0, colorAttachment)}; - initialDownsampleWrites.samplerWrites = {vkcv::SamplerDescriptorWrite(1, m_LinearSampler)}; - initialDownsampleWrites.storageImageWrites = {vkcv::StorageImageDescriptorWrite(2, m_Blur.getHandle(), 0) }; - p_Core->writeDescriptorSet(m_DownsampleDescSets[0], initialDownsampleWrites); - - p_Core->recordComputeDispatchToCmdStream( - cmdStream, - m_DownsamplePipe, - initialDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[0]).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); - - // downsample dispatches of blur buffer's mip maps - float mipDispatchCountX = dispatchCountX; - float mipDispatchCountY = dispatchCountY; - for(uint32_t mipLevel = 1; mipLevel < m_DownsampleDescSets.size(); mipLevel++) - { - // mip descriptor writes - vkcv::DescriptorWrites mipDescriptorWrites; - mipDescriptorWrites.sampledImageWrites = {vkcv::SampledImageDescriptorWrite(0, m_Blur.getHandle(), mipLevel - 1, true)}; - mipDescriptorWrites.samplerWrites = {vkcv::SamplerDescriptorWrite(1, m_LinearSampler)}; - mipDescriptorWrites.storageImageWrites = {vkcv::StorageImageDescriptorWrite(2, m_Blur.getHandle(), mipLevel) }; - p_Core->writeDescriptorSet(m_DownsampleDescSets[mipLevel], mipDescriptorWrites); - - // mip dispatch calculation - mipDispatchCountX /= 2.0f; - mipDispatchCountY /= 2.0f; - - uint32_t mipDispatchCount[3] = { - static_cast<uint32_t>(glm::ceil(mipDispatchCountX)), - static_cast<uint32_t>(glm::ceil(mipDispatchCountY)), - 1 - }; - - if(mipDispatchCount[0] == 0) - mipDispatchCount[0] = 1; - if(mipDispatchCount[1] == 0) - mipDispatchCount[1] = 1; - - // mip blur dispatch - p_Core->recordComputeDispatchToCmdStream( - cmdStream, - m_DownsamplePipe, - mipDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[mipLevel]).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); - - // image barrier between mips - p_Core->recordImageMemoryBarrier(cmdStream, m_Blur.getHandle()); - } -} - -void BloomAndFlares::execUpsamplePipe(const vkcv::CommandStreamHandle &cmdStream) -{ - // upsample dispatch - p_Core->prepareImageForStorage(cmdStream, m_Blur.getHandle()); - - const uint32_t upsampleMipLevels = std::min( - static_cast<uint32_t>(m_UpsampleDescSets.size() - 1), - static_cast<uint32_t>(5) - ); - - // upsample dispatch for each mip map - for(uint32_t mipLevel = upsampleMipLevels; mipLevel > 0; mipLevel--) - { - // mip descriptor writes - vkcv::DescriptorWrites mipUpsampleWrites; - mipUpsampleWrites.sampledImageWrites = {vkcv::SampledImageDescriptorWrite(0, m_Blur.getHandle(), mipLevel, true)}; - mipUpsampleWrites.samplerWrites = {vkcv::SamplerDescriptorWrite(1, m_LinearSampler)}; - mipUpsampleWrites.storageImageWrites = {vkcv::StorageImageDescriptorWrite(2, m_Blur.getHandle(), mipLevel - 1) }; - p_Core->writeDescriptorSet(m_UpsampleDescSets[mipLevel], mipUpsampleWrites); - - auto mipDivisor = glm::pow(2.0f, static_cast<float>(mipLevel) - 1.0f); - - auto upsampleDispatchX = static_cast<float>(m_Width) / mipDivisor; - auto upsampleDispatchY = static_cast<float>(m_Height) / mipDivisor; - upsampleDispatchX /= 8.0f; - upsampleDispatchY /= 8.0f; - - const uint32_t upsampleDispatchCount[3] = { - static_cast<uint32_t>(glm::ceil(upsampleDispatchX)), - static_cast<uint32_t>(glm::ceil(upsampleDispatchY)), - 1 - }; - - p_Core->recordComputeDispatchToCmdStream( - cmdStream, - m_UpsamplePipe, - upsampleDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_UpsampleDescSets[mipLevel]).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0) - ); - // image barrier between mips - p_Core->recordImageMemoryBarrier(cmdStream, m_Blur.getHandle()); - } -} - -void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStream) -{ - // lens feature generation descriptor writes - p_Core->prepareImageForSampling(cmdStream, m_Blur.getHandle()); - p_Core->prepareImageForStorage(cmdStream, m_LensFeatures.getHandle()); - - vkcv::DescriptorWrites lensFeatureWrites; - lensFeatureWrites.sampledImageWrites = {vkcv::SampledImageDescriptorWrite(0, m_Blur.getHandle(), 0)}; - lensFeatureWrites.samplerWrites = {vkcv::SamplerDescriptorWrite(1, m_LinearSampler)}; - lensFeatureWrites.storageImageWrites = {vkcv::StorageImageDescriptorWrite(2, m_LensFeatures.getHandle(), 0)}; - p_Core->writeDescriptorSet(m_LensFlareDescSet, lensFeatureWrites); - - auto dispatchCountX = static_cast<float>(m_Width) / 8.0f; - auto dispatchCountY = static_cast<float>(m_Height) / 8.0f; - // lens feature generation dispatch - uint32_t lensFeatureDispatchCount[3] = { - static_cast<uint32_t>(glm::ceil(dispatchCountX)), - static_cast<uint32_t>(glm::ceil(dispatchCountY)), - 1 - }; - p_Core->recordComputeDispatchToCmdStream( - cmdStream, - m_LensFlarePipe, - lensFeatureDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_LensFlareDescSet).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); -} - -void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStream, - const vkcv::ImageHandle &colorAttachment) -{ - p_Core->prepareImageForSampling(cmdStream, m_Blur.getHandle()); - p_Core->prepareImageForSampling(cmdStream, m_LensFeatures.getHandle()); - p_Core->prepareImageForStorage(cmdStream, colorAttachment); - - // bloom composite descriptor write - vkcv::DescriptorWrites compositeWrites; - compositeWrites.sampledImageWrites = {vkcv::SampledImageDescriptorWrite(0, m_Blur.getHandle()), - vkcv::SampledImageDescriptorWrite(1, m_LensFeatures.getHandle())}; - compositeWrites.samplerWrites = {vkcv::SamplerDescriptorWrite(2, m_LinearSampler)}; - compositeWrites.storageImageWrites = {vkcv::StorageImageDescriptorWrite(3, colorAttachment)}; - p_Core->writeDescriptorSet(m_CompositeDescSet, compositeWrites); - - float dispatchCountX = static_cast<float>(m_Width) / 8.0f; - float dispatchCountY = static_cast<float>(m_Height) / 8.0f; - - uint32_t compositeDispatchCount[3] = { - static_cast<uint32_t>(glm::ceil(dispatchCountX)), - static_cast<uint32_t>(glm::ceil(dispatchCountY)), - 1 - }; - - // bloom composite dispatch - p_Core->recordComputeDispatchToCmdStream( - cmdStream, - m_CompositePipe, - compositeDispatchCount, - {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_CompositeDescSet).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); -} - -void BloomAndFlares::execWholePipeline(const vkcv::CommandStreamHandle &cmdStream, - const vkcv::ImageHandle &colorAttachment) -{ - execDownsamplePipe(cmdStream, colorAttachment); - execUpsamplePipe(cmdStream); - execLensFeaturePipe(cmdStream); - execCompositePipe(cmdStream, colorAttachment); -} - -void BloomAndFlares::updateImageDimensions(uint32_t width, uint32_t height) -{ - m_Width = width; - m_Height = height; - - p_Core->getContext().getDevice().waitIdle(); - m_Blur = p_Core->createImage(m_ColorBufferFormat, m_Width, m_Height, 1, true, true, false); - m_LensFeatures = p_Core->createImage(m_ColorBufferFormat, m_Width, m_Height, 1, false, true, false); -} - - diff --git a/projects/bloom/src/BloomAndFlares.hpp b/projects/bloom/src/BloomAndFlares.hpp deleted file mode 100644 index 756b1ca154ea5232df04eb09a88bb743c5bd28aa..0000000000000000000000000000000000000000 --- a/projects/bloom/src/BloomAndFlares.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include <vkcv/Core.hpp> -#include <glm/glm.hpp> - -class BloomAndFlares{ -public: - BloomAndFlares(vkcv::Core *p_Core, - vk::Format colorBufferFormat, - uint32_t width, - uint32_t height); - - void execWholePipeline(const vkcv::CommandStreamHandle &cmdStream, const vkcv::ImageHandle &colorAttachment); - - void updateImageDimensions(uint32_t width, uint32_t height); - -private: - vkcv::Core *p_Core; - - vk::Format m_ColorBufferFormat; - uint32_t m_Width; - uint32_t m_Height; - - vkcv::SamplerHandle m_LinearSampler; - vkcv::Image m_Blur; - vkcv::Image m_LensFeatures; - - - vkcv::PipelineHandle m_DownsamplePipe; - std::vector<vkcv::DescriptorSetHandle> m_DownsampleDescSets; // per mip desc set - - vkcv::PipelineHandle m_UpsamplePipe; - std::vector<vkcv::DescriptorSetHandle> m_UpsampleDescSets; // per mip desc set - - vkcv::PipelineHandle m_LensFlarePipe; - vkcv::DescriptorSetHandle m_LensFlareDescSet; - - vkcv::PipelineHandle m_CompositePipe; - vkcv::DescriptorSetHandle m_CompositeDescSet; - - void execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStream, const vkcv::ImageHandle &colorAttachment); - void execUpsamplePipe(const vkcv::CommandStreamHandle &cmdStream); - void execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStream); - void execCompositePipe(const vkcv::CommandStreamHandle &cmdStream, const vkcv::ImageHandle &colorAttachment); -}; - - - diff --git a/projects/bloom/src/main.cpp b/projects/bloom/src/main.cpp deleted file mode 100644 index 7a17a51f1c7d638575c0b5aafcdca49b589533ef..0000000000000000000000000000000000000000 --- a/projects/bloom/src/main.cpp +++ /dev/null @@ -1,419 +0,0 @@ -#include <iostream> -#include <vkcv/Core.hpp> -#include <GLFW/glfw3.h> -#include <vkcv/camera/CameraManager.hpp> -#include <chrono> -#include <vkcv/asset/asset_loader.hpp> -#include <vkcv/shader/GLSLCompiler.hpp> -#include <vkcv/Logger.hpp> -#include "BloomAndFlares.hpp" -#include <glm/glm.hpp> - -int main(int argc, const char** argv) { - const char* applicationName = "Bloom"; - - uint32_t windowWidth = 1920; - uint32_t windowHeight = 1080; - - vkcv::Window window = vkcv::Window::create( - applicationName, - windowWidth, - windowHeight, - true - ); - - vkcv::camera::CameraManager cameraManager(window); - uint32_t camIndex = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); - uint32_t camIndex2 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL); - - cameraManager.getCamera(camIndex).setPosition(glm::vec3(0.f, 0.f, 3.f)); - cameraManager.getCamera(camIndex).setNearFar(0.1f, 30.0f); - cameraManager.getCamera(camIndex).setYaw(180.0f); - - cameraManager.getCamera(camIndex2).setNearFar(0.1f, 30.0f); - - vkcv::Core core = vkcv::Core::create( - window, - applicationName, - VK_MAKE_VERSION(0, 0, 1), - { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, - {}, - { "VK_KHR_swapchain" } - ); - - const char* path = argc > 1 ? argv[1] : "resources/Sponza/Sponza.gltf"; - vkcv::asset::Scene scene; - int result = vkcv::asset::loadScene(path, scene); - - if (result == 1) { - std::cout << "Scene loading successful!" << std::endl; - } - else { - std::cout << "Scene loading failed: " << result << std::endl; - return 1; - } - - // build index and vertex buffers - assert(!scene.vertexGroups.empty()); - std::vector<std::vector<uint8_t>> vBuffers; - std::vector<std::vector<uint8_t>> iBuffers; - - std::vector<vkcv::VertexBufferBinding> vBufferBindings; - std::vector<std::vector<vkcv::VertexBufferBinding>> vertexBufferBindings; - std::vector<vkcv::asset::VertexAttribute> vAttributes; - - for (int i = 0; i < scene.vertexGroups.size(); i++) { - - vBuffers.push_back(scene.vertexGroups[i].vertexBuffer.data); - iBuffers.push_back(scene.vertexGroups[i].indexBuffer.data); - - auto& attributes = scene.vertexGroups[i].vertexBuffer.attributes; - - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); - } - - std::vector<vkcv::Buffer<uint8_t>> vertexBuffers; - for (const vkcv::asset::VertexGroup& group : scene.vertexGroups) { - vertexBuffers.push_back(core.createBuffer<uint8_t>( - vkcv::BufferType::VERTEX, - group.vertexBuffer.data.size())); - vertexBuffers.back().fill(group.vertexBuffer.data); - } - - std::vector<vkcv::Buffer<uint8_t>> indexBuffers; - for (const auto& dataBuffer : iBuffers) { - indexBuffers.push_back(core.createBuffer<uint8_t>( - vkcv::BufferType::INDEX, - dataBuffer.size())); - indexBuffers.back().fill(dataBuffer); - } - - int vertexBufferIndex = 0; - for (const auto& vertexGroup : scene.vertexGroups) { - for (const auto& attribute : vertexGroup.vertexBuffer.attributes) { - vAttributes.push_back(attribute); - vBufferBindings.push_back(vkcv::VertexBufferBinding(attribute.offset, vertexBuffers[vertexBufferIndex].getVulkanHandle())); - } - vertexBufferBindings.push_back(vBufferBindings); - vBufferBindings.clear(); - vertexBufferIndex++; - } - - const vk::Format colorBufferFormat = vk::Format::eB10G11R11UfloatPack32; - const vkcv::AttachmentDescription color_attachment( - vkcv::AttachmentOperation::STORE, - vkcv::AttachmentOperation::CLEAR, - colorBufferFormat - ); - - const vk::Format depthBufferFormat = vk::Format::eD32Sfloat; - const vkcv::AttachmentDescription depth_attachment( - vkcv::AttachmentOperation::STORE, - vkcv::AttachmentOperation::CLEAR, - depthBufferFormat - ); - - vkcv::PassConfig forwardPassDefinition({ color_attachment, depth_attachment }); - vkcv::PassHandle forwardPass = core.createPass(forwardPassDefinition); - - vkcv::shader::GLSLCompiler compiler; - - vkcv::ShaderProgram forwardProgram; - compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/shader.vert"), - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - forwardProgram.addShader(shaderStage, path); - }); - compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/shader.frag"), - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - forwardProgram.addShader(shaderStage, path); - }); - - const std::vector<vkcv::VertexAttachment> vertexAttachments = forwardProgram.getVertexAttachments(); - - std::vector<vkcv::VertexBinding> vertexBindings; - for (size_t i = 0; i < vertexAttachments.size(); i++) { - vertexBindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] })); - } - const vkcv::VertexLayout vertexLayout (vertexBindings); - - // shadow map - vkcv::SamplerHandle shadowSampler = core.createSampler( - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerMipmapMode::NEAREST, - vkcv::SamplerAddressMode::CLAMP_TO_EDGE - ); - const vk::Format shadowMapFormat = vk::Format::eD16Unorm; - const uint32_t shadowMapResolution = 1024; - const vkcv::Image shadowMap = core.createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1); - - // light info buffer - struct LightInfo { - glm::vec3 direction; - float padding; - glm::mat4 lightMatrix; - }; - LightInfo lightInfo; - vkcv::Buffer lightBuffer = core.createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3)); - - vkcv::DescriptorSetHandle forwardShadingDescriptorSet = - core.createDescriptorSet({ forwardProgram.getReflectedDescriptors()[0] }); - - vkcv::DescriptorWrites forwardDescriptorWrites; - forwardDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(0, lightBuffer.getHandle()) }; - forwardDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(1, shadowMap.getHandle()) }; - forwardDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(2, shadowSampler) }; - core.writeDescriptorSet(forwardShadingDescriptorSet, forwardDescriptorWrites); - - vkcv::SamplerHandle colorSampler = core.createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - - // prepare per mesh descriptor sets - std::vector<vkcv::DescriptorSetHandle> perMeshDescriptorSets; - std::vector<vkcv::Image> sceneImages; - for (const auto& vertexGroup : scene.vertexGroups) { - perMeshDescriptorSets.push_back(core.createDescriptorSet(forwardProgram.getReflectedDescriptors()[1])); - - const auto& material = scene.materials[vertexGroup.materialIndex]; - - int baseColorIndex = material.baseColor; - if (baseColorIndex < 0) { - vkcv_log(vkcv::LogLevel::WARNING, "Material lacks base color"); - baseColorIndex = 0; - } - - vkcv::asset::Texture& sceneTexture = scene.textures[baseColorIndex]; - - sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, sceneTexture.w, sceneTexture.h)); - sceneImages.back().fill(sceneTexture.data.data()); - - vkcv::DescriptorWrites setWrites; - setWrites.sampledImageWrites = { - vkcv::SampledImageDescriptorWrite(0, sceneImages.back().getHandle()) - }; - setWrites.samplerWrites = { - vkcv::SamplerDescriptorWrite(1, colorSampler), - }; - core.writeDescriptorSet(perMeshDescriptorSets.back(), setWrites); - } - - const vkcv::PipelineConfig forwardPipelineConfig { - forwardProgram, - windowWidth, - windowHeight, - forwardPass, - vertexLayout, - { core.getDescriptorSet(forwardShadingDescriptorSet).layout, - core.getDescriptorSet(perMeshDescriptorSets[0]).layout }, - true - }; - - vkcv::PipelineHandle forwardPipeline = core.createGraphicsPipeline(forwardPipelineConfig); - - if (!forwardPipeline) { - std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; - return EXIT_FAILURE; - } - - vkcv::ImageHandle depthBuffer = core.createImage(depthBufferFormat, windowWidth, windowHeight).getHandle(); - vkcv::ImageHandle colorBuffer = core.createImage(colorBufferFormat, windowWidth, windowHeight, 1, false, true, true).getHandle(); - - const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); - - vkcv::ShaderProgram shadowShader; - compiler.compile(vkcv::ShaderStage::VERTEX, "resources/shaders/shadow.vert", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - shadowShader.addShader(shaderStage, path); - }); - compiler.compile(vkcv::ShaderStage::FRAGMENT, "resources/shaders/shadow.frag", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - shadowShader.addShader(shaderStage, path); - }); - - const std::vector<vkcv::AttachmentDescription> shadowAttachments = { - vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapFormat) - }; - const vkcv::PassConfig shadowPassConfig(shadowAttachments); - const vkcv::PassHandle shadowPass = core.createPass(shadowPassConfig); - const vkcv::PipelineConfig shadowPipeConfig{ - shadowShader, - shadowMapResolution, - shadowMapResolution, - shadowPass, - vertexLayout, - {}, - false - }; - const vkcv::PipelineHandle shadowPipe = core.createGraphicsPipeline(shadowPipeConfig); - - std::vector<std::array<glm::mat4, 2>> mainPassMatrices; - std::vector<glm::mat4> mvpLight; - - // gamma correction compute shader - vkcv::ShaderProgram gammaCorrectionProgram; - compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/gammaCorrection.comp", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - gammaCorrectionProgram.addShader(shaderStage, path); - }); - vkcv::DescriptorSetHandle gammaCorrectionDescriptorSet = core.createDescriptorSet(gammaCorrectionProgram.getReflectedDescriptors()[0]); - vkcv::PipelineHandle gammaCorrectionPipeline = core.createComputePipeline(gammaCorrectionProgram, - { core.getDescriptorSet(gammaCorrectionDescriptorSet).layout }); - - BloomAndFlares baf(&core, colorBufferFormat, windowWidth, windowHeight); - - - // model matrices per mesh - std::vector<glm::mat4> modelMatrices; - modelMatrices.resize(scene.vertexGroups.size(), glm::mat4(1.f)); - for (const auto& mesh : scene.meshes) { - const glm::mat4 m = *reinterpret_cast<const glm::mat4*>(&mesh.modelMatrix[0]); - for (const auto& vertexGroupIndex : mesh.vertexGroups) { - modelMatrices[vertexGroupIndex] = m; - } - } - - // prepare drawcalls - std::vector<vkcv::Mesh> meshes; - for (int i = 0; i < scene.vertexGroups.size(); i++) { - vkcv::Mesh mesh( - vertexBufferBindings[i], - indexBuffers[i].getVulkanHandle(), - scene.vertexGroups[i].numIndices); - meshes.push_back(mesh); - } - - std::vector<vkcv::DrawcallInfo> drawcalls; - std::vector<vkcv::DrawcallInfo> shadowDrawcalls; - for (int i = 0; i < meshes.size(); i++) { - drawcalls.push_back(vkcv::DrawcallInfo(meshes[i], { - vkcv::DescriptorSetUsage(0, core.getDescriptorSet(forwardShadingDescriptorSet).vulkanHandle), - vkcv::DescriptorSetUsage(1, core.getDescriptorSet(perMeshDescriptorSets[i]).vulkanHandle) })); - shadowDrawcalls.push_back(vkcv::DrawcallInfo(meshes[i], {})); - } - - auto start = std::chrono::system_clock::now(); - const auto appStartTime = start; - while (window.isWindowOpen()) { - vkcv::Window::pollEvents(); - - uint32_t swapchainWidth, swapchainHeight; - if (!core.beginFrame(swapchainWidth, swapchainHeight)) { - continue; - } - - if ((swapchainWidth != windowWidth) || ((swapchainHeight != windowHeight))) { - depthBuffer = core.createImage(depthBufferFormat, swapchainWidth, swapchainHeight).getHandle(); - colorBuffer = core.createImage(colorBufferFormat, swapchainWidth, swapchainHeight, 1, false, true, true).getHandle(); - - baf.updateImageDimensions(swapchainWidth, swapchainHeight); - - windowWidth = swapchainWidth; - windowHeight = swapchainHeight; - } - - auto end = std::chrono::system_clock::now(); - auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start); - - start = end; - cameraManager.update(0.000001 * static_cast<double>(deltatime.count())); - - auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - appStartTime); - - const float sunTheta = 0.0001f * static_cast<float>(duration.count()); - lightInfo.direction = glm::normalize(glm::vec3(std::cos(sunTheta), 1, std::sin(sunTheta))); - - const float shadowProjectionSize = 20.f; - glm::mat4 projectionLight = glm::ortho( - -shadowProjectionSize, - shadowProjectionSize, - -shadowProjectionSize, - shadowProjectionSize, - -shadowProjectionSize, - shadowProjectionSize); - - glm::mat4 vulkanCorrectionMatrix(1.f); - vulkanCorrectionMatrix[2][2] = 0.5; - vulkanCorrectionMatrix[3][2] = 0.5; - projectionLight = vulkanCorrectionMatrix * projectionLight; - - const glm::mat4 viewLight = glm::lookAt(glm::vec3(0), -lightInfo.direction, glm::vec3(0, -1, 0)); - - lightInfo.lightMatrix = projectionLight * viewLight; - lightBuffer.fill({ lightInfo }); - - const glm::mat4 viewProjectionCamera = cameraManager.getActiveCamera().getMVP(); - - mainPassMatrices.clear(); - mvpLight.clear(); - for (const auto& m : modelMatrices) { - mainPassMatrices.push_back({ viewProjectionCamera * m, m }); - mvpLight.push_back(lightInfo.lightMatrix * m); - } - - vkcv::PushConstantData pushConstantData((void*)mainPassMatrices.data(), 2 * sizeof(glm::mat4)); - const std::vector<vkcv::ImageHandle> renderTargets = { colorBuffer, depthBuffer }; - - const vkcv::PushConstantData shadowPushConstantData((void*)mvpLight.data(), sizeof(glm::mat4)); - - auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); - - // shadow map - core.recordDrawcallsToCmdStream( - cmdStream, - shadowPass, - shadowPipe, - shadowPushConstantData, - shadowDrawcalls, - { shadowMap.getHandle() }); - core.prepareImageForSampling(cmdStream, shadowMap.getHandle()); - - // main pass - core.recordDrawcallsToCmdStream( - cmdStream, - forwardPass, - forwardPipeline, - pushConstantData, - drawcalls, - renderTargets); - - const uint32_t gammaCorrectionLocalGroupSize = 8; - const uint32_t gammaCorrectionDispatchCount[3] = { - static_cast<uint32_t>(glm::ceil(static_cast<float>(windowWidth) / static_cast<float>(gammaCorrectionLocalGroupSize))), - static_cast<uint32_t>(glm::ceil(static_cast<float>(windowHeight) / static_cast<float>(gammaCorrectionLocalGroupSize))), - 1 - }; - - baf.execWholePipeline(cmdStream, colorBuffer); - - core.prepareImageForStorage(cmdStream, swapchainInput); - - // gamma correction descriptor write - vkcv::DescriptorWrites gammaCorrectionDescriptorWrites; - gammaCorrectionDescriptorWrites.storageImageWrites = { - vkcv::StorageImageDescriptorWrite(0, colorBuffer), - vkcv::StorageImageDescriptorWrite(1, swapchainInput) }; - core.writeDescriptorSet(gammaCorrectionDescriptorSet, gammaCorrectionDescriptorWrites); - - // gamma correction dispatch - core.recordComputeDispatchToCmdStream( - cmdStream, - gammaCorrectionPipeline, - gammaCorrectionDispatchCount, - { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(gammaCorrectionDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData(nullptr, 0)); - - // present and end - core.prepareSwapchainImageForPresent(cmdStream); - core.submitCommandStream(cmdStream); - - core.endFrame(); - } - - return 0; -} diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp deleted file mode 100644 index 6e53eb8c5ec1825135778dc91b11dd6e45f44276..0000000000000000000000000000000000000000 --- a/projects/cmd_sync_test/src/main.cpp +++ /dev/null @@ -1,317 +0,0 @@ -#include <iostream> -#include <vkcv/Core.hpp> -#include <GLFW/glfw3.h> -#include <vkcv/camera/CameraManager.hpp> -#include <chrono> -#include <vkcv/asset/asset_loader.hpp> - -int main(int argc, const char** argv) { - const char* applicationName = "First Mesh"; - - uint32_t windowWidth = 800; - uint32_t windowHeight = 600; - - vkcv::Window window = vkcv::Window::create( - applicationName, - windowWidth, - windowHeight, - true - ); - - vkcv::camera::CameraManager cameraManager(window); - uint32_t camIndex = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); - uint32_t camIndex2 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL); - - cameraManager.getCamera(camIndex).setPosition(glm::vec3(0.f, 0.f, 3.f)); - cameraManager.getCamera(camIndex).setNearFar(0.1f, 30.0f); - cameraManager.getCamera(camIndex).setYaw(180.0f); - - cameraManager.getCamera(camIndex2).setNearFar(0.1f, 30.0f); - - window.initEvents(); - - vkcv::Core core = vkcv::Core::create( - window, - applicationName, - VK_MAKE_VERSION(0, 0, 1), - { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, - {}, - { "VK_KHR_swapchain" } - ); - - vkcv::asset::Scene mesh; - - const char* path = argc > 1 ? argv[1] : "resources/cube/cube.gltf"; - int result = vkcv::asset::loadScene(path, mesh); - - if (result == 1) { - std::cout << "Mesh loading successful!" << std::endl; - } - else { - std::cout << "Mesh loading failed: " << result << std::endl; - return 1; - } - - assert(mesh.vertexGroups.size() > 0); - auto vertexBuffer = core.createBuffer<uint8_t>( - vkcv::BufferType::VERTEX, - mesh.vertexGroups[0].vertexBuffer.data.size(), - vkcv::BufferMemoryType::DEVICE_LOCAL - ); - - vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data); - - auto indexBuffer = core.createBuffer<uint8_t>( - vkcv::BufferType::INDEX, - mesh.vertexGroups[0].indexBuffer.data.size(), - vkcv::BufferMemoryType::DEVICE_LOCAL - ); - - indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data); - - auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes; - - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); - - const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = { - vkcv::VertexBufferBinding(attributes[0].offset, vertexBuffer.getVulkanHandle()), - vkcv::VertexBufferBinding(attributes[1].offset, vertexBuffer.getVulkanHandle()), - vkcv::VertexBufferBinding(attributes[2].offset, vertexBuffer.getVulkanHandle()) }; - - const vkcv::Mesh loadedMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices); - - // an example attachment for passes that output to the window - const vkcv::AttachmentDescription present_color_attachment( - vkcv::AttachmentOperation::STORE, - vkcv::AttachmentOperation::CLEAR, - core.getSwapchain().getFormat() - ); - - const vkcv::AttachmentDescription depth_attachment( - vkcv::AttachmentOperation::STORE, - vkcv::AttachmentOperation::CLEAR, - vk::Format::eD32Sfloat - ); - - vkcv::PassConfig firstMeshPassDefinition({ present_color_attachment, depth_attachment }); - vkcv::PassHandle firstMeshPass = core.createPass(firstMeshPassDefinition); - - if (!firstMeshPass) { - std::cout << "Error. Could not create renderpass. Exiting." << std::endl; - return EXIT_FAILURE; - } - - vkcv::ShaderProgram firstMeshProgram{}; - firstMeshProgram.addShader(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/vert.spv")); - firstMeshProgram.addShader(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/frag.spv")); - - const std::vector<vkcv::VertexAttachment> vertexAttachments = firstMeshProgram.getVertexAttachments(); - - std::vector<vkcv::VertexBinding> bindings; - for (size_t i = 0; i < vertexAttachments.size(); i++) { - bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] })); - } - - const vkcv::VertexLayout firstMeshLayout (bindings); - - std::vector<vkcv::DescriptorBinding> descriptorBindings = { firstMeshProgram.getReflectedDescriptors()[0] }; - vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings); - - const vkcv::PipelineConfig firstMeshPipelineConfig { - firstMeshProgram, - windowWidth, - windowHeight, - firstMeshPass, - firstMeshLayout, - { core.getDescriptorSet(descriptorSet).layout }, - true - }; - - vkcv::PipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig); - - if (!firstMeshPipeline) { - std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; - return EXIT_FAILURE; - } - - //vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, mesh.texture_hack.w, mesh.texture_hack.h); - //texture.fill(mesh.texture_hack.img); - vkcv::asset::Texture &tex = mesh.textures[0]; - vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, tex.w, tex.h); - texture.fill(tex.data.data()); - - vkcv::SamplerHandle sampler = core.createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - - vkcv::SamplerHandle shadowSampler = core.createSampler( - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerMipmapMode::NEAREST, - vkcv::SamplerAddressMode::CLAMP_TO_EDGE - ); - - vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle(); - - const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); - - const vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); - - const std::vector<glm::vec3> instancePositions = { - glm::vec3( 0.f, -2.f, 0.f), - glm::vec3( 3.f, 0.f, 0.f), - glm::vec3(-3.f, 0.f, 0.f), - glm::vec3( 0.f, 2.f, 0.f), - glm::vec3( 0.f, -5.f, 0.f) - }; - - std::vector<glm::mat4> modelMatrices; - std::vector<vkcv::DrawcallInfo> drawcalls; - std::vector<vkcv::DrawcallInfo> shadowDrawcalls; - for (const auto& position : instancePositions) { - modelMatrices.push_back(glm::translate(glm::mat4(1.f), position)); - drawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { descriptorUsage },1)); - shadowDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, {},1)); - } - - modelMatrices.back() *= glm::scale(glm::mat4(1.f), glm::vec3(10.f, 1.f, 10.f)); - - std::vector<std::array<glm::mat4, 2>> mainPassMatrices; - std::vector<glm::mat4> mvpLight; - - vkcv::ShaderProgram shadowShader; - shadowShader.addShader(vkcv::ShaderStage::VERTEX, "resources/shaders/shadow_vert.spv"); - shadowShader.addShader(vkcv::ShaderStage::FRAGMENT, "resources/shaders/shadow_frag.spv"); - - const vk::Format shadowMapFormat = vk::Format::eD16Unorm; - const std::vector<vkcv::AttachmentDescription> shadowAttachments = { - vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapFormat) - }; - const vkcv::PassConfig shadowPassConfig(shadowAttachments); - const vkcv::PassHandle shadowPass = core.createPass(shadowPassConfig); - - const uint32_t shadowMapResolution = 1024; - const vkcv::Image shadowMap = core.createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1); - const vkcv::PipelineConfig shadowPipeConfig { - shadowShader, - shadowMapResolution, - shadowMapResolution, - shadowPass, - firstMeshLayout, - {}, - false - }; - - const vkcv::PipelineHandle shadowPipe = core.createGraphicsPipeline(shadowPipeConfig); - - struct LightInfo { - glm::vec3 direction; - float padding; - glm::mat4 lightMatrix; - }; - LightInfo lightInfo; - vkcv::Buffer lightBuffer = core.createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3)); - - vkcv::DescriptorWrites setWrites; - setWrites.sampledImageWrites = { - vkcv::SampledImageDescriptorWrite(0, texture.getHandle()), - vkcv::SampledImageDescriptorWrite(3, shadowMap.getHandle()) }; - setWrites.samplerWrites = { - vkcv::SamplerDescriptorWrite(1, sampler), - vkcv::SamplerDescriptorWrite(4, shadowSampler) }; - setWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(2, lightBuffer.getHandle()) }; - core.writeDescriptorSet(descriptorSet, setWrites); - - auto start = std::chrono::system_clock::now(); - const auto appStartTime = start; - while (window.isWindowOpen()) { - window.pollEvents(); - - uint32_t swapchainWidth, swapchainHeight; - if (!core.beginFrame(swapchainWidth, swapchainHeight)) { - continue; - } - - if ((swapchainWidth != windowWidth) || ((swapchainHeight != windowHeight))) { - depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight).getHandle(); - - windowWidth = swapchainWidth; - windowHeight = swapchainHeight; - } - - auto end = std::chrono::system_clock::now(); - auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start); - - start = end; - cameraManager.update(0.000001 * static_cast<double>(deltatime.count())); - - auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - appStartTime); - - const float sunTheta = 0.001f * static_cast<float>(duration.count()); - lightInfo.direction = glm::normalize(glm::vec3(std::cos(sunTheta), 1, std::sin(sunTheta))); - - const float shadowProjectionSize = 5.f; - glm::mat4 projectionLight = glm::ortho( - -shadowProjectionSize, - shadowProjectionSize, - -shadowProjectionSize, - shadowProjectionSize, - -shadowProjectionSize, - shadowProjectionSize); - - glm::mat4 vulkanCorrectionMatrix(1.f); - vulkanCorrectionMatrix[2][2] = 0.5; - vulkanCorrectionMatrix[3][2] = 0.5; - projectionLight = vulkanCorrectionMatrix * projectionLight; - - const glm::mat4 viewLight = glm::lookAt(glm::vec3(0), -lightInfo.direction, glm::vec3(0, -1, 0)); - - lightInfo.lightMatrix = projectionLight * viewLight; - lightBuffer.fill({ lightInfo }); - - const glm::mat4 viewProjectionCamera = cameraManager.getActiveCamera().getMVP(); - - mainPassMatrices.clear(); - mvpLight.clear(); - for (const auto& m : modelMatrices) { - mainPassMatrices.push_back({ viewProjectionCamera * m, m }); - mvpLight.push_back(lightInfo.lightMatrix* m); - } - - vkcv::PushConstantData pushConstantData((void*)mainPassMatrices.data(), 2 * sizeof(glm::mat4)); - const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; - - vkcv::PushConstantData shadowPushConstantData((void*)mvpLight.data(), sizeof(glm::mat4)); - - auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); - - core.recordDrawcallsToCmdStream( - cmdStream, - shadowPass, - shadowPipe, - shadowPushConstantData, - shadowDrawcalls, - { shadowMap.getHandle() }); - - core.prepareImageForSampling(cmdStream, shadowMap.getHandle()); - - core.recordDrawcallsToCmdStream( - cmdStream, - firstMeshPass, - firstMeshPipeline, - pushConstantData, - drawcalls, - renderTargets); - core.prepareSwapchainImageForPresent(cmdStream); - core.submitCommandStream(cmdStream); - - core.endFrame(); - } - - return 0; -} diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index e7546fc3a143b3638cceb36869c519336ebec751..44a370be228be32f2e9d95685bb5297401605945 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -34,9 +34,8 @@ int main(int argc, const char** argv) { if (result == 1) { std::cout << "Mesh loading successful!" << std::endl; - } - else { - std::cout << "Mesh loading failed: " << result << std::endl; + } else { + std::cerr << "Mesh loading failed: " << result << std::endl; return 1; } @@ -74,7 +73,7 @@ int main(int argc, const char** argv) { vkcv::PassHandle firstMeshPass = core.createPass(firstMeshPassDefinition); if (!firstMeshPass) { - std::cout << "Error. Could not create renderpass. Exiting." << std::endl; + std::cerr << "Error. Could not create renderpass. Exiting." << std::endl; return EXIT_FAILURE; } @@ -113,12 +112,15 @@ int main(int argc, const char** argv) { vkcv::PipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig); if (!firstMeshPipeline) { - std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; + std::cerr << "Error. Could not create graphics pipeline. Exiting." << std::endl; + return EXIT_FAILURE; + } + + if (mesh.textures.empty()) { + std::cerr << "Error. No textures found. Exiting." << std::endl; return EXIT_FAILURE; } - // FIXME There should be a test here to make sure there is at least 1 - // texture in the mesh. vkcv::asset::Texture &tex = mesh.textures[0]; vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, tex.w, tex.h); texture.fill(tex.data.data()); @@ -161,7 +163,7 @@ int main(int argc, const char** argv) { auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { - window.pollEvents(); + vkcv::Window::pollEvents(); if(window.getHeight() == 0 || window.getWidth() == 0) continue; @@ -185,7 +187,8 @@ int main(int argc, const char** argv) { cameraManager.update(0.000001 * static_cast<double>(deltatime.count())); glm::mat4 mvp = cameraManager.getActiveCamera().getMVP(); - vkcv::PushConstantData pushConstantData((void*)&mvp, sizeof(glm::mat4)); + vkcv::PushConstants pushConstants (sizeof(glm::mat4)); + pushConstants.appendDrawcall(mvp); const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); @@ -194,7 +197,7 @@ int main(int argc, const char** argv) { cmdStream, firstMeshPass, firstMeshPipeline, - pushConstantData, + pushConstants, { drawcall }, renderTargets); core.prepareSwapchainImageForPresent(cmdStream); diff --git a/projects/first_scene/CMakeLists.txt b/projects/first_scene/CMakeLists.txt index 8b90739750011a36b4c1d9e0bff7cba986074228..467663dcb916da78d0625a33c6c88a1af3403af7 100644 --- a/projects/first_scene/CMakeLists.txt +++ b/projects/first_scene/CMakeLists.txt @@ -22,7 +22,7 @@ if(MSVC) endif() # including headers of dependencies and the VkCV framework -target_include_directories(first_scene SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include}) +target_include_directories(first_scene SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_scene_include}) # linking with libraries from all dependencies and the VkCV framework -target_link_libraries(first_scene vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera) +target_link_libraries(first_scene vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera vkcv_scene) diff --git a/projects/first_scene/resources/Sponza/SponzaFloor.bin b/projects/first_scene/resources/Sponza/SponzaFloor.bin new file mode 100644 index 0000000000000000000000000000000000000000..684251288f35070d2e7d244877fd844cc00ca632 --- /dev/null +++ b/projects/first_scene/resources/Sponza/SponzaFloor.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:678455aca641cb1f449aa1a5054a7cae132be81c2b333aac283053967da66df0 +size 512 diff --git a/projects/first_scene/resources/Sponza/SponzaFloor.gltf b/projects/first_scene/resources/Sponza/SponzaFloor.gltf new file mode 100644 index 0000000000000000000000000000000000000000..b45f1c55ef85f2aa1d4bff01df3d9625aa38c809 --- /dev/null +++ b/projects/first_scene/resources/Sponza/SponzaFloor.gltf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6deb75441b1138b50a6b0eec05e60df276fe8fb6d58118fdfce2090b6fbe734 +size 3139 diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index 521818732f7a60eabe9f0c2c080c6d343a71b1d8..486b21343926e1b922b73ba8ffb29428de6ea9a7 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -5,16 +5,9 @@ #include <chrono> #include <vkcv/asset/asset_loader.hpp> #include <vkcv/Logger.hpp> +#include <vkcv/scene/Scene.hpp> + -glm::mat4 arrayTo4x4Matrix(std::array<float,16> array){ - glm::mat4 matrix; - for (int i = 0; i < 4; i++){ - for (int j = 0; j < 4; j++){ - matrix[i][j] = array[j * 4 + i]; - } - } - return matrix; -} int main(int argc, const char** argv) { const char* applicationName = "First Scene"; @@ -32,8 +25,8 @@ int main(int argc, const char** argv) { vkcv::camera::CameraManager cameraManager(window); uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); uint32_t camIndex1 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL); - - cameraManager.getCamera(camIndex0).setPosition(glm::vec3(0, 0, -3)); + + cameraManager.getCamera(camIndex0).setPosition(glm::vec3(-8, 1, -0.5)); cameraManager.getCamera(camIndex0).setNearFar(0.1f, 30.0f); cameraManager.getCamera(camIndex1).setNearFar(0.1f, 30.0f); @@ -46,66 +39,10 @@ int main(int argc, const char** argv) { {}, { "VK_KHR_swapchain" } ); - - vkcv::asset::Scene scene; - - const char* path = argc > 1 ? argv[1] : "resources/Sponza/Sponza.gltf"; - int result = vkcv::asset::loadScene(path, scene); - - if (result == 1) { - std::cout << "Mesh loading successful!" << std::endl; - } - else { - std::cout << "Mesh loading failed: " << result << std::endl; - return 1; - } - - assert(!scene.vertexGroups.empty()); - std::vector<std::vector<uint8_t>> vBuffers; - std::vector<std::vector<uint8_t>> iBuffers; - - std::vector<vkcv::VertexBufferBinding> vBufferBindings; - std::vector<std::vector<vkcv::VertexBufferBinding>> vertexBufferBindings; - std::vector<vkcv::asset::VertexAttribute> vAttributes; - - for (int i = 0; i < scene.vertexGroups.size(); i++) { - - vBuffers.push_back(scene.vertexGroups[i].vertexBuffer.data); - iBuffers.push_back(scene.vertexGroups[i].indexBuffer.data); - - auto& attributes = scene.vertexGroups[i].vertexBuffer.attributes; - - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); - } - - std::vector<vkcv::Buffer<uint8_t>> vertexBuffers; - for (const vkcv::asset::VertexGroup& group : scene.vertexGroups) { - vertexBuffers.push_back(core.createBuffer<uint8_t>( - vkcv::BufferType::VERTEX, - group.vertexBuffer.data.size())); - vertexBuffers.back().fill(group.vertexBuffer.data); - } - - std::vector<vkcv::Buffer<uint8_t>> indexBuffers; - for (const auto& dataBuffer : iBuffers) { - indexBuffers.push_back(core.createBuffer<uint8_t>( - vkcv::BufferType::INDEX, - dataBuffer.size())); - indexBuffers.back().fill(dataBuffer); - } - - int vertexBufferIndex = 0; - for (const auto& vertexGroup : scene.vertexGroups) { - for (const auto& attribute : vertexGroup.vertexBuffer.attributes) { - vAttributes.push_back(attribute); - vBufferBindings.push_back(vkcv::VertexBufferBinding(attribute.offset, vertexBuffers[vertexBufferIndex].getVulkanHandle())); - } - vertexBufferBindings.push_back(vBufferBindings); - vBufferBindings.clear(); - vertexBufferIndex++; - } + + vkcv::scene::Scene scene = vkcv::scene::Scene::load(core, std::filesystem::path( + argc > 1 ? argv[1] : "resources/Sponza/Sponza.gltf" + )); const vkcv::AttachmentDescription present_color_attachment( vkcv::AttachmentOperation::STORE, @@ -138,41 +75,8 @@ int main(int argc, const char** argv) { } const vkcv::VertexLayout sceneLayout(bindings); - - uint32_t setID = 0; - - std::vector<vkcv::DescriptorBinding> descriptorBindings = { sceneShaderProgram.getReflectedDescriptors()[setID] }; - - vkcv::SamplerHandle sampler = core.createSampler( - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerFilterType::LINEAR, - vkcv::SamplerMipmapMode::LINEAR, - vkcv::SamplerAddressMode::REPEAT - ); - - std::vector<vkcv::Image> sceneImages; - std::vector<vkcv::DescriptorSetHandle> descriptorSets; - for (const auto& vertexGroup : scene.vertexGroups) { - descriptorSets.push_back(core.createDescriptorSet(descriptorBindings)); - - const auto& material = scene.materials[vertexGroup.materialIndex]; - - int baseColorIndex = material.baseColor; - if (baseColorIndex < 0) { - vkcv_log(vkcv::LogLevel::WARNING, "Material lacks base color"); - baseColorIndex = 0; - } - - vkcv::asset::Texture& sceneTexture = scene.textures[baseColorIndex]; - - sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, sceneTexture.w, sceneTexture.h)); - sceneImages.back().fill(sceneTexture.data.data()); - - vkcv::DescriptorWrites setWrites; - setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, sceneImages.back().getHandle()) }; - setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) }; - core.writeDescriptorSet(descriptorSets.back(), setWrites); - } + + const auto& material0 = scene.getMaterial(0); const vkcv::PipelineConfig scenePipelineDefsinition{ sceneShaderProgram, @@ -180,7 +84,7 @@ int main(int argc, const char** argv) { UINT32_MAX, scenePass, {sceneLayout}, - { core.getDescriptorSet(descriptorSets[0]).layout }, + { core.getDescriptorSet(material0.getDescriptorSet()).layout }, true }; vkcv::PipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefsinition); @@ -192,26 +96,7 @@ int main(int argc, const char** argv) { vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle(); const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); - - std::vector<vkcv::DrawcallInfo> drawcalls; - for(int i = 0; i < scene.vertexGroups.size(); i++){ - vkcv::Mesh renderMesh(vertexBufferBindings[i], indexBuffers[i].getVulkanHandle(), scene.vertexGroups[i].numIndices); - - vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSets[i]).vulkanHandle); - - drawcalls.push_back(vkcv::DrawcallInfo(renderMesh, {descriptorUsage},1)); - } - - std::vector<glm::mat4> modelMatrices; - modelMatrices.resize(scene.vertexGroups.size(), glm::mat4(1.f)); - for (const auto &mesh : scene.meshes) { - const glm::mat4 m = arrayTo4x4Matrix(mesh.modelMatrix); - for (const auto &vertexGroupIndex : mesh.vertexGroups) { - modelMatrices[vertexGroupIndex] = m; - } - } - std::vector<glm::mat4> mvp; - + auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { vkcv::Window::pollEvents(); @@ -236,25 +121,24 @@ int main(int argc, const char** argv) { start = end; cameraManager.update(0.000001 * static_cast<double>(deltatime.count())); - glm::mat4 vp = cameraManager.getActiveCamera().getMVP(); - - mvp.clear(); - for (const auto& m : modelMatrices) { - mvp.push_back(vp * m); - } - - vkcv::PushConstantData pushConstantData((void*)mvp.data(), sizeof(glm::mat4)); const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); - core.recordDrawcallsToCmdStream( - cmdStream, - scenePass, - scenePipeline, - pushConstantData, - drawcalls, - renderTargets); + auto recordMesh = [](const glm::mat4& MVP, const glm::mat4& M, + vkcv::PushConstants &pushConstants, + vkcv::DrawcallInfo& drawcallInfo) { + pushConstants.appendDrawcall(MVP); + }; + + scene.recordDrawcalls(cmdStream, + cameraManager.getActiveCamera(), + scenePass, + scenePipeline, + sizeof(glm::mat4), + recordMesh, + renderTargets); + core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); core.endFrame(); diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 5bdd55a263f4d81d8f424c056d7d6c0b54ccb1ca..a69f9bc755f9cfa3a75d0a51dd242876aedabf79 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -27,57 +27,13 @@ int main(int argc, const char** argv) { {}, { "VK_KHR_swapchain" } ); - - vkcv::gui::GUI gui (core, window); const auto& context = core.getContext(); - const vk::Instance& instance = context.getInstance(); - const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice(); - const vk::Device& device = context.getDevice(); - - struct vec3 { - float x, y, z; - }; - - const size_t n = 5027; - - auto testBuffer = core.createBuffer<vec3>(vkcv::BufferType::VERTEX, n, vkcv::BufferMemoryType::DEVICE_LOCAL); - vec3 vec_data[n]; - - for (size_t i = 0; i < n; i++) { - vec_data[i] = { 42, static_cast<float>(i), 7 }; - } - testBuffer.fill(vec_data); - - auto triangleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, n, vkcv::BufferMemoryType::DEVICE_LOCAL); + auto triangleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL); uint16_t indices[3] = { 0, 1, 2 }; triangleIndexBuffer.fill(&indices[0], sizeof(indices)); - /*vec3* m = buffer.map(); - m[0] = { 0, 0, 0 }; - m[1] = { 0, 0, 0 }; - m[2] = { 0, 0, 0 }; - buffer.unmap();*/ - - vkcv::SamplerHandle sampler = core.createSampler( - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerFilterType::NEAREST, - vkcv::SamplerMipmapMode::NEAREST, - vkcv::SamplerAddressMode::REPEAT - ); - - std::cout << "Physical device: " << physicalDevice.getProperties().deviceName << std::endl; - - switch (physicalDevice.getProperties().vendorID) { - case 0x1002: std::cout << "Running AMD huh? You like underdogs, are you a Linux user?" << std::endl; break; - case 0x10DE: std::cout << "An NVidia GPU, how predictable..." << std::endl; break; - case 0x8086: std::cout << "Poor child, running on an Intel GPU, probably integrated..." - "or perhaps you are from the future with a dedicated one?" << std::endl; break; - case 0x13B5: std::cout << "ARM? What the hell are you running on, next thing I know you're trying to run Vulkan on a leg..." << std::endl; break; - default: std::cout << "Unknown GPU vendor?! Either you're on an exotic system or your driver is broken..." << std::endl; - } - // an example attachment for passes that output to the window const vkcv::AttachmentDescription present_color_attachment( vkcv::AttachmentOperation::STORE, @@ -123,49 +79,9 @@ int main(int argc, const char** argv) { std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; return EXIT_FAILURE; } - - // Compute Pipeline - vkcv::ShaderProgram computeShaderProgram{}; - computeShaderProgram.addShader(vkcv::ShaderStage::COMPUTE, std::filesystem::path("shaders/comp.spv")); - - // take care, assuming shader has exactly one descriptor set - vkcv::DescriptorSetHandle computeDescriptorSet = core.createDescriptorSet(computeShaderProgram.getReflectedDescriptors()[0]); - - vkcv::PipelineHandle computePipeline = core.createComputePipeline( - computeShaderProgram, - { core.getDescriptorSet(computeDescriptorSet).layout }); - - struct ComputeTestBuffer { - float test1[10]; - float test2[10]; - float test3[10]; - }; - - vkcv::Buffer computeTestBuffer = core.createBuffer<ComputeTestBuffer>(vkcv::BufferType::STORAGE, 1); - - vkcv::DescriptorWrites computeDescriptorWrites; - computeDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, computeTestBuffer.getHandle()) }; - core.writeDescriptorSet(computeDescriptorSet, computeDescriptorWrites); - - /* - * BufferHandle triangleVertices = core.createBuffer(vertices); - * BufferHandle triangleIndices = core.createBuffer(indices); - * - * // triangle Model creation goes here - * - * - * // attachment creation goes here - * PassHandle trianglePass = core.CreatePass(presentationPass); - * - * // shader creation goes here - * // material creation goes here - * - * PipelineHandle trianglePipeline = core.CreatePipeline(trianglePipeline); - */ + auto start = std::chrono::system_clock::now(); - vkcv::ImageHandle swapchainImageHandle = vkcv::ImageHandle::createSwapchainImageHandle(); - const vkcv::Mesh renderMesh({}, triangleIndexBuffer.getVulkanHandle(), 3); vkcv::DrawcallInfo drawcall(renderMesh, {},1); @@ -181,7 +97,7 @@ int main(int argc, const char** argv) { while (window.isWindowOpen()) { - window.pollEvents(); + vkcv::Window::pollEvents(); uint32_t swapchainWidth, swapchainHeight; // No resizing = No problem if (!core.beginFrame(swapchainWidth, swapchainHeight)) { @@ -195,37 +111,21 @@ int main(int argc, const char** argv) { cameraManager.update(0.000001 * static_cast<double>(deltatime.count())); glm::mat4 mvp = cameraManager.getActiveCamera().getMVP(); - vkcv::PushConstantData pushConstantData((void*)&mvp, sizeof(glm::mat4)); + vkcv::PushConstants pushConstants (sizeof(glm::mat4)); + pushConstants.appendDrawcall(mvp); + auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); core.recordDrawcallsToCmdStream( cmdStream, trianglePass, trianglePipeline, - pushConstantData, + pushConstants, { drawcall }, { swapchainInput }); - const uint32_t dispatchSize[3] = { 2, 1, 1 }; - const float theMeaningOfLife = 42; - - core.recordComputeDispatchToCmdStream( - cmdStream, - computePipeline, - dispatchSize, - { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(computeDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData((void*)&theMeaningOfLife, sizeof(theMeaningOfLife))); - core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); - - gui.beginGUI(); - - ImGui::Begin("Hello world"); - ImGui::Text("This is a test!"); - ImGui::End(); - - gui.endGUI(); core.endFrame(); } diff --git a/projects/particle_simulation/src/BloomAndFlares.cpp b/projects/particle_simulation/src/BloomAndFlares.cpp index 23ace2bc35a2e421613718c62380f9161a408f70..98d53c2a1a2c08d40473858b47aacf34da30f7ed 100644 --- a/projects/particle_simulation/src/BloomAndFlares.cpp +++ b/projects/particle_simulation/src/BloomAndFlares.cpp @@ -104,7 +104,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre m_DownsamplePipe, initialDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[0]).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); // downsample dispatches of blur buffer's mip maps float mipDispatchCountX = dispatchCountX; @@ -139,7 +139,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre m_DownsamplePipe, mipDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[mipLevel]).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); // image barrier between mips p_Core->recordImageMemoryBarrier(cmdStream, m_Blur.getHandle()); @@ -184,7 +184,7 @@ void BloomAndFlares::execUpsamplePipe(const vkcv::CommandStreamHandle &cmdStream m_UpsamplePipe, upsampleDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_UpsampleDescSets[mipLevel]).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0) + vkcv::PushConstants(0) ); // image barrier between mips p_Core->recordImageMemoryBarrier(cmdStream, m_Blur.getHandle()); @@ -216,7 +216,7 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr m_LensFlarePipe, lensFeatureDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_LensFlareDescSet).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); } void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStream, @@ -249,7 +249,7 @@ void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStrea m_CompositePipe, compositeDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_CompositeDescSet).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); } void BloomAndFlares::execWholePipeline(const vkcv::CommandStreamHandle &cmdStream, diff --git a/projects/particle_simulation/src/Particle.cpp b/projects/particle_simulation/src/Particle.cpp index 387728eb366430e4373282da785bbff47de17e7a..b80d063d382c9ae1cb63887388cce065b8289b63 100644 --- a/projects/particle_simulation/src/Particle.cpp +++ b/projects/particle_simulation/src/Particle.cpp @@ -3,16 +3,17 @@ Particle::Particle(glm::vec3 position, glm::vec3 velocity, float lifeTime) : m_position(position), -m_velocity(velocity), -m_lifeTime(lifeTime), -m_reset_velocity(velocity) + m_lifeTime(lifeTime), + m_velocity(velocity), + m_mass(1.0f), + m_reset_velocity(velocity) {} const glm::vec3& Particle::getPosition()const{ return m_position; } -const bool Particle::isAlive()const{ +bool Particle::isAlive()const{ return m_lifeTime > 0.f; } diff --git a/projects/particle_simulation/src/Particle.hpp b/projects/particle_simulation/src/Particle.hpp index f374218fd8a08f1e1bf367bdc899a71c55ea1b78..73e7cbf517709ee03274cfd199081ade3f756545 100644 --- a/projects/particle_simulation/src/Particle.hpp +++ b/projects/particle_simulation/src/Particle.hpp @@ -17,7 +17,7 @@ public: void update( const float delta ); - const bool isAlive()const; + bool isAlive()const; void setLifeTime( const float lifeTime ); @@ -28,7 +28,7 @@ private: glm::vec3 m_position; float m_lifeTime; glm::vec3 m_velocity; - float mass = 1.f; + float m_mass; glm::vec3 m_reset_velocity; - float padding_3 = 0.f; + float padding_3; }; diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp index a22044f0d2588a43a5e7a0f6cba25d9c7460be9f..0d83644b866f5f89fb33c68f1d5a79fcee8c028a 100644 --- a/projects/particle_simulation/src/main.cpp +++ b/projects/particle_simulation/src/main.cpp @@ -58,12 +58,28 @@ int main(int argc, const char **argv) { return EXIT_FAILURE; } - // use space or use water - bool useSpace = true; + // use space or use water or gravity + std::string shaderPathCompute = "shaders/shader_space.comp"; + std::string shaderPathFragment = "shaders/shader_space.frag"; + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--space") == 0) { + shaderPathCompute = "shaders/shader_space.comp"; + shaderPathFragment = "shaders/shader_space.frag"; + } else + if (strcmp(argv[i], "--water") == 0) { + shaderPathCompute = "shaders/shader_water.comp"; + shaderPathFragment = "shaders/shader_water.frag"; + } else + if (strcmp(argv[i], "--gravity") == 0) { + shaderPathCompute = "shaders/shader_gravity.comp"; + shaderPathFragment = "shaders/shader_space.frag"; + } + } vkcv::shader::GLSLCompiler compiler; vkcv::ShaderProgram computeShaderProgram{}; - compiler.compile(vkcv::ShaderStage::COMPUTE, useSpace ? "shaders/shader_space.comp" : "shaders/shader_water.comp", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + compiler.compile(vkcv::ShaderStage::COMPUTE, shaderPathCompute, [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { computeShaderProgram.addShader(shaderStage, path); }); @@ -81,7 +97,7 @@ int main(int argc, const char **argv) { compiler.compile(vkcv::ShaderStage::VERTEX, "shaders/shader.vert", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { particleShaderProgram.addShader(shaderStage, path); }); - compiler.compile(vkcv::ShaderStage::FRAGMENT, useSpace ? "shaders/shader_space.frag" : "shaders/shader_water.frag", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + compiler.compile(vkcv::ShaderStage::FRAGMENT, shaderPathFragment, [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { particleShaderProgram.addShader(shaderStage, path); }); @@ -167,38 +183,16 @@ int main(int argc, const char **argv) { const vkcv::Mesh renderMesh({vertexBufferBindings}, particleIndexBuffer.getVulkanHandle(), particleIndexBuffer.getCount()); vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); - //vkcv::DrawcallInfo drawcalls(renderMesh, {vkcv::DescriptorSetUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle)}); - glm::vec2 pos = glm::vec2(0.f); - glm::vec3 spawnPosition = glm::vec3(0.f); - glm::vec4 tempPosition = glm::vec4(0.f); + auto pos = glm::vec2(0.f); + auto spawnPosition = glm::vec3(0.f); window.e_mouseMove.add([&](double offsetX, double offsetY) { pos = glm::vec2(static_cast<float>(offsetX), static_cast<float>(offsetY)); -// std::cout << offsetX << " , " << offsetY << std::endl; - // borders are assumed to be 0.5 - //pos = glm::vec2((pos.x -0.5f * static_cast<float>(window.getWidth()))/static_cast<float>(window.getWidth()), (pos.y -0.5f * static_cast<float>(window.getHeight()))/static_cast<float>(window.getHeight())); - //borders are assumed to be 1 pos.x = (-2 * pos.x + static_cast<float>(window.getWidth())) / static_cast<float>(window.getWidth()); pos.y = (-2 * pos.y + static_cast<float>(window.getHeight())) / static_cast<float>(window.getHeight()); - glm::vec4 row1 = glm::row(cameraManager.getCamera(0).getView(), 0); - glm::vec4 row2 = glm::row(cameraManager.getCamera(0).getView(), 1); - glm::vec4 row3 = glm::row(cameraManager.getCamera(0).getView(), 2); - glm::vec4 camera_pos = glm::column(cameraManager.getCamera(0).getView(), 3); -// std::cout << "row1: " << row1.x << ", " << row1.y << ", " << row1.z << std::endl; -// std::cout << "row2: " << row2.x << ", " << row2.y << ", " << row2.z << std::endl; -// std::cout << "row3: " << row3.x << ", " << row3.y << ", " << row3.z << std::endl; -// std::cout << "camerapos: " << camera_pos.x << ", " << camera_pos.y << ", " << camera_pos.z << std::endl; -// std::cout << "camerapos: " << camera_pos.x << ", " << camera_pos.y << ", " << camera_pos.z << std::endl; - //glm::vec4 view_axis = glm::row(cameraManager.getCamera().getView(), 2); - // std::cout << "view_axis: " << view_axis.x << ", " << view_axis.y << ", " << view_axis.z << std::endl; - //std::cout << "Front: " << cameraManager.getCamera().getFront().x << ", " << cameraManager.getCamera().getFront().z << ", " << cameraManager.getCamera().getFront().z << std::endl; - glm::mat4 viewmat = cameraManager.getCamera(0).getView(); spawnPosition = glm::vec3(pos.x, pos.y, 0.f); - tempPosition = glm::vec4(spawnPosition, 1.0f); - spawnPosition = glm::vec3(tempPosition.x, tempPosition.y, tempPosition.z); particleSystem.setRespawnPos(glm::vec3(-spawnPosition.x, spawnPosition.y, spawnPosition.z)); -// std::cout << "respawn pos: " << spawnPosition.x << ", " << spawnPosition.y << ", " << spawnPosition.z << std::endl; }); std::vector<glm::mat4> modelMatrices; @@ -242,7 +236,7 @@ int main(int argc, const char **argv) { std::uniform_real_distribution<float> rdm = std::uniform_real_distribution<float>(0.95f, 1.05f); std::default_random_engine rdmEngine; while (window.isWindowOpen()) { - window.pollEvents(); + vkcv::Window::pollEvents(); uint32_t swapchainWidth, swapchainHeight; if (!core.beginFrame(swapchainWidth, swapchainHeight)) { @@ -255,35 +249,42 @@ int main(int argc, const char **argv) { auto end = std::chrono::system_clock::now(); float deltatime = 0.000001 * static_cast<float>( std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() ); start = end; -// particleSystem.updateParticles(deltatime); cameraManager.update(deltatime); // split view and projection to allow for easy billboarding in shader - glm::mat4 renderingMatrices[2]; - renderingMatrices[0] = cameraManager.getActiveCamera().getView(); - renderingMatrices[1] = cameraManager.getActiveCamera().getProjection(); + struct { + glm::mat4 view; + glm::mat4 projection; + } renderingMatrices; + + renderingMatrices.view = cameraManager.getActiveCamera().getView(); + renderingMatrices.projection = cameraManager.getActiveCamera().getProjection(); auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); float random = rdm(rdmEngine); glm::vec2 pushData = glm::vec2(deltatime, random); - vkcv::PushConstantData pushConstantDataCompute( &pushData, sizeof(glm::vec2)); + vkcv::PushConstants pushConstantsCompute (sizeof(glm::vec2)); + pushConstantsCompute.appendDrawcall(pushData); + uint32_t computeDispatchCount[3] = {static_cast<uint32_t> (std::ceil(particleSystem.getParticles().size()/256.f)),1,1}; core.recordComputeDispatchToCmdStream(cmdStream, computePipeline, computeDispatchCount, {vkcv::DescriptorSetUsage(0,core.getDescriptorSet(computeDescriptorSet).vulkanHandle)}, - pushConstantDataCompute); + pushConstantsCompute); core.recordBufferMemoryBarrier(cmdStream, particleBuffer.getHandle()); - vkcv::PushConstantData pushConstantDataDraw((void *) &renderingMatrices[0], 2 * sizeof(glm::mat4)); + vkcv::PushConstants pushConstantsDraw (sizeof(renderingMatrices)); + pushConstantsDraw.appendDrawcall(renderingMatrices); + core.recordDrawcallsToCmdStream( cmdStream, particlePass, particlePipeline, - pushConstantDataDraw, + pushConstantsDraw, {drawcalls}, { colorBuffer }); @@ -309,7 +310,7 @@ int main(int argc, const char **argv) { tonemappingPipe, tonemappingDispatchCount, {vkcv::DescriptorSetUsage(0, core.getDescriptorSet(tonemappingDescriptor).vulkanHandle) }, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); diff --git a/projects/voxelization/src/BloomAndFlares.cpp b/projects/voxelization/src/BloomAndFlares.cpp index fac57735a6544c197f880f78e1f512382607d048..6cb02e9035daf7abebc047d26137d0ba973bb4f1 100644 --- a/projects/voxelization/src/BloomAndFlares.cpp +++ b/projects/voxelization/src/BloomAndFlares.cpp @@ -128,7 +128,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre m_DownsamplePipe, initialDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[0]).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); // downsample dispatches of blur buffer's mip maps float mipDispatchCountX = dispatchCountX; @@ -163,7 +163,7 @@ void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStre m_DownsamplePipe, mipDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_DownsampleDescSets[mipLevel]).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); // image barrier between mips p_Core->recordImageMemoryBarrier(cmdStream, m_Blur.getHandle()); @@ -208,7 +208,7 @@ void BloomAndFlares::execUpsamplePipe(const vkcv::CommandStreamHandle &cmdStream m_UpsamplePipe, upsampleDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_UpsampleDescSets[mipLevel]).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0) + vkcv::PushConstants(0) ); // image barrier between mips p_Core->recordImageMemoryBarrier(cmdStream, m_Blur.getHandle()); @@ -243,7 +243,7 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr m_LensFlarePipe, lensFeatureDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_LensFlareDescSet).vulkanHandle)}, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); // upsample dispatch p_Core->prepareImageForStorage(cmdStream, m_LensFeatures.getHandle()); @@ -276,7 +276,7 @@ void BloomAndFlares::execLensFeaturePipe(const vkcv::CommandStreamHandle &cmdStr m_UpsamplePipe, upsampleDispatchCount, { vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_UpsampleLensFlareDescSets[i]).vulkanHandle) }, - vkcv::PushConstantData(nullptr, 0) + vkcv::PushConstants(0) ); // image barrier between mips p_Core->recordImageMemoryBarrier(cmdStream, m_LensFeatures.getHandle()); @@ -309,6 +309,9 @@ void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStrea static_cast<uint32_t>(glm::ceil(dispatchCountY)), 1 }; + + vkcv::PushConstants pushConstants (sizeof(cameraForward)); + pushConstants.appendDrawcall(cameraForward); // bloom composite dispatch p_Core->recordComputeDispatchToCmdStream( @@ -316,7 +319,7 @@ void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStrea m_CompositePipe, compositeDispatchCount, {vkcv::DescriptorSetUsage(0, p_Core->getDescriptorSet(m_CompositeDescSet).vulkanHandle)}, - vkcv::PushConstantData((void*)&cameraForward, sizeof(cameraForward))); + pushConstants); } void BloomAndFlares::execWholePipeline(const vkcv::CommandStreamHandle &cmdStream, const vkcv::ImageHandle &colorAttachment, diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp index a330394b7bd7ff2a4b8c347bd79e676dbc70f846..32dd5457541f8f09f4d2711ea831e3c78de2303a 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -248,12 +248,13 @@ void ShadowMapping::recordShadowMapRendering( voxelVolumeOffset, voxelVolumeExtent); m_lightInfoBuffer.fill({ lightInfo }); - - std::vector<glm::mat4> mvpLight; + + vkcv::PushConstants shadowPushConstants (sizeof(glm::mat4)); + for (const auto& m : modelMatrices) { - mvpLight.push_back(lightInfo.lightMatrix * m); + shadowPushConstants.appendDrawcall(lightInfo.lightMatrix * m); } - const vkcv::PushConstantData shadowPushConstantData((void*)mvpLight.data(), sizeof(glm::mat4)); + std::vector<vkcv::DrawcallInfo> drawcalls; for (const auto& mesh : meshes) { @@ -264,7 +265,7 @@ void ShadowMapping::recordShadowMapRendering( cmdStream, m_shadowMapPass, m_shadowMapPipe, - shadowPushConstantData, + shadowPushConstants, drawcalls, { m_shadowMapDepth.getHandle() }); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMapDepth.getHandle()); @@ -276,6 +277,9 @@ void ShadowMapping::recordShadowMapRendering( dispatchCount[2] = 1; const uint32_t msaaSampleCount = msaaToSampleCount(msaa); + + vkcv::PushConstants msaaPushConstants (sizeof(msaaSampleCount)); + msaaPushConstants.appendDrawcall(msaaSampleCount); m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle()); m_corePtr->recordComputeDispatchToCmdStream( @@ -283,7 +287,7 @@ void ShadowMapping::recordShadowMapRendering( m_depthToMomentsPipe, dispatchCount, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_depthToMomentsDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData((void*)&msaaSampleCount, sizeof(msaaSampleCount))); + msaaPushConstants); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle()); // blur X @@ -293,7 +297,7 @@ void ShadowMapping::recordShadowMapRendering( m_shadowBlurXPipe, dispatchCount, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurXDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMapIntermediate.getHandle()); // blur Y @@ -303,7 +307,7 @@ void ShadowMapping::recordShadowMapRendering( m_shadowBlurYPipe, dispatchCount, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurYDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); m_shadowMap.recordMipChainGeneration(cmdStream); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle()); } diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index c117b4b9e6b896fbf51aae83343f30281061be9f..bbf161ddeb0899a1ce61279b4c476fb19cb906d7 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -232,34 +232,36 @@ void Voxelization::voxelizeMeshes( const glm::mat4 voxelizationView = glm::translate(glm::mat4(1.f), -m_voxelInfo.offset); const glm::mat4 voxelizationViewProjection = voxelizationProjection * voxelizationView; - - std::vector<std::array<glm::mat4, 2>> voxelizationMatrices; + + vkcv::PushConstants voxelizationPushConstants (2 * sizeof(glm::mat4)); + for (const auto& m : modelMatrices) { - voxelizationMatrices.push_back({ voxelizationViewProjection * m, m }); + voxelizationPushConstants.appendDrawcall(std::array<glm::mat4, 2>{ voxelizationViewProjection * m, m }); } - const vkcv::PushConstantData voxelizationPushConstantData((void*)voxelizationMatrices.data(), 2 * sizeof(glm::mat4)); - // reset voxels const uint32_t resetVoxelGroupSize = 64; uint32_t resetVoxelDispatchCount[3]; resetVoxelDispatchCount[0] = glm::ceil(voxelCount / float(resetVoxelGroupSize)); resetVoxelDispatchCount[1] = 1; resetVoxelDispatchCount[2] = 1; + + vkcv::PushConstants voxelCountPushConstants (sizeof(voxelCount)); + voxelCountPushConstants.appendDrawcall(voxelCount); m_corePtr->recordComputeDispatchToCmdStream( cmdStream, m_voxelResetPipe, resetVoxelDispatchCount, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelResetDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData(&voxelCount, sizeof(voxelCount))); + voxelCountPushConstants); m_corePtr->recordBufferMemoryBarrier(cmdStream, m_voxelBuffer.getHandle()); // voxelization std::vector<vkcv::DrawcallInfo> drawcalls; - for (int i = 0; i < meshes.size(); i++) { + for (size_t i = 0; i < meshes.size(); i++) { drawcalls.push_back(vkcv::DrawcallInfo( - meshes[i], + meshes[i], { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_voxelizationDescriptorSet).vulkanHandle), vkcv::DescriptorSetUsage(1, m_corePtr->getDescriptorSet(perMeshDescriptorSets[i]).vulkanHandle) @@ -271,7 +273,7 @@ void Voxelization::voxelizeMeshes( cmdStream, m_voxelizationPass, m_voxelizationPipe, - voxelizationPushConstantData, + voxelizationPushConstants, drawcalls, { m_dummyRenderTarget.getHandle() }); @@ -287,7 +289,7 @@ void Voxelization::voxelizeMeshes( m_bufferToImagePipe, bufferToImageDispatchCount, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_bufferToImageDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImageIntermediate.getHandle()); @@ -303,7 +305,7 @@ void Voxelization::voxelizeMeshes( m_secondaryBouncePipe, bufferToImageDispatchCount, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_secondaryBounceDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); m_voxelImage.recordMipChainGeneration(cmdStream); m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle()); @@ -319,7 +321,8 @@ void Voxelization::renderVoxelVisualisation( const std::vector<vkcv::ImageHandle>& renderTargets, uint32_t mipLevel) { - const vkcv::PushConstantData voxelVisualisationPushConstantData((void*)&viewProjectin, sizeof(glm::mat4)); + vkcv::PushConstants voxelVisualisationPushConstants (sizeof(glm::mat4)); + voxelVisualisationPushConstants.appendDrawcall(viewProjectin); mipLevel = std::clamp(mipLevel, (uint32_t)0, m_voxelImage.getMipCount()-1); @@ -342,7 +345,7 @@ void Voxelization::renderVoxelVisualisation( cmdStream, m_visualisationPass, m_visualisationPipe, - voxelVisualisationPushConstantData, + voxelVisualisationPushConstants, { drawcall }, renderTargets); } diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index edc50c554b6c73bd2f06914eba6dd7adf9e43483..ca9951490e57b4b6afa3bbee986a55342a40582e 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -111,7 +111,7 @@ int main(int argc, const char** argv) { std::vector<std::vector<vkcv::VertexBufferBinding>> vertexBufferBindings; std::vector<vkcv::asset::VertexAttribute> vAttributes; - for (int i = 0; i < scene.vertexGroups.size(); i++) { + for (size_t i = 0; i < scene.vertexGroups.size(); i++) { vBuffers.push_back(scene.vertexGroups[i].vertexBuffer.data); iBuffers.push_back(scene.vertexGroups[i].indexBuffer.data); @@ -452,14 +452,14 @@ int main(int argc, const char** argv) { // prepare meshes std::vector<vkcv::Mesh> meshes; - for (int i = 0; i < scene.vertexGroups.size(); i++) { + for (size_t i = 0; i < scene.vertexGroups.size(); i++) { vkcv::Mesh mesh(vertexBufferBindings[i], indexBuffers[i].getVulkanHandle(), scene.vertexGroups[i].numIndices); meshes.push_back(mesh); } std::vector<vkcv::DrawcallInfo> drawcalls; std::vector<vkcv::DrawcallInfo> prepassDrawcalls; - for (int i = 0; i < meshes.size(); i++) { + for (size_t i = 0; i < meshes.size(); i++) { drawcalls.push_back(vkcv::DrawcallInfo(meshes[i], { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(forwardShadingDescriptorSet).vulkanHandle), @@ -618,29 +618,32 @@ int main(int argc, const char** argv) { // depth prepass const glm::mat4 viewProjectionCamera = cameraManager.getActiveCamera().getMVP(); - + + vkcv::PushConstants prepassPushConstants (sizeof(glm::mat4)); + std::vector<glm::mat4> prepassMatrices; for (const auto& m : modelMatrices) { - prepassMatrices.push_back(viewProjectionCamera * m); + prepassPushConstants.appendDrawcall(viewProjectionCamera * m); } - const vkcv::PushConstantData prepassPushConstantData((void*)prepassMatrices.data(), sizeof(glm::mat4)); + const std::vector<vkcv::ImageHandle> prepassRenderTargets = { depthBuffer }; core.recordDrawcallsToCmdStream( cmdStream, prepassPass, prepassPipeline, - prepassPushConstantData, + prepassPushConstants, prepassDrawcalls, prepassRenderTargets); core.recordImageMemoryBarrier(cmdStream, depthBuffer); - + + vkcv::PushConstants pushConstants (2 * sizeof(glm::mat4)); + // main pass - std::vector<std::array<glm::mat4, 2>> mainPassMatrices; for (const auto& m : modelMatrices) { - mainPassMatrices.push_back({ viewProjectionCamera * m, m }); + pushConstants.appendDrawcall(std::array<glm::mat4, 2>{ viewProjectionCamera * m, m }); } VolumetricSettings volumeSettings; @@ -648,28 +651,30 @@ int main(int argc, const char** argv) { volumeSettings.absorptionCoefficient = absorptionColor * absorptionDensity; volumeSettings.ambientLight = volumetricAmbient; volumetricSettingsBuffer.fill({ volumeSettings }); - - const vkcv::PushConstantData pushConstantData((void*)mainPassMatrices.data(), 2 * sizeof(glm::mat4)); + const std::vector<vkcv::ImageHandle> renderTargets = { colorBuffer, depthBuffer }; core.recordDrawcallsToCmdStream( cmdStream, forwardPass, forwardPipeline, - pushConstantData, + pushConstants, drawcalls, renderTargets); if (renderVoxelVis) { voxelization.renderVoxelVisualisation(cmdStream, viewProjectionCamera, renderTargets, voxelVisualisationMip); } + + vkcv::PushConstants skySettingsPushConstants (sizeof(skySettings)); + skySettingsPushConstants.appendDrawcall(skySettings); // sky core.recordDrawcallsToCmdStream( cmdStream, skyPass, skyPipe, - vkcv::PushConstantData((void*)&skySettings, sizeof(skySettings)), + skySettingsPushConstants, { vkcv::DrawcallInfo(vkcv::Mesh({}, nullptr, 3), {}) }, renderTargets); @@ -692,7 +697,7 @@ int main(int argc, const char** argv) { resolvePipeline, fulsscreenDispatchCount, { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(resolveDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData(nullptr, 0)); + vkcv::PushConstants(0)); core.recordImageMemoryBarrier(cmdStream, resolvedColorBuffer); } @@ -710,12 +715,15 @@ int main(int argc, const char** argv) { auto timeSinceStart = std::chrono::duration_cast<std::chrono::microseconds>(end - appStartTime); float timeF = static_cast<float>(timeSinceStart.count()) * 0.01; + vkcv::PushConstants timePushConstants (sizeof(timeF)); + timePushConstants.appendDrawcall(timeF); + core.recordComputeDispatchToCmdStream( cmdStream, tonemappingPipeline, fulsscreenDispatchCount, { vkcv::DescriptorSetUsage(0, core.getDescriptorSet(tonemappingDescriptorSet).vulkanHandle) }, - vkcv::PushConstantData(&timeF, sizeof(timeF))); + timePushConstants); // present and end core.prepareSwapchainImageForPresent(cmdStream); diff --git a/src/vkcv/CommandStreamManager.cpp b/src/vkcv/CommandStreamManager.cpp index 5a5b359b912d9cef36e0b03379d7f0f6f0951381..52b73213dbc5837f6be4a2aa25c28615dccf5969 100644 --- a/src/vkcv/CommandStreamManager.cpp +++ b/src/vkcv/CommandStreamManager.cpp @@ -32,11 +32,10 @@ namespace vkcv { // find unused stream int unusedStreamIndex = -1; - for (int i = 0; i < m_commandStreams.size(); i++) { + for (size_t i = 0; i < m_commandStreams.size(); i++) { if (m_commandStreams[i].cmdBuffer) { // still in use - } - else { + } else { unusedStreamIndex = i; break; } diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 352a1cf62eabe55ce1bbf2f53a6b5a4bd6e91753..a66c1e6220261679a85241fff42de08a57428d4c 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -71,7 +71,6 @@ namespace vkcv const auto& queueManager = context.getQueueManager(); - const int graphicQueueFamilyIndex = queueManager.getGraphicsQueues()[0].familyIndex; const std::unordered_set<int> queueFamilySet = generateQueueFamilyIndexSet(queueManager); const auto commandResources = createCommandResources(context.getDevice(), queueFamilySet); const auto defaultSyncResources = createSyncResources(context.getDevice()); @@ -163,9 +162,9 @@ namespace vkcv nullptr, &imageIndex, {} ); - } catch (vk::OutOfDateKHRError e) { + } catch (const vk::OutOfDateKHRError& e) { result = vk::Result::eErrorOutOfDateKHR; - } catch (vk::DeviceLostError e) { + } catch (const vk::DeviceLostError& e) { result = vk::Result::eErrorDeviceLost; } @@ -232,7 +231,7 @@ namespace vkcv const CommandStreamHandle cmdStreamHandle, const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, - const PushConstantData &pushConstantData, + const PushConstants &pushConstants, const std::vector<DrawcallInfo> &drawcalls, const std::vector<ImageHandle> &renderTargets) { @@ -268,7 +267,7 @@ namespace vkcv const vk::Rect2D renderArea(vk::Offset2D(0, 0), vk::Extent2D(width, height)); std::vector<vk::ImageView> attachmentsViews; - for (const ImageHandle handle : renderTargets) { + for (const ImageHandle& handle : renderTargets) { vk::ImageView targetHandle; const auto cmdBuffer = m_CommandStreamManager->getStreamCommandBuffer(cmdStreamHandle); @@ -305,8 +304,6 @@ namespace vkcv vk::Rect2D dynamicScissor({0, 0}, {width, height}); - auto &bufferManager = m_BufferManager; - SubmitInfo submitInfo; submitInfo.queueType = QueueType::Graphics; submitInfo.signalSemaphores = { m_SyncResources.renderFinished }; @@ -338,14 +335,13 @@ namespace vkcv cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); const PipelineConfig &pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle); - if(pipeConfig.m_UseDynamicViewport) - { + if (pipeConfig.m_UseDynamicViewport) { cmdBuffer.setViewport(0, 1, &dynamicViewport); cmdBuffer.setScissor(0, 1, &dynamicScissor); } - for (int i = 0; i < drawcalls.size(); i++) { - recordDrawcall(drawcalls[i], cmdBuffer, pipelineLayout, pushConstantData, i); + for (size_t i = 0; i < drawcalls.size(); i++) { + recordDrawcall(drawcalls[i], cmdBuffer, pipelineLayout, pushConstants, i); } cmdBuffer.endRenderPass(); @@ -364,7 +360,7 @@ namespace vkcv PipelineHandle computePipeline, const uint32_t dispatchCount[3], const std::vector<DescriptorSetUsage>& descriptorSetUsages, - const PushConstantData& pushConstantData) { + const PushConstants& pushConstants) { auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) { @@ -379,13 +375,13 @@ namespace vkcv { usage.vulkanHandle }, {}); } - if (pushConstantData.sizePerDrawcall > 0) { + if (pushConstants.getSizePerDrawcall() > 0) { cmdBuffer.pushConstants( pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, - pushConstantData.sizePerDrawcall, - pushConstantData.data); + pushConstants.getSizePerDrawcall(), + pushConstants.getData()); } cmdBuffer.dispatch(dispatchCount[0], dispatchCount[1], dispatchCount[2]); }; @@ -417,9 +413,9 @@ namespace vkcv try { result = queueManager.getPresentQueue().handle.presentKHR(presentInfo); - } catch (vk::OutOfDateKHRError e) { + } catch (const vk::OutOfDateKHRError& e) { result = vk::Result::eErrorOutOfDateKHR; - } catch (vk::DeviceLostError e) { + } catch (const vk::DeviceLostError& e) { result = vk::Result::eErrorDeviceLost; } @@ -463,8 +459,6 @@ namespace vkcv } CommandStreamHandle Core::createCommandStream(QueueType queueType) { - - const vk::Device& device = m_Context.getDevice(); const vkcv::Queue queue = getQueueForSubmit(queueType, m_Context.getQueueManager()); const vk::CommandPool cmdPool = chooseCmdPool(queue, m_CommandResources); @@ -522,12 +516,12 @@ namespace vkcv multisampling); } - const uint32_t Core::getImageWidth(ImageHandle imageHandle) + uint32_t Core::getImageWidth(ImageHandle imageHandle) { return m_ImageManager->getImageWidth(imageHandle); } - const uint32_t Core::getImageHeight(ImageHandle imageHandle) + uint32_t Core::getImageHeight(ImageHandle imageHandle) { return m_ImageManager->getImageHeight(imageHandle); } diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp index 8e565a766cd407dc33c0291d3d07b01d6d3066e7..07ca97b5ade9b69eed724000d9c7b388818d6725 100644 --- a/src/vkcv/DescriptorManager.cpp +++ b/src/vkcv/DescriptorManager.cpp @@ -16,7 +16,8 @@ namespace vkcv vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1000), vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 1000) }; - m_PoolInfo = vk::DescriptorPoolCreateInfo({}, + m_PoolInfo = vk::DescriptorPoolCreateInfo( + vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1000, static_cast<uint32_t>(m_PoolSizes.size()), m_PoolSizes.data()); @@ -29,9 +30,13 @@ namespace vkcv for (uint64_t id = 0; id < m_DescriptorSets.size(); id++) { destroyDescriptorSetById(id); } + m_DescriptorSets.clear(); + for (const auto &pool : m_Pools) { - m_Device.destroy(pool); + if (pool) { + m_Device.destroy(pool); + } } } @@ -40,12 +45,12 @@ namespace vkcv std::vector<vk::DescriptorSetLayoutBinding> setBindings = {}; //create each set's binding - for (uint32_t i = 0; i < bindings.size(); i++) { + for (auto binding : bindings) { vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding( - bindings[i].bindingID, - convertDescriptorTypeFlag(bindings[i].descriptorType), - bindings[i].descriptorCount, - convertShaderStageFlag(bindings[i].shaderStage)); + binding.bindingID, + convertDescriptorTypeFlag(binding.descriptorType), + binding.descriptorCount, + convertShaderStageFlag(binding.shaderStage)); setBindings.push_back(descriptorSetLayoutBinding); } @@ -53,8 +58,7 @@ namespace vkcv //create the descriptor set's layout from the bindings gathered above vk::DescriptorSetLayoutCreateInfo layoutInfo({}, setBindings); - if(m_Device.createDescriptorSetLayout(&layoutInfo, nullptr, &set.layout) != vk::Result::eSuccess) - { + if (m_Device.createDescriptorSetLayout(&layoutInfo, nullptr, &set.layout) != vk::Result::eSuccess) { vkcv_log(LogLevel::ERROR, "Failed to create descriptor set layout"); return DescriptorSetHandle(); }; @@ -70,6 +74,7 @@ namespace vkcv allocInfo.setDescriptorPool(m_Pools.back()); result = m_Device.allocateDescriptorSets(&allocInfo, &set.vulkanHandle); } + if (result != vk::Result::eSuccess) { vkcv_log(LogLevel::ERROR, "Failed to create descriptor set (%s)", vk::to_string(result).c_str()); @@ -78,6 +83,8 @@ namespace vkcv return DescriptorSetHandle(); } }; + + set.poolIndex = (m_Pools.size() - 1); const uint64_t id = m_DescriptorSets.size(); @@ -277,17 +284,22 @@ namespace vkcv m_Device.destroyDescriptorSetLayout(set.layout); set.layout = nullptr; } - // FIXME: descriptor set itself not destroyed + + if (set.vulkanHandle) { + m_Device.freeDescriptorSets(m_Pools[set.poolIndex], 1, &(set.vulkanHandle)); + set.vulkanHandle = nullptr; + } } vk::DescriptorPool DescriptorManager::allocateDescriptorPool() { vk::DescriptorPool pool; - if (m_Device.createDescriptorPool(&m_PoolInfo, nullptr, &pool) != vk::Result::eSuccess) - { + if (m_Device.createDescriptorPool(&m_PoolInfo, nullptr, &pool) != vk::Result::eSuccess) { vkcv_log(LogLevel::WARNING, "Failed to allocate descriptor pool"); pool = nullptr; - }; - m_Pools.push_back(pool); + } else { + m_Pools.push_back(pool); + } + return pool; } diff --git a/src/vkcv/DrawcallRecording.cpp b/src/vkcv/DrawcallRecording.cpp index e6ea18588c251b5e49f454618a5ac9962cc8a264..32ed00e98f7ef72f0c391f61924444c26844869b 100644 --- a/src/vkcv/DrawcallRecording.cpp +++ b/src/vkcv/DrawcallRecording.cpp @@ -6,7 +6,7 @@ namespace vkcv { const DrawcallInfo &drawcall, vk::CommandBuffer cmdBuffer, vk::PipelineLayout pipelineLayout, - const PushConstantData &pushConstantData, + const PushConstants &pushConstants, const size_t drawcallIndex) { for (uint32_t i = 0; i < drawcall.mesh.vertexBufferBindings.size(); i++) { @@ -23,17 +23,13 @@ namespace vkcv { nullptr); } - const size_t drawcallPushConstantOffset = drawcallIndex * pushConstantData.sizePerDrawcall; - // char* cast because void* does not support pointer arithmetic - const void* drawcallPushConstantData = drawcallPushConstantOffset + (char*)pushConstantData.data; - - if (pushConstantData.data && pushConstantData.sizePerDrawcall > 0) { + if (pushConstants.getSizePerDrawcall() > 0) { cmdBuffer.pushConstants( pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, - pushConstantData.sizePerDrawcall, - drawcallPushConstantData); + pushConstants.getSizePerDrawcall(), + pushConstants.getDrawcallData(drawcallIndex)); } if (drawcall.mesh.indexBuffer) { diff --git a/src/vkcv/Handles.cpp b/src/vkcv/Handles.cpp index 020489418c8e2db6ce2062d6fd20f06f90a05c37..65fc02dedeba39953c173103efe9b228f49e5d7f 100644 --- a/src/vkcv/Handles.cpp +++ b/src/vkcv/Handles.cpp @@ -1,5 +1,7 @@ #include "vkcv/Handles.hpp" +#include <iostream> + namespace vkcv { Handle::Handle() : @@ -11,7 +13,7 @@ namespace vkcv { {} Handle::~Handle() { - if ((m_rc) && (--(*m_rc) == 0)) { + if ((m_rc) && (*m_rc > 0) && (--(*m_rc) == 0)) { if (m_destroy) { m_destroy(m_id); } @@ -82,9 +84,9 @@ namespace vkcv { std::ostream& operator << (std::ostream& out, const Handle& handle) { if (handle) { - return out << "[Handle: " << handle.getId() << ":" << handle.getRC() << "]"; + return out << "[" << typeid(handle).name() << ": " << handle.getId() << ":" << handle.getRC() << "]"; } else { - return out << "[Handle: none]"; + return out << "[" << typeid(handle).name() << ": none]"; } } diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp index f8d94b734599cbf1f55aad7b590ab4796501d951..15a2fc5240176742f50141407a3c72b531757ee9 100644 --- a/src/vkcv/Image.cpp +++ b/src/vkcv/Image.cpp @@ -56,7 +56,7 @@ namespace vkcv{ m_manager->switchImageLayoutImmediate(m_handle, newLayout); } - vkcv::ImageHandle Image::getHandle() const { + const vkcv::ImageHandle& Image::getHandle() const { return m_handle; } @@ -64,7 +64,7 @@ namespace vkcv{ return m_manager->getImageMipCount(m_handle); } - void Image::fill(void *data, size_t size) { + void Image::fill(const void *data, size_t size) { m_manager->fillImage(m_handle, data, size); } diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index ae554e6babdd2b2f42c352515c02a34e45182fec..ba96cf8ff1be1988dbaf3f9cb01bdaa96c84ac0b 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -67,7 +67,8 @@ namespace vkcv { for (uint64_t id = 0; id < m_images.size(); id++) { destroyImageById(id); } - for (const auto swapchainImage : m_swapchainImages) { + + for (const auto& swapchainImage : m_swapchainImages) { for (const auto view : swapchainImage.m_viewPerMip) { m_core->getContext().getDevice().destroy(view); } @@ -196,7 +197,7 @@ namespace vkcv { } std::vector<vk::ImageView> views; - for (int mip = 0; mip < mipCount; mip++) { + for (uint32_t mip = 0; mip < mipCount; mip++) { const vk::ImageViewCreateInfo imageViewCreateInfo( {}, image, @@ -369,7 +370,7 @@ namespace vkcv { } } - void ImageManager::fillImage(const ImageHandle& handle, void* data, size_t size) + void ImageManager::fillImage(const ImageHandle& handle, const void* data, size_t size) { const uint64_t id = handle.getId(); @@ -504,9 +505,6 @@ namespace vkcv { } void ImageManager::generateImageMipChainImmediate(const ImageHandle& handle) { - - const auto& device = m_core->getContext().getDevice(); - SubmitInfo submitInfo; submitInfo.queueType = QueueType::Graphics; @@ -655,7 +653,6 @@ namespace vkcv { uint32_t ImageManager::getImageMipCount(const ImageHandle& handle) const { const uint64_t id = handle.getId(); - const bool isSwapchainFormat = handle.isSwapchainImage(); if (handle.isSwapchainImage()) { return 1; @@ -685,7 +682,7 @@ namespace vkcv { assert(images.size() == views.size()); m_swapchainImages.clear(); - for (int i = 0; i < images.size(); i++) { + for (size_t i = 0; i < images.size(); i++) { m_swapchainImages.push_back(Image(images[i], nullptr, { views[i] }, width, height, 1, format, 1)); } } diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp index 1d8ce207b645e30cee291816eac3c934ed40e92a..9edd747141305a8a795a2ec8ada04f46e96c9852 100644 --- a/src/vkcv/ImageManager.hpp +++ b/src/vkcv/ImageManager.hpp @@ -103,7 +103,7 @@ namespace vkcv { const ImageHandle& handle, vk::CommandBuffer cmdBuffer); - void fillImage(const ImageHandle& handle, void* data, size_t size); + void fillImage(const ImageHandle& handle, const void* data, size_t size); void generateImageMipChainImmediate(const ImageHandle& handle); void recordImageMipChainGenerationToCmdStream(const vkcv::CommandStreamHandle& cmdStream, const ImageHandle& handle); void recordMSAAResolve(vk::CommandBuffer cmdBuffer, ImageHandle src, ImageHandle dst); diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp index df6c74cccf6c4652adc6a4c78802f282ea6ae293..b4891c6be387b817b87f059f4155f5708d4f4710 100644 --- a/src/vkcv/QueueManager.cpp +++ b/src/vkcv/QueueManager.cpp @@ -51,7 +51,7 @@ namespace vkcv { } //resort flags with heighest priority before allocating the queues std::vector<vk::QueueFlagBits> newFlags; - for(int i = 0; i < prios.size(); i++) { + for(size_t i = 0; i < prios.size(); i++) { auto minElem = std::min_element(prios.begin(), prios.end()); int index = minElem - prios.begin(); newFlags.push_back(queueFlags[index]); @@ -79,7 +79,7 @@ namespace vkcv { switch (qFlag) { case vk::QueueFlagBits::eGraphics: found = false; - for (int i = 0; i < queueFamilyStatus.size() && !found; i++) { + for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (queueFamilyStatus[i][0] > 0) { queuePairsGraphics.push_back(std::pair(i, initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0])); queueFamilyStatus[i][0]--; @@ -89,7 +89,7 @@ namespace vkcv { } } if (!found) { - for (int i = 0; i < queueFamilyStatus.size() && !found; i++) { + for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (initialQueueFamilyStatus[i][0] > 0) { queuePairsGraphics.push_back(std::pair(i, 0)); found = true; @@ -101,7 +101,7 @@ namespace vkcv { break; case vk::QueueFlagBits::eCompute: found = false; - for (int i = 0; i < queueFamilyStatus.size() && !found; i++) { + for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (queueFamilyStatus[i][1] > 0) { queuePairsCompute.push_back(std::pair(i, initialQueueFamilyStatus[i][1] - queueFamilyStatus[i][1])); queueFamilyStatus[i][0]--; @@ -111,7 +111,7 @@ namespace vkcv { } } if (!found) { - for (int i = 0; i < queueFamilyStatus.size() && !found; i++) { + for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (initialQueueFamilyStatus[i][1] > 0) { queuePairsCompute.push_back(std::pair(i, 0)); found = true; @@ -123,7 +123,7 @@ namespace vkcv { break; case vk::QueueFlagBits::eTransfer: found = false; - for (int i = 0; i < queueFamilyStatus.size() && !found; i++) { + for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (queueFamilyStatus[i][2] > 0) { queuePairsTransfer.push_back(std::pair(i, initialQueueFamilyStatus[i][2] - queueFamilyStatus[i][2])); queueFamilyStatus[i][0]--; @@ -133,7 +133,7 @@ namespace vkcv { } } if (!found) { - for (int i = 0; i < queueFamilyStatus.size() && !found; i++) { + for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (initialQueueFamilyStatus[i][2] > 0) { queuePairsTransfer.push_back(std::pair(i, 0)); found = true; @@ -149,7 +149,7 @@ namespace vkcv { } // create all requested queues - for (int i = 0; i < qFamilyProperties.size(); i++) { + for (size_t i = 0; i < qFamilyProperties.size(); i++) { uint32_t create = std::abs(initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0]); if (create > 0) { vk::DeviceQueueCreateInfo qCreateInfo( diff --git a/src/vkcv/Swapchain.cpp b/src/vkcv/Swapchain.cpp index 94e7301d66bfcc513434ef6d22520d1b95f98161..d0aa26db9c661ea40caf06349a72cc9188e791a9 100644 --- a/src/vkcv/Swapchain.cpp +++ b/src/vkcv/Swapchain.cpp @@ -100,18 +100,14 @@ namespace vkcv * @return available Format */ vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { - uint32_t formatCount; - physicalDevice.getSurfaceFormatsKHR(surface, &formatCount, nullptr); - std::vector<vk::SurfaceFormatKHR> availableFormats(formatCount); - if (physicalDevice.getSurfaceFormatsKHR(surface, &formatCount, &availableFormats[0]) != vk::Result::eSuccess) { - throw std::runtime_error("Failed to get surface formats"); - } + std::vector<vk::SurfaceFormatKHR> availableFormats = physicalDevice.getSurfaceFormatsKHR(surface); for (const auto& availableFormat : availableFormats) { if (availableFormat.format == vk::Format::eB8G8R8A8Unorm && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) { return availableFormat; } } + return availableFormats[0]; } @@ -122,12 +118,7 @@ namespace vkcv * @return available PresentationMode */ vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { - uint32_t modeCount; - physicalDevice.getSurfacePresentModesKHR( surface, &modeCount, nullptr ); - std::vector<vk::PresentModeKHR> availablePresentModes(modeCount); - if (physicalDevice.getSurfacePresentModesKHR(surface, &modeCount, &availablePresentModes[0]) != vk::Result::eSuccess) { - throw std::runtime_error("Failed to get presentation modes"); - } + std::vector<vk::PresentModeKHR> availablePresentModes = physicalDevice.getSurfacePresentModesKHR(surface); for (const auto& availablePresentMode : availablePresentModes) { if (availablePresentMode == vk::PresentModeKHR::eMailbox) { @@ -145,12 +136,11 @@ namespace vkcv * @return available ImageCount */ uint32_t chooseImageCount(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { - vk::SurfaceCapabilitiesKHR surfaceCapabilities; - if(physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) != vk::Result::eSuccess){ - throw std::runtime_error("cannot get surface capabilities. There is an issue with the surface."); - } - - uint32_t imageCount = surfaceCapabilities.minImageCount + 1; // minImageCount should always be at least 2; set to 3 for triple buffering + vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface); + + // minImageCount should always be at least 2; set to 3 for triple buffering + uint32_t imageCount = surfaceCapabilities.minImageCount + 1; + // check if requested image count is supported if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) { imageCount = surfaceCapabilities.maxImageCount; @@ -215,8 +205,9 @@ namespace vkcv } void Swapchain::updateSwapchain(const Context &context, const Window &window) { - if (!m_RecreationRequired.exchange(false)) - return; + if (!m_RecreationRequired.exchange(false)) { + return; + } vk::SwapchainKHR oldSwapchain = m_Swapchain; vk::Extent2D extent2D = chooseExtent(context.getPhysicalDevice(), m_Surface.handle, window); diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp index ea72582d67d5350e5fbf3f3c0fa2aae2ba407b0e..025cb388c6880cc8132b454c799d39e2b530ceb3 100644 --- a/src/vkcv/Window.cpp +++ b/src/vkcv/Window.cpp @@ -150,11 +150,15 @@ namespace vkcv { } void Window::onGamepadEvent(int gamepadIndex) { - int activeWindowIndex = std::find_if(s_Windows.begin(), - s_Windows.end(), - [](GLFWwindow* window){return glfwGetWindowAttrib(window, GLFW_FOCUSED);}) - - s_Windows.begin(); - activeWindowIndex *= (activeWindowIndex < s_Windows.size()); // fixes index getting out of bounds (e.g. if there is no focused window) + size_t activeWindowIndex = std::find_if( + s_Windows.begin(), + s_Windows.end(), + [](GLFWwindow* window){return glfwGetWindowAttrib(window, GLFW_FOCUSED);} + ) - s_Windows.begin(); + + // fixes index getting out of bounds (e.g. if there is no focused window) + activeWindowIndex *= (activeWindowIndex < s_Windows.size()); + auto window = static_cast<Window *>(glfwGetWindowUserPointer(s_Windows[activeWindowIndex])); if (window != nullptr) {