Merge pull request 'Enhancements & Fixes' (#78) from enhancements into master

Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/78
This commit is contained in:
Georg Hagen
2024-07-24 16:06:01 +02:00
45 changed files with 442 additions and 110 deletions

View File

@@ -20,3 +20,5 @@ YAMLCPP_REPO=https://git.madvoxel.net/Mirrors/yaml-cpp.git
UTFCPP_REPO=https://git.madvoxel.net/Mirrors/utfcpp.git
TRACY_REPO=https://git.madvoxel.net/Mirrors/tracy.git
STB_REPO=https://git.madvoxel.net/Mirrors/stb.git
UNITS_REPO=https://git.madvoxel.net/Mirrors/units.git
ANKERLUD_REPO=https://git.madvoxel.net/Mirrors/ankerl_unordered_dense.git

View File

@@ -20,8 +20,9 @@ add_subdirectory(tracy)
add_subdirectory(libstud-uuid)
add_subdirectory(rapidyaml)
add_subdirectory(libarchive)
add_subdirectory(libjpeg-turbo)
add_subdirectory(boost)
add_subdirectory(units)
if (NOT IOS)
add_subdirectory(libjpeg-turbo)
add_subdirectory(curl)
endif()

View File

@@ -29,6 +29,7 @@ if (glfw_FOUND)
target_link_libraries(imgui_internal PUBLIC glfw)
endif ()
set(NO_SHADERC ON)
SetupVulkan(imgui_internal)
target_include_directories(imgui_internal PUBLIC ${Vulkan_INCLUDE_DIR})

15
3rdParty/units/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,15 @@
include(FetchContent)
if(NOT DEFINED UNITS_REPO)
set(UNITS_REPO https://github.com/nholthaus/units.git)
endif ()
FetchContent_Declare(
units
EXCLUDE_FROM_ALL
GIT_REPOSITORY ${UNITS_REPO}
GIT_TAG v2.3.3
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(units)

View File

@@ -109,7 +109,7 @@ endif()
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR}/deps/INSTALL)
target_link_libraries(openVulkanoCpp PRIVATE magic_enum yaml-cpp fmt spdlog glm pugixml stb eigen utf8cpp imgui_internal TracyClient stud-uuid ryml unordered_dense Boost::regex)
target_link_libraries(openVulkanoCpp PRIVATE magic_enum yaml-cpp fmt spdlog glm pugixml stb eigen utf8cpp imgui_internal TracyClient stud-uuid ryml unordered_dense Boost::regex units)
LinkCurl(openVulkanoCpp)
add_compile_definitions(LIBARCHIVE_STATIC)

View File

@@ -5,12 +5,16 @@ function(SetupVulkan TARGET)
else ()
find_package(Vulkan REQUIRED)
target_link_libraries(${TARGET} PRIVATE Vulkan::Vulkan)
if (NO_SHADERC)
message("Disable shaderc linking")
else()
find_package(Vulkan OPTIONAL_COMPONENTS shaderc_combined)
if (Vulkan_shaderc_combined_FOUND)
target_link_libraries(${TARGET} PRIVATE Vulkan::shaderc_combined)
target_compile_definitions(${TARGET} PRIVATE HAS_SHADERC)
endif ()
endif ()
endif ()
target_include_directories(${TARGET} PUBLIC ${Vulkan_INCLUDE_DIR})
if (ANDROID)

2
doc

Submodule doc updated: 88fb9e13fc...25bfd5114c

View File

@@ -45,6 +45,11 @@ namespace OpenVulkano::AR
Math::CameraIntrinsic intrinsic;
Format format = Format::NV12;
[[nodiscard]] Math::Vector4uc Sample(float nx, float ny, bool asRgb = true) const
{
return Sample(static_cast<uint32_t>(nx * luminescenceOrColor.resolution.x), static_cast<uint32_t>(ny * luminescenceOrColor.resolution.y), asRgb);
}
[[nodiscard]] Math::Vector4uc Sample(uint32_t x, uint32_t y, bool asRgb = true) const
{
const uint8_t* lumColBuffer = static_cast<const uint8_t*>(luminescenceOrColor.data);

View File

@@ -10,6 +10,8 @@
#include "Scene/Texture.hpp"
#include <filesystem>
using namespace std::chrono_literals;
namespace OpenVulkano::AR::Playback
{
ArSessionPlayback::ArSessionPlayback(const std::string& recordingPath, bool autoAdvance)
@@ -60,6 +62,7 @@ namespace OpenVulkano::AR::Playback
void ArSessionPlayback::ReadWorker()
{
std::this_thread::sleep_for(128ms); // Delay startup of playback
while (playbackReader.HasNext() && IsRunning())
{
while (!m_frameConsumed) { std::this_thread::yield(); }

View File

@@ -6,6 +6,7 @@
#pragma once
#include "IResourceManager.hpp"
#include "Base/ITickable.hpp"
#include "Base/ICloseable.hpp"
#include "Scene/Scene.hpp"
@@ -32,5 +33,7 @@ namespace OpenVulkano
virtual void SetActiveUi(Scene::UI::Ui* ui) = 0;
virtual Scene::UI::Ui* GetActiveUi() = 0;
virtual IResourceManager* GetIResourceManager() = 0;
};
}

View File

@@ -0,0 +1,25 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "Base/Wrapper.hpp"
#include "Math/Math.hpp"
#include "Scene/DataFormat.hpp"
namespace OpenVulkano
{
namespace Scene
{
class Texture;
}
class IResourceManager
{
public:
[[nodiscard]] virtual Unique<Scene::Texture> CreateSharedMemoryTexture(const Math::Vector3ui& resolution, DataFormat format) = 0;
};
}

View File

@@ -37,7 +37,7 @@ namespace OpenVulkano
[[nodiscard]] uint32_t Patch() const { return GetComponent(2); }
[[nodiscard]] uint32_t Build() const { return m_buildNumber; }
[[nodiscard]] uint64_t Build() const { return m_buildNumber; }
[[nodiscard]] bool IsPreRelease() const { return m_preRelease; }

View File

@@ -30,7 +30,7 @@ namespace OpenVulkano
[[nodiscard]] bool IsInitialized() const { return initialized; }
void Init();
void Init() override;
void Tick() override;

View File

@@ -149,8 +149,7 @@ namespace OpenVulkano::GLFW
void WindowGLFW::SetSize(uint32_t width, uint32_t height)
{
windowConfig.size.x = width;
windowConfig.size.y = height;
currentSize = { width, height };
if (window)
{
glfwSetWindowSize(window, width, height);
@@ -169,9 +168,9 @@ namespace OpenVulkano::GLFW
Math::Vector2ui WindowGLFW::GetSize()
{
Math::Vector2i size;
glfwGetWindowSize(window, &size.x, &size.y);
return size;
if (currentSize.x == 0 || currentSize.y == 0)
glfwGetWindowSize(window, reinterpret_cast<int*>(&currentSize.x), reinterpret_cast<int*>(&currentSize.y));
return currentSize;
}
Math::Vector2i WindowGLFW::GetPosition()
@@ -269,6 +268,11 @@ namespace OpenVulkano::GLFW
void WindowGLFW::OnResize(const uint32_t newWidth, const uint32_t newHeight)
{
Logger::WINDOW->debug("Window (id: {0}) resized (width: {1}, height: {2})", GetWindowId(), newWidth, newHeight);
currentSize = { newWidth, newHeight };
if (GetWindowMode() == WINDOWED || GetWindowMode() == BORDERLESS)
{
windowConfig.size = currentSize;
}
handler->OnWindowResize(this, newWidth, newHeight);
}

View File

@@ -23,6 +23,7 @@ namespace OpenVulkano::GLFW
InputProviderGLFW& inputProvider;
GLFWwindow* window = nullptr;
IWindowHandler* handler = nullptr;
Math::Vector2ui currentSize = {};
public:
WindowGLFW(InputProviderGLFW& inputProvider);

View File

@@ -29,6 +29,12 @@ namespace OpenVulkano::Math
constexpr T CONVERSION = std::numbers::pi_v<T> / 180.0;
return degree * CONVERSION;
}
template<typename T>
constexpr T Square(T val)
{
return val * val;
}
}
template<typename T> using Matrix2_SIMD = glm::tmat2x2<T, glm::aligned>;

View File

@@ -0,0 +1,46 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "Math/Math.hpp"
namespace OpenVulkano::Math
{
class RGB565
{
uint16_t Make5(uint8_t val)
{
return val * 31.0f / 255.0f;
}
uint16_t Make6(uint8_t val)
{
return val * 63.0f / 255.0f;
}
public:
union
{
uint16_t value;
struct
{
uint16_t b : 5;
uint16_t g : 6;
uint16_t r : 5;
};
};
RGB565(Math::Vector4uc color = {0, 0, 0, 1})
: b(Make5(color.b))
, g(Make6(color.g))
, r(Make5(color.r))
{
}
};
static_assert(sizeof(RGB565) == 2);
}

View File

@@ -97,8 +97,6 @@ namespace OpenVulkano::Scene
void UpdateViewProjectionMatrix()
{
//TODO this should be done based on the clipspace used by the rendering api
// In vulkan the screen space is defined as y=0=top and y=1=bottom and thus the coordinate have to be flipped
m_viewProjection = m_projection * m_view;
}
@@ -115,6 +113,14 @@ namespace OpenVulkano::Scene
SetMatrix(Math::Utils::inverse(view));
}
void SetProjectionMatrix(const Math::Matrix4f& projection)
{
//TODO this should be done based on the clipspace used by the rendering api
// In vulkan the screen space is defined as y=0=top and y=1=bottom and thus the coordinate have to be flipped
m_projection = projection * Math::Matrix4f(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
UpdateViewProjectionMatrix();
}
[[nodiscard]] const Math::Matrix4f& GetViewProjectionMatrix() const
{
return m_viewProjection;
@@ -251,9 +257,7 @@ namespace OpenVulkano::Scene
void UpdateProjectionMatrix() override
{
m_projection = Math::Utils::perspectiveRH_ZO(m_fov, m_aspect, m_nearPlane, m_farPlane);
m_projection *= Math::Matrix4f(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
UpdateViewProjectionMatrix();
SetProjectionMatrix(Math::Utils::perspectiveRH_ZO(m_fov, m_aspect, m_nearPlane, m_farPlane));
}
[[nodiscard]] bool IsPerspective() const override { return true; }
@@ -266,11 +270,9 @@ namespace OpenVulkano::Scene
{
const float scale = 0.5f * m_contentScaleFactor * m_zoom;
const float widthHalf = m_width * scale, heightHalf = m_height * scale;
m_projection = Math::Utils::orthoRH_ZO(-widthHalf, widthHalf, -heightHalf, heightHalf, m_nearPlane, m_farPlane);
UpdateViewProjectionMatrix();
SetProjectionMatrix(Math::Utils::orthoRH_ZO(-widthHalf, widthHalf, -heightHalf, heightHalf, m_nearPlane, m_farPlane));
}
[[nodiscard]] bool IsOrtho() const override { return true; }
};
}

View File

@@ -5,10 +5,50 @@
*/
#include "DataFormat.hpp"
#include "Base/Logger.hpp"
#include <magic_enum.hpp>
namespace OpenVulkano
{
namespace
{
std::unordered_map<DataFormat::Format, uint32_t> MakeFormatSizeMap()
{
std::unordered_map<DataFormat::Format, uint32_t> map;
for (auto format : magic_enum::enum_values<DataFormat::Format>())
{
uint32_t size = 0;
if (format == DataFormat::R4G4_UNORM_PACK8 || format == DataFormat::S8_UINT) size = 1;
else if (format >= DataFormat::R4G4B4A4_UNORM_PACK16 && format <= DataFormat::A1R5G5B5_UNORM_PACK16) size = 2;
else if (format >= DataFormat::R8_UNORM && format <= DataFormat::R8_SRGB) size = 1;
else if (format >= DataFormat::R8G8_UNORM && format <= DataFormat::R8G8_SRGB) size = 2;
else if (format >= DataFormat::R8G8B8_UNORM && format <= DataFormat::B8G8R8_SRGB) size = 3;
else if (format >= DataFormat::R8G8B8A8_UNORM && format <= DataFormat::A2B10G10R10_SINT_PACK32) size = 4;
else if (format >= DataFormat::R16_UNORM && format <= DataFormat::R16_SFLOAT) size = 2;
else if (format >= DataFormat::R16G16_UNORM && format <= DataFormat::R16G16_SFLOAT) size = 4;
else if (format >= DataFormat::R16G16B16_UNORM && format <= DataFormat::R16G16B16_SFLOAT) size = 6;
else if (format >= DataFormat::R16G16B16A16_UNORM && format <= DataFormat::R16G16B16A16_SFLOAT) size = 8;
else if (format >= DataFormat::R32_UINT && format <= DataFormat::R32_SFLOAT) size = 4;
else if (format >= DataFormat::R32G32_UINT && format <= DataFormat::R32G32_SFLOAT) size = 8;
else if (format >= DataFormat::R32G32B32_UINT && format <= DataFormat::R32G32B32_SFLOAT) size = 12;
else if (format >= DataFormat::R32G32B32A32_UINT && format <= DataFormat::R32G32B32A32_SFLOAT) size = 16;
else if (format >= DataFormat::R64_UINT && format <= DataFormat::R64_SFLOAT) size = 8;
else if (format >= DataFormat::R64G64_UINT && format <= DataFormat::R64G64_SFLOAT) size = 16;
else if (format >= DataFormat::R64G64B64_UINT && format <= DataFormat::R64G64B64_SFLOAT) size = 24;
else if (format >= DataFormat::R64G64B64A64_UINT && format <= DataFormat::R64G64B64A64_SFLOAT) size = 32;
else if (format == DataFormat::B10G11R11_UFLOAT_PACK32 || format == DataFormat::E5B9G9R9_UFLOAT_PACK32 ||
format == DataFormat::X8_D24_UNORM_PACK32 || format == DataFormat::D32_SFLOAT || format == DataFormat::D24_UNORM_S8_UINT) size = 4;
else if (format == DataFormat::D16_UNORM) size = 2;
else if (format == DataFormat::D16_UNORM_S8_UINT) size = 3;
else if (format == DataFormat::D32_SFLOAT_S8_UINT) size = 5;
map[format] = size;
}
return map;
}
const std::unordered_map<DataFormat::Format, uint32_t> FORMAT_SIZE_MAP = MakeFormatSizeMap();
}
std::string_view DataFormat::GetName() const
{
return magic_enum::enum_name(m_format);
@@ -20,4 +60,22 @@ namespace OpenVulkano
if (result.has_value()) return { result.value() };
return { UNDEFINED };
}
uint32_t DataFormat::GetBytesPerPixel()
{
auto size = FORMAT_SIZE_MAP.find(m_format);
if (size == FORMAT_SIZE_MAP.end() || size->second == 0) [[unlikely]]
{
Logger::RENDER->warn("Failed to get pixel size for format: {}", GetName());
return 0;
}
return size->second;
}
#ifndef __APPLE__
DataFormat DataFormat::GetFromMetalPixelFormat(int formatId)
{
return UNDEFINED;
}
#endif
}

View File

@@ -371,9 +371,12 @@ namespace OpenVulkano
return reinterpret_cast<const vk::Format&>(m_format);
}
uint32_t GetBytesPerPixel();
static DataFormat GetFromName(std::string_view name);
static DataFormat GetFromMetalPixelFormat(int formatId);
private:
Format m_format;
};

View File

@@ -22,21 +22,21 @@ namespace OpenVulkano::Scene
}
void MorphableCamera::UpdateProjectionMatrix()
{
PerspectiveCamera::UpdateProjectionMatrix();
if (m_morphState == 0) PerspectiveCamera::UpdateProjectionMatrix();
if (m_morphState != 0)
{
const float scale = 0.5f * m_contentScaleFactor * m_zoom;
const float widthHalf = m_width * scale, heightHalf = m_height * scale;
m_orthoMatrix = Math::Utils::orthoRH_ZO(-widthHalf, widthHalf, -heightHalf, heightHalf, m_nearPlane, m_farPlane);
Math::Matrix4f orthoMatrix = Math::Utils::orthoRH_ZO(-widthHalf, widthHalf, -heightHalf, heightHalf, m_nearPlane, m_farPlane);
if (m_morphState == 1)
{
m_projection = m_orthoMatrix;
SetProjectionMatrix(orthoMatrix);
}
else
{
m_projection = BlendMatrices(m_projection, m_orthoMatrix, m_morphState);
Math::Matrix4f projection = Math::Utils::perspectiveRH_ZO(m_fov, m_aspect, m_nearPlane, m_farPlane);
SetProjectionMatrix(BlendMatrices(projection, orthoMatrix, m_morphState));
}
UpdateViewProjectionMatrix();
}
}
}

View File

@@ -13,7 +13,6 @@ namespace OpenVulkano::Scene
class MorphableCamera : public PerspectiveCamera
{
float m_morphState;
Math::Matrix4f m_orthoMatrix;
public:
MorphableCamera(float fovDegrees, float nearPlane = 0.1f, float farPlane = 1000.0f, float width = 16, float height = 9)

View File

@@ -15,6 +15,10 @@ namespace OpenVulkano::Scene
: localMat(1), worldMat(1), enabled(true)
{}
Node::Node(const Math::Matrix4f& pose)
: localMat(pose), worldMat(pose), enabled(true)
{}
Node::~Node() noexcept
{
if (parent || scene || !children.empty() || !drawables.empty())

View File

@@ -28,17 +28,19 @@ namespace OpenVulkano::Scene
static constexpr DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_UNIFORM_BUFFER_DYNAMIC, 1, ShaderProgramType::ALL_GRAPHICS };
Math::Matrix4f localMat, worldMat;
bool enabled = true;
Node* parent = nullptr;
Scene* scene = nullptr;
std::vector<Node*> children;
std::vector<Drawable*> drawables;
UpdateFrequency matrixUpdateFrequency = UpdateFrequency::Never;
ICloseable* renderNode = nullptr;
bool enabled = true;
public:
Node();
Node(const Math::Matrix4f& pose);
~Node() noexcept override;
void Init();
@@ -81,6 +83,8 @@ namespace OpenVulkano::Scene
void Disable() { enabled = false; }
void SetEnabled(bool enable) { enabled = enable; }
[[nodiscard]] Node* GetParent() const { return parent; }
[[nodiscard]] Scene* GetScene() const { return scene; }

View File

@@ -34,6 +34,7 @@ namespace OpenVulkano::Scene
PlaneCameraController(Camera* camera = nullptr);
void Init(Camera* camera) override { Init(camera, DefaultAxis::OXZ); }
void Init(Camera* camera, const Math::Vector3f& planeNormal);
void Init(Camera* camera, DefaultAxis axis);
void Tick() override;

View File

@@ -46,7 +46,8 @@ namespace OpenVulkano::Scene
void ArBackgroundDrawable::Close()
{
m_arSession->OnNewFrame -= EventHandler(this, &ArBackgroundDrawable::OnNewArFrame);
if (m_arSession) m_arSession->OnNewFrame -= EventHandler(this, &ArBackgroundDrawable::OnNewArFrame);
m_arSession = nullptr;
m_nextFrame = nullptr;
Drawable::Close();
}

View File

@@ -0,0 +1,39 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "ShaderProgramType.hpp"
namespace OpenVulkano
{
struct PushConstantRange
{
ShaderProgramType::Type stageFlags;
uint32_t offset, size;
PushConstantRange(ShaderProgramType::Type stages, uint32_t offset, uint32_t size)
: stageFlags(stages), offset(offset), size(size)
{}
PushConstantRange(uint32_t size, uint32_t offset = 0, ShaderProgramType::Type stages = ShaderProgramType::ALL_GRAPHICS)
: stageFlags(stages), offset(offset), size(size)
{}
};
struct PushConstant : PushConstantRange
{
const void* data;
PushConstant(ShaderProgramType::Type stages, uint32_t offset, uint32_t size, const void* data)
: PushConstantRange(stages, offset, size), data(data)
{}
PushConstant(const void* data, uint32_t size, uint32_t offset = 0, ShaderProgramType::Type stages = ShaderProgramType::ALL_GRAPHICS)
: PushConstantRange(stages, offset, size), data(data)
{}
};
}

View File

@@ -11,6 +11,7 @@
#include "VertexInputDescription.hpp"
#include "ShaderProgramType.hpp"
#include "DescriptorInputDescription.hpp"
#include "PushConstant.hpp"
#include <string>
#include <stdexcept>
@@ -72,10 +73,13 @@ namespace OpenVulkano::Scene
std::vector<ShaderProgram> shaderPrograms{};
std::vector<VertexInputDescription> vertexInputDescriptions{};
std::vector<std::vector<DescriptorSetLayoutBinding>> descriptorSets;
std::vector<PushConstantRange> pushConstantRanges;
Topology topology = Topology::TRIANGLE_LIST;
CullMode cullMode = CullMode::BACK;
ICloseable* renderShader = nullptr;
bool alphaBlend = false; // TODO allow fine control over blending
bool depthTest = true;
bool depthWrite = true;
Shader() = default;
~Shader() override { /*if (renderShader) Shader::Close();*/ }
@@ -138,6 +142,11 @@ namespace OpenVulkano::Scene
}
#pragma clang diagnostic pop
void AddPushConstantRange(const PushConstantRange& pushConstantRange)
{
pushConstantRanges.push_back(pushConstantRange);
}
void Close() override
{
renderShader->Close();

View File

@@ -21,10 +21,12 @@ namespace OpenVulkano::Scene
UniformBuffer* m_uniBuffer = nullptr;
public:
SimpleDrawable() : Drawable(DrawEncoder::GetDrawEncoder<SimpleDrawable>()) {}
SimpleDrawable(const DrawPhase phase = DrawPhase::MAIN)
: Drawable(DrawEncoder::GetDrawEncoder<SimpleDrawable>(), phase)
{}
explicit SimpleDrawable(const SimpleDrawable* toCopy)
: Drawable(DrawEncoder::GetDrawEncoder<SimpleDrawable>())
: Drawable(DrawEncoder::GetDrawEncoder<SimpleDrawable>(), toCopy->GetDrawPhase())
, m_mesh(toCopy->m_mesh)
, m_material(toCopy->m_material)
, m_uniBuffer(toCopy->m_uniBuffer)

View File

@@ -14,22 +14,36 @@
namespace OpenVulkano::Scene
{
class Texture;
struct RenderTexture
{
Texture* m_texture = nullptr;
};
class Texture
{
public:
static Texture PLACEHOLDER;
static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_COMBINED_IMAGE_SAMPLER, 1, ShaderProgramType::ALL_GRAPHICS };
Texture(bool placeholder = false) { if (placeholder) MakePlaceholder(); }
ICloseable* renderTexture = nullptr;
RenderTexture* renderTexture = nullptr;
void* textureBuffer = nullptr;
Math::Vector3ui resolution = {0,0,0};
size_t size = 0;
Math::Vector3ui resolution = {0,0,0};
DataFormat format = DataFormat::B8G8R8A8_UNORM;
bool updated = true;
UpdateFrequency updateFrequency = UpdateFrequency::Never;
Texture(bool placeholder = false) { if (placeholder) MakePlaceholder(); }
~Texture()
{
if (renderTexture)
{
renderTexture->m_texture = nullptr;
}
}
void MakePlaceholder(uint32_t width = 32, uint32_t height = 32,
Math::Vector4uc color1 = {248, 123, 255, 255}, Math::Vector4uc color2 = {250, 19, 255, 255});

View File

@@ -7,6 +7,8 @@
#pragma once
#include "Base/ICloseable.hpp"
#include "Scene/Shader/DescriptorInputDescription.hpp"
#include "Scene/UpdateFrequency.hpp"
namespace OpenVulkano::Scene
{

View File

@@ -1,13 +1,14 @@
#version 450
layout (set = 3, binding = 0) uniform sampler2D camTexture;
layout(set = 3, binding = 0) uniform sampler2D camTexture;
#ifdef ENABLE_DEPTH_WRITE
layout (set = 2, binding = 1) uniform sampler2D depthMap;
layout(set = 2, binding = 1) uniform sampler2D depthMap;
#endif
layout (location = 0) in vec2 texCoords;
layout (location = 0) out vec4 fragColor;
layout(location = 0) in vec2 texCoords;
layout(location = 1) in float scale;
layout(location = 0) out vec4 fragColor;
layout(set = 1, binding = 0) uniform CameraData
{
@@ -21,7 +22,13 @@ layout(set = 1, binding = 0) uniform CameraData
void main()
{
vec2 rm = (texCoords - 0.5) * 2;
float intensity = rm.x * rm.x + rm.y * rm.y;
intensity = (intensity / 1.4) * scale / 2;
fragColor = texture(camTexture, texCoords);
fragColor.rgb = fragColor.rgb - intensity;
#ifdef ENABLE_DEPTH_WRITE
gl_FragDepth = (texture(depthMap, texCoords).r - cam.near) / (cam.far - cam.near);
#endif

View File

@@ -25,15 +25,16 @@ layout(set = 2, binding = 0) uniform RealCameraData
} realCam;
layout(location = 0) out vec2 textureCoordinates;
layout(location = 1) out float scaleOut;
const float FLOAT_MAX_LESS_THAN_1 = 0.999999940395355224609;
// Background plane positions are in clipped space
const vec4 PLANE[4] = vec4[] (
const vec4 PLANE[4] = vec4[](
vec4(1, -1, FLOAT_MAX_LESS_THAN_1, 1), vec4(-1, -1, FLOAT_MAX_LESS_THAN_1, 1), vec4(1, 1, FLOAT_MAX_LESS_THAN_1, 1), vec4(-1, 1, FLOAT_MAX_LESS_THAN_1, 1)
);
const vec2 TEX_COORDS[4] = vec2[] (
);
const vec2 TEX_COORDS[4] = vec2[](
vec2(1, 0), vec2(0, 0), vec2(1, 1), vec2(0, 1)
);
);
void main() {
vec4 position = PLANE[gl_VertexIndex];
@@ -45,14 +46,15 @@ void main() {
float scaleY = realScale / cam.scaleFactor;
float scaleX = scaleY / (cam.aspect * realAspect);
// Scale the quad's position
position.xy *= vec2(scaleX, scaleY);
// Handle center
vec2 centerOffset = realCam.intrinsic[2].xy / vec2(realCam.width, realCam.height);
centerOffset -= 0.5;
position.xy -= centerOffset;
position.xy -= centerOffset * vec2(2, 2);
// Scale the quad's position
position.xy *= vec2(scaleX, scaleY);
scaleOut = 1 / scaleY;
gl_Position = position;
textureCoordinates = TEX_COORDS[gl_VertexIndex];
}

View File

@@ -202,7 +202,7 @@ namespace OpenVulkano::Vulkan
bool Device::GetMemoryType(uint32_t typeBits, const vk::MemoryPropertyFlags& properties, uint32_t* typeIndex) const
{
for (uint32_t i = 0; i < 32; i++)
for (uint32_t i = 0; i < 32 && typeBits; i++)
{
if ((typeBits & 1) == 1)
{

View File

@@ -35,14 +35,22 @@ namespace OpenVulkano::Vulkan
cmdBuffer.pipelineBarrier(/*VulkanUtils::GetPipelineStageForLayout(oldLayout)*/vk::PipelineStageFlagBits::eTopOfPipe, /*VulkanUtils::GetPipelineStageForLayout(newLayout)*/ vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, imgMemBarrier);
}
void Image::Init(const Device* device, const DataFormat& format, const vk::Extent3D& resolution)
void Image::Init(const Device* device, const DataFormat& format, const vk::Extent3D& resolution, const vk::MemoryPropertyFlags& memoryPropertyFlags)
{
vk::ImageCreateInfo imgCreateInfo { {}, vk::ImageType::e2D, format, resolution, 1, 1 };
imgCreateInfo.usage = vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled;
if (memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)
{
imgCreateInfo.tiling = vk::ImageTiling::eLinear;
imgCreateInfo.initialLayout = vk::ImageLayout::ePreinitialized;
}
else
{
imgCreateInfo.tiling = vk::ImageTiling::eOptimal;
imgCreateInfo.sharingMode = vk::SharingMode::eExclusive;
imgCreateInfo.initialLayout = vk::ImageLayout::eUndefined;
}
imgCreateInfo.sharingMode = vk::SharingMode::eExclusive;
vk::ImageViewCreateInfo imgViewCreateInfo { {}, image, vk::ImageViewType::e2D, imgCreateInfo.format };
imgViewCreateInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
@@ -51,7 +59,7 @@ namespace OpenVulkano::Vulkan
imgViewCreateInfo.subresourceRange.baseArrayLayer = 0;
imgViewCreateInfo.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
Init(device, imgCreateInfo, imgViewCreateInfo);
Init(device, imgCreateInfo, imgViewCreateInfo, true, memoryPropertyFlags);
}
void Image::Close()

View File

@@ -38,7 +38,7 @@ namespace OpenVulkano::Vulkan
*/
void Init(const Device* device, const vk::ImageCreateInfo& imageCreateInfo, vk::ImageViewCreateInfo imageViewCreateInfo, bool allocateMem = true, const vk::MemoryPropertyFlags& memoryPropertyFlags = vk::MemoryPropertyFlagBits::eDeviceLocal);
void Init(const Device* device, const DataFormat& format, const vk::Extent3D& resolution);
void Init(const Device* device, const DataFormat& format, const vk::Extent3D& resolution, const vk::MemoryPropertyFlags& memoryPropertyFlags = vk::MemoryPropertyFlagBits::eDeviceLocal);
void SetLayout(vk::CommandBuffer& cmdBuffer, const vk::ImageSubresourceRange& subResourceRange, vk::ImageLayout newLayout, vk::ImageLayout oldLayout = vk::ImageLayout::eUndefined) const;

View File

@@ -64,7 +64,7 @@ namespace OpenVulkano::Vulkan
void MetalBackedTexture::Close()
{
m_vulkanTexture.Close();
if (m_vulkanTexture) m_vulkanTexture.Close();
if (m_metalTexture)
{
[m_metalTexture release];

View File

@@ -84,5 +84,7 @@ namespace OpenVulkano::Vulkan
void RegisterCloseable(ICloseable* closeable) { closeables.push_back(closeable); }
void UnregisterCloseable(ICloseable* closeable) { Utils::Remove(closeables, closeable); }
IResourceManager* GetIResourceManager() override { return &resourceManager; }
};
}

View File

@@ -133,7 +133,11 @@ namespace OpenVulkano::Vulkan
{
GetCmdBuffer().end();
vk::SubmitInfo si = { 0, nullptr, nullptr, 1, &frameResources[currentBuffer].cmdBuffer, 1, &frameResources[currentBuffer].semaphore };
transferQueue.submit(1, &si, vk::Fence());
vk::Result result = transferQueue.submit(1, &si, vk::Fence());
if (result != vk::Result::eSuccess) [[unlikely]]
{
Logger::RENDER->error("Failed to submit resource manager transfer queue");
}
return frameResources[currentBuffer].semaphore;
}
@@ -222,12 +226,22 @@ namespace OpenVulkano::Vulkan
return static_cast<VulkanCamera*>(camera->renderCamera);
}
UniformBuffer* ResourceManager::CreateUniformBuffer(const DescriptorSetLayoutBinding& binding, size_t size, void* data, uint32_t setId)
UniformBuffer* ResourceManager::CreateUniformBuffer(const DescriptorSetLayoutBinding& binding, size_t size, void* data, uint32_t setId, bool hostVis)
{
const std::unique_lock lock(mutex);
const vk::DeviceSize allocSize = Utils::Align(size, uniformBufferAlignment);
auto buffer = CreateDeviceOnlyBufferWithData(allocSize, vk::BufferUsageFlagBits::eUniformBuffer, data);
MemoryPool::ManagedBufferPtr buffer;
if (hostVis)
{
buffer = memPool.CreateBuffer(allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
buffer->Map();
buffer->Copy(data, size, 0);
}
else
{
buffer = CreateDeviceOnlyBufferWithData(allocSize, vk::BufferUsageFlagBits::eUniformBuffer, data);
}
UniformBuffer* uBuffer = new UniformBuffer();
uBuffer->Init(std::move(buffer), 0, allocSize, GetDescriptorLayoutSet(binding), binding, setId);
@@ -322,10 +336,8 @@ namespace OpenVulkano::Vulkan
VulkanUniformBuffer* vkBuffer;
ManagedBuffer::Ptr mBuffer;
const vk::DeviceSize allocSize = Utils::Align(buffer->size, uniformBufferAlignment);
vk::DeviceSize frameSize = 0;
if (buffer->GetUpdateFrequency() != Scene::UpdateFrequency::Never)
{
frameSize = allocSize;
vkBuffer = new VulkanUniformBufferDynamic();
const uint32_t imgs = context->swapChain.GetImageCount();
mBuffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
@@ -354,4 +366,19 @@ namespace OpenVulkano::Vulkan
if (!sampler) sampler = device.createSampler(samplerConfig);
return sampler;
}
Unique<Scene::Texture> ResourceManager::CreateSharedMemoryTexture(const Math::Vector3ui& resolution, DataFormat format)
{
const std::unique_lock lock(mutex);
Unique<Scene::Texture> texture = std::make_unique<Scene::Texture>();
texture->resolution = resolution;
texture->format = format;
texture->size = resolution.x * resolution.y * resolution.z * format.GetBytesPerPixel();
VulkanTexture* vkTexture = new VulkanTexture();
vkTexture->InitSharedMem(this, texture.get(), GetDescriptorLayoutSet(Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
textures.emplace_back(vkTexture);
return texture;
}
}

View File

@@ -14,6 +14,7 @@
#include "IShaderOwner.hpp"
#include "MemoryPool.hpp"
#include "Base/Wrapper.hpp"
#include "Base/Render/IResourceManager.hpp"
#include "Vulkan/Image.hpp"
#include "Scene/Shader/DescriptorInputDescription.hpp"
#include <vulkan/vulkan.hpp>
@@ -47,7 +48,7 @@ namespace OpenVulkano
class ManagedBuffer;
class MemoryAllocation;
class ResourceManager : public IShaderOwner
class ResourceManager : public IShaderOwner, public IResourceManager
{
friend UniformBuffer;
friend VulkanTexture;
@@ -114,10 +115,12 @@ namespace OpenVulkano
[[nodiscard]] vk::Device GetDevice() const { return device; }
UniformBuffer* CreateUniformBuffer(const DescriptorSetLayoutBinding& binding, size_t size, void* data, uint32_t setId = 2);
UniformBuffer* CreateUniformBuffer(const DescriptorSetLayoutBinding& binding, size_t size, void* data, uint32_t setId = 2, bool hostVis = false);
vk::Sampler CreateSampler(const vk::SamplerCreateInfo& samplerConfig);
[[nodiscard]] Unique<Scene::Texture> CreateSharedMemoryTexture(const Math::Vector3ui& resolution, DataFormat format) override;
protected: // Allocation management
MemoryPool::ManagedBufferPtr CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data);

View File

@@ -7,6 +7,7 @@
#pragma once
#include "Base/ICloseable.hpp"
#include "Scene/Camera.hpp"
#include "IRecordable.hpp"
#include "Vulkan/Resources/UniformBuffer.hpp"
@@ -39,5 +40,7 @@ namespace OpenVulkano::Vulkan
m_camera = nullptr;
delete m_buffer;
}
[[nodiscard]] Scene::Camera* GetCamera() const { return m_camera; }
};
}

View File

@@ -13,6 +13,7 @@
namespace OpenVulkano::Vulkan
{
static_assert(sizeof(vk::DescriptorSetLayoutBinding) == sizeof(DescriptorSetLayoutBinding));
static_assert(sizeof(vk::PushConstantRange) == sizeof(PushConstantRange));
VulkanShader::~VulkanShader()
{
@@ -79,7 +80,7 @@ namespace OpenVulkano::Vulkan
vk::PipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.cullMode = static_cast<vk::CullModeFlagBits>(shader->cullMode);
vk::PipelineMultisampleStateCreateInfo msaa = {};
vk::PipelineDepthStencilStateCreateInfo depth = { {}, 1, 1, vk::CompareOp::eLess };
vk::PipelineDepthStencilStateCreateInfo depth = { {}, shader->depthTest, shader->depthWrite, vk::CompareOp::eLess };
depth.maxDepthBounds = 1;
vk::PipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask = vk::ColorComponentFlagBits::eA | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eR;
@@ -148,9 +149,8 @@ namespace OpenVulkano::Vulkan
vk::DescriptorSetLayoutCreateInfo createInfo { {}, static_cast<uint32_t>(set.size()), reinterpret_cast<const vk::DescriptorSetLayoutBinding*>(set.data()) };
descriptorSetLayouts.push_back(device.createDescriptorSetLayout(createInfo));
}
vk::PipelineLayoutCreateInfo plci = { {}, static_cast<uint32_t>(descriptorSetLayouts.size()), descriptorSetLayouts.data(), 0, nullptr };
vk::PushConstantRange* pcRanges = reinterpret_cast<vk::PushConstantRange*>(shader->pushConstantRanges.data());
vk::PipelineLayoutCreateInfo plci = {{}, static_cast<uint32_t>(descriptorSetLayouts.size()), descriptorSetLayouts.data(), static_cast<uint32_t>(shader->pushConstantRanges.size()), pcRanges };
pipelineLayout = this->device.createPipelineLayout(plci);
}
}

View File

@@ -16,11 +16,10 @@
namespace OpenVulkano::Vulkan
{
class VulkanTexture : public IRecordable, public Image
class VulkanTexture : public Scene::RenderTexture, public IRecordable, public Image
{
public:
static inline vk::SamplerCreateInfo DEFAULT_SAMPLER_CONFIG {};
Scene::Texture* m_texture = nullptr;
vk::Sampler m_sampler;
vk::DescriptorSet m_descriptorSet;
@@ -37,9 +36,22 @@ namespace OpenVulkano::Vulkan
texture->renderTexture = this;
}
void InitSharedMem(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding)
{
m_texture = texture;
Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z }, vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible);
texture->updated = false;
texture->textureBuffer = Map();
m_sampler = resManager->CreateSampler(DEFAULT_SAMPLER_CONFIG);
SetDescriptorSet(resManager, descriptorSetLayout, binding);
texture->renderTexture = this;
}
virtual ~VulkanTexture() override
{
if (m_texture) Close();
if (m_sampler) Close();
}
void Close() override

View File

@@ -50,13 +50,25 @@ namespace OpenVulkano::Vulkan
{
currentSemaphoreId = (currentSemaphoreId + 1) % imageAvailableSemaphores.size();
const auto resultValue = device->device.acquireNextImageKHR(swapChain, UINT64_MAX, imageAvailableSemaphores[currentSemaphoreId], fence);
const vk::Result result = resultValue.result;
if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) throw std::error_code(result);
vk::Result result = resultValue.result;
if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) [[unlikely]]
{
Logger::RENDER->error("Failed to acquire next swapchain image: {}", vk::to_string(result));
throw std::error_code(result);
}
SetCurrentFrameId(resultValue.value);
vk::Fence submitFence = GetCurrentSubmitFence();
device->device.waitForFences(1, &submitFence, true, -1);
device->device.resetFences(1, &submitFence);
result = device->device.waitForFences(1, &submitFence, true, -1);
if (result != vk::Result::eSuccess) [[unlikely]]
{
Logger::RENDER->error("Failed to wait for fence: {}", vk::to_string(result));
}
result = device->device.resetFences(1, &submitFence);
if (result != vk::Result::eSuccess) [[unlikely]]
{
Logger::RENDER->error("Failed to reset fence: {}", vk::to_string(result));
}
return currentFrameBufferId;
}

View File

@@ -35,6 +35,8 @@ namespace OpenVulkano::Vulkan
void SetCamera(Scene::Camera* camera);
VulkanShader* GetShader() const { return m_lastShader; }
[[nodiscard]] VulkanShader* GetShader() const { return m_lastShader; }
[[nodiscard]] VulkanCamera* GetCamera() const { return m_lastCamera; }
};
}