Merge remote-tracking branch 'origin/master' into

feature/BinSearchArrayMap
This commit is contained in:
Metehan Tuncbilek
2024-09-23 14:28:30 +03:00
24 changed files with 1516 additions and 153 deletions

View File

@@ -93,6 +93,7 @@ function(LinkMsdf TARGET)
if (FREETYPE_BUILT_FROM_SOURCES) if (FREETYPE_BUILT_FROM_SOURCES)
target_include_directories(${TARGET} PUBLIC ${FREETYPE_INCLUDE_DIR}) target_include_directories(${TARGET} PUBLIC ${FREETYPE_INCLUDE_DIR})
else() else()
find_package(Freetype REQUIRED)
target_include_directories(${TARGET} PUBLIC ${FREETYPE_INCLUDE_DIRS}) target_include_directories(${TARGET} PUBLIC ${FREETYPE_INCLUDE_DIRS})
endif() endif()
endif() endif()

View File

@@ -1,17 +0,0 @@
Find_Package(OpenCV)
include(FetchContent)
if(NOT DEFINED OPENCV_REPO)
set(OPENCV_REPO https://github.com/opencv/opencv.git)
endif ()
if (NOT OpenCV_FOUND)
FetchContent_Declare(
opencv
EXCLUDE_FROM_ALL
GIT_REPOSITORY ${OPENCV_REPO}
GIT_TAG v4.8.1
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(opencv)
endif()

View File

@@ -18,6 +18,13 @@ FetchContent_Declare(
-DTINYUSDZ_BUILD_TESTS:BOOL=OFF -DTINYUSDZ_BUILD_TESTS:BOOL=OFF
-DTINYUSDZ_BUILD_EXAMPLES:BOOL=OFF -DTINYUSDZ_BUILD_EXAMPLES:BOOL=OFF
) )
set(TINYUSDZ_NO_WERROR ON)
set(TINYUSDZ_BUILD_TESTS OFF)
set(TINYUSDZ_BUILD_BENCHMARKS OFF)
set(TINYUSDZ_BUILD_EXAMPLES OFF)
set(TINYUSDZ_WITH_BUILTIN_IMAGE_LOADER OFF)
FetchContent_MakeAvailable(tinyusdz) FetchContent_MakeAvailable(tinyusdz)
function (LinkTinyUSDZ TARGET) function (LinkTinyUSDZ TARGET)

View File

@@ -109,6 +109,7 @@ namespace OpenVulkano::AR
} }
} }
tjFree(outBuffer); tjFree(outBuffer);
tjDestroy(handle);
#endif #endif
} }

View File

@@ -29,7 +29,7 @@ namespace OpenVulkano
EngineConfiguration::EngineConfiguration() EngineConfiguration::EngineConfiguration()
{ {
const std::string filePath = (AppFolders::GetAppConfigHomeDir() / "EngineConfig.yml").string(); const std::string filePath = (AppFolders::GetAppConfigHomeDir() / "EngineConfig.yml").string();
Array<char> fileContents = Utils::ReadFile(filePath, true); Array<char> fileContents = Utils::ReadFile(filePath, true, true);
if(fileContents.Size() == 0) if(fileContents.Size() == 0)
return; return;

View File

@@ -167,6 +167,12 @@ namespace OpenVulkano
bool HasRenderResource() const { return renderResource; } bool HasRenderResource() const { return renderResource; }
RenderResourceHolder& operator =(const RenderResourceHolder& copy) noexcept
{
renderResource.Release();
return *this;
}
RenderResourceHolder& operator =(RenderResourceHolder&& move) noexcept RenderResourceHolder& operator =(RenderResourceHolder&& move) noexcept
{ {
renderResource = std::move(move.renderResource); renderResource = std::move(move.renderResource);

View File

@@ -108,7 +108,7 @@ namespace OpenVulkano
if (GetCamera()->IsOrtho()) if (GetCamera()->IsOrtho())
{ {
HandleMovementOrtho(); HandleMovementOrtho();
if (GetCamera()->GetZoom() > 50) /*if (GetCamera()->GetZoom() > 50)
{ {
float nDist = std::max<float>(((ZOOM_RANGE - sqrt(GetCamera()->GetZoom())) / ZOOM_RANGE) * m_distance, 0.1f); float nDist = std::max<float>(((ZOOM_RANGE - sqrt(GetCamera()->GetZoom())) / ZOOM_RANGE) * m_distance, 0.1f);
if (nDist != m_frameDistance) if (nDist != m_frameDistance)
@@ -116,7 +116,7 @@ namespace OpenVulkano
m_distUpated = true; m_distUpated = true;
m_frameDistance = nDist; m_frameDistance = nDist;
} }
} }*/
} }
else else
{ {

View File

@@ -0,0 +1,464 @@
#pragma once
#include "Base/Wrapper.hpp"
#include <initializer_list>
#include <iterator>
#include <stdexcept>
#include <list>
#include <vector>
#include <algorithm>
#pragma warning(push)
#pragma warning(disable : 4200)
#pragma warning(disable : 6011)
#pragma warning(disable : 6386)
namespace OpenVulkano
{
/**
* @class Stable Vector
* @brief Stable Vector is an alternative version for std::vector that provides chunk based memory allocation without re-aligning
*
* @throw Please know that this vector creates array gaps when you remove an element.
*/
template<typename T, size_t DEFAULT_CHUNK_SIZE = 32, int GROWTH_FACTOR = 2> class StableVector
{
struct VectorChunk
{
VectorChunk* m_prev = nullptr;
VectorChunk* m_next = nullptr;
size_t m_chunkSize;
int64_t m_lastUsedIndex;
bool* m_fill;
T m_data[0];
VectorChunk(size_t size) : m_chunkSize(size), m_lastUsedIndex(-1)
{
m_fill = reinterpret_cast<bool*>(m_data + size);
memset(m_fill, 0, size * sizeof(bool));
}
~VectorChunk()
{
for (size_t i = 0; i < m_chunkSize; i++)
{
if (m_fill[i])
{
m_data[i].~T();
}
}
m_prev = nullptr;
m_next = nullptr;
}
};
public:
class Iterator
{
public:
Iterator(VectorChunk* ptr, size_t index = 0) : m_ptr(ptr), m_index(index) {}
T& operator*() { return m_ptr->m_data[m_index]; }
T* operator->() { return &m_ptr->m_data[m_index]; }
Iterator operator++()
{
++m_index;
MovetoNextValidChunk();
return *this;
}
Iterator operator++(int)
{
Iterator temp = *this;
++(*this);
return temp;
}
bool operator==(const Iterator& other) const { return m_ptr == other.m_ptr && m_index == other.m_index; }
bool operator!=(const Iterator& other) const { return !(*this == other); }
private:
void MovetoNextValidChunk()
{
while (m_ptr && (m_index > m_ptr->m_chunkSize || !m_ptr->m_fill[m_index]))
{
if (m_index >= m_ptr->m_chunkSize)
{
m_ptr = m_ptr->m_next;
m_index = 0;
}
else ++m_index;
}
if (m_ptr && m_index >= m_ptr->m_chunkSize)
{
m_ptr = m_ptr->m_next;
m_index = 0;
MovetoNextValidChunk();
}
}
private:
VectorChunk* m_ptr;
size_t m_index;
};
public:
StableVector() : m_firstChunk(nullptr), m_lastChunk(nullptr)
{
VectorChunk* chunk = SpawnChunk(DEFAULT_CHUNK_SIZE);
m_firstChunk = chunk;
m_lastChunk = chunk;
m_currentSize = 0;
m_totalCap = DEFAULT_CHUNK_SIZE;
}
StableVector(const StableVector<T>& copy)
{
m_firstChunk = nullptr;
m_lastChunk = nullptr;
m_currentSize = 0;
m_totalCap = 0;
VectorChunk* currentChunk = copy.m_firstChunk;
while (currentChunk)
{
for (size_t i = 0; i < currentChunk->m_chunkSize; i++)
{
if (currentChunk->m_fill[i]) { PushBack(currentChunk->m_data[i]); }
}
currentChunk = currentChunk->m_next;
}
}
StableVector(StableVector<T>&& move) noexcept
{
m_firstChunk = move.m_firstChunk;
m_lastChunk = move.m_lastChunk;
m_currentSize = move.m_currentSize;
m_totalCap = move.m_totalCap;
move.m_firstChunk = nullptr;
move.m_lastChunk = nullptr;
move.m_currentSize = 0;
move.m_totalCap = 0;
}
~StableVector()
{
VectorChunk* currentChunk = m_firstChunk;
while (currentChunk)
{
VectorChunk* temp = currentChunk;
currentChunk = currentChunk->m_next;
temp->~VectorChunk();
::operator delete(temp);
}
}
/**
* Adds the value to the first empty slot in the StableVector
*
* @param value - The value to be added
*/
void Add(const T& value)
{
VectorChunk* currentChunk = m_firstChunk;
while (currentChunk)
{
for (size_t i = 0; i < currentChunk->m_chunkSize; i++)
{
if (!currentChunk->m_fill[i])
{
currentChunk->m_data[i] = value;
currentChunk->m_fill[i] = true;
m_currentSize++;
if (i > currentChunk->m_lastUsedIndex) currentChunk->m_lastUsedIndex = i;
return;
}
}
currentChunk = currentChunk->m_next;
}
VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR));
new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(value);
m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true;
m_currentSize++;
}
void PushBack(const T& value)
{
if (m_lastChunk->m_lastUsedIndex + 1 == m_lastChunk->m_chunkSize)
{
VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR));
}
new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(value);
m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true;
m_currentSize++;
}
void PushBack(T&& value) noexcept
{
if (m_lastChunk->m_lastUsedIndex + 1 == m_lastChunk->m_chunkSize)
{
VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR));
}
new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(std::move(value));
m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true;
m_currentSize++;
}
template<typename... Args> void Emplace(Args&&... args)
{
VectorChunk* currentChunk = m_firstChunk;
while (currentChunk)
{
for (size_t i = 0; i < currentChunk->m_chunkSize; i++)
{
if (!currentChunk->m_fill[i])
{
currentChunk->m_data[i] = T(std::forward<Args>(args)...);
currentChunk->m_fill[i] = true;
m_currentSize++;
if (i > currentChunk->m_lastUsedIndex) currentChunk->m_lastUsedIndex = i;
return;
}
}
currentChunk = currentChunk->m_next;
}
VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR));
new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(std::forward<Args>(args)...);
m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true;
m_currentSize++;
}
template<typename... Args> void EmplaceBack(Args&&... args)
{
if (m_lastChunk->m_lastUsedIndex + 1 == m_lastChunk->m_chunkSize)
VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR));
new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(std::forward<Args>(args)...);
m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true;
m_currentSize++;
}
/**
* Pops the last element of the StableVector
*
* @throw Please know that this pop function also reduces the chunk's lastUsedIndex
*/
void PopBack()
{
if (m_currentSize == 0) return;
if (m_lastChunk->m_lastUsedIndex == -1)
{
VectorChunk* temp = m_lastChunk;
m_lastChunk = m_lastChunk->m_prev;
m_lastChunk->m_next = nullptr;
temp->~VectorChunk();
::operator delete(temp);
}
m_lastChunk->m_data[m_lastChunk->m_lastUsedIndex].~T();
m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = false;
m_lastChunk->m_lastUsedIndex--;
m_currentSize--;
}
void Remove(size_t index)
{
size_t localIndex = index;
VectorChunk* chunk = GetChunk(localIndex);
if (chunk)
{
chunk->m_data[localIndex].~T();
chunk->m_fill[localIndex] = false;
m_currentSize--;
}
else throw std::out_of_range("Index out of range!");
}
void Remove(const T& value)
{
VectorChunk* currentChunk = m_firstChunk;
while (currentChunk)
{
for (size_t i = 0; i < currentChunk->m_chunkSize; i++)
{
if (currentChunk->m_fill[i] && currentChunk->m_data[i] == value)
{
currentChunk->m_data[i].~T();
currentChunk->m_fill[i] = false;
m_currentSize--;
return;
}
}
currentChunk = currentChunk->m_next;
}
}
std::vector<T> ToVector() const
{
std::vector<T> vec;
VectorChunk* currentChunk = m_firstChunk;
while (currentChunk)
{
for (size_t i = 0; i < currentChunk->m_chunkSize; i++)
{
if (currentChunk->m_fill[i])
{
vec.push_back(currentChunk->m_data[i]);
}
}
currentChunk = currentChunk->m_next;
}
return vec;
}
T& At(size_t index) const
{
if (index >= Size()) [[unlikely]]
throw std::out_of_range("Index out of range!");
return (*this)[index];
}
T& operator[](size_t index) const
{
VectorChunk* chunk = m_firstChunk;
size_t localIndex = index;
while (chunk)
{
if (localIndex > chunk->m_chunkSize - 1)
{
localIndex -= (chunk->m_chunkSize);
chunk = chunk->m_next;
}
else break;
}
return chunk->m_data[localIndex];
}
size_t Size() const { return m_currentSize; }
size_t Capacity() const { return m_totalCap; }
void Clear()
{
VectorChunk* currentChunk = m_firstChunk;
while (currentChunk)
{
VectorChunk* temp = currentChunk;
currentChunk = currentChunk->m_next;
delete temp;
}
m_firstChunk = nullptr;
m_lastChunk = nullptr;
m_currentSize = 0;
m_totalCap = DEFAULT_CHUNK_SIZE;
m_firstChunk = SpawnChunk(DEFAULT_CHUNK_SIZE);
m_lastChunk = m_firstChunk;
}
StableVector<T>& operator=(const StableVector<T>& copy)
{
if (this == &copy) return *this;
Clear();
m_firstChunk = nullptr;
m_lastChunk = nullptr;
m_currentSize = 0;
m_totalCap = 0;
VectorChunk* currentChunk = copy.m_firstChunk;
for (auto it = copy.begin(); it != copy.end(); ++it) PushBack(*it);
}
StableVector<T>& operator=(StableVector<T>&& move) noexcept
{
if (this == &move) return *this;
Clear();
m_firstChunk = move.m_firstChunk;
m_lastChunk = move.m_lastChunk;
m_currentSize = move.m_currentSize;
m_totalCap = move.m_totalCap;
move.m_firstChunk = nullptr;
move.m_lastChunk = nullptr;
move.m_currentSize = 0;
move.m_totalCap = 0;
return *this;
}
Iterator begin() { return Iterator(m_firstChunk, 0); }
Iterator end() { return Iterator(m_lastChunk, m_lastChunk->m_lastUsedIndex + 1); }
const Iterator& cbegin() const { return Iterator(m_firstChunk, 0); }
const Iterator& cend() const { return Iterator(m_lastChunk, m_lastChunk->m_lastUsedIndex + 1); }
private:
VectorChunk* SpawnChunk(size_t requestedSize)
{
VectorChunk* chunk = static_cast<VectorChunk*>(
::operator new(sizeof(VectorChunk) + requestedSize * sizeof(T) + requestedSize * sizeof(bool)));
new (chunk) VectorChunk(requestedSize);
if (m_lastChunk)
{
chunk->m_prev = m_lastChunk;
m_lastChunk->m_next = chunk;
m_lastChunk = chunk;
m_totalCap += m_lastChunk->m_chunkSize;
}
return chunk;
}
VectorChunk* GetChunk(size_t& localIndex)
{
VectorChunk* chunk = m_firstChunk;
while (chunk)
{
if (localIndex > chunk->m_chunkSize - 1)
{
localIndex -= (chunk->m_chunkSize);
chunk = chunk->m_next;
}
else break;
}
return chunk;
}
private:
VectorChunk* m_firstChunk;
VectorChunk* m_lastChunk;
size_t m_currentSize;
size_t m_totalCap;
};
}
#pragma warning(pop)

View File

@@ -15,7 +15,10 @@
#include <thread> #include <thread>
#include <stdexcept> #include <stdexcept>
#include <tracy/Tracy.hpp> #if __has_include("tracy/Tracy.hpp")
#include <tracy/Tracy.hpp>
#define HAS_TRACY
#endif
namespace OpenVulkano namespace OpenVulkano
{ {
@@ -25,7 +28,10 @@ namespace OpenVulkano
: app(app), renderApi(renderApi) : app(app), renderApi(renderApi)
{ {
Utils::SetThreadName("Main"); Utils::SetThreadName("Main");
#ifdef HAS_TRACY
ZoneScoped; ZoneScoped;
#endif
Logger::SetupLogger(); Logger::SetupLogger();
if (!app) if (!app)
@@ -53,7 +59,9 @@ namespace OpenVulkano
: app(app), renderApi(renderApi) : app(app), renderApi(renderApi)
{ {
Utils::SetThreadName("Main"); Utils::SetThreadName("Main");
#ifdef HAS_TRACY
ZoneScoped; ZoneScoped;
#endif
Logger::SetupLogger(); Logger::SetupLogger();
if (!app) if (!app)
@@ -136,7 +144,9 @@ namespace OpenVulkano
void GraphicsAppManager::StartUp() void GraphicsAppManager::StartUp()
{ {
#ifdef HAS_TRACY
ZoneScoped; ZoneScoped;
#endif
try try
{ {
Logger::MANAGER->info("Initializing ..."); Logger::MANAGER->info("Initializing ...");
@@ -169,8 +179,11 @@ namespace OpenVulkano
void GraphicsAppManager::LoopTick() void GraphicsAppManager::LoopTick()
{ {
#ifdef HAS_TRACY
FrameMark; FrameMark;
ZoneScoped; ZoneScoped;
#endif
if (platform) platform->Tick(); if (platform) platform->Tick();
if (paused) if (paused)
{ // The rendering is paused { // The rendering is paused
@@ -197,7 +210,9 @@ namespace OpenVulkano
void GraphicsAppManager::ShutDown() void GraphicsAppManager::ShutDown()
{ {
#ifdef HAS_TRACY
ZoneScoped; ZoneScoped;
#endif
Logger::MANAGER->info("Shutting down ..."); Logger::MANAGER->info("Shutting down ...");
app->Close(); app->Close();
renderer->Close(); renderer->Close();

View File

@@ -0,0 +1,45 @@
/*
* 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/.
*/
#include "ErrorUtils.hpp"
#if defined(_MSC_VER)
#include "Windows.h"
#endif
namespace OpenVulkano
{
#if defined(_MSC_VER)
std::string ErrorUtils::GetLastErrorMessage()
{
// Get the error message ID, if any.
DWORD errorID = GetLastError();
if (errorID == 0)
{
return std::string();
}
LPSTR messageBuffer = nullptr;
// Format the error message
uint64_t size =
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &messageBuffer, 0, NULL);
// Buffer it up
std::string message(messageBuffer, size);
// Free the buffer and return the message
LocalFree(messageBuffer);
return message;
}
#else
std::string ErrorUtils::GetLastErrorMessage()
{
return std::string();
}
#endif
}

View File

@@ -0,0 +1,18 @@
/*
* 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 <string>
namespace OpenVulkano
{
class ErrorUtils
{
public:
static std::string GetLastErrorMessage();
};
}

View File

@@ -6,121 +6,15 @@
#include "MemMappedFile.hpp" #include "MemMappedFile.hpp"
#include "Base/Logger.hpp" #include "Base/Logger.hpp"
#ifdef _MSC_VER #include "MemMappedFileInternal.hpp"
#include <windows.h>
#else
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#endif
namespace OpenVulkano namespace OpenVulkano
{ {
class MemMappedFile::Internal final
{
public:
void* address = nullptr;
size_t size = 0;
#ifdef _MSC_VER
HANDLE fileHandle;
HANDLE fileMappingHandle;
Internal(const char* file, FileMode fileMode)
{ //TODO handle other file modes than read
fileHandle = CreateFile(
TEXT(file), // file to open
GENERIC_READ, // open for reading
0, // do not share
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attribute template
if (fileHandle == INVALID_HANDLE_VALUE)
{
Logger::FILESYS->critical("Failed to open file: {}", file);
return;
}
LARGE_INTEGER fileSize;
if (!GetFileSizeEx(fileHandle, &fileSize))
{
Logger::FILESYS->critical("Failed to get size of file: {}", file);
CloseHandle(fileHandle);
return;
}
size = fileSize.QuadPart;
fileMappingHandle = CreateFileMapping(
fileHandle,
NULL, // default security
PAGE_READONLY, // read-only access
0, // maximum object size (high-order)
0, // maximum object size (low-order)
NULL); // name of the mapping object
if (fileMappingHandle == 0)
{
Logger::FILESYS->critical("Failed to create file mapping handle: {}", file);
CloseHandle(fileHandle);
size = 0;
return;
}
address = MapViewOfFile(
fileMappingHandle, // handle to the map object
FILE_MAP_READ, // read access
0, // max. object size
0, // size of the hFile
0); // map the entire file
if (address == nullptr)
{
Logger::FILESYS->critical("Failed to create file mapping: {}", file);
CloseHandle(fileMappingHandle);
CloseHandle(fileHandle);
size = 0;
}
}
~Internal()
{
UnmapViewOfFile(address);
CloseHandle(fileMappingHandle);
CloseHandle(fileHandle);
}
#else
int fileHandle;
struct stat fileStat;
Internal(const char* file, FileMode fileMode)
{
fileHandle = open(file, fileMode);
if (fstat(fileHandle, &fileStat) == -1)
{
Logger::FILESYS->critical("Failed to query stats for file: {}", file);
return;
}
address = mmap(nullptr, fileStat.st_size, fileMode + 1, MAP_PRIVATE, fileHandle, 0);
if (address == MAP_FAILED)
{
Logger::FILESYS->critical("Failed to memory map file: {}", file);
address = nullptr;
}
size = fileStat.st_size;
}
~Internal()
{
munmap(address, fileStat.st_size);
close(fileHandle);
}
#endif
};
MemMappedFile::MemMappedFile(const std::filesystem::path& path, FileMode fileMode) MemMappedFile::MemMappedFile(const std::filesystem::path& path, FileMode fileMode)
: m_data(nullptr), m_size(0)
{ {
m_internal = std::make_shared<Internal>(path.string().c_str(), fileMode); std::string file = path.string();
m_internal = std::make_shared<MemMappedFileInternal>(file.c_str(), fileMode);
m_data = m_internal->address; m_data = m_internal->address;
m_size = (m_data) ? m_internal->size : 0; m_size = (m_data) ? m_internal->size : 0;
} }

View File

@@ -10,16 +10,22 @@
namespace OpenVulkano namespace OpenVulkano
{ {
class MemMappedFileInternal;
class MemMappedFile class MemMappedFile
{ {
class Internal; friend class MemMappedFileWriteHelper;
std::shared_ptr<Internal> m_internal; std::shared_ptr<MemMappedFileInternal> m_internal;
void* m_data; void* m_data;
size_t m_size; size_t m_size;
public: public:
enum FileMode : int { READ_ONLY = 0, WRITE_ONLY, READ_WRITE }; enum FileMode : int
{
READ_ONLY = 0,
WRITE_ONLY,
READ_WRITE
};
MemMappedFile(const std::filesystem::path& path, FileMode fileMode = READ_ONLY); MemMappedFile(const std::filesystem::path& path, FileMode fileMode = READ_ONLY);

View File

@@ -0,0 +1,125 @@
/*
* 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/.
*/
#include "MemMappedFileInternal.hpp"
#include "Base/Logger.hpp"
#include "Host/Windows/ErrorUtils.hpp"
namespace OpenVulkano
{
#ifdef _MSC_VER
MemMappedFileInternal::MemMappedFileInternal(const char* file, MemMappedFile::FileMode fileMode)
: size(0), fileHandle(nullptr), fileMappingHandle(nullptr)
{
DWORD openMode { 0 }, mapMode { 0 }, viewMode { 0 };
switch (fileMode)
{
case MemMappedFile::FileMode::READ_ONLY:
openMode = GENERIC_READ;
mapMode = PAGE_READONLY;
viewMode = FILE_MAP_READ;
break;
case MemMappedFile::FileMode::WRITE_ONLY:
openMode = GENERIC_WRITE;
mapMode = PAGE_READWRITE;
viewMode = FILE_MAP_WRITE;
break;
case MemMappedFile::FileMode::READ_WRITE:
openMode = GENERIC_ALL;
mapMode = PAGE_READWRITE;
viewMode = FILE_MAP_ALL_ACCESS;
break;
default:
break;
}
fileHandle = CreateFileA(file, // file to open
openMode, // open for switch case
NULL, // share mode
NULL, // default security
OPEN_ALWAYS, // always
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attribute template
if (fileHandle == INVALID_HANDLE_VALUE || fileHandle == NULL)
{
Logger::FILESYS->critical("Failed to open file: {}.", ErrorUtils::GetLastErrorMessage());
return;
}
LARGE_INTEGER fileSize;
if (!GetFileSizeEx(fileHandle, &fileSize))
{
Logger::FILESYS->critical("Failed to get size of file: {}", ErrorUtils::GetLastErrorMessage());
CloseHandle(fileHandle);
return;
}
size = fileSize.QuadPart;
fileMappingHandle = CreateFileMappingA(fileHandle,
NULL, // default security
mapMode, // mod for switch case
0, // maximum object size (high-order)
0, // maximum object size (low-order)
NULL); // name of the mapping object
if (fileMappingHandle == INVALID_HANDLE_VALUE || fileMappingHandle == NULL)
{
Logger::FILESYS->critical("Failed to create file mapping handle: {}", ErrorUtils::GetLastErrorMessage());
CloseHandle(fileHandle);
size = 0;
return;
}
address = MapViewOfFile(fileMappingHandle, // handle to the map object
viewMode, // access for switch case
0, // max. object size
0, // size of the hFile
0); // map the entire file
if (address == nullptr)
{
Logger::FILESYS->critical("Failed to create file mapping: {}", ErrorUtils::GetLastErrorMessage());
CloseHandle(fileMappingHandle);
CloseHandle(fileHandle);
size = 0;
}
}
MemMappedFileInternal::~MemMappedFileInternal()
{
UnmapViewOfFile(address);
CloseHandle(fileMappingHandle);
CloseHandle(fileHandle);
}
#else
MemMappedFileInternal::MemMappedFileInternal(const char* file, MemMappedFile::FileMode fileMode)
{
fileHandle = open(file, fileMode);
if (fstat(fileHandle, &fileStat) == -1)
{
Logger::FILESYS->critical("Failed to query stats for file: {}", file);
return;
}
address = mmap(nullptr, fileStat.st_size, fileMode + 1, MAP_SHARED, fileHandle, 0);
if (address == MAP_FAILED)
{
Logger::FILESYS->critical("Failed to memory map file: {}", file);
address = nullptr;
}
size = fileStat.st_size;
}
MemMappedFileInternal::~MemMappedFileInternal()
{
munmap(address, fileStat.st_size);
close(fileHandle);
}
#endif
}

View File

@@ -0,0 +1,50 @@
/*
* 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 "MemMappedFile.hpp"
#ifdef _MSC_VER
#include <Windows.h>
#else
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#endif
namespace OpenVulkano
{
class MemMappedFileInternal
{
friend class MemMappedFileWriteHelper;
friend class MemMappedFile;
public:
MemMappedFileInternal(const char* file, MemMappedFile::FileMode fileMode);
~MemMappedFileInternal();
private:
#if defined(_MSC_VER)
bool InvalidHandle() const { return fileHandle == INVALID_HANDLE_VALUE || fileHandle == NULL; }
#else
[[nodiscard]] bool InvalidHandle() const { return fileHandle == -1; }
#endif
private:
void* address = nullptr;
size_t size = 0;
#ifdef _MSC_VER
HANDLE fileHandle;
HANDLE fileMappingHandle;
#else
int fileHandle;
struct stat fileStat;
#endif
};
}

View File

@@ -0,0 +1,367 @@
/*
* 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/.
*/
#include "MemMappedFileWriteHelper.hpp"
#include "MemMappedFile.hpp"
#include "MemMappedFileInternal.hpp"
#if defined(_WIN32)
#include <windows.h>
#include <Host/Windows/ErrorUtils.hpp>
#else
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#endif
#include "Base/Logger.hpp"
#include <iostream>
namespace OpenVulkano
{
#if defined(_WIN32)
MemMappedFileWriteHelper::MemMappedFileWriteHelper(const std::filesystem::path& path, size_t maxFileSize)
: m_path(path), m_file(nullptr)
{
// Check if file exists, so we can open it in the correct mode
DWORD openMode = CREATE_ALWAYS;
if (std::filesystem::exists(path))
{
openMode = OPEN_ALWAYS;
}
// Open the file
HANDLE fileHandle =
CreateFileA(path.string().c_str(), GENERIC_ALL, FILE_SHARE_WRITE, NULL, openMode, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE || fileHandle == NULL)
{
throw std::runtime_error(ErrorUtils::GetLastErrorMessage().c_str());
}
// Control the file size
LARGE_INTEGER currentSize {};
if (fileHandle)
{
if (!GetFileSizeEx(fileHandle, &currentSize))
{
throw std::runtime_error(ErrorUtils::GetLastErrorMessage().c_str());
}
}
if (currentSize.QuadPart <= 0 && maxFileSize == 0)
{
throw std::runtime_error("Either the file size has to be greater than 0 or Initial Size!");
}
// Set the file size
if (maxFileSize > 0)
{
if (fileHandle)
{
// Set the file size
if (!SetFilePointer(fileHandle, DWORD(maxFileSize), NULL, FILE_BEGIN))
{
throw std::runtime_error(ErrorUtils::GetLastErrorMessage().c_str());
}
if (!SetEndOfFile(fileHandle))
{
throw std::runtime_error(ErrorUtils::GetLastErrorMessage().c_str());
}
}
}
if (fileHandle)
{
CloseHandle(fileHandle);
}
m_file = new MemMappedFile(path.string().c_str(), MemMappedFile::FileMode::READ_WRITE);
}
MemMappedFileWriteHelper::~MemMappedFileWriteHelper() = default;
bool MemMappedFileWriteHelper::Resize(const size_t newSize)
{
if (newSize == 0)
{
// Handle the case where the new size is zero
Logger::FILESYS->critical("New size is zero.");
return false;
}
// Get the current file handle
if (m_file->m_internal->fileHandle == INVALID_HANDLE_VALUE)
{
Logger::FILESYS->critical("Invalid file handle.");
return false;
}
// Unmap the old view of the file and close the file mapping handle
if (!(m_file->m_internal->fileMappingHandle == NULL)
&& !(m_file->m_internal->fileMappingHandle == INVALID_HANDLE_VALUE))
{
UnmapViewOfFile(m_file->m_internal->address);
CloseHandle(m_file->m_internal->fileMappingHandle);
}
// Resize the file
if (!SetFilePointer(m_file->m_internal->fileHandle, static_cast<DWORD>(newSize), NULL, FILE_BEGIN))
{
Logger::FILESYS->critical("Failed to set file pointer. Reason: {}", GetLastError());
return false;
}
if (!SetEndOfFile(m_file->m_internal->fileHandle))
{
Logger::FILESYS->critical("Failed to set end of file.");
return false;
}
// Create a new file mapping handle
m_file->m_internal->fileMappingHandle =
CreateFileMappingW(m_file->m_internal->fileHandle, NULL, PAGE_READWRITE, 0, 0, NULL);
if (m_file->m_internal->fileMappingHandle == NULL)
{
Logger::FILESYS->critical("Failed to create file mapping.");
return false;
}
// Map the file to a new view
m_file->m_internal->address =
MapViewOfFile(m_file->m_internal->fileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (m_file->m_internal->address == NULL || m_file->m_internal->address == INVALID_HANDLE_VALUE)
{
Logger::FILESYS->critical("Failed to map view of file.");
return false;
}
return true;
}
bool MemMappedFileWriteHelper::Trim(const size_t finalFileSize)
{
HANDLE fileHandle {};
if (m_file->m_internal->InvalidHandle())
{
auto file = m_path.string();
fileHandle = CreateFileA(file.c_str(), // file to open
GENERIC_WRITE, // open for reading
0, // do not share
NULL, // default security
CREATE_ALWAYS, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attribute template
}
else
{
fileHandle = m_file->m_internal->fileHandle;
}
if (m_file)
{
if (!UnmapViewOfFile(m_file->m_internal->address))
{
Logger::FILESYS->critical("Failed to unmap view of file on trim.");
return false;
}
if (!CloseHandle(m_file->m_internal->fileMappingHandle))
{
Logger::FILESYS->critical("Failed to close file mapping handle.");
return false;
}
}
LARGE_INTEGER liSize;
liSize.QuadPart = finalFileSize;
if (!SetFilePointerEx(fileHandle, liSize, NULL, FILE_BEGIN) || !SetEndOfFile(fileHandle))
{
Logger::FILESYS->critical("Failed to trim file: {}", ErrorUtils::GetLastErrorMessage());
return false;
}
// Create a new file mapping handle
if (m_file)
{
m_file->m_internal->fileMappingHandle = CreateFileMappingW(fileHandle, NULL, PAGE_READWRITE, 0, 0, NULL);
if (m_file->m_internal->fileMappingHandle == NULL)
{
Logger::FILESYS->critical("Failed to create file mapping.");
return false;
}
// Map the file to a new view
m_file->m_internal->address =
MapViewOfFile(m_file->m_internal->fileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (m_file->m_internal->address == NULL || m_file->m_internal->address == INVALID_HANDLE_VALUE)
{
Logger::FILESYS->critical("Failed to map view of file.");
return false;
}
}
if (m_file)
{
m_file->m_size = finalFileSize;
m_file->m_internal->size = finalFileSize;
}
return true;
}
#else
MemMappedFileWriteHelper::MemMappedFileWriteHelper(const std::filesystem::path& path, size_t maxFileSize)
{
const auto file = path.string();
const int fileHandle = open(file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fileHandle == -1)
{
throw std::runtime_error("Failed to open file: " + file);
}
struct stat fileStat
{
};
if (fstat(fileHandle, &fileStat) == -1)
{
close(fileHandle);
throw std::runtime_error("Failed to get file size: " + file);
}
if (const size_t fileSize = fileStat.st_size; fileSize < maxFileSize)
{
if (ftruncate(fileHandle, maxFileSize) == -1)
{
close(fileHandle);
throw std::runtime_error("Failed to resize file: " + file);
}
}
close(fileHandle);
m_file = new MemMappedFile(file.c_str(), MemMappedFile::FileMode::READ_WRITE);
}
MemMappedFileWriteHelper::~MemMappedFileWriteHelper() = default;
bool MemMappedFileWriteHelper::Resize(const size_t newSize)
{
if (newSize == 0)
{
// Handle the case where the new size is zero
Logger::FILESYS->error("New size is zero. New size must be greater than zero.");
return false;
}
// Get the current file handle
if (m_file->m_internal->fileHandle == -1)
{
Logger::FILESYS->critical("Invalid file handle.");
return false;
}
// Resize the file
if (ftruncate(m_file->m_internal->fileHandle, newSize) == -1)
{
Logger::FILESYS->critical("Failed to resize file.");
return false;
}
// Unmap the old view and map a new view of the resized file
if (m_file->m_internal->address != nullptr)
{
if (munmap(m_file->m_internal->address, m_file->m_internal->size) == -1)
{
Logger::FILESYS->critical("Failed to unmap view of file.");
return false;
}
}
// Map the file to a new view
m_file->m_internal->address =
mmap(nullptr, newSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_file->m_internal->fileHandle, 0);
if (m_file->m_internal->address == MAP_FAILED)
{
Logger::FILESYS->critical("Failed to map file.");
return false;
}
// Update the size of the file
m_file->m_internal->size = newSize;
return true;
}
bool MemMappedFileWriteHelper::Trim(const size_t finalFileSize)
{
// If getting handle returns invalid file recreate the file
if (m_file->m_internal->InvalidHandle())
{
const auto file = m_path.string();
m_file->m_internal->fileHandle = open(file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
}
// Unmap the old view of the file
if(munmap(m_file->m_internal->address, m_file->m_internal->size) == -1)
{
Logger::FILESYS->critical("Failed to unmap address.");
}
// Trim the file
if (ftruncate(m_file->m_internal->fileHandle, finalFileSize) == -1)
{
Logger::FILESYS->critical("Failed to trim file.");
return false;
}
// Remap the file with the new size
m_file->m_internal->address = mmap(nullptr, finalFileSize, PROT_READ | PROT_WRITE, MAP_SHARED,
m_file->m_internal->fileHandle, 0);
if (m_file->m_internal->address == MAP_FAILED)
{
Logger::FILESYS->critical("Failed to map file.");
return false;
}
// Update the size in MemMappedFile structure
m_file->m_size = finalFileSize;
return true;
}
#endif
void MemMappedFileWriteHelper::Close()
{
if (m_file->IsOpen())
{
delete m_file;
}
}
MemMappedFileWriter::MemMappedFileWriter(const std::filesystem::path& path, size_t maxFileSize)
: m_helper(MemMappedFileWriteHelper(path, maxFileSize))
{
}
MemMappedFileWriter::~MemMappedFileWriter() { m_helper.Close(); }
void MemMappedFileWriter::Write(const char* data, const size_t size)
{
// If the new size is greater than the current size, resize the file
if (m_writtenSize + size > m_helper.Size())
{
m_helper.Resize(m_writtenSize + size);
}
// Write to the end of the file
memcpy(static_cast<char*>(m_helper.Data()) + m_writtenSize, data, size);
m_writtenSize += size;
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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 "IO/MemMappedFile.hpp"
#include <filesystem>
namespace OpenVulkano
{
class MemMappedFileWriteHelper
{
public:
MemMappedFileWriteHelper(const std::filesystem::path& path, size_t maxFileSize);
~MemMappedFileWriteHelper();
[[nodiscard]] void* Data() const { return m_file->Data(); }
[[nodiscard]] size_t Size() const { return m_file->Size(); }
bool Resize(size_t newSize);
void Close();
bool Trim(size_t finalFileSize);
static constexpr size_t USE_CURRENT_FILE_SIZE = 0;
private:
MemMappedFile* m_file;
std::filesystem::path m_path;
};
class MemMappedFileWriter final
{
public:
MemMappedFileWriter(const std::filesystem::path& path, size_t maxFileSize);
~MemMappedFileWriter();
void Write(const char* data, size_t size);
void SetOffset(size_t offset) { m_writtenSize = offset; }
[[nodiscard]] size_t GetOffset() const { return m_writtenSize; }
private:
MemMappedFileWriteHelper m_helper;
size_t m_writtenSize = 0;
};
}

View File

@@ -6,7 +6,8 @@
#include "ImageLoaderJpeg.hpp" #include "ImageLoaderJpeg.hpp"
#include "Base/Utils.hpp" #include "Base/Utils.hpp"
#include <Data/Containers/Array.hpp> #include "Base/Logger.hpp"
#include "Data/Containers/Array.hpp"
#include <fstream> #include <fstream>
#include <cstring> #include <cstring>
@@ -21,8 +22,8 @@ namespace OpenVulkano::Image
{ {
std::unique_ptr<Image> ImageLoaderJpeg::loadFromFile(const std::string& filePath) std::unique_ptr<Image> ImageLoaderJpeg::loadFromFile(const std::string& filePath)
{ {
Array<char> buffer = OpenVulkano::Utils::ReadFile(filePath); const auto file = Utils::ReadFile(filePath);
return loadJpeg(reinterpret_cast<uint8_t*>(buffer.Data()), buffer.Size()); return loadJpeg(reinterpret_cast<const uint8_t*>(file.Data()), file.Size());
} }
std::unique_ptr<Image> ImageLoaderJpeg::loadFromMemory(const std::vector<uint8_t>& buffer) std::unique_ptr<Image> ImageLoaderJpeg::loadFromMemory(const std::vector<uint8_t>& buffer)
@@ -36,19 +37,29 @@ namespace OpenVulkano::Image
{ {
Image result; Image result;
int rows, cols; int rows = 0, cols = 0;
unsigned char* compressedImage = const_cast<uint8_t*>(data); unsigned char* compressedImage = const_cast<uint8_t*>(data);
int jpegSubsamp; int jpegSubsamp = 0;
tjhandle jpegDecompressor = tjInitDecompress(); tjhandle jpegDecompressor = tjInitDecompress();
tjDecompressHeader2(jpegDecompressor, compressedImage, size, &cols, &rows, &jpegSubsamp); if (!jpegDecompressor)
{
Logger::FILESYS->error("Failed to read jpeg header. Error: {}", tjGetErrorStr());
return nullptr;
}
int status = tjDecompressHeader2(jpegDecompressor, compressedImage, size, &cols, &rows, &jpegSubsamp);
if (status != 0)
{
Logger::FILESYS->error("Failed to read jpeg header. Error: {}", tjGetErrorStr());
return nullptr;
}
const int channels = 4; const int channels = 4;
result.data = OpenVulkano::Array<uint8_t>(cols * rows * channels); result.data = OpenVulkano::Array<uint8_t>(cols * rows * channels);
result.dataFormat = OpenVulkano::DataFormat::R8G8B8A8_UINT; result.dataFormat = OpenVulkano::DataFormat::B8G8R8A8_UINT;
tjDecompress2(jpegDecompressor, compressedImage, size, result.data.Data(), cols, 0 /*pitch*/, rows, tjDecompress2(jpegDecompressor, compressedImage, size, result.data.Data(), cols, 0 /*pitch*/, rows,
TJPF_RGBA, TJFLAG_FASTDCT); TJPF_BGRA, TJFLAG_FASTDCT);
tjDestroy(jpegDecompressor); tjDestroy(jpegDecompressor);
result.resolution.x = cols; result.resolution.x = cols;
result.resolution.y = rows; result.resolution.y = rows;
@@ -62,4 +73,4 @@ namespace OpenVulkano::Image
} }
#endif #endif
} }
} }

View File

@@ -7,6 +7,7 @@
#pragma once #pragma once
#include "Math.hpp" #include "Math.hpp"
#include <fmt/format.h>
#include <cstdint> #include <cstdint>
#include <type_traits> #include <type_traits>
#include <typeinfo> #include <typeinfo>
@@ -109,9 +110,14 @@ namespace OpenVulkano::Math
data = (data & !(BITMASK << BITS)) | ((z & BITMASK) << BITS); data = (data & !(BITMASK << BITS)) | ((z & BITMASK) << BITS);
} }
[[nodiscard]] std::string ToString(const std::string& separator = ", ") const [[nodiscard]] std::string ToString(const std::string& separator) const
{ {
return std::to_string(X()) + "," + std::to_string(Y()) + "," + std::to_string(Z()); return std::to_string(X()) + separator + std::to_string(Y()) + separator + std::to_string(Z());
}
[[nodiscard]] std::string ToString() const
{
return fmt::format("{},{},{}", X(), Y(), Z());
} }
[[nodiscard]] constexpr operator T() const { return data; } [[nodiscard]] constexpr operator T() const { return data; }

View File

@@ -6,6 +6,7 @@
#pragma once #pragma once
#include "Base/Wrapper.hpp"
#include "Math/Math.hpp" #include "Math/Math.hpp"
#include "Image/Image.hpp" #include "Image/Image.hpp"
#include "Scene/Texture.hpp" #include "Scene/Texture.hpp"
@@ -56,7 +57,7 @@ namespace OpenVulkano::Scene
{ {
std::map<uint32_t, GlyphInfo> glyphs; std::map<uint32_t, GlyphInfo> glyphs;
AtlasMetadata meta; AtlasMetadata meta;
std::unique_ptr<Image::Image> img; Unique<Image::Image> img;
Texture texture; Texture texture;
}; };

View File

@@ -93,7 +93,6 @@ namespace OpenVulkano::Scene
m_atlasData = std::make_shared<AtlasData>(); m_atlasData = std::make_shared<AtlasData>();
if (isPacked) if (isPacked)
{ {
m_atlasData->texture = Texture();
m_material.texture = &m_atlasData->texture; m_material.texture = &m_atlasData->texture;
m_atlasData->img = Image::IImageLoader::loadData((const uint8_t*) atlasMetadata.Data(), m_atlasData->img = Image::IImageLoader::loadData((const uint8_t*) atlasMetadata.Data(),
offsetToMetadata); offsetToMetadata);

View File

@@ -23,7 +23,7 @@ namespace OpenVulkano::Vulkan
if (labelDrawable->IsBillboard()) if (labelDrawable->IsBillboard())
{ {
OpenVulkano::Scene::UniformBuffer* buffer = labelDrawable->GetBillboardBuffer(); OpenVulkano::Scene::UniformBuffer* buffer = labelDrawable->GetBillboardBuffer();
VulkanUniformBuffer* vkBuffer = static_cast<VulkanUniformBuffer*>(buffer->renderBuffer); VulkanUniformBuffer* vkBuffer = buffer->GetRenderResource();
if (!vkBuffer) if (!vkBuffer)
{ {
vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(buffer); vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(buffer);
@@ -32,7 +32,7 @@ namespace OpenVulkano::Vulkan
} }
OpenVulkano::Scene::UniformBuffer* labelBuffer = labelDrawable->GetLabelBuffer(); OpenVulkano::Scene::UniformBuffer* labelBuffer = labelDrawable->GetLabelBuffer();
VulkanUniformBuffer* vkBuffer = static_cast<VulkanUniformBuffer*>(labelBuffer->renderBuffer); VulkanUniformBuffer* vkBuffer = labelBuffer->GetRenderResource();
if (!vkBuffer) if (!vkBuffer)
{ {
vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(labelBuffer); vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(labelBuffer);
@@ -57,7 +57,7 @@ namespace OpenVulkano::Vulkan
OpenVulkano::Scene::Shader* shader = entry.GetShader(); OpenVulkano::Scene::Shader* shader = entry.GetShader();
drawContext->EncodeShader(shader); drawContext->EncodeShader(shader);
Geometry* mesh = entry.GetMesh(); Geometry* mesh = entry.GetMesh();
VulkanGeometry* renderGeo = static_cast<VulkanGeometry*>(mesh->renderGeo); VulkanGeometry* renderGeo = mesh->GetRenderResource();
if (!renderGeo) if (!renderGeo)
{ {
renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh); renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh);
@@ -77,7 +77,7 @@ namespace OpenVulkano::Vulkan
{ {
if (buffer) if (buffer)
{ {
VulkanUniformBuffer* vkBuffer = static_cast<VulkanUniformBuffer*>(buffer->renderBuffer); VulkanUniformBuffer* vkBuffer = buffer->GetRenderResource();
if (!vkBuffer) if (!vkBuffer)
{ {
vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(buffer); vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(buffer);
@@ -90,11 +90,11 @@ namespace OpenVulkano::Vulkan
{ {
if (Texture* texture = material->texture) if (Texture* texture = material->texture)
{ {
VulkanTexture* renderTexture = static_cast<VulkanTexture*>(texture->renderTexture); VulkanTexture* renderTexture = texture->GetRenderResource();
if (!renderTexture) if (!renderTexture)
{ {
drawContext->renderer->GetResourceManager().PrepareMaterial(entry.GetMaterial()); drawContext->renderer->GetResourceManager().PrepareMaterial(entry.GetMaterial());
renderTexture = static_cast<VulkanTexture*>(texture->renderTexture); renderTexture = texture->GetRenderResource();
} }
renderTexture->Record(drawContext); renderTexture->Record(drawContext);
} }

126
tests/MemFileTests.cpp Normal file
View File

@@ -0,0 +1,126 @@
#include <catch2/catch_all.hpp>
#include "IO/MemMappedFile.hpp"
#include "IO/MemMappedFileWriteHelper.hpp"
#include "IO/AppFolders.hpp"
#include "Base/Logger.hpp"
#include <fstream>
#include <filesystem>
namespace fs = std::filesystem;
TEST_CASE("MemMappedFileWrite")
{
OpenVulkano::Logger::SetupLogger("", "tests.log");
auto path = OpenVulkano::AppFolders::GetAppTempDir();
path += "/MemFileTest.txt";
std::string data = "Hello World X\n"
"Hello World Y\n"
"Hello World Z\n"
"Hello World W\n"
"Hello World A\n"
"Hello World B\n"
"Hello World C\n"
"Hello World D\n"
"Hello World E\n"
"Hello World F\n"
"Hello World G\n"
"Hello World H\n"
"Hello World I\n"
"Hello World J\n"
"Hello World K\n"
"Hello World L\n"
"Hello World M\n"
"Hello World N\n";
SECTION("Write to MemMappedFile")
{
OpenVulkano::MemMappedFileWriter writer(path, 1024);
writer.Write(data.data(), data.size());
REQUIRE(writer.GetOffset() == data.size());
}
SECTION("Control Size")
{
OpenVulkano::MemMappedFile memFile(path, OpenVulkano::MemMappedFile::READ_ONLY);
REQUIRE(memFile.Size() == 1024); // The size that comes from the first Test.
}
SECTION("Compare String Data for per char")
{
OpenVulkano::MemMappedFileWriteHelper memFileHelper(path, OpenVulkano::MemMappedFile::READ_ONLY);
REQUIRE(memFileHelper.Trim(data.size()));
std::string testData((char*) memFileHelper.Data());
for (size_t i = 0; i < data.size(); i++)
{
if (data[i] != testData[i])
{
REQUIRE(false);
}
}
memFileHelper.Close();
}
SECTION("Trim File")
{
OpenVulkano::MemMappedFileWriteHelper helper(path,
OpenVulkano::MemMappedFileWriteHelper::USE_CURRENT_FILE_SIZE);
REQUIRE(helper.Trim(100));
REQUIRE(helper.Size() == 100);
helper.Close();
}
SECTION("Write Data 2")
{
OpenVulkano::MemMappedFileWriter writer(path, OpenVulkano::MemMappedFileWriteHelper::USE_CURRENT_FILE_SIZE);
writer.Write(data.data(), data.size());
writer.Write(data.data(), data.size());
writer.Write(data.data(), data.size());
REQUIRE(writer.GetOffset() == data.size() * 3);
}
SECTION("Compare Data")
{
OpenVulkano::MemMappedFileWriteHelper helper(path,
OpenVulkano::MemMappedFileWriteHelper::USE_CURRENT_FILE_SIZE);
REQUIRE(helper.Data() != nullptr);
std::string testData((char*) helper.Data());
printf("size: %llu", helper.Size());
helper.Close();
std::ifstream file(path, std::ios::binary);
std::string streamData;
std::getline(file, streamData, '\0');
file.close();
for (size_t i = 0; i < testData.size(); i++)
{
if (streamData[i] != testData[i])
{
REQUIRE(false);
}
}
REQUIRE(streamData.size() == testData.size());
printf("helper size: %llu\n", helper.Size());
}
SECTION("Actual Size")
{
std::error_code ec;
std::uintmax_t size = fs::file_size(path, ec);
REQUIRE(size == 756);
}
}

190
tests/StableVectorTest.cpp Normal file
View File

@@ -0,0 +1,190 @@
#include <catch2/catch_all.hpp>
#include "Data/Containers/StableVector.hpp"
using namespace OpenVulkano;
struct Test
{
uint32_t mValue;
Test(uint32_t value) : mValue(value) {}
Test() : mValue(0) {}
};
static int incrementCounter = 0;
static int decrementCounter = 0;
struct TestCount
{
TestCount() : m_value("") { ++incrementCounter; }
TestCount(const std::string& val) : m_value(val) { ++incrementCounter; }
TestCount(TestCount&& other) noexcept : m_value(std::move(other.m_value)) { ++incrementCounter; }
TestCount(const TestCount& other) : m_value(other.m_value) { ++incrementCounter; }
TestCount& operator=(const TestCount& other)
{
m_value = other.m_value;
return *this;
}
TestCount& operator=(TestCount&& other) noexcept
{
m_value = std::move(other.m_value);
return *this;
}
~TestCount() { ++decrementCounter; }
std::string m_value;
};
TEST_CASE("ChunkVector")
{
SECTION("PushBack")
{
StableVector<uint32_t> vec;
REQUIRE(vec.Size() == 0);
REQUIRE(vec.Capacity() == 32);
for (uint32_t i = 0; i < 100; ++i)
{
vec.PushBack(i);
}
REQUIRE(vec.Size() == 100);
REQUIRE(vec.Capacity() == 224); // 32 + 64 + 128 = 3 | previous chunk size multiplied by 2
}
SECTION("EmplaceBack")
{
StableVector<Test> vec;
REQUIRE(vec.Size() == 0);
REQUIRE(vec.Capacity() == 32);
for (uint32_t i = 0; i < 100; ++i)
{
vec.EmplaceBack(i);
}
REQUIRE(vec.Size() == 100);
for (uint32_t i = 0; i < 100; ++i)
{
REQUIRE(vec[i].mValue == i);
}
}
SECTION("PopBack")
{
StableVector<uint32_t> vec;
REQUIRE(vec.Size() == 0);
REQUIRE(vec.Capacity() == 32);
for (uint32_t i = 0; i < 100; ++i)
{
vec.PushBack(i);
}
REQUIRE(vec.Size() == 100);
uint64_t tempVal = vec.Capacity();
for (uint32_t i = 0; i < 50; ++i)
{
vec.PopBack();
}
REQUIRE(vec.Size() == 50);
REQUIRE(vec.Capacity() == tempVal);
}
SECTION("Clear")
{
StableVector<uint32_t> vec;
REQUIRE(vec.Size() == 0);
REQUIRE(vec.Capacity() == 32);
for (uint32_t i = 0; i < 100; ++i)
{
vec.PushBack(i);
}
REQUIRE(vec.Size() == 100);
vec.Clear();
REQUIRE(vec.Size() == 0);
REQUIRE(vec.Capacity() == 32);
}
SECTION("Add/Fill")
{
StableVector<std::string> vec;
REQUIRE(vec.Size() == 0);
REQUIRE(vec.Capacity() == 32);
for (uint32_t i = 0; i < 100; ++i)
{
vec.PushBack("a");
}
REQUIRE(vec.Size() == 100);
vec.Remove(56);
vec.Add("z");
REQUIRE(vec.Size() == 100);
REQUIRE(vec[56] == "z");
}
SECTION("Correct Initialization")
{
StableVector<TestCount> vec;
REQUIRE(incrementCounter == 0);
REQUIRE(decrementCounter == 0);
vec.EmplaceBack("a");
REQUIRE(incrementCounter == 1);
REQUIRE(decrementCounter == 0);
vec.PushBack(TestCount("b"));
REQUIRE(incrementCounter == 3);
REQUIRE(decrementCounter == 1);
TestCount testClass = TestCount("c");
vec.PushBack(std::move(testClass));
REQUIRE(incrementCounter == 5);
REQUIRE(decrementCounter == 1);
vec.Clear();
REQUIRE(incrementCounter == 5);
REQUIRE(decrementCounter == 4);
vec.PushBack(TestCount("d"));
REQUIRE(incrementCounter == 7);
REQUIRE(decrementCounter == 5);
TestCount testClass2 = TestCount("e");
vec.PushBack(testClass2);
REQUIRE(incrementCounter == 9);
REQUIRE(decrementCounter == 5);
}
SECTION("Out of scope check")
{
REQUIRE(incrementCounter == 9);
REQUIRE(decrementCounter == 9);
}
}