Adding nlohmanns json library

This commit is contained in:
Dynamitos
2020-05-05 01:52:07 +02:00
parent 3ef8342247
commit bb5b48698a
83 changed files with 2426 additions and 646 deletions
+3
View File
@@ -10,3 +10,6 @@
[submodule "external/slang"] [submodule "external/slang"]
path = external/slang path = external/slang
url = https://github.com/shader-slang/slang.git url = https://github.com/shader-slang/slang.git
[submodule "external/json"]
path = external/json
url = https://github.com/nlohmann/json.git
+7 -1
View File
@@ -14,6 +14,12 @@
"type_traits": "cpp", "type_traits": "cpp",
"vector": "cpp", "vector": "cpp",
"*.rh": "cpp", "*.rh": "cpp",
"memory": "cpp" "memory": "cpp",
"*.ipp": "cpp",
"iostream": "cpp",
"initializer_list": "cpp"
}, },
"C_Cpp.default.browse.limitSymbolsToIncludedHeaders": false,
"C_Cpp.default.intelliSenseMode": "msvc-x64",
"C_Cpp.errorSquiggles": "Disabled",
} }
+8 -4
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.15)
set(CMAKE_CXX_STANDARD_REQUIRED 17) set(CMAKE_CXX_STANDARD_REQUIRED 20)
# Handle superbuild first # Handle superbuild first
option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON) option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON)
@@ -11,6 +11,7 @@ set(SLANG_ROOT ${EXTERNAL_ROOT}/slang)
set(BOOST_ROOT ${EXTERNAL_ROOT}/boost) set(BOOST_ROOT ${EXTERNAL_ROOT}/boost)
set(GLM_ROOT ${EXTERNAL_ROOT}/glm) set(GLM_ROOT ${EXTERNAL_ROOT}/glm)
set(GLFW_ROOT ${EXTERNAL_ROOT}/glfw) set(GLFW_ROOT ${EXTERNAL_ROOT}/glfw)
set(JSON_ROOT ${EXTERNAL_ROOT}/json)
set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}) set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE})
set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
@@ -34,9 +35,11 @@ else()
project (Seele) project (Seele)
endif() endif()
add_subdirectory(${GLFW_ROOT})
find_package(Vulkan REQUIRED) find_package(Vulkan REQUIRED)
find_package(Boost REQUIRED COMPONENTS serialization) find_package(Boost REQUIRED COMPONENTS serialization)
find_package(Threads)
include(${JSON_IMPORT})
include(${GLFW_IMPORT})
include_directories(${GLFW_ROOT}/include) include_directories(${GLFW_ROOT}/include)
include_directories(${GLM_INCLUDE_DIRS}) include_directories(${GLM_INCLUDE_DIRS})
@@ -52,11 +55,12 @@ if(WIN32)
add_compile_definitions(USE_EXTENSIONS) add_compile_definitions(USE_EXTENSIONS)
endif() endif()
add_executable(SeeleEngine "") add_executable(SeeleEngine "")
add_subdirectory(src/) target_link_libraries(SeeleEngine glfw)
target_link_libraries(SeeleEngine nlohmann_json::nlohmann_json)
target_link_libraries(SeeleEngine ${Boost_LIBRARIES}) target_link_libraries(SeeleEngine ${Boost_LIBRARIES})
target_link_libraries(SeeleEngine ${Vulkan_LIBRARY}) target_link_libraries(SeeleEngine ${Vulkan_LIBRARY})
target_link_libraries(SeeleEngine glfw ${GLFW_LIBRARIES})
target_link_libraries(SeeleEngine ${SLANG_LIBRARY}) target_link_libraries(SeeleEngine ${SLANG_LIBRARY})
add_subdirectory(src/)
if(MSVC) if(MSVC)
target_compile_options(SeeleEngine PRIVATE /DEBUG:FASTLINK /Zi /W4) target_compile_options(SeeleEngine PRIVATE /DEBUG:FASTLINK /Zi /W4)
+1 -1
View File
@@ -7,7 +7,7 @@
"inheritEnvironments": [ "msvc_x64_x64" ], "inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\bin\\${name}", "buildRoot": "${projectDir}\\bin\\${name}",
"installRoot": "${projectDir}\\install\\${name}", "installRoot": "${projectDir}\\install\\${name}",
"cmakeCommandArgs": "", "cmakeCommandArgs": "-DUSE_SUPERBUILD=TRUE",
"buildCommandArgs": "-v", "buildCommandArgs": "-v",
"ctestCommandArgs": "", "ctestCommandArgs": "",
"variables": [] "variables": []
+30 -17
View File
@@ -18,7 +18,7 @@ ExternalProject_Add(boost
SOURCE_DIR ${BOOST_ROOT} SOURCE_DIR ${BOOST_ROOT}
UPDATE_COMMAND "" UPDATE_COMMAND ""
CONFIGURE_COMMAND ./bootstrap.${BOOTSTRAP_EXTENSION} --with-libraries=serialization,test CONFIGURE_COMMAND ./bootstrap.${BOOTSTRAP_EXTENSION} --with-libraries=serialization,test
BUILD_COMMAND ./b2 link=static BUILD_COMMAND ./b2 link=static -d0
BUILD_IN_SOURCE 1 BUILD_IN_SOURCE 1
INSTALL_COMMAND "") INSTALL_COMMAND "")
@@ -37,23 +37,36 @@ list(APPEND EXTRA_CMAKE_ARGS
-DGLM_INCLUDE_DIRS=${GLM_ROOT} -DGLM_INCLUDE_DIRS=${GLM_ROOT}
) )
#--------------------JSON------------------
#list(APPEND DEPENDENCIES nlohmann_json)
set(JSON_MultipleHeaders ON CACHE INTERNAL "")
set(JSON_BuildTests OFF CACHE INTERNAL "")
set(JSON_Install OFF CACHE INTERNAL "")
add_subdirectory(${JSON_ROOT})
export(TARGETS nlohmann_json
NAMESPACE nlohmann_json::
FILE ${nlohmann_json_BINARY_DIR}/json_target.cmake)
list(APPEND EXTRA_CMAKE_ARGS
-DJSON_IMPORT=${nlohmann_json_BINARY_DIR}/json_target.cmake
)
#--------------GLFW------------------------------ #--------------GLFW------------------------------
#list(APPEND DEPENDENCIES glfw) list(APPEND DEPENDENCIES glfw)
#set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
#set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
#set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
#
#ExternalProject_Add(glfw add_subdirectory(${GLFW_ROOT})
# SOURCE_DIR ${GLFW_ROOT} export(TARGETS glfw
# BINARY_DIR ${CMAKE_BINARY_DIR}/lib FILE ${GLFW_BINARY_DIR}/glfw.cmake)
# INSTALL_COMMAND "")
# list(APPEND EXTRA_CMAKE_ARGS
#list(APPEND EXTRA_CMAKE_ARGS -DGLFW_IMPORT=${GLFW_BINARY_DIR}/glfw.cmake
# -DGLFW_INCLUDE_DIRS=${GLFW_ROOT}/include )
# -DGLFW_LIBRARY=${CMAKE_BINARY_DIR}/lib/src/glfw3.lib
# )
#
#--------------SLang------------------------------ #--------------SLang------------------------------
list(APPEND DEPENDENCIES slang) list(APPEND DEPENDENCIES slang)
string(TOLOWER ${CMAKE_BUILD_TYPE}_${CMAKE_PLATFORM} SLANG_CONFIG) string(TOLOWER ${CMAKE_BUILD_TYPE}_${CMAKE_PLATFORM} SLANG_CONFIG)
@@ -83,7 +96,7 @@ endif()
list(APPEND EXTRA_CMAKE_ARGS list(APPEND EXTRA_CMAKE_ARGS
-DSLANG_INCLUDE_DIRS=${EXTERNAL_ROOT} -DSLANG_INCLUDE_DIRS=${EXTERNAL_ROOT}/slang
-DSLANG_LIBRARY=${SLANG_LIB_PATH}) -DSLANG_LIBRARY=${SLANG_LIB_PATH})
list(APPEND DEPENDENT_BINARIES ${SLANG_ROOT}/${SLANG_BINARY}) list(APPEND DEPENDENT_BINARIES ${SLANG_ROOT}/${SLANG_BINARY})
Vendored Submodule
+1
Submodule external/json added at 634fa87e5a
+11
View File
@@ -0,0 +1,11 @@
#include "Asset.h"
using namespace Seele;
Asset::Asset()
{
}
Asset::~Asset()
{
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include "MinimalEngine.h"
namespace Seele
{
class Asset
{
public:
Asset();
virtual ~Asset();
private:
};
DEFINE_REF(Asset);
} // namespace Seele
+6
View File
@@ -0,0 +1,6 @@
target_sources(SeeleEngine
PRIVATE
Asset.h
Asset.cpp
FileAsset.h
FileAsset.cpp)
+62
View File
@@ -0,0 +1,62 @@
#include "FileAsset.h"
using namespace Seele;
FileAsset::FileAsset()
: path("")
, name("")
{
}
FileAsset::FileAsset(const std::string &fullPath)
: path(fullPath)
{
name = fullPath.substr(fullPath.find_last_of('\\')+1);
}
FileAsset::FileAsset(const std::string &directory, const std::string &name)
: path(directory+name)
, name(name)
{
}
FileAsset::~FileAsset()
{
}
std::ifstream &FileAsset::getReadStream()
{
if(inStream.is_open())
{
return inStream;
}
inStream.open(path);
return inStream;
}
std::ofstream &FileAsset::getWriteStream()
{
if(outStream.is_open())
{
return outStream;
}
outStream.open(path);
return outStream;
}
void FileAsset::rename(const std::string& newName)
{
if(inStream.is_open())
{
inStream.close();
}
if(outStream.is_open())
{
outStream.flush();
outStream.close();
}
path.replace(path.find_last_of(name), name.size(), newName);
name = newName;
inStream.open(path);
outStream.open(path);
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "Asset.h"
#include <fstream>
namespace Seele
{
class FileAsset
{
public:
FileAsset();
FileAsset(const std::string& directory, const std::string& name);
FileAsset(const std::string& fullPath);
virtual ~FileAsset();
std::ifstream& getReadStream();
std::ofstream& getWriteStream();
void rename(const std::string& newName);
private:
std::string name;
std::string path;
uint32 byteSize;
std::ifstream inStream;
std::ofstream outStream;
};
}
+5 -2
View File
@@ -4,6 +4,9 @@ target_sources(SeeleEngine
MinimalEngine.cpp MinimalEngine.cpp
main.cpp) main.cpp)
add_subdirectory(Graphics/) add_subdirectory(Asset/)
add_subdirectory(Math/)
add_subdirectory(Containers/) add_subdirectory(Containers/)
add_subdirectory(Graphics/)
add_subdirectory(Material/)
add_subdirectory(Math/)
add_subdirectory(Scene/)
+5 -1
View File
@@ -372,7 +372,11 @@ public:
{ {
return N; return N;
} }
inline T *data() const inline T *data()
{
return _data;
}
inline const T* data() const
{ {
return _data; return _data;
} }
+9 -9
View File
@@ -2,13 +2,13 @@
namespace Seele namespace Seele
{ {
typedef uint64_t uint64; typedef uint64_t uint64;
typedef uint32_t uint32; typedef uint32_t uint32;
typedef uint16_t uint16; typedef uint16_t uint16;
typedef uint8_t uint8; typedef uint8_t uint8;
typedef int64_t int64; typedef int64_t int64;
typedef int32_t int32; typedef int32_t int32;
typedef int16_t int16; typedef int16_t int16;
typedef int8_t int8; typedef int8_t int8;
} } // namespace Seele
+1
View File
@@ -4,6 +4,7 @@ target_sources(SeeleEngine
ForwardPlusRenderPath.cpp ForwardPlusRenderPath.cpp
GraphicsResources.h GraphicsResources.h
GraphicsResources.cpp GraphicsResources.cpp
GraphicsInitializer.h
GraphicsEnums.h GraphicsEnums.h
Graphics.h Graphics.h
Graphics.cpp Graphics.cpp
+21 -2
View File
@@ -1,15 +1,21 @@
#include "ForwardPlusRenderPath.h" #include "ForwardPlusRenderPath.h"
#include "Scene/Scene.h"
#include "Material/MaterialInstance.h"
#include "Material/Material.h"
#include "GraphicsResources.h"
using namespace Seele; using namespace Seele;
Seele::ForwardPlusRenderPath::ForwardPlusRenderPath(Gfx::PGraphics graphics, Gfx::PViewport viewport) Seele::ForwardPlusRenderPath::ForwardPlusRenderPath(Gfx::PGraphics graphics, Gfx::PViewport viewport)
: SceneRenderPath(graphics, viewport) : SceneRenderPath(graphics, viewport)
{ {
PMaterial material = new Material("D:\\Private\\Programming\\C++\\Seele\\test.mat");
material->compile();
} }
Seele::ForwardPlusRenderPath::~ForwardPlusRenderPath() Seele::ForwardPlusRenderPath::~ForwardPlusRenderPath()
{} {
}
void Seele::ForwardPlusRenderPath::beginFrame() void Seele::ForwardPlusRenderPath::beginFrame()
{ {
@@ -17,6 +23,19 @@ void Seele::ForwardPlusRenderPath::beginFrame()
void Seele::ForwardPlusRenderPath::render() void Seele::ForwardPlusRenderPath::render()
{ {
for (auto entry : scene->getMeshBatches())
{
PMaterial material = entry.key;
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
renderCommand->bindPipeline(material->getPipeline());
for (auto drawState : entry.value.instances)
{
renderCommand->bindVertexBuffer(drawState.vertexBuffer);
renderCommand->bindIndexBuffer(drawState.indexBuffer);
renderCommand->bindDescriptor(drawState.instance->getDescriptor());
renderCommand->draw(drawState);
}
}
} }
void Seele::ForwardPlusRenderPath::endFrame() void Seele::ForwardPlusRenderPath::endFrame()
+2 -1
View File
@@ -11,6 +11,7 @@ public:
virtual void beginFrame() override; virtual void beginFrame() override;
virtual void render() override; virtual void render() override;
virtual void endFrame() override; virtual void endFrame() override;
private: private:
}; };
} } // namespace Seele
+6 -3
View File
@@ -20,12 +20,15 @@ public:
virtual void beginRenderPass(PRenderPass renderPass) = 0; virtual void beginRenderPass(PRenderPass renderPass) = 0;
virtual void endRenderPass() = 0; virtual void endRenderPass() = 0;
virtual void executeCommands(Array<PRenderCommand> commands) = 0;
virtual PTexture2D createTexture2D(const TextureCreateInfo &createInfo) = 0; virtual PTexture2D createTexture2D(const TextureCreateInfo &createInfo) = 0;
virtual PUniformBuffer createUniformBuffer(const BulkResourceData &bulkData) = 0; virtual PUniformBuffer createUniformBuffer(const BulkResourceData &bulkData) = 0;
virtual PStructuredBuffer createStructuredBuffer(const BulkResourceData &bulkData) = 0; virtual PStructuredBuffer createStructuredBuffer(const BulkResourceData &bulkData) = 0;
virtual PVertexBuffer createVertexBuffer(const BulkResourceData &bulkData) = 0; virtual PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) = 0;
virtual PIndexBuffer createIndexBuffer(const BulkResourceData &bulkData) = 0; virtual PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) = 0;
virtual PRenderCommand createRenderCommand() = 0;
virtual PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) = 0;
protected: protected:
friend class Window; friend class Window;
}; };
+7
View File
@@ -1846,5 +1846,12 @@ typedef enum SeStencilFaceFlagBits
SE_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF SE_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} SeStencilFaceFlagBits; } SeStencilFaceFlagBits;
typedef SeFlags SeStencilFaceFlags; typedef SeFlags SeStencilFaceFlags;
enum class QueueType
{
GRAPHICS = 1,
COMPUTE = 2,
TRANSFER = 3,
DEDICATED_TRANSFER = 4
};
} // namespace Gfx } // namespace Gfx
} // namespace Seele } // namespace Seele
+188
View File
@@ -0,0 +1,188 @@
#include "GraphicsEnums.h"
namespace Seele
{
struct GraphicsInitializer
{
const char *windowLayoutFile;
const char *applicationName;
const char *engineName;
void *windowHandle;
/**
* layers defines the enabled Vulkan layers used in the instance,
* if ENABLE_VALIDATION is defined, standard validation is already enabled
* not yet implemented
*/
Array<const char *> layers;
Array<const char *> instanceExtensions;
Array<const char *> deviceExtensions;
GraphicsInitializer()
: applicationName("SeeleEngine"), engineName("SeeleEngine"), layers{"VK_LAYER_LUNARG_standard_validation"}, instanceExtensions{}, deviceExtensions{"VK_KHR_swapchain"}, windowHandle(nullptr)
{
}
GraphicsInitializer(const GraphicsInitializer &other)
: applicationName(other.applicationName), engineName(other.engineName), layers(other.layers), instanceExtensions(other.instanceExtensions), deviceExtensions(other.deviceExtensions)
{
}
};
struct WindowCreateInfo
{
int32 width;
int32 height;
const char *title;
bool bFullscreen;
Gfx::SeFormat pixelFormat;
void *windowHandle;
};
struct ViewportCreateInfo
{
uint32 sizeX;
uint32 sizeY;
uint32 offsetX;
uint32 offsetY;
};
struct TextureCreateInfo
{
uint32 width;
uint32 height;
uint32 depth;
bool bArray;
uint32 arrayLayers;
uint32 mipLevels;
uint32 samples;
Gfx::SeFormat format;
Gfx::SeImageUsageFlagBits usage;
Gfx::QueueType queueType;
TextureCreateInfo()
: width(1), height(1), depth(1), bArray(false), arrayLayers(1), mipLevels(1), samples(1), format(Gfx::SE_FORMAT_R32G32B32A32_SFLOAT), queueType(Gfx::QueueType::GRAPHICS), usage(Gfx::SE_IMAGE_USAGE_SAMPLED_BIT)
{
}
};
// doesnt own the data, only proxy it
struct BulkResourceData
{
uint32 size;
uint8 *data;
Gfx::QueueType owner;
BulkResourceData()
: size(0), data(nullptr), owner(Gfx::QueueType::GRAPHICS)
{
}
};
struct VertexBufferCreateInfo
{
BulkResourceData resourceData;
// bytes per vertex
uint32 vertexSize;
uint32 numVertices;
VertexBufferCreateInfo()
: resourceData(), vertexSize(0), numVertices(0)
{
}
};
struct IndexBufferCreateInfo
{
BulkResourceData resourceData;
Gfx::SeIndexType indexType;
IndexBufferCreateInfo()
: resourceData(), indexType(Gfx::SeIndexType::SE_INDEX_TYPE_UINT16)
{
}
};
namespace Gfx
{
struct SePushConstantRange
{
SeShaderStageFlags stageFlags;
uint32_t offset;
uint32_t size;
};
struct VertexElement
{
uint32 location;
SeFormat vertexFormat;
uint32 offset;
};
struct RasterizationState
{
uint8 depthClampEnable : 1;
uint8 rasterizerDiscardEnable : 1;
uint8 depthBiasEnable : 1;
float depthBoasConstantFactor;
float depthBiasClamp;
float depthBiasSlopeFactor;
float lineWidth;
SePolygonMode polygonMode;
SeCullModeFlags cullMode;
SeFrontFace frontFace;
};
struct MultisampleState
{
uint32 samples;
float minSampleShading;
uint8 sampleShadingEnable : 1;
uint8 alphaCoverageEnable;
uint8 alphaToOneEnable;
};
struct DepthStencilState
{
uint8 depthTestEnable : 1;
uint8 depthWriteEnable : 1;
uint8 depthBoundsTestEnable : 1;
uint8 stencilTestEnable : 1;
SeCompareOp depthCompareOp;
SeStencilOp front;
SeStencilOp back;
float minDepthBounds;
float maxDepthBounds;
};
struct ColorBlendState
{
uint8 logicOpEnable : 1;
SeLogicOp logicOp;
uint32 attachmentCount;
struct BlendAttachment
{
uint8 blendEnable;
SeBlendFactor srcColorBlendFactor;
SeBlendFactor dstColorBlendFactor;
SeBlendOp colorBlendOp;
SeBlendFactor srcAlphaBlendFactor;
SeBlendFactor dstAlphaBlendFactor;
SeBlendOp alphaBlendOp;
SeColorComponentFlags colorWriteMask;
} blendAttachments[16];
float blendConstants[4];
};
} // namespace Gfx
DECLARE_NAME_REF(Gfx, VertexDeclaration);
DECLARE_NAME_REF(Gfx, VertexShader);
DECLARE_NAME_REF(Gfx, ControlShader);
DECLARE_NAME_REF(Gfx, EvaluationShader);
DECLARE_NAME_REF(Gfx, GeometryShader);
DECLARE_NAME_REF(Gfx, FragmentShader);
DECLARE_NAME_REF(Gfx, PipelineLayout);
DECLARE_NAME_REF(Gfx, RenderPass);
struct GraphicsPipelineCreateInfo
{
Gfx::PVertexDeclaration vertexDeclaration;
Gfx::PVertexShader vertexShader;
Gfx::PControlShader controlShader;
Gfx::PEvaluationShader evalShader;
Gfx::PGeometryShader geometryShader;
Gfx::PFragmentShader fragmentShader;
Gfx::PPipelineLayout pipelineLayout;
Gfx::PRenderPass renderPass;
Gfx::SePrimitiveTopology topology;
Gfx::RasterizationState rasterizationState;
Gfx::DepthStencilState depthStencilState;
Gfx::MultisampleState multisampleState;
Gfx::ColorBlendState colorBlend;
GraphicsPipelineCreateInfo()
{
std::memset(this, 0, sizeof(*this));
}
};
} // namespace Seele
+63
View File
@@ -1,4 +1,5 @@
#include "GraphicsResources.h" #include "GraphicsResources.h"
#include "Material/MaterialInstance.h"
using namespace Seele; using namespace Seele;
using namespace Seele::Gfx; using namespace Seele::Gfx;
@@ -46,6 +47,7 @@ void PipelineLayout::addDescriptorLayout(uint32 setIndex, PDescriptorLayout layo
else else
{ {
descriptorSetLayouts[setIndex] = layout; descriptorSetLayouts[setIndex] = layout;
layout->setIndex = setIndex;
} }
} }
@@ -61,6 +63,67 @@ UniformBuffer::UniformBuffer()
UniformBuffer::~UniformBuffer() UniformBuffer::~UniformBuffer()
{ {
} }
VertexBuffer::VertexBuffer(uint32 numVertices, uint32 vertexSize)
: numVertices(numVertices), vertexSize(vertexSize)
{
}
VertexBuffer::~VertexBuffer()
{
}
IndexBuffer::IndexBuffer(uint32 size, Gfx::SeIndexType indexType)
: indexType(indexType)
{
switch (indexType)
{
case SE_INDEX_TYPE_UINT16:
numIndices = size / 16;
break;
case SE_INDEX_TYPE_UINT32:
numIndices = size / 32;
default:
break;
}
}
IndexBuffer::~IndexBuffer()
{
}
VertexStream::VertexStream(PVertexBuffer buffer, uint8 instanced)
: buffer(buffer)
, instanced(instanced)
{
}
VertexStream::~VertexStream()
{
}
void VertexStream::addVertexElement(VertexElement element)
{
vertexDescription.add(element);
}
const Array<VertexElement> VertexStream::getVertexDescriptions() const
{
return vertexDescription;
}
Gfx::PVertexBuffer VertexStream::getVertexBuffer()
{
return buffer;
}
VertexDeclaration::VertexDeclaration()
{
}
VertexDeclaration::~VertexDeclaration()
{
}
uint32 VertexDeclaration::addVertexStream(const VertexStream &element)
{
uint32 currIndex = vertexStreams.size();
vertexStreams.add(element);
return currIndex;
}
const Array<VertexStream> &VertexDeclaration::getVertexStreams() const
{
return vertexStreams;
}
RenderTargetLayout::RenderTargetLayout() RenderTargetLayout::RenderTargetLayout()
: inputAttachments(), colorAttachments(), depthAttachment() : inputAttachments(), colorAttachments(), depthAttachment()
+162 -105
View File
@@ -1,7 +1,10 @@
#pragma once #pragma once
#include "GraphicsEnums.h" #include "GraphicsEnums.h"
#include "Containers/Array.h" #include "Containers/Array.h"
#include "Containers/List.h"
#include "Math/MemCRC.h" #include "Math/MemCRC.h"
#include "Material/MaterialInstance.h"
#include "GraphicsInitializer.h"
#ifdef _DEBUG #ifdef _DEBUG
#define ENABLE_VALIDATION #define ENABLE_VALIDATION
@@ -9,97 +12,35 @@
namespace Seele namespace Seele
{ {
namespace Gfx
DECLARE_NAME_REF(Gfx, VertexBuffer);
DECLARE_NAME_REF(Gfx, IndexBuffer);
struct DrawInstance
{ {
enum class QueueType Matrix4 modelMatrix;
{ PMaterialInstance instance;
GRAPHICS = 1, Gfx::PIndexBuffer indexBuffer;
COMPUTE = 2, Gfx::PVertexBuffer vertexBuffer;
TRANSFER = 3,
DEDICATED_TRANSFER = 4 uint32 numInstances;
}; uint32 baseVertexIndex;
} // namespace Gfx uint32 minVertexIndex;
struct GraphicsInitializer uint32 firstInstance;
{ DrawInstance()
const char *windowLayoutFile; : instance(nullptr), indexBuffer(nullptr), vertexBuffer(nullptr), modelMatrix(1), numInstances(1), baseVertexIndex(0), minVertexIndex(0), firstInstance(0)
const char *applicationName;
const char *engineName;
void *windowHandle;
/**
* layers defines the enabled Vulkan layers used in the instance,
* if ENABLE_VALIDATION is defined, standard validation is already enabled
* not yet implemented
*/
Array<const char *> layers;
Array<const char *> instanceExtensions;
Array<const char *> deviceExtensions;
GraphicsInitializer()
: applicationName("SeeleEngine"), engineName("SeeleEngine"), layers{"VK_LAYER_LUNARG_standard_validation"}, instanceExtensions{}, deviceExtensions{"VK_KHR_swapchain"}, windowHandle(nullptr)
{
}
GraphicsInitializer(const GraphicsInitializer &other)
: applicationName(other.applicationName), engineName(other.engineName), layers(other.layers), instanceExtensions(other.instanceExtensions), deviceExtensions(other.deviceExtensions)
{ {
} }
}; };
struct WindowCreateInfo struct DrawState
{ {
int32 width; Array<DrawInstance> instances;
int32 height;
const char *title; DrawState()
bool bFullscreen;
Gfx::SeFormat pixelFormat;
void *windowHandle;
};
struct ViewportCreateInfo
{
uint32 sizeX;
uint32 sizeY;
uint32 offsetX;
uint32 offsetY;
bool bFullscreen;
bool bVsync;
};
struct TextureCreateInfo
{
uint32 width;
uint32 height;
uint32 depth;
bool bArray;
uint32 arrayLayers;
uint32 mipLevels;
uint32 samples;
Gfx::SeFormat format;
Gfx::SeImageUsageFlagBits usage;
Gfx::QueueType queueType;
TextureCreateInfo()
: width(1), height(1), depth(1), bArray(false), arrayLayers(1), mipLevels(1), samples(1), format(Gfx::SE_FORMAT_R32G32B32A32_SFLOAT), usage(Gfx::SE_IMAGE_USAGE_SAMPLED_BIT)
{ {
} }
}; };
//doesnt own the data, only proxy it
struct BulkResourceData
{
uint32 size;
uint8 *data;
Gfx::QueueType owner;
};
namespace Gfx namespace Gfx
{ {
struct SePushConstantRange
{
SeShaderStageFlags stageFlags;
uint32_t offset;
uint32_t size;
};
class RenderCommandBase
{
public:
virtual ~RenderCommandBase()
{
}
};
DEFINE_REF(RenderCommandBase);
class SamplerState class SamplerState
{ {
public: public:
@@ -108,6 +49,54 @@ public:
} }
}; };
DEFINE_REF(SamplerState); DEFINE_REF(SamplerState);
class VertexShader
{
public:
VertexShader() {}
virtual ~VertexShader() {}
};
DEFINE_REF(VertexShader);
class ControlShader
{
public:
ControlShader() {}
virtual ~ControlShader() {}
uint32 getNumPatches() const { return numPatchPoints; }
protected:
uint32 numPatchPoints;
};
DEFINE_REF(ControlShader);
class EvaluationShader
{
public:
EvaluationShader() {}
virtual ~EvaluationShader() {}
};
DEFINE_REF(EvaluationShader);
class GeometryShader
{
public:
GeometryShader() {}
virtual ~GeometryShader() {}
};
DEFINE_REF(GeometryShader);
class FragmentShader
{
public:
FragmentShader() {}
virtual ~FragmentShader() {}
};
DEFINE_REF(FragmentShader);
class ComputeShader
{
public:
ComputeShader() {}
virtual ~ComputeShader() {}
};
DEFINE_REF(ComputeShader);
class DescriptorBinding class DescriptorBinding
{ {
public: public:
@@ -155,13 +144,18 @@ public:
virtual void updateSampler(uint32 binding, PSamplerState samplerState) = 0; virtual void updateSampler(uint32 binding, PSamplerState samplerState) = 0;
virtual void updateTexture(uint32 binding, PTexture texture, PSamplerState samplerState = nullptr) = 0; virtual void updateTexture(uint32 binding, PTexture texture, PSamplerState samplerState = nullptr) = 0;
virtual bool operator<(PDescriptorSet other) = 0; virtual bool operator<(PDescriptorSet other) = 0;
virtual uint32 getSetIndex() const = 0;
}; };
DEFINE_REF(DescriptorSet); DEFINE_REF(DescriptorSet);
class DescriptorLayout class DescriptorLayout
{ {
public: public:
DescriptorLayout() {} DescriptorLayout()
: setIndex(0)
{
}
virtual ~DescriptorLayout() {} virtual ~DescriptorLayout() {}
void operator=(const DescriptorLayout &other) void operator=(const DescriptorLayout &other)
{ {
@@ -172,10 +166,12 @@ public:
virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1); virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1);
virtual PDescriptorSet allocatedDescriptorSet(); virtual PDescriptorSet allocatedDescriptorSet();
const Array<DescriptorBinding> &getBindings() const { return descriptorBindings; } const Array<DescriptorBinding> &getBindings() const { return descriptorBindings; }
inline uint32 getSetIndex() const { return setIndex; }
protected: protected:
Array<DescriptorBinding> descriptorBindings; Array<DescriptorBinding> descriptorBindings;
PDescriptorAllocator allocator; PDescriptorAllocator allocator;
uint32 setIndex;
friend class PipelineLayout; friend class PipelineLayout;
friend class DescriptorAllocator; friend class DescriptorAllocator;
}; };
@@ -195,22 +191,6 @@ protected:
Array<SePushConstantRange> pushConstants; Array<SePushConstantRange> pushConstants;
}; };
DEFINE_REF(PipelineLayout); DEFINE_REF(PipelineLayout);
class VertexDeclaration
{
public:
virtual ~VertexDeclaration()
{
}
};
DEFINE_REF(VertexDeclaration);
class GraphicsPipeline
{
public:
virtual ~GraphicsPipeline()
{
}
};
DEFINE_REF(GraphicsPipeline);
class UniformBuffer class UniformBuffer
{ {
public: public:
@@ -221,17 +201,40 @@ DEFINE_REF(UniformBuffer);
class VertexBuffer class VertexBuffer
{ {
public: public:
virtual ~VertexBuffer() VertexBuffer(uint32 numVertices, uint32 vertexSize);
virtual ~VertexBuffer();
inline uint32 getNumVertices()
{ {
return numVertices;
} }
// Size of one vertex in bytes
inline uint32 getVertexSize()
{
return vertexSize;
}
protected:
uint32 numVertices;
uint32 vertexSize;
}; };
DEFINE_REF(VertexBuffer); DEFINE_REF(VertexBuffer);
class IndexBuffer class IndexBuffer
{ {
public: public:
virtual ~IndexBuffer() IndexBuffer(uint32 size, Gfx::SeIndexType index);
virtual ~IndexBuffer();
inline uint32 getNumIndices() const
{ {
return numIndices;
} }
inline Gfx::SeIndexType getIndexType() const
{
return indexType;
}
protected:
Gfx::SeIndexType indexType;
uint32 numIndices;
}; };
DEFINE_REF(IndexBuffer); DEFINE_REF(IndexBuffer);
class StructuredBuffer class StructuredBuffer
@@ -242,6 +245,44 @@ public:
} }
}; };
DEFINE_REF(StructuredBuffer); DEFINE_REF(StructuredBuffer);
class VertexStream
{
public:
VertexStream() {}
VertexStream(PVertexBuffer buffer, uint8 instanced);
~VertexStream();
void addVertexElement(VertexElement element);
const Array<VertexElement> getVertexDescriptions() const;
PVertexBuffer getVertexBuffer();
inline uint8 isInstanced() const { return instanced; }
private:
PVertexBuffer buffer;
Array<VertexElement> vertexDescription;
uint8 instanced;
};
class VertexDeclaration
{
public:
VertexDeclaration();
~VertexDeclaration();
uint32 addVertexStream(const VertexStream &vertexStream);
const Array<VertexStream> &getVertexStreams() const;
private:
Array<VertexStream> vertexStreams;
};
DEFINE_REF(VertexDeclaration);
class GraphicsPipeline
{
public:
GraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) : createInfo(createInfo) {}
virtual ~GraphicsPipeline(){}
const GraphicsPipelineCreateInfo& getCreateInfo() const {return createInfo;}
protected:
GraphicsPipelineCreateInfo createInfo;
};
DEFINE_REF(GraphicsPipeline);
class Texture class Texture
{ {
public: public:
@@ -259,6 +300,20 @@ public:
}; };
DEFINE_REF(Texture2D); DEFINE_REF(Texture2D);
class RenderCommand
{
public:
virtual ~RenderCommand()
{
}
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) = 0;
virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0;
virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) = 0;
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0;
virtual void draw(DrawInstance data) = 0;
};
DEFINE_REF(RenderCommand);
class Window class Window
{ {
public: public:
@@ -285,6 +340,7 @@ public:
virtual ~Viewport(); virtual ~Viewport();
virtual void resize(uint32 newX, uint32 newY) = 0; virtual void resize(uint32 newX, uint32 newY) = 0;
virtual void move(uint32 newOffsetX, uint32 newOffsetY) = 0; virtual void move(uint32 newOffsetX, uint32 newOffsetY) = 0;
protected: protected:
uint32 sizeX; uint32 sizeX;
uint32 sizeY; uint32 sizeY;
@@ -364,12 +420,13 @@ DEFINE_REF(RenderTargetLayout);
class RenderPass class RenderPass
{ {
public: public:
virtual ~RenderPass() RenderPass(PRenderTargetLayout layout) : layout(layout) {}
{ virtual ~RenderPass() {}
} inline PRenderTargetLayout getLayout() const { return layout; }
};
DEFINE_REF(RenderPass);
protected:
PRenderTargetLayout layout;
};
DEFINE_REF(RenderPass); DEFINE_REF(RenderPass);
} // namespace Gfx } // namespace Gfx
} // namespace Seele } // namespace Seele
+2 -1
View File
@@ -8,8 +8,9 @@ class Mesh
public: public:
Mesh(Gfx::PVertexBuffer vertexBuffer, Gfx::PIndexBuffer indexBuffer); Mesh(Gfx::PVertexBuffer vertexBuffer, Gfx::PIndexBuffer indexBuffer);
~Mesh(); ~Mesh();
private: private:
Gfx::VertexBuffer vertexBuffer; Gfx::VertexBuffer vertexBuffer;
Gfx::IndexBuffer indexBuffer; Gfx::IndexBuffer indexBuffer;
}; };
} } // namespace Seele
+8 -1
View File
@@ -1,4 +1,5 @@
#include "RenderCore.h" #include "RenderCore.h"
#include "SceneView.h"
Seele::RenderCore::RenderCore() Seele::RenderCore::RenderCore()
{ {
@@ -16,7 +17,13 @@ void Seele::RenderCore::init()
mainWindowInfo.width = 1280; mainWindowInfo.width = 1280;
mainWindowInfo.height = 720; mainWindowInfo.height = 720;
mainWindowInfo.bFullscreen = false; mainWindowInfo.bFullscreen = false;
windowManager->addWindow(mainWindowInfo); auto window = windowManager->addWindow(mainWindowInfo);
ViewportCreateInfo sceneViewInfo;
sceneViewInfo.sizeX = 1280;
sceneViewInfo.sizeY = 720;
sceneViewInfo.offsetX = 0;
sceneViewInfo.offsetY = 0;
PSceneView sceneView = new SceneView(windowManager->getGraphics(), window, sceneViewInfo);
} }
void Seele::RenderCore::renderLoop() void Seele::RenderCore::renderLoop()
+2
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "WindowManager.h" #include "WindowManager.h"
#include "Scene/Scene.h"
namespace Seele namespace Seele
{ {
class RenderCore class RenderCore
@@ -12,6 +13,7 @@ public:
void shutdown(); void shutdown();
private: private:
PScene scene;
PWindowManager windowManager; PWindowManager windowManager;
}; };
} // namespace Seele } // namespace Seele
+3 -3
View File
@@ -1,8 +1,8 @@
#include "RenderPath.h" #include "RenderPath.h"
#include "GraphicsResources.h"
Seele::RenderPath::RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target) Seele::RenderPath::RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target)
: graphics(graphics) : graphics(graphics), target(target)
, target(target)
{ {
} }
@@ -10,7 +10,7 @@ Seele::RenderPath::~RenderPath()
{ {
} }
void Seele::RenderPath::applyArea(Rect newArea) void Seele::RenderPath::applyArea(URect newArea)
{ {
target->resize(newArea.size.x, newArea.size.y); target->resize(newArea.size.x, newArea.size.y);
target->move(newArea.offset.x, newArea.offset.y); target->move(newArea.offset.x, newArea.offset.y);
+2 -1
View File
@@ -8,10 +8,11 @@ class RenderPath
public: public:
RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target); RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
virtual ~RenderPath(); virtual ~RenderPath();
virtual void applyArea(Rect area); virtual void applyArea(URect area);
virtual void beginFrame() = 0; virtual void beginFrame() = 0;
virtual void render() = 0; virtual void render() = 0;
virtual void endFrame() = 0; virtual void endFrame() = 0;
protected: protected:
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
Gfx::PViewport target; Gfx::PViewport target;
+2
View File
@@ -1,8 +1,10 @@
#include "SceneRenderPath.h" #include "SceneRenderPath.h"
#include "Scene/Scene.h"
Seele::SceneRenderPath::SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target) Seele::SceneRenderPath::SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target)
: RenderPath(graphics, target) : RenderPath(graphics, target)
{ {
scene = new Scene();
} }
Seele::SceneRenderPath::~SceneRenderPath() Seele::SceneRenderPath::~SceneRenderPath()
+4
View File
@@ -3,6 +3,7 @@
namespace Seele namespace Seele
{ {
DECLARE_REF(Scene);
class SceneRenderPath : public RenderPath class SceneRenderPath : public RenderPath
{ {
public: public:
@@ -11,5 +12,8 @@ public:
virtual void beginFrame() = 0; virtual void beginFrame() = 0;
virtual void render() = 0; virtual void render() = 0;
virtual void endFrame() = 0; virtual void endFrame() = 0;
protected:
PScene scene;
}; };
} // namespace Seele } // namespace Seele
+2 -1
View File
@@ -1,7 +1,8 @@
#include "SceneView.h" #include "SceneView.h"
#include "ForwardPlusRenderPath.h" #include "ForwardPlusRenderPath.h"
#include "Window.h"
Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo& createInfo) Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo)
: View(graphics, owner, createInfo) : View(graphics, owner, createInfo)
{ {
renderer = new ForwardPlusRenderPath(graphics, viewport); renderer = new ForwardPlusRenderPath(graphics, viewport);
+2 -1
View File
@@ -5,7 +5,8 @@ namespace Seele
class SceneView : public View class SceneView : public View
{ {
public: public:
SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo& createInfo); SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo);
~SceneView(); ~SceneView();
}; };
DEFINE_REF(SceneView);
} // namespace Seele } // namespace Seele
+3 -4
View File
@@ -1,9 +1,8 @@
#include "View.h" #include "View.h"
#include "Window.h" #include "Window.h"
Seele::View::View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& viewportInfo) Seele::View::View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &viewportInfo)
: graphics(graphics) : graphics(graphics), owner(window)
, owner(owner)
{ {
viewport = graphics->createViewport(owner->getGfxHandle(), viewportInfo); viewport = graphics->createViewport(owner->getGfxHandle(), viewportInfo);
} }
@@ -27,7 +26,7 @@ void Seele::View::endFrame()
renderer->endFrame(); renderer->endFrame();
} }
void Seele::View::applyArea(Rect area) void Seele::View::applyArea(URect area)
{ {
renderer->applyArea(area); renderer->applyArea(area);
} }
+2 -2
View File
@@ -7,12 +7,12 @@ DECLARE_REF(Window);
class View class View
{ {
public: public:
View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo); View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo);
virtual ~View(); virtual ~View();
void beginFrame(); void beginFrame();
void render(); void render();
void endFrame(); void endFrame();
void applyArea(Rect area); void applyArea(URect area);
protected: protected:
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
@@ -18,6 +18,12 @@ target_sources(SeeleEngine
VulkanInitializer.cpp VulkanInitializer.cpp
VulkanRenderPass.h VulkanRenderPass.h
VulkanRenderPass.cpp VulkanRenderPass.cpp
VulkanPipeline.h
VulkanPipeline.cpp
VulkanPipelineCache.h
VulkanPipelineCache.cpp
VulkanShader.h
VulkanShader.cpp
VulkanTexture.cpp VulkanTexture.cpp
VulkanQueue.h VulkanQueue.h
VulkanQueue.cpp VulkanQueue.cpp
+35 -52
View File
@@ -5,12 +5,8 @@
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
SubAllocation::SubAllocation(Allocation* owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize) SubAllocation::SubAllocation(Allocation *owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize)
: owner(owner) : owner(owner), size(size), allocatedOffset(allocatedOffset), alignedOffset(alignedOffset), allocatedSize(allocatedSize)
, size(size)
, allocatedOffset(allocatedOffset)
, alignedOffset(alignedOffset)
, allocatedSize(allocatedSize)
{ {
} }
@@ -29,9 +25,9 @@ bool SubAllocation::isReadable() const
return owner->isReadable(); return owner->isReadable();
} }
void* SubAllocation::getMappedPointer() void *SubAllocation::getMappedPointer()
{ {
return (uint8*)owner->getMappedPointer() + alignedOffset; return (uint8 *)owner->getMappedPointer() + alignedOffset;
} }
void SubAllocation::flushMemory() void SubAllocation::flushMemory()
@@ -44,15 +40,9 @@ void SubAllocation::invalidateMemory()
owner->invalidateMemory(); owner->invalidateMemory();
} }
Allocation::Allocation(PGraphics graphics, Allocator* allocator, VkDeviceSize size, uint8 memoryTypeIndex, Allocation::Allocation(PGraphics graphics, Allocator *allocator, VkDeviceSize size, uint8 memoryTypeIndex,
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo* dedicatedInfo) VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
: device(graphics->getDevice()) : device(graphics->getDevice()), allocator(allocator), bytesAllocated(0), bytesUsed(0), readable(properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), properties(properties), memoryTypeIndex(memoryTypeIndex)
, allocator(allocator)
, bytesAllocated(0)
, bytesUsed(0)
, readable(properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
, properties(properties)
, memoryTypeIndex(memoryTypeIndex)
{ {
VkMemoryAllocateInfo allocInfo = VkMemoryAllocateInfo allocInfo =
init::MemoryAllocateInfo(); init::MemoryAllocateInfo();
@@ -110,8 +100,8 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
{ {
freeAllocation->size -= size; freeAllocation->size -= size;
freeAllocation->allocatedSize -= size; freeAllocation->allocatedSize -= size;
freeAllocation->allocatedOffset += allocatedOffset; freeAllocation->allocatedOffset += size;
freeAllocation->alignedOffset += allocatedOffset; freeAllocation->alignedOffset += size;
PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size); PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size);
activeAllocations[allocatedOffset] = subAlloc.getHandle(); activeAllocations[allocatedOffset] = subAlloc.getHandle();
freeRanges.erase(allocatedOffset); freeRanges.erase(allocatedOffset);
@@ -123,15 +113,15 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
return nullptr; return nullptr;
} }
void Allocation::markFree(SubAllocation* allocation) void Allocation::markFree(SubAllocation *allocation)
{ {
VkDeviceSize lowerBound = allocation->allocatedOffset; VkDeviceSize lowerBound = allocation->allocatedOffset;
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize; VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
PSubAllocation allocHandle; PSubAllocation allocHandle;
for(auto freeRange : freeRanges) for (auto freeRange : freeRanges)
{ {
PSubAllocation freeAlloc = freeRange.value; PSubAllocation freeAlloc = freeRange.value;
if(freeAlloc->allocatedOffset + freeAlloc->allocatedSize + 1 == lowerBound) if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize + 1 == lowerBound)
{ {
freeAlloc->allocatedSize += allocation->allocatedSize; freeAlloc->allocatedSize += allocation->allocatedSize;
allocHandle = freeAlloc; allocHandle = freeAlloc;
@@ -139,9 +129,9 @@ void Allocation::markFree(SubAllocation* allocation)
} }
} }
auto foundAlloc = freeRanges.find(upperBound + 1); auto foundAlloc = freeRanges.find(upperBound + 1);
if(foundAlloc != freeRanges.end()) if (foundAlloc != freeRanges.end())
{ {
if(allocHandle == nullptr) if (allocHandle == nullptr)
{ {
allocHandle->allocatedSize += foundAlloc->value->allocatedSize; allocHandle->allocatedSize += foundAlloc->value->allocatedSize;
freeRanges.erase(foundAlloc->key); freeRanges.erase(foundAlloc->key);
@@ -153,7 +143,7 @@ void Allocation::markFree(SubAllocation* allocation)
allocHandle->alignedOffset -= allocation->allocatedSize; allocHandle->alignedOffset -= allocation->allocatedSize;
} }
} }
if(allocHandle == nullptr) if (allocHandle == nullptr)
{ {
allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize); allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize);
freeRanges[allocation->allocatedOffset] = allocHandle; freeRanges[allocation->allocatedOffset] = allocHandle;
@@ -170,16 +160,16 @@ Allocator::Allocator(PGraphics graphics)
for (size_t i = 0; i < memProperties.memoryHeapCount; ++i) for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
{ {
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i]; VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
HeapInfo& heapInfo = heaps[i]; HeapInfo &heapInfo = heaps[i];
heapInfo.maxSize = memoryHeap.size; heapInfo.maxSize = memoryHeap.size;
} }
} }
Allocator::~Allocator() Allocator::~Allocator()
{ {
for(auto heap : heaps) for (auto heap : heaps)
{ {
for(auto alloc : heap.allocations) for (auto alloc : heap.allocations)
{ {
assert(alloc->activeAllocations.empty()); assert(alloc->activeAllocations.empty());
assert(alloc->freeRanges.size() == 1); assert(alloc->freeRanges.size() == 1);
@@ -189,27 +179,27 @@ Allocator::~Allocator()
graphics = nullptr; graphics = nullptr;
} }
PSubAllocation Allocator::allocate(const VkMemoryRequirements2& memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo* dedicatedInfo) PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
{ {
const VkMemoryRequirements& requirements = memRequirements2.memoryRequirements; const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
uint8 memoryTypeIndex; uint8 memoryTypeIndex;
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex)); VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex; uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
if(memRequirements2.pNext != nullptr) if (memRequirements2.pNext != nullptr)
{ {
VkMemoryDedicatedRequirements* dedicatedReq = (VkMemoryDedicatedRequirements*)memRequirements2.pNext; VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext;
if(dedicatedReq->prefersDedicatedAllocation) if (dedicatedReq->prefersDedicatedAllocation)
{ {
PAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo); PAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
heaps[heapIndex].allocations.add(newAllocation); heaps[heapIndex].allocations.add(newAllocation);
return newAllocation->getSuballocation(requirements.size, requirements.alignment); return newAllocation->getSuballocation(requirements.size, requirements.alignment);
} }
} }
for(auto alloc : heaps[heapIndex].allocations) for (auto alloc : heaps[heapIndex].allocations)
{ {
PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment); PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
if(suballoc != nullptr) if (suballoc != nullptr)
{ {
return suballoc; return suballoc;
} }
@@ -221,13 +211,13 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2& memRequirements2
return newAllocation->getSuballocation(requirements.size, requirements.alignment); return newAllocation->getSuballocation(requirements.size, requirements.alignment);
} }
void Allocator::free(Allocation* allocation) void Allocator::free(Allocation *allocation)
{ {
for(auto heap : heaps) for (auto heap : heaps)
{ {
for(uint32 i = 0; i < heap.allocations.size(); ++i) for (uint32 i = 0; i < heap.allocations.size(); ++i)
{ {
if(heap.allocations[i] == allocation) if (heap.allocations[i] == allocation)
{ {
heap.allocations.remove(i, false); heap.allocations.remove(i, false);
return; return;
@@ -236,7 +226,7 @@ void Allocator::free(Allocation* allocation)
} }
} }
VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8* typeIndex) VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex)
{ {
for (uint8 memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex) for (uint8 memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex)
{ {
@@ -256,37 +246,31 @@ VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags proper
StagingBuffer::StagingBuffer() StagingBuffer::StagingBuffer()
{ {
} }
StagingBuffer::~StagingBuffer() StagingBuffer::~StagingBuffer()
{ {
} }
StagingManager::StagingManager(PGraphics graphics, PAllocator allocator) StagingManager::StagingManager(PGraphics graphics, PAllocator allocator)
: graphics(graphics) : graphics(graphics), allocator(allocator)
, allocator(allocator)
{ {
} }
StagingManager::~StagingManager() StagingManager::~StagingManager()
{ {
} }
void StagingManager::clearPending() void StagingManager::clearPending()
{ {
} }
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead) PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
{ {
for(auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it) for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
{ {
auto freeBuffer = *it; auto freeBuffer = *it;
if(freeBuffer->allocation->getSize() == size && freeBuffer->allocation->isReadable() == bCPURead) if (freeBuffer->allocation->getSize() == size && freeBuffer->allocation->isReadable() == bCPURead)
{ {
activeBuffers.add(freeBuffer.getHandle()); activeBuffers.add(freeBuffer.getHandle());
freeBuffers.remove(it, false); freeBuffers.remove(it, false);
@@ -312,10 +296,9 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF
vkGetBufferMemoryRequirements2(vulkanDevice, &bufferQuery, &memReqs); vkGetBufferMemoryRequirements2(vulkanDevice, &bufferQuery, &memReqs);
memReqs.memoryRequirements.alignment = memReqs.memoryRequirements.alignment =
(16 > memReqs.memoryRequirements.alignment) ? (16 > memReqs.memoryRequirements.alignment) ? 16 : memReqs.memoryRequirements.alignment;
16 : memReqs.memoryRequirements.alignment;
stagingBuffer->allocation = allocator->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | (bCPURead ? VK_MEMORY_PROPERTY_HOST_CACHED_BIT : VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), stagingBuffer->buffer); stagingBuffer->allocation = allocator->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | (bCPURead ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : VK_MEMORY_PROPERTY_HOST_CACHED_BIT), stagingBuffer->buffer);
stagingBuffer->bReadable = bCPURead; stagingBuffer->bReadable = bCPURead;
vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset()); vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset());
+17 -11
View File
@@ -58,9 +58,14 @@ Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::Q
Buffer::~Buffer() Buffer::~Buffer()
{ {
auto fence = getCommands()->getCommands()->getFence();
auto &deletionQueue = graphics->getDeletionQueue();
VkDevice device = graphics->getDevice();
VkBuffer buf[Gfx::numFramesBuffered];
for (uint32 i = 0; i < numBuffers; ++i) for (uint32 i = 0; i < numBuffers; ++i)
{ {
vkDestroyBuffer(graphics->getDevice(), buffers[i].buffer, nullptr); buf[i] = buffers[i].buffer;
deletionQueue.addPendingDelete(fence, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); });
buffers[i].allocation = nullptr; buffers[i].allocation = nullptr;
} }
} }
@@ -221,10 +226,9 @@ void Buffer::unlock()
std::memset(&region, 0, sizeof(VkBufferCopy)); std::memset(&region, 0, sizeof(VkBufferCopy));
region.size = size; region.size = size;
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region); vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
graphics->getStagingManager()->releaseStagingBuffer(stagingBuffer);
} }
transferOwnership(pending.prevQueue); transferOwnership(pending.prevQueue);
graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer);
} }
} }
@@ -278,13 +282,14 @@ VkAccessFlags StructuredBuffer::getDestAccessMask()
return VK_ACCESS_MEMORY_READ_BIT; return VK_ACCESS_MEMORY_READ_BIT;
} }
VertexBuffer::VertexBuffer(PGraphics graphics, const BulkResourceData &resourceData) VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData)
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.owner) : Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner)
, Gfx::VertexBuffer(resourceData.numVertices, resourceData.vertexSize)
{ {
if (resourceData.data != nullptr) if (resourceData.resourceData.data != nullptr)
{ {
void *data = lock(); void *data = lock();
std::memcpy(data, resourceData.data, resourceData.size); std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size);
unlock(); unlock();
} }
} }
@@ -303,13 +308,14 @@ VkAccessFlags VertexBuffer::getDestAccessMask()
return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
} }
IndexBuffer::IndexBuffer(PGraphics graphics, const BulkResourceData &resourceData) IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData)
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.owner) : Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner)
, Gfx::IndexBuffer(resourceData.resourceData.size, resourceData.indexType)
{ {
if (resourceData.data != nullptr) if (resourceData.resourceData.data != nullptr)
{ {
void *data = lock(); void *data = lock();
std::memcpy(data, resourceData.data, resourceData.size); std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size);
unlock(); unlock();
} }
} }
@@ -1,9 +1,12 @@
#include "VulkanCommandBuffer.h" #include "VulkanCommandBuffer.h"
#include "VulkanInitializer.h" #include "VulkanInitializer.h"
#include "VulkanGraphics.h" #include "VulkanGraphics.h"
#include "VulkanPipeline.h"
#include "VulkanGraphicsEnums.h" #include "VulkanGraphicsEnums.h"
#include "VulkanFramebuffer.h" #include "VulkanFramebuffer.h"
#include "VulkanRenderPass.h" #include "VulkanRenderPass.h"
#include "VulkanPipeline.h"
#include "VulkanDescriptorSets.h"
using namespace Seele; using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
@@ -74,7 +77,6 @@ void CmdBuffer::endRenderPass()
{ {
vkCmdEndRenderPass(handle); vkCmdEndRenderPass(handle);
state = State::InsideBegin; state = State::InsideBegin;
} }
void CmdBuffer::executeCommands(Array<PSecondaryCmdBuffer> commands) void CmdBuffer::executeCommands(Array<PSecondaryCmdBuffer> commands)
@@ -112,6 +114,11 @@ void CmdBuffer::refreshFence()
} }
} }
PFence CmdBuffer::getFence()
{
return fence;
}
SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool) SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool)
: CmdBufferBase(graphics, cmdPool) : CmdBufferBase(graphics, cmdPool)
{ {
@@ -145,6 +152,33 @@ void SecondaryCmdBuffer::end()
VK_CHECK(vkEndCommandBuffer(handle)); VK_CHECK(vkEndCommandBuffer(handle));
} }
void SecondaryCmdBuffer::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline)
{
pipeline = gfxPipeline.cast<GraphicsPipeline>();
pipeline->bind(handle);
}
void SecondaryCmdBuffer::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
{
VkDescriptorSet setHandle = descriptorSet.cast<DescriptorSet>()->getHandle();
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr);
}
void SecondaryCmdBuffer::bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer)
{
PVertexBuffer buf = vertexBuffer.cast<VertexBuffer>();
const VkBuffer bufHandle[1] = {buf->getHandle()};
const VkDeviceSize offsets[1] = {0};
vkCmdBindVertexBuffers(handle, 0, 1, bufHandle, offsets);
}
void SecondaryCmdBuffer::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
{
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, VK_INDEX_TYPE_UINT16);
}
void SecondaryCmdBuffer::draw(DrawInstance data)
{
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, data.firstInstance);
}
CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue) CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue)
: graphics(graphics), queue(queue) : graphics(graphics), queue(queue)
{ {
@@ -8,7 +8,7 @@ namespace Vulkan
{ {
DECLARE_REF(RenderPass); DECLARE_REF(RenderPass);
DECLARE_REF(Framebuffer); DECLARE_REF(Framebuffer);
class CmdBufferBase : public Gfx::RenderCommandBase class CmdBufferBase
{ {
public: public:
CmdBufferBase(PGraphics graphics, VkCommandPool cmdPool); CmdBufferBase(PGraphics graphics, VkCommandPool cmdPool);
@@ -41,6 +41,7 @@ public:
void executeCommands(Array<PSecondaryCmdBuffer> secondaryCommands); void executeCommands(Array<PSecondaryCmdBuffer> secondaryCommands);
void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore); void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore);
void refreshFence(); void refreshFence();
PFence getFence();
enum State enum State
{ {
ReadyBegin, ReadyBegin,
@@ -64,15 +65,22 @@ private:
}; };
DEFINE_REF(CmdBuffer); DEFINE_REF(CmdBuffer);
class SecondaryCmdBuffer : public CmdBufferBase DECLARE_REF(GraphicsPipeline);
class SecondaryCmdBuffer : public CmdBufferBase, public Gfx::RenderCommand
{ {
public: public:
SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool); SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool);
virtual ~SecondaryCmdBuffer(); virtual ~SecondaryCmdBuffer();
void begin(PCmdBuffer parent); void begin(PCmdBuffer parent);
void end(); void end();
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override;
virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override;
virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) override;
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
virtual void draw(DrawInstance data) override;
private: private:
PGraphicsPipeline pipeline;
}; };
DEFINE_REF(SecondaryCmdBuffer); DEFINE_REF(SecondaryCmdBuffer);
@@ -23,7 +23,6 @@ private:
PGraphics graphics; PGraphics graphics;
Array<VkDescriptorSetLayoutBinding> bindings; Array<VkDescriptorSetLayoutBinding> bindings;
VkDescriptorSetLayout layoutHandle; VkDescriptorSetLayout layoutHandle;
friend class PipelineStateCacheManager;
}; };
DEFINE_REF(DescriptorLayout); DEFINE_REF(DescriptorLayout);
class PipelineLayout : public Gfx::PipelineLayout class PipelineLayout : public Gfx::PipelineLayout
@@ -49,10 +48,33 @@ private:
uint32 layoutHash; uint32 layoutHash;
VkPipelineLayout layoutHandle; VkPipelineLayout layoutHandle;
PGraphics graphics; PGraphics graphics;
friend class PipelineStateCacheManager;
}; };
DEFINE_REF(PipelineLayout); DEFINE_REF(PipelineLayout);
class DescriptorAllocator : public Gfx::DescriptorAllocator
{
public:
DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout);
virtual ~DescriptorAllocator();
virtual void allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet);
inline VkDescriptorPool getHandle() const
{
return poolHandle;
}
inline DescriptorLayout getLayout() const
{
return layout;
}
private:
PGraphics graphics;
int maxSets = 512;
VkDescriptorPool poolHandle;
DescriptorLayout &layout;
};
DEFINE_REF(DescriptorAllocator);
class DescriptorSet : public Gfx::DescriptorSet class DescriptorSet : public Gfx::DescriptorSet
{ {
public: public:
@@ -70,6 +92,10 @@ public:
{ {
return setHandle; return setHandle;
} }
virtual uint32 getSetIndex() const
{
return owner->getLayout().getSetIndex();
}
private: private:
virtual void writeChanges(); virtual void writeChanges();
@@ -83,24 +109,5 @@ private:
}; };
DEFINE_REF(DescriptorSet); DEFINE_REF(DescriptorSet);
class DescriptorAllocator : public Gfx::DescriptorAllocator
{
public:
DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout);
virtual ~DescriptorAllocator();
virtual void allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet);
inline VkDescriptorPool getHandle()
{
return poolHandle;
}
private:
PGraphics graphics;
int maxSets = 512;
VkDescriptorPool poolHandle;
DescriptorLayout &layout;
};
DEFINE_REF(DescriptorAllocator);
} // namespace Vulkan } // namespace Vulkan
} // namespace Seele } // namespace Seele
@@ -8,9 +8,7 @@ using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRenderTargetLayout renderTargetLayout) Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRenderTargetLayout renderTargetLayout)
: graphics(graphics) : graphics(graphics), layout(renderTargetLayout), renderPass(renderPass)
, layout(renderTargetLayout)
, renderPass(renderPass)
{ {
FramebufferDescription description; FramebufferDescription description;
std::memset(&description, 0, sizeof(FramebufferDescription)); std::memset(&description, 0, sizeof(FramebufferDescription));
@@ -27,6 +27,7 @@ public:
{ {
return hash; return hash;
} }
private: private:
uint32 hash; uint32 hash;
PGraphics graphics; PGraphics graphics;
+29 -3
View File
@@ -6,6 +6,7 @@
#include "VulkanCommandBuffer.h" #include "VulkanCommandBuffer.h"
#include "VulkanRenderPass.h" #include "VulkanRenderPass.h"
#include "VulkanFramebuffer.h" #include "VulkanFramebuffer.h"
#include "VulkanPipelineCache.h"
#include "Graphics/GraphicsResources.h" #include "Graphics/GraphicsResources.h"
#include <glfw/glfw3.h> #include <glfw/glfw3.h>
@@ -42,6 +43,7 @@ void Graphics::init(GraphicsInitializer initInfo)
computeCommands = new CommandBufferManager(this, computeQueue); computeCommands = new CommandBufferManager(this, computeQueue);
transferCommands = new CommandBufferManager(this, transferQueue); transferCommands = new CommandBufferManager(this, transferQueue);
dedicatedTransferCommands = new CommandBufferManager(this, dedicatedTransferQueue); dedicatedTransferCommands = new CommandBufferManager(this, dedicatedTransferQueue);
pipelineCache = new PipelineCache(this, "pipeline.cache");
} }
Gfx::PWindow Graphics::createWindow(const WindowCreateInfo &createInfo) Gfx::PWindow Graphics::createWindow(const WindowCreateInfo &createInfo)
@@ -67,7 +69,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
uint32 framebufferHash = rp->getFramebufferHash(); uint32 framebufferHash = rp->getFramebufferHash();
PFramebuffer framebuffer; PFramebuffer framebuffer;
auto found = allocatedFramebuffers.find(framebufferHash); auto found = allocatedFramebuffers.find(framebufferHash);
if(found == allocatedFramebuffers.end()) if (found == allocatedFramebuffers.end())
{ {
framebuffer = new Framebuffer(this, rp, rp->getLayout()); framebuffer = new Framebuffer(this, rp, rp->getLayout());
} }
@@ -83,6 +85,18 @@ void Graphics::endRenderPass()
graphicsCommands->getCommands()->endRenderPass(); graphicsCommands->getCommands()->endRenderPass();
} }
void Graphics::executeCommands(Array<Gfx::PRenderCommand> commands)
{
Array<VkCommandBuffer> cmdBuffers(commands.size());
for (uint32 i = 0; i < commands.size(); ++i)
{
PSecondaryCmdBuffer buf = commands[i].cast<SecondaryCmdBuffer>();
buf->end();
cmdBuffers[i] = buf->getHandle();
}
vkCmdExecuteCommands(graphicsCommands->getCommands()->getHandle(), cmdBuffers.size(), cmdBuffers.data());
}
Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo) Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo)
{ {
PTexture2D result = new Texture2D(this, createInfo.width, createInfo.height, createInfo.bArray, PTexture2D result = new Texture2D(this, createInfo.width, createInfo.height, createInfo.bArray,
@@ -102,17 +116,28 @@ Gfx::PStructuredBuffer Graphics::createStructuredBuffer(const BulkResourceData &
PStructuredBuffer structuredBuffer = new StructuredBuffer(this, bulkData); PStructuredBuffer structuredBuffer = new StructuredBuffer(this, bulkData);
return structuredBuffer; return structuredBuffer;
} }
Gfx::PVertexBuffer Graphics::createVertexBuffer(const BulkResourceData &bulkData) Gfx::PVertexBuffer Graphics::createVertexBuffer(const VertexBufferCreateInfo &bulkData)
{ {
PVertexBuffer vertexBuffer = new VertexBuffer(this, bulkData); PVertexBuffer vertexBuffer = new VertexBuffer(this, bulkData);
return vertexBuffer; return vertexBuffer;
} }
Gfx::PIndexBuffer Graphics::createIndexBuffer(const BulkResourceData &bulkData) Gfx::PIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkData)
{ {
PIndexBuffer indexBuffer = new IndexBuffer(this, bulkData); PIndexBuffer indexBuffer = new IndexBuffer(this, bulkData);
return indexBuffer; return indexBuffer;
} }
Gfx::PRenderCommand Graphics::createRenderCommand()
{
PSecondaryCmdBuffer cmdBuffer = graphicsCommands->createSecondaryCmdBuffer();
cmdBuffer->begin(getGraphicsCommands()->getCommands());
return cmdBuffer;
}
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo)
{
PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo);
return pipeline;
}
VkInstance Graphics::getInstance() const VkInstance Graphics::getInstance() const
{ {
@@ -173,6 +198,7 @@ Array<const char *> Graphics::getRequiredExtensions()
} }
void Graphics::initInstance(GraphicsInitializer initInfo) void Graphics::initInstance(GraphicsInitializer initInfo)
{ {
glfwInit();
VkApplicationInfo appInfo = {}; VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = initInfo.applicationName; appInfo.pApplicationName = initInfo.applicationName;
+14 -2
View File
@@ -11,6 +11,8 @@ DECLARE_REF(StagingManager);
DECLARE_REF(CommandBufferManager); DECLARE_REF(CommandBufferManager);
DECLARE_REF(Queue); DECLARE_REF(Queue);
DECLARE_REF(Framebuffer); DECLARE_REF(Framebuffer);
DECLARE_REF(RenderCommand);
DECLARE_REF(PipelineCache);
class Graphics : public Gfx::Graphics class Graphics : public Gfx::Graphics
{ {
public: public:
@@ -29,6 +31,10 @@ public:
{ {
return queueMapping; return queueMapping;
} }
QueueOwnedResourceDeletion &getDeletionQueue()
{
return deletionQueue;
}
PAllocator getAllocator(); PAllocator getAllocator();
PStagingManager getStagingManager(); PStagingManager getStagingManager();
@@ -42,11 +48,15 @@ public:
virtual void beginRenderPass(Gfx::PRenderPass renderPass) override; virtual void beginRenderPass(Gfx::PRenderPass renderPass) override;
virtual void endRenderPass() override; virtual void endRenderPass() override;
virtual void executeCommands(Array<Gfx::PRenderCommand> commands) override;
virtual Gfx::PTexture2D createTexture2D(const TextureCreateInfo &createInfo) override; virtual Gfx::PTexture2D createTexture2D(const TextureCreateInfo &createInfo) override;
virtual Gfx::PUniformBuffer createUniformBuffer(const BulkResourceData &bulkData) override; virtual Gfx::PUniformBuffer createUniformBuffer(const BulkResourceData &bulkData) override;
virtual Gfx::PStructuredBuffer createStructuredBuffer(const BulkResourceData &bulkData) override; virtual Gfx::PStructuredBuffer createStructuredBuffer(const BulkResourceData &bulkData) override;
virtual Gfx::PVertexBuffer createVertexBuffer(const BulkResourceData &bulkData) override; virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override;
virtual Gfx::PIndexBuffer createIndexBuffer(const BulkResourceData &bulkData) override; virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override;
virtual Gfx::PRenderCommand createRenderCommand() override;
virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override;
protected: protected:
Array<const char *> getRequiredExtensions(); Array<const char *> getRequiredExtensions();
@@ -64,6 +74,8 @@ protected:
PQueue transferQueue; PQueue transferQueue;
PQueue dedicatedTransferQueue; PQueue dedicatedTransferQueue;
QueueFamilyMapping queueMapping; QueueFamilyMapping queueMapping;
QueueOwnedResourceDeletion deletionQueue;
PPipelineCache pipelineCache;
PCommandBufferManager graphicsCommands; PCommandBufferManager graphicsCommands;
PCommandBufferManager computeCommands; PCommandBufferManager computeCommands;
PCommandBufferManager transferCommands; PCommandBufferManager transferCommands;
@@ -1145,3 +1145,166 @@ Gfx::SeAttachmentLoadOp Seele::Vulkan::cast(const VkAttachmentLoadOp &loadOp)
return SE_ATTACHMENT_LOAD_OP_MAX_ENUM; return SE_ATTACHMENT_LOAD_OP_MAX_ENUM;
} }
} }
VkIndexType Seele::Vulkan::cast(const Gfx::SeIndexType &indexType)
{
switch (indexType)
{
case Gfx::SE_INDEX_TYPE_UINT16:
return VK_INDEX_TYPE_UINT16;
case Gfx::SE_INDEX_TYPE_UINT32:
return VK_INDEX_TYPE_UINT32;
default:
return VK_INDEX_TYPE_MAX_ENUM;
}
}
Gfx::SeIndexType Seele::Vulkan::cast(const VkIndexType &indexType)
{
switch (indexType)
{
case VK_INDEX_TYPE_UINT16:
return Gfx::SE_INDEX_TYPE_UINT16;
case VK_INDEX_TYPE_UINT32:
return Gfx::SE_INDEX_TYPE_UINT32;
default:
return Gfx::SE_INDEX_TYPE_MAX_ENUM;
}
}
VkPrimitiveTopology Seele::Vulkan::cast(const Gfx::SePrimitiveTopology &topology)
{
switch (topology)
{
case SE_PRIMITIVE_TOPOLOGY_POINT_LIST:
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
case SE_PRIMITIVE_TOPOLOGY_LINE_LIST:
return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
case SE_PRIMITIVE_TOPOLOGY_LINE_STRIP:
return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
case SE_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
case SE_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
case SE_PRIMITIVE_TOPOLOGY_PATCH_LIST:
return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
default:
return VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
}
}
Gfx::SePrimitiveTopology Seele::Vulkan::cast(const VkPrimitiveTopology &topology)
{
switch (topology)
{
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
return SE_PRIMITIVE_TOPOLOGY_POINT_LIST;
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
return SE_PRIMITIVE_TOPOLOGY_LINE_LIST;
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
return SE_PRIMITIVE_TOPOLOGY_LINE_STRIP;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
return SE_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
return SE_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
return SE_PRIMITIVE_TOPOLOGY_PATCH_LIST;
default:
return SE_PRIMITIVE_TOPOLOGY_MAX_ENUM;
}
}
VkPolygonMode Seele::Vulkan::cast(const Gfx::SePolygonMode &mode)
{
switch (mode)
{
case SE_POLYGON_MODE_FILL:
return VK_POLYGON_MODE_FILL;
case SE_POLYGON_MODE_LINE:
return VK_POLYGON_MODE_LINE;
case SE_POLYGON_MODE_POINT:
return VK_POLYGON_MODE_POINT;
default:
return VK_POLYGON_MODE_MAX_ENUM;
}
}
Gfx::SePolygonMode Seele::Vulkan::cast(const VkPolygonMode &mode)
{
switch (mode)
{
case VK_POLYGON_MODE_FILL:
return SE_POLYGON_MODE_FILL;
case VK_POLYGON_MODE_LINE:
return SE_POLYGON_MODE_LINE;
case VK_POLYGON_MODE_POINT:
return SE_POLYGON_MODE_POINT;
default:
return SE_POLYGON_MODE_MAX_ENUM;
}
}
VkCompareOp Seele::Vulkan::cast(const Gfx::SeCompareOp &op)
{
switch (op)
{
case SE_COMPARE_OP_NEVER:
return VK_COMPARE_OP_NEVER;
case SE_COMPARE_OP_LESS:
return VK_COMPARE_OP_LESS;
case SE_COMPARE_OP_EQUAL:
return VK_COMPARE_OP_EQUAL;
case SE_COMPARE_OP_LESS_OR_EQUAL:
return VK_COMPARE_OP_LESS_OR_EQUAL;
case SE_COMPARE_OP_GREATER:
return VK_COMPARE_OP_GREATER;
case SE_COMPARE_OP_NOT_EQUAL:
return VK_COMPARE_OP_NOT_EQUAL;
case SE_COMPARE_OP_GREATER_OR_EQUAL:
return VK_COMPARE_OP_GREATER_OR_EQUAL;
case SE_COMPARE_OP_ALWAYS:
return VK_COMPARE_OP_ALWAYS;
default:
return VK_COMPARE_OP_MAX_ENUM;
}
}
Gfx::SeCompareOp Seele::Vulkan::cast(const VkCompareOp &op)
{
switch (op)
{
case VK_COMPARE_OP_NEVER:
return SE_COMPARE_OP_NEVER;
case VK_COMPARE_OP_LESS:
return SE_COMPARE_OP_LESS;
case VK_COMPARE_OP_EQUAL:
return SE_COMPARE_OP_EQUAL;
case VK_COMPARE_OP_LESS_OR_EQUAL:
return SE_COMPARE_OP_LESS_OR_EQUAL;
case VK_COMPARE_OP_GREATER:
return SE_COMPARE_OP_GREATER;
case VK_COMPARE_OP_NOT_EQUAL:
return SE_COMPARE_OP_NOT_EQUAL;
case VK_COMPARE_OP_GREATER_OR_EQUAL:
return SE_COMPARE_OP_GREATER_OR_EQUAL;
case VK_COMPARE_OP_ALWAYS:
return SE_COMPARE_OP_ALWAYS;
default:
return SE_COMPARE_OP_MAX_ENUM;
}
}
@@ -16,6 +16,17 @@ namespace Seele
{ {
namespace Vulkan namespace Vulkan
{ {
enum class ShaderType
{
VERTEX = 0,
CONTROL = 1,
EVALUATION = 2,
GEOMETRY = 3,
FRAGMENT = 4,
COMPUTE = 5,
};
VkDescriptorType cast(const Gfx::SeDescriptorType &descriptorType); VkDescriptorType cast(const Gfx::SeDescriptorType &descriptorType);
Gfx::SeDescriptorType cast(const VkDescriptorType &descriptorType); Gfx::SeDescriptorType cast(const VkDescriptorType &descriptorType);
VkShaderStageFlagBits cast(const Gfx::SeShaderStageFlagBits &stage); VkShaderStageFlagBits cast(const Gfx::SeShaderStageFlagBits &stage);
@@ -26,5 +37,13 @@ VkAttachmentStoreOp cast(const Gfx::SeAttachmentStoreOp &storeOp);
Gfx::SeAttachmentStoreOp cast(const VkAttachmentStoreOp &storeOp); Gfx::SeAttachmentStoreOp cast(const VkAttachmentStoreOp &storeOp);
VkAttachmentLoadOp cast(const Gfx::SeAttachmentLoadOp &loadOp); VkAttachmentLoadOp cast(const Gfx::SeAttachmentLoadOp &loadOp);
Gfx::SeAttachmentLoadOp cast(const VkAttachmentLoadOp &loadOp); Gfx::SeAttachmentLoadOp cast(const VkAttachmentLoadOp &loadOp);
VkIndexType cast(const Gfx::SeIndexType &indexType);
Gfx::SeIndexType cast(const VkIndexType &indexType);
VkPrimitiveTopology cast(const Gfx::SePrimitiveTopology &topology);
Gfx::SePrimitiveTopology cast(const VkPrimitiveTopology &topology);
VkPolygonMode cast(const Gfx::SePolygonMode &mode);
Gfx::SePolygonMode cast(const VkPolygonMode &mode);
VkCompareOp cast(const Gfx::SeCompareOp &op);
Gfx::SeCompareOp cast(const VkCompareOp &op);
} // namespace Vulkan } // namespace Vulkan
} // namespace Seele } // namespace Seele
@@ -7,6 +7,49 @@
using namespace Seele; using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
List<QueueOwnedResourceDeletion::PendingItem> QueueOwnedResourceDeletion::deletionQueue;
volatile bool QueueOwnedResourceDeletion::running;
std::mutex QueueOwnedResourceDeletion::mutex;
std::condition_variable QueueOwnedResourceDeletion::cv;
QueueOwnedResourceDeletion::QueueOwnedResourceDeletion()
{
worker = std::thread(&run);
running = true;
}
QueueOwnedResourceDeletion::~QueueOwnedResourceDeletion()
{
worker.join();
}
void QueueOwnedResourceDeletion::addPendingDelete(PFence fence, std::function<void()> func)
{
PendingItem item;
item.fence = fence;
item.func = func;
deletionQueue.add(item);
std::unique_lock<std::mutex> lock(mutex);
cv.notify_all();
}
void QueueOwnedResourceDeletion::run()
{
while (running || !deletionQueue.empty())
{
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock);
auto entry = deletionQueue.begin();
PFence fence = entry->fence;
fence->wait(1000ull);
if (fence->isSignaled())
{
entry->func();
deletionQueue.remove(entry);
}
}
}
QueueOwnedResource::QueueOwnedResource(PGraphics graphics, Gfx::QueueType startQueueType) QueueOwnedResource::QueueOwnedResource(PGraphics graphics, Gfx::QueueType startQueueType)
: graphics(graphics), currentOwner(startQueueType) : graphics(graphics), currentOwner(startQueueType)
{ {
@@ -1,5 +1,8 @@
#pragma once #pragma once
#include "Graphics/GraphicsResources.h" #include "Graphics/GraphicsResources.h"
#include <thread>
#include <functional>
#include <condition_variable>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
namespace Seele namespace Seele
@@ -39,6 +42,10 @@ public:
return fence; return fence;
} }
void wait(uint32 timeout); void wait(uint32 timeout);
bool operator<(const Fence &other) const
{
return fence < other.fence;
}
private: private:
bool signaled; bool signaled;
@@ -76,6 +83,26 @@ struct QueueFamilyMapping
return srcIndex != dstIndex; return srcIndex != dstIndex;
} }
}; };
class QueueOwnedResourceDeletion
{
public:
QueueOwnedResourceDeletion();
virtual ~QueueOwnedResourceDeletion();
static void addPendingDelete(PFence fence, std::function<void()> function);
private:
std::thread worker;
static volatile bool running;
static void run();
struct PendingItem
{
PFence fence;
std::function<void()> func;
};
static std::mutex mutex;
static std::condition_variable cv;
static List<PendingItem> deletionQueue;
};
class QueueOwnedResource class QueueOwnedResource
{ {
public: public:
@@ -154,7 +181,7 @@ DEFINE_REF(StructuredBuffer);
class VertexBuffer : public Buffer, public Gfx::VertexBuffer class VertexBuffer : public Buffer, public Gfx::VertexBuffer
{ {
public: public:
VertexBuffer(PGraphics graphics, const BulkResourceData &resourceData); VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData);
virtual ~VertexBuffer(); virtual ~VertexBuffer();
protected: protected:
@@ -166,7 +193,7 @@ DEFINE_REF(VertexBuffer);
class IndexBuffer : public Buffer, public Gfx::IndexBuffer class IndexBuffer : public Buffer, public Gfx::IndexBuffer
{ {
public: public:
IndexBuffer(PGraphics graphics, const BulkResourceData &resourceData); IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData);
virtual ~IndexBuffer(); virtual ~IndexBuffer();
protected: protected:
@@ -251,7 +278,8 @@ class Texture2D : public TextureBase, public Gfx::Texture2D
public: public:
Texture2D(PGraphics graphics, uint32 sizeX, uint32 sizeY, Texture2D(PGraphics graphics, uint32 sizeX, uint32 sizeY,
bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format, bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format,
uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE); uint32 samples, Gfx::SeImageUsageFlags usage,
Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE);
virtual ~Texture2D(); virtual ~Texture2D();
inline uint32 getSizeX() const inline uint32 getSizeX() const
{ {
@@ -334,6 +362,7 @@ public:
virtual ~Viewport(); virtual ~Viewport();
virtual void resize(uint32 newX, uint32 newY); virtual void resize(uint32 newX, uint32 newY);
virtual void move(uint32 newOffsetX, uint32 newOffsetY); virtual void move(uint32 newOffsetX, uint32 newOffsetY);
protected: protected:
private: private:
PGraphics graphics; PGraphics graphics;
@@ -0,0 +1,28 @@
#include "VulkanPipeline.h"
#include "VulkanDescriptorSets.h"
#include "VulkanGraphics.h"
using namespace Seele;
using namespace Seele::Vulkan;
GraphicsPipeline::GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo)
: Gfx::GraphicsPipeline(createInfo)
, graphics(graphics)
, layout(pipelineLayout)
, pipeline(handle)
{
}
GraphicsPipeline::~GraphicsPipeline()
{
}
void GraphicsPipeline::bind(VkCommandBuffer handle)
{
vkCmdBindPipeline(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
}
VkPipelineLayout GraphicsPipeline::getLayout() const
{
return layout->getHandle();
}
@@ -0,0 +1,24 @@
#pragma once
#include "VulkanGraphicsResources.h"
namespace Seele
{
namespace Vulkan
{
DECLARE_REF(PipelineLayout);
DECLARE_REF(Graphics);
class GraphicsPipeline : public Gfx::GraphicsPipeline
{
public:
GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo);
virtual ~GraphicsPipeline();
void bind(VkCommandBuffer handle);
VkPipelineLayout getLayout() const;
private:
VkPipeline pipeline;
PPipelineLayout layout;
PGraphics graphics;
};
DEFINE_REF(GraphicsPipeline);
} // namespace Vulkan
} // namespace Seele
@@ -0,0 +1,240 @@
#include "VulkanPipelineCache.h"
#include "VulkanGraphics.h"
#include "VulkanGraphicsEnums.h"
#include "VulkanInitializer.h"
#include "VulkanRenderPass.h"
#include "VulkanDescriptorSets.h"
#include "VulkanShader.h"
using namespace Seele;
using namespace Seele::Vulkan;
PipelineCache::PipelineCache(PGraphics graphics, const std::string& cacheFilePath)
: graphics(graphics)
, cacheFile(cacheFilePath)
{
std::ifstream stream(cacheFilePath, std::ios::binary | std::ios::ate);
VkPipelineCacheCreateInfo cacheCreateInfo;
cacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
cacheCreateInfo.pNext = nullptr;
cacheCreateInfo.flags = 0;
cacheCreateInfo.initialDataSize = 0;
if(stream.good())
{
Array<uint8> cacheData;
uint32 fileSize = static_cast<uint32>(stream.tellg());
cacheData.resize(fileSize);
stream.seekg(0);
stream.read((char*)cacheData.data(), fileSize);
cacheCreateInfo.initialDataSize = fileSize;
cacheCreateInfo.pInitialData = cacheData.data();
}
VK_CHECK(vkCreatePipelineCache(graphics->getDevice(), &cacheCreateInfo, nullptr, &cache));
}
PipelineCache::~PipelineCache()
{
VkDeviceSize cacheSize;
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, nullptr);
Array<uint8> cacheData;
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, cacheData.data());
std::ofstream stream(cacheFile, std::ios::binary);
stream.write((char*)cacheData.data(), cacheSize);
stream.flush();
stream.close();
vkDestroyPipelineCache(graphics->getDevice(), cache, nullptr);
}
PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo& gfxInfo)
{
VkGraphicsPipelineCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
createInfo.pNext = 0;
createInfo.flags = 0;
createInfo.stageCount = 0;
VkPipelineTessellationStateCreateInfo tessInfo;
VkPipelineShaderStageCreateInfo stageInfos[5];
std::memset(stageInfos, 0, sizeof(stageInfos));
if(gfxInfo.vertexShader != nullptr)
{
PVertexShader shader = gfxInfo.vertexShader.cast<VertexShader>();
VkPipelineShaderStageCreateInfo& vertInfo = stageInfos[createInfo.stageCount++];
vertInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertInfo.module = shader->getModuleHandle();
vertInfo.pName = shader->getEntryPointName();
}
if(gfxInfo.controlShader != nullptr)
{
assert(gfxInfo.evalShader != nullptr);
PControlShader control = gfxInfo.controlShader.cast<ControlShader>();
PEvaluationShader eval = gfxInfo.evalShader.cast<EvaluationShader>();
VkPipelineShaderStageCreateInfo& controlInfo = stageInfos[createInfo.stageCount++];
controlInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
controlInfo.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
controlInfo.module = control->getModuleHandle();
controlInfo.pName = control->getEntryPointName();
VkPipelineShaderStageCreateInfo& evalInfo = stageInfos[createInfo.stageCount++];
evalInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
evalInfo.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
evalInfo.module = eval->getModuleHandle();
evalInfo.pName = eval->getEntryPointName();
tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
tessInfo.pNext = 0;
tessInfo.flags = 0;
tessInfo.patchControlPoints = control->getNumPatches();
}
if(gfxInfo.geometryShader != nullptr)
{
PGeometryShader geometry = gfxInfo.geometryShader.cast<GeometryShader>();
VkPipelineShaderStageCreateInfo& geometryInfo = stageInfos[createInfo.stageCount++];
geometryInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
geometryInfo.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
geometryInfo.module = geometry->getModuleHandle();
geometryInfo.pName = geometry->getEntryPointName();
}
if(gfxInfo.fragmentShader != nullptr)
{
PFragmentShader fragment = gfxInfo.fragmentShader.cast<FragmentShader>();
VkPipelineShaderStageCreateInfo& fragmentInfo = stageInfos[createInfo.stageCount++];
fragmentInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragmentInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragmentInfo.module = fragment->getModuleHandle();
fragmentInfo.pName = fragment->getEntryPointName();
}
VkPipelineVertexInputStateCreateInfo vertexInput =
init::PipelineVertexInputStateCreateInfo();
Gfx::PVertexDeclaration vertexDecl = gfxInfo.vertexDeclaration;
auto vertexStreams = vertexDecl->getVertexStreams();
Array<VkVertexInputBindingDescription> bindingDesc(vertexStreams.size());
Array<VkVertexInputAttributeDescription> attribDesc;
uint32 bindingNum = 0;
for(auto vertexBinding : vertexStreams)
{
uint32 stride = vertexBinding.getVertexBuffer()->getVertexSize();
for(auto vertexAttrib : vertexBinding.getVertexDescriptions())
{
auto attrib = attribDesc.add();
attrib.binding = bindingNum;
attrib.format = cast(vertexAttrib.vertexFormat);
attrib.location = vertexAttrib.location;
attrib.offset = vertexAttrib.offset;
}
bindingDesc[bindingNum].binding = bindingNum;
bindingDesc[bindingNum].stride = stride;
bindingDesc[bindingNum].inputRate = vertexBinding.isInstanced() ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
bindingNum++;
}
vertexInput.pVertexBindingDescriptions = bindingDesc.data();
vertexInput.vertexBindingDescriptionCount = bindingDesc.size();
vertexInput.pVertexAttributeDescriptions = attribDesc.data();
vertexInput.vertexAttributeDescriptionCount = attribDesc.size();
VkPipelineInputAssemblyStateCreateInfo assemblyInfo =
init::PipelineInputAssemblyStateCreateInfo(
cast(gfxInfo.topology),
0,
false
);
VkPipelineViewportStateCreateInfo viewportInfo =
init::PipelineViewportStateCreateInfo(
1,
1,
0
);
VkPipelineRasterizationStateCreateInfo rasterizationState =
init::PipelineRasterizationStateCreateInfo(
cast(gfxInfo.rasterizationState.polygonMode),
gfxInfo.rasterizationState.cullMode,
(VkFrontFace)gfxInfo.rasterizationState.frontFace,
0
);
rasterizationState.depthBiasEnable = gfxInfo.rasterizationState.depthBiasEnable;
rasterizationState.depthBiasClamp = gfxInfo.rasterizationState.depthBiasClamp;
rasterizationState.depthBiasConstantFactor = gfxInfo.rasterizationState.depthBoasConstantFactor;
rasterizationState.depthBiasSlopeFactor = gfxInfo.rasterizationState.depthBiasSlopeFactor;
rasterizationState.depthClampEnable = gfxInfo.rasterizationState.depthClampEnable;
rasterizationState.lineWidth = gfxInfo.rasterizationState.lineWidth;
rasterizationState.rasterizerDiscardEnable = gfxInfo.rasterizationState.rasterizerDiscardEnable;
VkPipelineMultisampleStateCreateInfo multisampleState =
init::PipelineMultisampleStateCreateInfo((VkSampleCountFlagBits)gfxInfo.multisampleState.samples, 0);
multisampleState.alphaToCoverageEnable = gfxInfo.multisampleState.alphaCoverageEnable;
multisampleState.alphaToOneEnable = gfxInfo.multisampleState.alphaToOneEnable;
multisampleState.minSampleShading = gfxInfo.multisampleState.minSampleShading;
multisampleState.sampleShadingEnable = gfxInfo.multisampleState.sampleShadingEnable;
VkPipelineDepthStencilStateCreateInfo depthStencilState =
init::PipelineDepthStencilStateCreateInfo(
gfxInfo.depthStencilState.depthTestEnable,
gfxInfo.depthStencilState.depthWriteEnable,
cast(gfxInfo.depthStencilState.depthCompareOp)
);
const auto colorAttachments = gfxInfo.renderPass->getLayout()->colorAttachments;
Array<VkPipelineColorBlendAttachmentState> blendAttachments(colorAttachments.size());
for(uint32 i = 0; i < colorAttachments.size(); ++i)
{
const Gfx::ColorBlendState::BlendAttachment& attachment = gfxInfo.colorBlend.blendAttachments[i];
VkPipelineColorBlendAttachmentState& blendAttachment = blendAttachments[i];
blendAttachment.alphaBlendOp = (VkBlendOp)attachment.alphaBlendOp;
blendAttachment.blendEnable = attachment.blendEnable;
blendAttachment.colorBlendOp = (VkBlendOp)attachment.colorBlendOp;
blendAttachment.colorWriteMask = attachment.colorWriteMask;
blendAttachment.dstAlphaBlendFactor = (VkBlendFactor)attachment.dstAlphaBlendFactor;
blendAttachment.srcAlphaBlendFactor = (VkBlendFactor)attachment.srcAlphaBlendFactor;
blendAttachment.dstColorBlendFactor = (VkBlendFactor)attachment.dstColorBlendFactor;
blendAttachment.srcColorBlendFactor = (VkBlendFactor)attachment.srcColorBlendFactor;
}
VkPipelineColorBlendStateCreateInfo blendState =
init::PipelineColorBlendStateCreateInfo(
blendAttachments.size(),
blendAttachments.data()
);
blendState.logicOpEnable = gfxInfo.colorBlend.logicOpEnable;
blendState.logicOp = (VkLogicOp)gfxInfo.colorBlend.logicOp;
std::memcpy(blendState.blendConstants, gfxInfo.colorBlend.blendConstants, sizeof(float)*4);
uint32 numDynamicEnabled = 0;
StaticArray<VkDynamicState, VK_DYNAMIC_STATE_RANGE_SIZE> dynamicEnabled;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_VIEWPORT;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_SCISSOR;
VkPipelineDynamicStateCreateInfo dynamicState =
init::PipelineDynamicStateCreateInfo(
dynamicEnabled.data(),
numDynamicEnabled,
0
);
createInfo.pStages = stageInfos;
createInfo.pVertexInputState = &vertexInput;
createInfo.pInputAssemblyState = &assemblyInfo;
createInfo.pTessellationState = &tessInfo;
createInfo.pViewportState = &viewportInfo;
createInfo.pRasterizationState = &rasterizationState;
createInfo.pMultisampleState = &multisampleState;
createInfo.pDepthStencilState = &depthStencilState;
createInfo.pColorBlendState = &blendState;
createInfo.pDynamicState = &dynamicState;
createInfo.renderPass = gfxInfo.renderPass.cast<RenderPass>()->getHandle();
createInfo.layout = gfxInfo.pipelineLayout.cast<PipelineLayout>()->getHandle();
createInfo.subpass = 0;
VkPipeline pipelineHandle;
auto beginTime = std::chrono::high_resolution_clock::now();
VK_CHECK(vkCreateGraphicsPipelines(graphics->getDevice(), cache, 1, &createInfo, nullptr, &pipelineHandle));
auto endTime = std::chrono::high_resolution_clock::now();
int64 delta = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - beginTime).count();
std::cout << "Gfx creation time: " << delta << std::endl;
PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, gfxInfo.pipelineLayout.cast<PipelineLayout>(), gfxInfo);
return result;
}
@@ -0,0 +1,21 @@
#pragma once
#include "VulkanPipeline.h"
namespace Seele
{
namespace Vulkan
{
class PipelineCache
{
public:
PipelineCache(PGraphics graphics, const std::string& cacheFilePath);
~PipelineCache();
PGraphicsPipeline createPipeline(const GraphicsPipelineCreateInfo& createInfo);
private:
VkPipelineCache cache;
PGraphics graphics;
std::string cacheFile;
};
DEFINE_REF(PipelineCache);
} // namespace Vulkan
} // namespace Seele
+5 -8
View File
@@ -9,19 +9,16 @@ using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
Queue::Queue(PGraphics graphics, Gfx::QueueType queueType, uint32 familyIndex, uint32 queueIndex) Queue::Queue(PGraphics graphics, Gfx::QueueType queueType, uint32 familyIndex, uint32 queueIndex)
: familyIndex(familyIndex) : familyIndex(familyIndex), graphics(graphics), queueType(queueType)
, graphics(graphics)
, queueType(queueType)
{ {
vkGetDeviceQueue(graphics->getDevice(), familyIndex, queueIndex, &queue); vkGetDeviceQueue(graphics->getDevice(), familyIndex, queueIndex, &queue);
} }
Queue::~Queue() Queue::~Queue()
{ {
} }
void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore* signalSemaphores) void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore *signalSemaphores)
{ {
assert(cmdBuffer->state == CmdBuffer::State::Ended); assert(cmdBuffer->state == CmdBuffer::State::Ended);
@@ -38,9 +35,9 @@ void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores
submitInfo.pSignalSemaphores = signalSemaphores; submitInfo.pSignalSemaphores = signalSemaphores;
Array<VkSemaphore> waitSemaphores; Array<VkSemaphore> waitSemaphores;
if(cmdBuffer->waitSemaphores.size() > 0) if (cmdBuffer->waitSemaphores.size() > 0)
{ {
for(PSemaphore semaphore : cmdBuffer->waitSemaphores) for (PSemaphore semaphore : cmdBuffer->waitSemaphores)
{ {
waitSemaphores.add(semaphore->getHandle()); waitSemaphores.add(semaphore->getHandle());
} }
@@ -55,7 +52,7 @@ void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores
cmdBuffer->waitFlags.clear(); cmdBuffer->waitFlags.clear();
cmdBuffer->waitSemaphores.clear(); cmdBuffer->waitSemaphores.clear();
if(Gfx::waitIdleOnSubmit) if (Gfx::waitIdleOnSubmit)
{ {
fence->wait(200 * 1000ull); fence->wait(200 * 1000ull);
} }
@@ -8,7 +8,8 @@ using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
RenderPass::RenderPass(PGraphics graphics, Gfx::PRenderTargetLayout layout) RenderPass::RenderPass(PGraphics graphics, Gfx::PRenderTargetLayout layout)
: layout(layout), graphics(graphics) : Gfx::RenderPass(layout)
, graphics(graphics)
{ {
Array<VkAttachmentDescription> attachments; Array<VkAttachmentDescription> attachments;
Array<VkAttachmentReference> inputRefs; Array<VkAttachmentReference> inputRefs;
@@ -108,17 +109,17 @@ uint32 RenderPass::getFramebufferHash()
{ {
FramebufferDescription description; FramebufferDescription description;
std::memset(&description, 0, sizeof(FramebufferDescription)); std::memset(&description, 0, sizeof(FramebufferDescription));
for(auto inputAttachment : layout->inputAttachments) for (auto inputAttachment : layout->inputAttachments)
{ {
PTexture2D tex = inputAttachment->getTexture().cast<Texture2D>(); PTexture2D tex = inputAttachment->getTexture().cast<Texture2D>();
description.inputAttachments[description.numInputAttachments++] = tex->getView(); description.inputAttachments[description.numInputAttachments++] = tex->getView();
} }
for(auto colorAttachment : layout->colorAttachments) for (auto colorAttachment : layout->colorAttachments)
{ {
PTexture2D tex = colorAttachment->getTexture().cast<Texture2D>(); PTexture2D tex = colorAttachment->getTexture().cast<Texture2D>();
description.colorAttachments[description.numColorAttachments++] = tex->getView(); description.colorAttachments[description.numColorAttachments++] = tex->getView();
} }
if(layout->depthAttachment != nullptr) if (layout->depthAttachment != nullptr)
{ {
PTexture2D tex = layout->depthAttachment->getTexture().cast<Texture2D>(); PTexture2D tex = layout->depthAttachment->getTexture().cast<Texture2D>();
description.depthAttachment = tex->getView(); description.depthAttachment = tex->getView();
@@ -30,13 +30,8 @@ public:
{ {
return subpassContents; return subpassContents;
} }
inline Gfx::PRenderTargetLayout getLayout()
{
return layout;
}
private: private:
PGraphics graphics; PGraphics graphics;
Gfx::PRenderTargetLayout layout;
VkRenderPass renderPass; VkRenderPass renderPass;
Array<VkClearValue> clearValues; Array<VkClearValue> clearValues;
VkRect2D renderArea; VkRect2D renderArea;
@@ -0,0 +1,4 @@
#include "VulkanShader.h"
using namespace Seele;
using namespace Seele::Vulkan;
+57
View File
@@ -0,0 +1,57 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "VulkanGraphicsEnums.h"
namespace Seele
{
namespace Vulkan
{
class Shader
{
public:
Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage);
virtual ~Shader();
VkShaderModule getModuleHandle() const
{
return module;
}
const char* getEntryPointName() const
{
return entryPointName.c_str();
}
private:
VkShaderModule module;
std::string entryPointName;
};
DEFINE_REF(Shader);
template <typename Base, ShaderType shaderType, VkShaderStageFlags stage>
class ShaderBase : public Base, public Shader
{
public:
ShaderBase(PGraphics graphics)
: Shader(graphics, shaderType, stage)
{
}
virtual ~ShaderBase()
{
}
};
typedef ShaderBase<Gfx::VertexShader, ShaderType::VERTEX, VK_SHADER_STAGE_VERTEX_BIT> VertexShader;
typedef ShaderBase<Gfx::ControlShader, ShaderType::CONTROL, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT> ControlShader;
typedef ShaderBase<Gfx::EvaluationShader, ShaderType::EVALUATION, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT> EvaluationShader;
typedef ShaderBase<Gfx::GeometryShader, ShaderType::GEOMETRY, VK_SHADER_STAGE_GEOMETRY_BIT> GeometryShader;
typedef ShaderBase<Gfx::FragmentShader, ShaderType::FRAGMENT, VK_SHADER_STAGE_FRAGMENT_BIT> FragmentShader;
typedef ShaderBase<Gfx::ComputeShader, ShaderType::COMPUTE, VK_SHADER_STAGE_COMPUTE_BIT> ComputeShader;
DEFINE_REF(VertexShader);
DEFINE_REF(ControlShader);
DEFINE_REF(EvaluationShader);
DEFINE_REF(GeometryShader);
DEFINE_REF(FragmentShader);
DEFINE_REF(ComputeShader);
} // namespace Vulkan
}
+9 -4
View File
@@ -32,7 +32,7 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format)
TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint32 sizeX, uint32 sizeY, uint32 sizeZ, TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint32 sizeX, uint32 sizeY, uint32 sizeZ,
bool bArray, uint32 arraySize, uint32 mipLevel, bool bArray, uint32 arraySize, uint32 mipLevel,
Gfx::SeFormat format, uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner, VkImage existingImage) Gfx::SeFormat format, uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner, VkImage existingImage)
: QueueOwnedResource(graphics, owner), graphics(graphics), sizeX(sizeX), sizeY(sizeY), sizeZ(sizeZ), mipLevels(mipLevel), format(format), samples(samples), usage(usage), arrayCount(bArray ? arraySize : 1), aspect(getAspectFromFormat(format)) : QueueOwnedResource(graphics, owner), graphics(graphics), sizeX(sizeX), sizeY(sizeY), sizeZ(sizeZ), mipLevels(mipLevel), format(format), samples(samples), usage(usage), arrayCount(bArray ? arraySize : 1), aspect(getAspectFromFormat(format)), image(existingImage), layout(VK_IMAGE_LAYOUT_UNDEFINED)
{ {
if (existingImage == VK_NULL_HANDLE) if (existingImage == VK_NULL_HANDLE)
{ {
@@ -105,8 +105,13 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
TextureHandle::~TextureHandle() TextureHandle::~TextureHandle()
{ {
vkDestroyImageView(graphics->getDevice(), defaultView, nullptr); auto &deletionQueue = graphics->getDeletionQueue();
vkDestroyImage(graphics->getDevice(), image, nullptr); auto fence = getCommands()->getCommands()->getFence();
VkDevice device = graphics->getDevice();
VkImageView view = defaultView;
VkImage img = image;
deletionQueue.addPendingDelete(fence, [device, view]() { vkDestroyImageView(device, view, nullptr); });
deletionQueue.addPendingDelete(fence, [device, img]() { vkDestroyImage(device, img, nullptr); });
} }
void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner) void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
@@ -145,7 +150,7 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstManager = graphics->getTransferCommands(); dstManager = graphics->getTransferCommands();
} }
else if(currentOwner == Gfx::QueueType::DEDICATED_TRANSFER) else if (currentOwner == Gfx::QueueType::DEDICATED_TRANSFER)
{ {
imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+29 -11
View File
@@ -9,7 +9,7 @@ using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo) Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo)
: Gfx::Window(createInfo), graphics(graphics), instance(graphics->getInstance()) : Gfx::Window(createInfo), graphics(graphics), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE)
{ {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow *handle = glfwCreateWindow(createInfo.width, createInfo.height, createInfo.title, createInfo.bFullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr); GLFWwindow *handle = glfwCreateWindow(createInfo.width, createInfo.height, createInfo.title, createInfo.bFullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr);
@@ -19,7 +19,28 @@ Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo)
glfwCreateWindowSurface(instance, handle, nullptr, &surface); glfwCreateWindowSurface(instance, handle, nullptr, &surface);
createSwapchain(); uint32_t numQueueFamilies = 0;
vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, nullptr);
Array<VkQueueFamilyProperties> queueProperties(numQueueFamilies);
vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, queueProperties.data());
bool viableDevice = false;
for (uint32 i = 0; i < numQueueFamilies; ++i)
{
VkBool32 supportsPresent;
vkGetPhysicalDeviceSurfaceSupportKHR(graphics->getPhysicalDevice(), i, surface, &supportsPresent);
if (supportsPresent)
{
viableDevice = true;
break;
}
}
if (!viableDevice)
{
std::cerr << "Device not suitable for presenting to surface " << surface << ", use a different one" << std::endl;
}
recreateSwapchain(createInfo);
} }
Window::~Window() Window::~Window()
@@ -30,6 +51,7 @@ Window::~Window()
void Window::beginFrame() void Window::beginFrame()
{ {
glfwPollEvents();
advanceBackBuffer(); advanceBackBuffer();
} }
@@ -75,16 +97,9 @@ void Window::advanceBackBuffer()
imageAcquiredSemaphore = imageAcquired[semaphoreIndex]; imageAcquiredSemaphore = imageAcquired[semaphoreIndex];
currentImageIndex = imageIndex; currentImageIndex = imageIndex;
VkImageMemoryBarrier barrier = backBufferImages[currentImageIndex]->changeLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
init::ImageMemoryBarrier(
backBufferImages[currentImageIndex]->getHandle(),
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands(); PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands();
vkCmdPipelineBarrier(cmdBuffer->getHandle(), graphics->getGraphicsCommands()->getCommands()->addWaitSemaphore(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, imageAcquiredSemaphore);
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0, 0, nullptr, 0, nullptr, 1, &barrier);
cmdBuffer->addWaitSemaphore(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, imageAcquiredSemaphore);
graphics->getGraphicsCommands()->submitCommands(); graphics->getGraphicsCommands()->submitCommands();
} }
@@ -187,7 +202,10 @@ void Window::createSwapchain()
void Window::destroySwapchain() void Window::destroySwapchain()
{ {
if (swapchain != VK_NULL_HANDLE)
{
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr); vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
}
for (uint32 i = 0; i < Gfx::numFramesBuffered; ++i) for (uint32 i = 0; i < Gfx::numFramesBuffered; ++i)
{ {
imageAcquired[i] = nullptr; imageAcquired[i] = nullptr;
+3 -4
View File
@@ -7,7 +7,6 @@ Seele::Window::Window(Gfx::PWindow handle)
Seele::Window::~Window() Seele::Window::~Window()
{ {
} }
void Seele::Window::addView(PView view) void Seele::Window::addView(PView view)
@@ -18,7 +17,7 @@ void Seele::Window::addView(PView view)
void Seele::Window::beginFrame() void Seele::Window::beginFrame()
{ {
gfxHandle->beginFrame(); gfxHandle->beginFrame();
for(auto view : viewports) for (auto view : viewports)
{ {
view->beginFrame(); view->beginFrame();
} }
@@ -26,7 +25,7 @@ void Seele::Window::beginFrame()
void Seele::Window::render() void Seele::Window::render()
{ {
for(auto view : viewports) for (auto view : viewports)
{ {
view->render(); view->render();
} }
@@ -35,7 +34,7 @@ void Seele::Window::render()
void Seele::Window::endFrame() void Seele::Window::endFrame()
{ {
gfxHandle->endFrame(); gfxHandle->endFrame();
for(auto view : viewports) for (auto view : viewports)
{ {
view->endFrame(); view->endFrame();
} }
+2 -1
View File
@@ -15,9 +15,10 @@ public:
void render(); void render();
void endFrame(); void endFrame();
Gfx::PWindow getGfxHandle(); Gfx::PWindow getGfxHandle();
private: private:
Array<PView> viewports; Array<PView> viewports;
Gfx::PWindow gfxHandle; Gfx::PWindow gfxHandle;
}; };
DEFINE_REF(Window); DEFINE_REF(Window);
} } // namespace Seele
+4 -2
View File
@@ -24,10 +24,12 @@ Seele::WindowManager::~WindowManager()
{ {
} }
void Seele::WindowManager::addWindow(const WindowCreateInfo &createInfo) PWindow Seele::WindowManager::addWindow(const WindowCreateInfo &createInfo)
{ {
Gfx::PWindow window = graphics->createWindow(createInfo); Gfx::PWindow handle = graphics->createWindow(createInfo);
PWindow window = new Window(handle);
windows.add(window); windows.add(window);
return window;
} }
void Seele::WindowManager::beginFrame() void Seele::WindowManager::beginFrame()
+7 -2
View File
@@ -2,6 +2,7 @@
#include "GraphicsResources.h" #include "GraphicsResources.h"
#include "Graphics.h" #include "Graphics.h"
#include "Containers/Array.h" #include "Containers/Array.h"
#include "Window.h"
namespace Seele namespace Seele
{ {
@@ -10,16 +11,20 @@ class WindowManager
public: public:
WindowManager(); WindowManager();
~WindowManager(); ~WindowManager();
void addWindow(const WindowCreateInfo &createInfo); PWindow addWindow(const WindowCreateInfo &createInfo);
void beginFrame(); void beginFrame();
void endFrame(); void endFrame();
Gfx::PGraphics getGraphics()
{
return graphics;
}
inline bool isActive() const inline bool isActive() const
{ {
return windows.size(); return windows.size();
} }
private: private:
Array<Gfx::PWindow> windows; Array<PWindow> windows;
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
}; };
DEFINE_REF(WindowManager); DEFINE_REF(WindowManager);
+6
View File
@@ -0,0 +1,6 @@
target_sources(SeeleEngine
PRIVATE
Material.h
Material.cpp
MaterialInstance.h
MaterialInstance.cpp)
+37
View File
@@ -0,0 +1,37 @@
#include "Material.h"
#include <nlohmann/json.hpp>
using namespace Seele;
using json = nlohmann::json;
Material::Material()
{
}
Material::Material(const std::string& directory, const std::string& name)
: FileAsset(directory, name)
{
}
Material::Material(const std::string& fullPath)
: FileAsset(fullPath)
{
}
Material::~Material()
{
}
void Material::compile()
{
auto& stream = getReadStream();
stream.seekg(0);
json j;
stream >> j;
std::cout << j["test"] << std::endl;
}
Gfx::PGraphicsPipeline Material::getPipeline()
{
return pipeline;
}
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "MinimalEngine.h"
#include "Asset/FileAsset.h"
#include "Graphics/GraphicsResources.h"
#include <nlohmann/json_fwd.hpp>
namespace Seele
{
struct FloatExpression
{
float data;
std::string name;
uint32 location;
};
struct VectorExpression
{
Vector data;
std::string name;
uint32 location;
};
struct TextureExpression
{
Gfx::PTexture texture;
std::string name;
uint32 location;
};
DECLARE_NAME_REF(Gfx, GraphicsPipeline);
DECLARE_NAME_REF(Gfx, PipelineLayout);
class Material : public FileAsset
{
public:
Material();
Material(const std::string &directory, const std::string &name);
Material(const std::string &fullPath);
~Material();
void compile();
Gfx::PGraphicsPipeline getPipeline();
private:
Gfx::PGraphicsPipeline pipeline;
Gfx::PPipelineLayout pipelineLayout;
};
DEFINE_REF(Material);
} // namespace Seele
+32
View File
@@ -0,0 +1,32 @@
#include "MaterialInstance.h"
#include "Material.h"
using namespace Seele;
MaterialInstance::MaterialInstance()
{
}
MaterialInstance::MaterialInstance(const std::string& directory, const std::string& name)
: FileAsset(directory, name)
{
}
MaterialInstance::MaterialInstance(const std::string& fullPath)
: FileAsset(fullPath)
{
}
MaterialInstance::~MaterialInstance()
{
}
PMaterial MaterialInstance::getBaseMaterial() const
{
return baseMaterial;
}
Gfx::PDescriptorSet MaterialInstance::getDescriptor()
{
return nullptr;
}
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include "Asset/FileAsset.h"
namespace Seele
{
DECLARE_NAME_REF(Gfx, DescriptorSet);
DECLARE_REF(Material);
class MaterialInstance : public FileAsset
{
public:
MaterialInstance();
MaterialInstance(const std::string& directory, const std::string& name);
MaterialInstance(const std::string& fullPath);
~MaterialInstance();
PMaterial getBaseMaterial() const;
Gfx::PDescriptorSet getDescriptor();
private:
PMaterial baseMaterial;
};
DEFINE_REF(MaterialInstance);
} // namespace Seele
+23
View File
@@ -1,5 +1,6 @@
#include "Vector.h" #include "Vector.h"
#include "Matrix.h" #include "Matrix.h"
#include "EngineTypes.h"
namespace Seele namespace Seele
{ {
@@ -24,6 +25,28 @@ struct Rect
Vector2 size; Vector2 size;
Vector2 offset; Vector2 offset;
}; };
//Unsigned int
struct URect
{
URect()
: size(0, 0), offset(0, 0)
{
}
URect(uint32 sizeX, uint32 sizeY, uint32 offsetX, uint32 offsetY)
: size(sizeX, sizeY), offset(offsetX, offsetY)
{
}
URect(UVector2 size, UVector2 offset)
: size(size), offset(offset)
{
}
bool isEmpty() const
{
return size.x == 0 || size.y == 0;
}
UVector2 size;
UVector2 offset;
};
struct Rect3D struct Rect3D
{ {
Vector size; Vector size;
+111 -6
View File
@@ -7,6 +7,19 @@ Transform::Transform()
{ {
} }
Transform::Transform(Transform &&other)
: position(other.position), rotation(other.rotation), scale(scale)
{
other.position = Vector4(0, 0, 0, 0);
other.rotation = Quaternion(0, 0, 0, 0);
other.scale = Vector4(0, 0, 0, 0);
}
Transform::Transform(const Transform &other)
: position(other.position), rotation(other.rotation), scale(scale)
{
}
Transform::Transform(Vector position) Transform::Transform(Vector position)
: position(Vector4(position, 0)), rotation(Quaternion(0, 0, 0, 0)), scale(Vector4(1, 1, 1, 0)) : position(Vector4(position, 0)), rotation(Quaternion(0, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
{ {
@@ -26,12 +39,61 @@ Transform::Transform(Quaternion rotation, Vector scale)
Transform::~Transform() Transform::~Transform()
{ {
} }
Vector Transform::inverseTransformPosition(const Vector& v) const Vector Transform::inverseTransformPosition(const Vector &v) const
{ {
return (unrotateVector(rotation, v - Vector(position))) * getSafeScaleReciprocal(scale); return (unrotateVector(rotation, v - Vector(position))) * getSafeScaleReciprocal(scale);
} }
Matrix4 Transform::toMatrix()
{
Matrix4 mat;
Vector Transform::getSafeScaleReciprocal(const Vector4& inScale, float tolerance) mat[3][0] = position.x;
mat[3][1] = position.y;
mat[3][2] = position.z;
const float x2 = rotation.x + rotation.x;
const float y2 = rotation.y + rotation.y;
const float z2 = rotation.z + rotation.z;
{
const float xx2 = rotation.x * x2;
const float yy2 = rotation.y * y2;
const float zz2 = rotation.z * z2;
mat[0][0] = (1.0f - (yy2 + zz2)) * scale.x;
mat[1][1] = (1.0f - (xx2 + zz2)) * scale.y;
mat[2][2] = (1.0f - (xx2 + yy2)) * scale.z;
}
{
const float yz2 = rotation.y * z2;
const float wx2 = rotation.w * x2;
mat[2][1] = (yz2 - wx2) * scale.z;
mat[1][2] = (yz2 + wx2) * scale.y;
}
{
const float xy2 = rotation.x * y2;
const float wz2 = rotation.w * z2;
mat[1][0] = (xy2 - wz2) * scale.y;
mat[0][1] = (xy2 + wz2) * scale.x;
}
{
const float xz2 = rotation.x * z2;
const float wy2 = rotation.w * y2;
mat[2][0] = (xz2 + wy2) * scale.z;
mat[0][2] = (xz2 - wy2) * scale.x;
}
mat[0][3] = 0.0f;
mat[1][3] = 0.0f;
mat[2][3] = 0.0f;
mat[3][3] = 1.0f;
return mat;
}
Vector Transform::getSafeScaleReciprocal(const Vector4 &inScale, float tolerance)
{ {
Vector safeReciprocalScale; Vector safeReciprocalScale;
if (abs(inScale.x) <= tolerance) if (abs(inScale.x) <= tolerance)
@@ -61,24 +123,67 @@ Vector Transform::getSafeScaleReciprocal(const Vector4& inScale, float tolerance
return safeReciprocalScale; return safeReciprocalScale;
} }
inline Vector Transform::getPosition() const Vector Transform::getPosition() const
{ {
return Vector(position); return Vector(position);
} }
inline Quaternion Transform::getRotation() const Quaternion Transform::getRotation() const
{ {
return rotation; return rotation;
} }
inline Vector Transform::getScale() const Vector Transform::getScale() const
{ {
return Vector(scale); return Vector(scale);
} }
inline void Transform::multiply(Transform* outTransform, const Transform* a, const Transform* b) bool Transform::equals(const Transform &other, float tolerance)
{
if (abs(position - other.position).length() > tolerance)
{
return false;
}
if (abs(rotation.x - other.rotation.x) <= tolerance && abs(rotation.y - other.rotation.y) <= tolerance && abs(rotation.z - other.rotation.z) <= tolerance && abs(rotation.w - other.rotation.w) <= tolerance || abs(rotation.x + other.rotation.x) <= tolerance && abs(rotation.y + other.rotation.y) <= tolerance && abs(rotation.z + other.rotation.z) <= tolerance && abs(rotation.w - other.rotation.w) <= tolerance)
{
return false;
}
if (abs(scale - other.scale).length() > tolerance)
{
return false;
}
return true;
}
void Transform::multiply(Transform *outTransform, const Transform *a, const Transform *b)
{ {
outTransform->rotation = b->rotation * a->rotation; outTransform->rotation = b->rotation * a->rotation;
outTransform->position = b->position * (b->scale * a->position) + b->position; outTransform->position = b->position * (b->scale * a->position) + b->position;
outTransform->scale = b->scale * a->scale; outTransform->scale = b->scale * a->scale;
} }
Transform &Transform::operator=(const Transform &other)
{
position = other.position;
rotation = other.rotation;
scale = other.scale;
return *this;
}
Transform &Transform::operator=(Transform &&other)
{
position = other.position;
rotation = other.rotation;
scale = other.scale;
other.position = Vector4(0, 0, 0, 0);
other.rotation = Quaternion(0, 0, 0, 0);
other.scale = Vector4(0, 0, 0, 0);
return *this;
}
Transform &Transform::operator*(const Transform &other) const
{
Transform outTransform;
multiply(&outTransform, this, &other);
return outTransform;
}
+13 -11
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "Vector.h" #include "Vector.h"
#include "Matrix.h"
namespace Seele namespace Seele
{ {
@@ -7,26 +8,27 @@ class Transform
{ {
public: public:
Transform(); Transform();
Transform(const Transform &other);
Transform(Transform &&other);
Transform(Vector position); Transform(Vector position);
Transform(Vector position, Quaternion rotation); Transform(Vector position, Quaternion rotation);
Transform(Vector position, Quaternion rotation, Vector scale); Transform(Vector position, Quaternion rotation, Vector scale);
Transform(Quaternion rotation, Vector scale); Transform(Quaternion rotation, Vector scale);
~Transform(); ~Transform();
Vector inverseTransformPosition(const Vector &v) const; Vector inverseTransformPosition(const Vector &v) const;
static Vector getSafeScaleReciprocal(const Vector4 &inScale, float tolerance = 0.00001f); Matrix4 toMatrix();
static Vector getSafeScaleReciprocal(const Vector4 &inScale, float tolerance = 0.000000001f);
inline Vector getPosition() const; Vector getPosition() const;
inline Quaternion getRotation() const; Quaternion getRotation() const;
inline Vector getScale() const; Vector getScale() const;
inline static void multiply(Transform* outTransform, const Transform* a, const Transform* b); bool equals(const Transform &other, float tolerance = 0.000000001f);
static void multiply(Transform *outTransform, const Transform *a, const Transform *b);
Transform& operator*(const Transform& other) const Transform &operator=(const Transform &other);
{ Transform &operator=(Transform &&other);
Transform outTransform; Transform &operator*(const Transform &other) const;
multiply(&outTransform, this, &other);
return outTransform;
}
private: private:
Vector4 position; Vector4 position;
+7 -5
View File
@@ -2,7 +2,10 @@
#include <glm/vec2.hpp> #include <glm/vec2.hpp>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#pragma warning(disable : 4201)
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#pragma warning(default : 4201)
namespace Seele namespace Seele
{ {
typedef glm::vec2 Vector2; typedef glm::vec2 Vector2;
@@ -32,10 +35,9 @@ static inline Vector unrotateVector(Quaternion quaternion, Vector v)
return result; return result;
} }
static inline bool equalsQuaternion(const Quaternion& right, const Quaternion& left, float tolerance) static inline bool equalsQuaternion(const Quaternion &right, const Quaternion &left, float tolerance)
{ {
return (abs(right.x - left.x) <= tolerance && abs(right.y - left.y) <= tolerance && abs(right.z - left.z) <= tolerance && abs(right.w - left.w) <= tolerance) return (abs(right.x - left.x) <= tolerance && abs(right.y - left.y) <= tolerance && abs(right.z - left.z) <= tolerance && abs(right.w - left.w) <= tolerance) || (abs(right.x + left.x) <= tolerance && abs(right.y + left.y) <= tolerance && abs(right.z + left.z) <= tolerance && abs(right.w + left.w) <= tolerance);
|| (abs(right.x + left.x) <= tolerance && abs(right.y + left.y) <= tolerance && abs(right.z + left.z) <= tolerance && abs(right.w + left.w) <= tolerance);
} }
static inline float clampRotatorAxis(float angle) static inline float clampRotatorAxis(float angle)
@@ -58,7 +60,7 @@ static inline float normalizeRotatorAxis(float angle)
return angle; return angle;
} }
static inline Quaternion toQuaternion(const Vector& other) static inline Quaternion toQuaternion(const Vector &other)
{ {
Quaternion result; Quaternion result;
const float DEG_TO_RAD = glm::pi<float>() / (180.f); const float DEG_TO_RAD = glm::pi<float>() / (180.f);
@@ -83,7 +85,7 @@ static inline Quaternion toQuaternion(const Vector& other)
return result; return result;
} }
static inline Vector toRotator(const Quaternion& other) static inline Vector toRotator(const Quaternion &other)
{ {
const float singularityTest = other.z * other.x - other.w * other.y; const float singularityTest = other.z * other.x - other.w * other.y;
const float yawY = 2.f * (other.w * other.z + other.x * other.y); const float yawY = 2.f * (other.w * other.z + other.x * other.y);
+1 -1
View File
@@ -1,3 +1,3 @@
#include "MinimalEngine.h" #include "MinimalEngine.h"
Seele::Map<void*, void*> registeredObjects; Seele::Map<void *, void *> registeredObjects;
+119 -99
View File
@@ -8,54 +8,64 @@
#include "EngineTypes.h" #include "EngineTypes.h"
#include "Math/Math.h" #include "Math/Math.h"
#define DEFINE_REF(x) typedef RefPtr<x> P##x; \ #define DEFINE_REF(x) \
typedef UniquePtr<x> UP##x; \
typedef WeakPtr<x> W##x;
#define DECLARE_REF(x) class x; \
typedef RefPtr<x> P##x; \ typedef RefPtr<x> P##x; \
typedef UniquePtr<x> UP##x; \ typedef UniquePtr<x> UP##x; \
typedef WeakPtr<x> W##x; typedef WeakPtr<x> W##x;
extern Seele::Map<void*, void*> registeredObjects; #define DECLARE_REF(x) \
class x; \
typedef RefPtr<x> P##x; \
typedef UniquePtr<x> UP##x; \
typedef WeakPtr<x> W##x;
#define DECLARE_NAME_REF(nmsp, x) \
namespace nmsp \
{ \
class x; \
typedef RefPtr<x> P##x; \
typedef UniquePtr<x> UP##x; \
typedef WeakPtr<x> W##x; \
}
extern Seele::Map<void *, void *> registeredObjects;
namespace Seele namespace Seele
{ {
template<typename T> template <typename T>
class RefObject class RefObject
{ {
public: public:
RefObject(T* ptr) RefObject(T *ptr)
: handle(ptr) : handle(ptr), refCount(1)
, refCount(1)
{ {
registeredObjects[ptr] = this; registeredObjects[ptr] = this;
} }
RefObject(const RefObject& rhs) RefObject(const RefObject &rhs)
: handle(rhs.handle) : handle(rhs.handle), refCount(rhs.refCount)
, refCount(rhs.refCount) {
}
RefObject(RefObject &&rhs)
: handle(std::move(rhs.handle)), refCount(std::move(rhs.refCount))
{ {
} }
RefObject(RefObject&& rhs)
: handle(std::move(rhs.handle))
, refCount(std::move(rhs.refCount))
{}
~RefObject() ~RefObject()
{ {
registeredObjects.erase(handle); registeredObjects.erase(handle);
delete handle; delete handle;
} }
RefObject& operator=(const RefObject& rhs) RefObject &operator=(const RefObject &rhs)
{ {
if(*this != rhs) if (*this != rhs)
{ {
handle = rhs.handle; handle = rhs.handle;
refCount = rhs.refCount; refCount = rhs.refCount;
} }
return *this; return *this;
} }
RefObject& operator=(RefObject&& rhs) RefObject &operator=(RefObject &&rhs)
{ {
if(*this != rhs) if (*this != rhs)
{ {
handle = std::move(rhs.handle); handle = std::move(rhs.handle);
refCount = std::move(rhs.refCount); refCount = std::move(rhs.refCount);
@@ -64,15 +74,15 @@ namespace Seele
} }
return *this; return *this;
} }
bool operator==(const RefObject& other) const bool operator==(const RefObject &other) const
{ {
return handle == other.handle; return handle == other.handle;
} }
bool operator!=(const RefObject& other) const bool operator!=(const RefObject &other) const
{ {
return handle != other.handle; return handle != other.handle;
} }
bool operator<(const RefObject& other) const bool operator<(const RefObject &other) const
{ {
return handle < other.handle; return handle < other.handle;
} }
@@ -88,20 +98,20 @@ namespace Seele
delete this; delete this;
} }
} }
inline T* getHandle() const inline T *getHandle() const
{ {
return handle; return handle;
} }
private:
T* handle; private:
T *handle;
std::atomic_uint64_t refCount; std::atomic_uint64_t refCount;
}; };
template <typename T>
template<typename T> class RefPtr
class RefPtr {
{ public:
public:
RefPtr() RefPtr()
{ {
object = nullptr; object = nullptr;
@@ -110,73 +120,73 @@ namespace Seele
{ {
object = nullptr; object = nullptr;
} }
RefPtr(T* ptr) RefPtr(T *ptr)
{ {
auto registeredObj = registeredObjects.find(ptr); auto registeredObj = registeredObjects.find(ptr);
if(registeredObj == registeredObjects.end()) if (registeredObj == registeredObjects.end())
{ {
object = new RefObject<T>(ptr); object = new RefObject<T>(ptr);
} }
else else
{ {
object = (RefObject<T>*)registeredObj->value; object = (RefObject<T> *)registeredObj->value;
} }
} }
explicit RefPtr(RefObject<T>* other) explicit RefPtr(RefObject<T> *other)
: object(other) : object(other)
{ {
object->addRef(); object->addRef();
} }
RefPtr(const RefPtr& other) RefPtr(const RefPtr &other)
: object(other.object) : object(other.object)
{ {
if(object != nullptr) if (object != nullptr)
{ {
object->addRef(); object->addRef();
} }
} }
RefPtr(RefPtr&& rhs) RefPtr(RefPtr &&rhs)
: object(std::move(rhs.object)) : object(std::move(rhs.object))
{ {
rhs.object = nullptr; rhs.object = nullptr;
//Dont change references, they stay the same //Dont change references, they stay the same
} }
template<typename F> template <typename F>
RefPtr(const RefPtr<F>& other) RefPtr(const RefPtr<F> &other)
{ {
F* f = other.getObject()->getHandle(); F *f = other.getObject()->getHandle();
static_cast<T*>(f); static_cast<T *>(f);
object = (RefObject<T>*)other.getObject(); object = (RefObject<T> *)other.getObject();
object->addRef(); object->addRef();
} }
template<typename F> template <typename F>
RefPtr<F> cast() RefPtr<F> cast()
{ {
T* t = object->getHandle(); T *t = object->getHandle();
F* f = dynamic_cast<F*>(t); F *f = dynamic_cast<F *>(t);
if (f == nullptr) if (f == nullptr)
{ {
return nullptr; return nullptr;
} }
RefObject<F>* newObject = (RefObject<F>*)object; RefObject<F> *newObject = (RefObject<F> *)object;
return RefPtr<F>(newObject); return RefPtr<F>(newObject);
} }
template<typename F> template <typename F>
const RefPtr<F> cast() const const RefPtr<F> cast() const
{ {
T* t = object->getHandle(); T *t = object->getHandle();
F* f = dynamic_cast<F*>(t); F *f = dynamic_cast<F *>(t);
if (f == nullptr) if (f == nullptr)
{ {
return nullptr; return nullptr;
} }
RefObject<F>* newObject = (RefObject<F>*)object; RefObject<F> *newObject = (RefObject<F> *)object;
return RefPtr<F>(newObject); return RefPtr<F>(newObject);
} }
RefPtr& operator=(const RefPtr& other) RefPtr &operator=(const RefPtr &other)
{ {
if (*this != other) if (*this != other)
{ {
@@ -185,18 +195,18 @@ namespace Seele
object->removeRef(); object->removeRef();
} }
object = other.object; object = other.object;
if(object != nullptr) if (object != nullptr)
{ {
object->addRef(); object->addRef();
} }
} }
return *this; return *this;
} }
RefPtr& operator=(RefPtr&& rhs) RefPtr &operator=(RefPtr &&rhs)
{ {
if(*this != rhs) if (*this != rhs)
{ {
if(object != nullptr) if (object != nullptr)
{ {
object->removeRef(); object->removeRef();
} }
@@ -207,83 +217,92 @@ namespace Seele
} }
~RefPtr() ~RefPtr()
{ {
if(object != nullptr) if (object != nullptr)
{ {
object->removeRef(); object->removeRef();
} }
} }
bool operator==(const RefPtr& other) const bool operator==(const RefPtr &other) const
{ {
return object == other.object; return object == other.object;
} }
bool operator!=(const RefPtr& other) const bool operator!=(const RefPtr &other) const
{ {
return object != other.object; return object != other.object;
} }
T* operator->() bool operator<(const RefPtr &other) const
{
return object < other.object;
}
T *operator->()
{ {
assert(object != nullptr); assert(object != nullptr);
return object->getHandle(); return object->getHandle();
} }
const T* operator->() const const T *operator->() const
{ {
assert(object != nullptr); assert(object != nullptr);
return object->getHandle(); return object->getHandle();
} }
RefObject<T>* getObject() const RefObject<T> *getObject() const
{ {
return object; return object;
} }
T* getHandle() T *getHandle()
{ {
return object->getHandle(); return object->getHandle();
} }
const T* getHandle() const const T *getHandle() const
{ {
return object->getHandle(); return object->getHandle();
} }
private:
RefObject<T>* object; private:
}; RefObject<T> *object;
//A weak pointer has no ownership over an object and thus cant delete it };
template<typename T> //A weak pointer has no ownership over an object and thus cant delete it
class WeakPtr template <typename T>
{ class WeakPtr
public: {
public:
WeakPtr() WeakPtr()
: pointer(nullptr) : pointer(nullptr)
{} {
WeakPtr(RefPtr<T>& sharedPtr) }
WeakPtr(RefPtr<T> &sharedPtr)
: pointer(sharedPtr) : pointer(sharedPtr)
{} {
WeakPtr& operator=(WeakPtr<T>& weakPtr) }
WeakPtr &operator=(WeakPtr<T> &weakPtr)
{ {
pointer = weakPtr.pointer; pointer = weakPtr.pointer;
return *this; return *this;
} }
WeakPtr& operator=(RefPtr<T>& sharedPtr) WeakPtr &operator=(RefPtr<T> &sharedPtr)
{ {
pointer = sharedPtr; pointer = sharedPtr;
return *this; return *this;
} }
private:
private:
RefPtr<T> pointer; RefPtr<T> pointer;
}; };
template<typename T> template <typename T>
class UniquePtr class UniquePtr
{ {
public: public:
UniquePtr(T* ptr) UniquePtr(T *ptr)
: handle(ptr) : handle(ptr)
{} {
UniquePtr(const UniquePtr& rhs) = delete; }
UniquePtr(UniquePtr&& rhs) noexcept UniquePtr(const UniquePtr &rhs) = delete;
UniquePtr(UniquePtr &&rhs) noexcept
: handle(rhs.handle) : handle(rhs.handle)
{ {
rhs.handle = nullptr; rhs.handle = nullptr;
} }
UniquePtr& operator=(const UniquePtr& rhs) = delete; UniquePtr &operator=(const UniquePtr &rhs) = delete;
UniquePtr& operator=(UniquePtr&& rhs) UniquePtr &operator=(UniquePtr &&rhs)
{ {
handle = rhs.handle; handle = rhs.handle;
rhs.handle = nullptr; rhs.handle = nullptr;
@@ -293,7 +312,7 @@ namespace Seele
{ {
delete handle; delete handle;
} }
T* operator->() T *operator->()
{ {
return handle; return handle;
} }
@@ -301,9 +320,10 @@ namespace Seele
{ {
return handle != nullptr; return handle != nullptr;
} }
private:
T* handle; private:
}; T *handle;
} };
} // namespace Seele
using namespace Seele; using namespace Seele;
+30 -5
View File
@@ -1,5 +1,6 @@
#include "Actor.h" #include "Actor.h"
#include "Component.h" #include "Scene/Components/Component.h"
#include "Scene/Scene.h"
using namespace Seele; using namespace Seele;
@@ -11,6 +12,25 @@ Actor::~Actor()
{ {
} }
void Actor::tick(float deltaTime)
{
rootComponent->tick(deltaTime);
for(auto child : children)
{
child->tick(deltaTime);
}
}
void Actor::notifySceneAttach(PScene scene)
{
owningScene = scene;
rootComponent->notifySceneAttach(scene);
}
PScene Actor::getScene()
{
return owningScene;
}
void Actor::setParent(PActor newParent) void Actor::setParent(PActor newParent)
{ {
parent = newParent; parent = newParent;
@@ -18,10 +38,14 @@ void Actor::setParent(PActor newParent)
void Actor::addChild(PActor child) void Actor::addChild(PActor child)
{ {
children.add(child); children.add(child);
child->setParent(this);
child->notifySceneAttach(owningScene);
} }
void Actor::detachChild(PActor child) void Actor::detachChild(PActor child)
{ {
children.remove(children.find(child), false); children.remove(children.find(child), false);
child->setParent(nullptr);
child->notifySceneAttach(nullptr);
} }
void Actor::setWorldLocation(Vector location) void Actor::setWorldLocation(Vector location)
{ {
@@ -55,15 +79,16 @@ void Actor::addWorldRotation(Vector4 rotation)
{ {
rootComponent->addWorldRotation(rotation); rootComponent->addWorldRotation(rotation);
} }
void Actor::addWorldScale(Vector scale)
{
rootComponent->addWorldScale(scale);
}
PComponent Actor::getRootComponent() PComponent Actor::getRootComponent()
{ {
return rootComponent; return rootComponent;
} }
void Actor::setRootComponent(PComponent newRoot) void Actor::setRootComponent(PComponent newRoot)
{ {
if(rootComponent != nullptr)
{
rootComponent->owner = nullptr;
}
rootComponent = newRoot; rootComponent = newRoot;
rootComponent->owner = this;
} }
+11 -4
View File
@@ -1,17 +1,22 @@
#pragma once #pragma once
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Transform.h" #include "Math/Transform.h"
namespace Seele namespace Seele
{ {
DECLARE_REF(Actor); DECLARE_REF(Actor);
DECLARE_REF(Component); DECLARE_REF(Component);
DECLARE_REF(Scene);
class Actor class Actor
{ {
public: public:
Actor(); Actor();
virtual ~Actor(); virtual ~Actor();
void setParent(PActor parent);
void tick(float deltaTime);
void notifySceneAttach(PScene scene);
PScene getScene();
PActor getParent(); PActor getParent();
void addChild(PActor child); void addChild(PActor child);
void detachChild(PActor child); void detachChild(PActor child);
@@ -26,15 +31,17 @@ public:
void addWorldTranslation(Vector translation); void addWorldTranslation(Vector translation);
void addWorldRotation(Vector4 rotation); void addWorldRotation(Vector4 rotation);
void addWorldScale(Vector scale);
PComponent getRootComponent(); PComponent getRootComponent();
void setRootComponent(PComponent newRoot); void setRootComponent(PComponent newRoot);
private: private:
void setParent(PActor parent);
PScene owningScene;
PActor parent; PActor parent;
Array<PActor> children; Array<PActor> children;
PComponent rootComponent; PComponent rootComponent;
Transform transform; Transform transform;
}; };
DEFINE_REF(Actor); DEFINE_REF(Actor);
} } // namespace Seele
+109 -13
View File
@@ -1,4 +1,6 @@
#include "Component.h" #include "Component.h"
#include "Scene/Actor/Actor.h"
#include "Scene/Scene.h"
using namespace Seele; using namespace Seele;
@@ -8,58 +10,123 @@ Component::Component()
Component::~Component() Component::~Component()
{ {
} }
void Component::tick(float deltaTime)
{
for (auto child : children)
{
child->tick(deltaTime);
}
}
PComponent Component::getParent() PComponent Component::getParent()
{ {
return parent;
} }
PActor Component::getOwner() PActor Component::getOwner()
{ {
if (owner != nullptr)
{
return owner;
}
if (parent != nullptr)
{
return parent->getOwner();
}
return nullptr;
}
void Component::notifySceneAttach(PScene scene)
{
owningScene = scene;
for (auto child : children)
{
child->notifySceneAttach(scene);
}
} }
void Component::setWorldLocation(Vector location) void Component::setWorldLocation(Vector location)
{ {
Vector newRelLocation = location;
if (parent != nullptr)
{
Transform parentToWorld = getParent()->getTransform();
newRelLocation = parentToWorld.inverseTransformPosition(location);
}
setRelativeLocation(newRelLocation);
} }
void Component::setWorldRotation(Vector rotation) void Component::setWorldRotation(Vector rotation)
{ {
Vector newRelRotator = rotation;
if (parent == nullptr)
{
setRelativeRotation(rotation);
}
else
{
setWorldRotation(toQuaternion(newRelRotator));
}
} }
void Component::setWorldRotation(Quaternion rotation) void Component::setWorldRotation(Quaternion rotation)
{ {
Quaternion newRelRotation = getRelativeWorldRotation(rotation);
setRelativeRotation(newRelRotation);
} }
void Component::setWorldScale(Vector scale) void Component::setWorldScale(Vector scale)
{ {
Vector newRelScale = scale;
if (parent != nullptr)
{
Transform parentToWorld = parent->getTransform();
newRelScale = scale * parentToWorld.getSafeScaleReciprocal(Vector4(parentToWorld.getScale(), 0));
}
setRelativeScale(newRelScale);
} }
void Component::setRelativeLocation(Vector location) void Component::setRelativeLocation(Vector location)
{ {
setRelativeLocationAndRotation(location, relativeRotation);
} }
void Component::setRelativeRotation(Vector rotation) void Component::setRelativeRotation(Vector rotation)
{ {
setRelativeLocationAndRotation(relativeLocation, toQuaternion(rotation));
} }
void Component::setRelativeRotation(Quaternion rotation) void Component::setRelativeRotation(Quaternion rotation)
{ {
setRelativeLocationAndRotation(relativeLocation, rotation);
} }
void Component::setRelativeScale(Vector scale) void Component::setRelativeScale(Vector scale)
{ {
if (scale != relativeScale)
{
relativeScale = scale;
updateComponentTransform(relativeRotation);
}
} }
void Component::addWorldTranslation(Vector translation) void Component::addWorldTranslation(Vector translation)
{ {
const Vector newWorldLocation = translation + transform.getPosition();
setWorldLocation(newWorldLocation);
} }
void Component::addWorldRotation(Vector rotation) void Component::addWorldRotation(Vector rotation)
{ {
const Quaternion newWorldRotation = toQuaternion(rotation) * transform.getRotation();
setWorldRotation(newWorldRotation);
} }
void Component::addWorldRotation(Quaternion rotation) void Component::addWorldRotation(Quaternion rotation)
{ {
} const Quaternion newWorldRotation = rotation * transform.getRotation();
void Component::addWorldScale(Vector scale) setWorldRotation(newWorldRotation);
{
} }
Transform Component::getTransform() const Transform Component::getTransform() const
{ {
return transform; return transform;
} }
void Component::setParent(PComponent newParent)
{
parent = newParent;
}
void Component::internalSetTransform(Vector newLocation, Quaternion newRotation) void Component::internalSetTransform(Vector newLocation, Quaternion newRotation)
{ {
if(parent != nullptr) if (parent != nullptr)
{ {
Transform parentTransform = parent->getTransform(); Transform parentTransform = parent->getTransform();
newLocation = parentTransform.inverseTransformPosition(newLocation); newLocation = parentTransform.inverseTransformPosition(newLocation);
@@ -67,7 +134,7 @@ void Component::internalSetTransform(Vector newLocation, Quaternion newRotation)
} }
const Vector newRelRotation = toRotator(newRotation); const Vector newRelRotation = toRotator(newRotation);
if(newLocation != relativeLocation || newRelRotation != relativeLocation) if (newLocation != relativeLocation || newRelRotation != relativeLocation)
{ {
relativeLocation = newLocation; relativeLocation = newLocation;
relativeRotation = newRelRotation; relativeRotation = newRelRotation;
@@ -77,22 +144,19 @@ void Component::internalSetTransform(Vector newLocation, Quaternion newRotation)
void Component::propagateTransformUpdate() void Component::propagateTransformUpdate()
{ {
for(auto child : children) for (auto child : children)
{
if(child != nullptr)
{ {
child->updateComponentTransform(child->relativeRotation); child->updateComponentTransform(child->relativeRotation);
} }
}
} }
void Component::updateComponentTransform(Quaternion relativeRotationQuat) void Component::updateComponentTransform(Quaternion relativeRotationQuat)
{ {
if(parent != nullptr && !parent->bComponentTransformClean) if (parent != nullptr && !parent->bComponentTransformClean)
{ {
parent->updateComponentTransform(parent->relativeRotation); parent->updateComponentTransform(parent->relativeRotation);
if(bComponentTransformClean) if (bComponentTransformClean)
{ {
return; return;
} }
@@ -100,9 +164,41 @@ void Component::updateComponentTransform(Quaternion relativeRotationQuat)
bComponentTransformClean = true; bComponentTransformClean = true;
Transform newTransform; Transform newTransform;
const Transform relTransform(relativeLocation, relativeRotationQuat, relativeScale); const Transform relTransform(relativeLocation, relativeRotationQuat, relativeScale);
if(parent != nullptr) if (parent != nullptr)
{ {
newTransform = parent->getTransform() * relTransform; newTransform = parent->getTransform() * relTransform;
} }
bool bHasChanged = !getTransform().equals(newTransform);
if (bHasChanged)
{
transform = newTransform;
propagateTransformUpdate();
}
}
Quaternion Component::getRelativeWorldRotation(Quaternion worldRotation)
{
Quaternion newRelRotation = worldRotation;
if (parent != nullptr)
{
const Transform parentToWorld = parent->getTransform();
const Quaternion parentToWorldQuat = parentToWorld.getRotation();
const Quaternion newRelQuat = glm::inverse(parentToWorldQuat) * worldRotation;
newRelRotation = newRelQuat;
}
return newRelRotation;
}
void Component::setRelativeLocationAndRotation(Vector newLocation, Quaternion newRotation)
{
if (!bComponentTransformClean)
{
updateComponentTransform(toQuaternion(relativeRotation));
}
const Transform desiredRelTransform(newLocation, newRotation);
const Transform desiredWorldTransform = parent->getTransform() * desiredRelTransform;
internalSetTransform(desiredWorldTransform.getPosition(), desiredWorldTransform.getRotation());
} }
+13 -6
View File
@@ -1,19 +1,21 @@
#pragma once #pragma once
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Transform.h" #include "Math/Transform.h"
namespace Seele namespace Seele
{ {
DECLARE_REF(Actor); DECLARE_REF(Actor);
DECLARE_REF(Scene);
DECLARE_REF(Component);
class Component class Component
{ {
public: public:
Component(); Component();
virtual ~Component(); virtual ~Component();
void tick(float deltaTime);
PComponent getParent(); PComponent getParent();
void setParent(PComponent parent);
PActor getOwner(); PActor getOwner();
void setOwner(PActor owner); virtual void notifySceneAttach(PScene scene);
void setWorldLocation(Vector location); void setWorldLocation(Vector location);
void setWorldRotation(Vector rotation); void setWorldRotation(Vector rotation);
@@ -28,21 +30,26 @@ public:
void addWorldTranslation(Vector translation); void addWorldTranslation(Vector translation);
void addWorldRotation(Vector rotation); void addWorldRotation(Vector rotation);
void addWorldRotation(Quaternion rotation); void addWorldRotation(Quaternion rotation);
void addWorldScale(Vector scale);
Transform getTransform() const; Transform getTransform() const;
private: private:
void setParent(PComponent parent);
void internalSetTransform(Vector newLocation, Quaternion newRotation); void internalSetTransform(Vector newLocation, Quaternion newRotation);
void propagateTransformUpdate(); void propagateTransformUpdate();
void updateComponentTransform(Quaternion relativeRotationQuat); void updateComponentTransform(Quaternion relativeRotationQuat);
uint8 bComponentTransformClean:1; Quaternion getRelativeWorldRotation(Quaternion worldRotation);
void setRelativeLocationAndRotation(Vector newLocation, Quaternion newRotation);
uint8 bComponentTransformClean : 1;
Vector relativeLocation; Vector relativeLocation;
Vector relativeRotation; Vector relativeRotation;
Vector relativeScale; Vector relativeScale;
Transform transform; Transform transform;
PScene owningScene;
PActor owner; PActor owner;
PComponent parent; PComponent parent;
Array<PComponent> children; Array<PComponent> children;
friend class Actor;
}; };
DEFINE_REF(Component) DEFINE_REF(Component)
} } // namespace Seele
@@ -0,0 +1,23 @@
#include "PrimitiveComponent.h"
#include "Scene/Scene.h"
#include "Material/MaterialInstance.h"
using namespace Seele;
PrimitiveComponent::PrimitiveComponent()
{
}
PrimitiveComponent::~PrimitiveComponent()
{
}
void PrimitiveComponent::notifySceneAttach(PScene scene)
{
scene->addPrimitiveComponent(this);
}
Matrix4 PrimitiveComponent::getRenderMatrix()
{
return getTransform().toMatrix();
}
@@ -1,12 +1,23 @@
#pragma once #pragma once
#include "Component.h" #include "Component.h"
#include "Graphics/GraphicsResources.h"
#include "Material/MaterialInstance.h"
namespace Seele namespace Seele
{ {
class PrimitiveComponent : public Component class PrimitiveComponent : public Component
{ {
public: public:
private: PrimitiveComponent();
~PrimitiveComponent();
virtual void notifySceneAttach(PScene scene) override;
Matrix4 getRenderMatrix();
private:
PMaterialInstance instance;
Gfx::PVertexBuffer vertexBuffer;
Gfx::PIndexBuffer indexBuffer;
friend class Scene;
}; };
} DEFINE_REF(PrimitiveComponent);
} // namespace Seele
+61
View File
@@ -0,0 +1,61 @@
#include "Scene.h"
#include "Components/PrimitiveComponent.h"
#include "Material/MaterialInstance.h"
#include "Material/Material.h"
using namespace Seele;
Scene::Scene()
{
}
Scene::~Scene()
{
}
void Scene::tick(float deltaTime)
{
for (auto actor : rootActors)
{
actor->tick(deltaTime);
}
}
void Scene::addActor(PActor actor)
{
rootActors.add(actor);
actor->notifySceneAttach(this);
}
void Scene::addPrimitiveComponent(PPrimitiveComponent comp)
{
primitives.add(comp);
}
Map<PMaterial, DrawState> Scene::getMeshBatches()
{
meshBatches.clear();
for (auto primitive : primitives)
{
PMaterialInstance matInstance = primitive->instance;
PMaterial mat = matInstance->getBaseMaterial();
DrawInstance inst;
inst.instance = primitive->instance;
inst.vertexBuffer = primitive->vertexBuffer;
inst.indexBuffer = primitive->indexBuffer;
inst.modelMatrix = primitive->getRenderMatrix();
if (meshBatches.find(mat) != meshBatches.end())
{
DrawState &state = meshBatches[mat];
state.instances.add(inst);
}
else
{
DrawState state;
state.instances.add(inst);
meshBatches[mat] = state;
}
}
return meshBatches;
}
+15 -1
View File
@@ -1,14 +1,28 @@
#pragma once
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Actor/Actor.h" #include "Actor/Actor.h"
#include "Graphics/GraphicsResources.h"
#include "Components/PrimitiveComponent.h"
namespace Seele namespace Seele
{ {
DECLARE_REF(Material);
class Scene class Scene
{ {
public: public:
Scene(); Scene();
~Scene(); ~Scene();
void tick(float deltaTime);
void addActor(PActor actor);
void addPrimitiveComponent(PPrimitiveComponent comp);
private: private:
Map<PMaterial, DrawState> meshBatches;
Array<PActor> rootActors; Array<PActor> rootActors;
Array<PPrimitiveComponent> primitives;
public:
Map<PMaterial, DrawState> getMeshBatches();
}; };
} } // namespace Seele
+3
View File
@@ -0,0 +1,3 @@
{
"test": "Hello World"
}