Basic crashing text rendering
This commit is contained in:
@@ -28,3 +28,6 @@
|
||||
[submodule "external/ttf-parser"]
|
||||
path = external/ttf-parser
|
||||
url = git@github.com:kv01/ttf-parser.git
|
||||
[submodule "external/freetype"]
|
||||
path = external/freetype
|
||||
url = https://gitlab.freedesktop.org/freetype/freetype.git
|
||||
|
||||
Vendored
+1
-1
@@ -4,7 +4,7 @@
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/src/**",
|
||||
"${workspaceFolder}/external/**"
|
||||
"${workspaceFolder}/src/Engine"
|
||||
],
|
||||
"defines": [
|
||||
"_DEBUG",
|
||||
|
||||
@@ -18,6 +18,7 @@ set(JSON_ROOT ${EXTERNAL_ROOT}/json)
|
||||
set(KTX_ROOT ${EXTERNAL_ROOT}/ktx)
|
||||
set(STB_ROOT ${EXTERNAL_ROOT}/stb)
|
||||
set(TTFPARSER_ROOT ${EXTERNAL_ROOT}/ttf-parser)
|
||||
set(FREETYPE_ROOT ${EXTERNAL_ROOT}/freetype)
|
||||
set(SPIRV_ROOT ${EXTERNAL_ROOT}/SPIRV-Cross)
|
||||
set(NSAM_ROOT ${EXTERNAL_ROOT}/aftermath)
|
||||
|
||||
@@ -50,6 +51,7 @@ find_package(Threads REQUIRED)
|
||||
find_package(Assimp REQUIRED)
|
||||
find_package(JSON REQUIRED)
|
||||
find_package(GLFW REQUIRED)
|
||||
find_package(FreeType REQUIRED)
|
||||
find_package(TTFParser REQUIRED)
|
||||
find_package(GLM REQUIRED)
|
||||
find_package(KTX REQUIRED)
|
||||
@@ -130,6 +132,7 @@ if(WIN32)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_BINARIES} $<TARGET_FILE_DIR:Engine>
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_GLSLANG} $<TARGET_FILE_DIR:Engine>
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GLFW_BINARY} $<TARGET_FILE_DIR:Engine>
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FREETYPE_BINARY} $<TARGET_FILE_DIR:Engine>
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ASSIMP_BINARY} $<TARGET_FILE_DIR:Engine>
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${NSAM_BINARIES} $<TARGET_FILE_DIR:Engine>
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${NSAM_LLVM} $<TARGET_FILE_DIR:Engine>
|
||||
|
||||
@@ -62,9 +62,9 @@ set(GLFW_VULKAN_STATIC OFF CACHE BOOL "GLFW vulkan static")
|
||||
add_subdirectory(${GLFW_ROOT} ${GLFW_ROOT})
|
||||
|
||||
#--------------FreeType------------------------------
|
||||
#list(APPEND DEPENDENCIES freetype)
|
||||
list(APPEND DEPENDENCIES freetype)
|
||||
|
||||
#add_subdirectory(${FREETYPE_ROOT} ${FREETYPE_ROOT})
|
||||
add_subdirectory(${FREETYPE_ROOT} ${FREETYPE_ROOT})
|
||||
|
||||
#--------------SLang------------------------------
|
||||
list(APPEND DEPENDENCIES slang)
|
||||
@@ -73,7 +73,7 @@ if(WIN32)
|
||||
ExternalProject_Add(slang
|
||||
SOURCE_DIR ${SLANG_ROOT}
|
||||
BINARY_DIR ${SLANG_ROOT}
|
||||
CONFIGURE_COMMAND ""
|
||||
CONFIGURE_COMMAND premake.bat vs2019 --file=${CMAKE_SOURCE_DIR}/external/slang/premake5.lua gmake --arch=${CMAKE_PLATFORM} --deps=true
|
||||
BUILD_COMMAND msbuild slang.sln -p:Configuration=Release -p:Platform=${CMAKE_PLATFORM}
|
||||
INSTALL_COMMAND "")
|
||||
elseif(UNIX)
|
||||
|
||||
+1
Submodule external/freetype added at e50798b720
Vendored
+1
-1
Submodule external/slang updated: 858c7c57b1...2e1a84add5
Binary file not shown.
@@ -0,0 +1,69 @@
|
||||
|
||||
struct GlyphData
|
||||
{
|
||||
float2 bearing;
|
||||
float2 size;
|
||||
};
|
||||
struct ViewData
|
||||
{
|
||||
float4x4 projectionMatrix;
|
||||
}
|
||||
layout(set = 0, binding = 0)
|
||||
ConstantBuffer<ViewData> viewData;
|
||||
layout(set = 0, binding = 1)
|
||||
SamplerState glyphSampler;
|
||||
layout(set = 0, binding = 2)
|
||||
StructuredBuffer<GlyphData> glyphData;
|
||||
layout(set = 1)
|
||||
Texture2D glyphTextures[];
|
||||
layout(push_constant)
|
||||
float scale;
|
||||
|
||||
struct VertexStageInput
|
||||
{
|
||||
uint glyphIndex;
|
||||
float2 position;
|
||||
uint vertexId : SV_VertexID;
|
||||
};
|
||||
|
||||
struct VertexStageOutput
|
||||
{
|
||||
float4 position : SV_Position;
|
||||
float2 uvCoords : TEXCOORD;
|
||||
uint glyphIndex : GLYPHINDEX;
|
||||
};
|
||||
|
||||
[shader("vertex")]
|
||||
VertexStageOutput vertexMain(VertexStageInput input)
|
||||
{
|
||||
GlyphData glyph = glyphData[input.glyphIndex];
|
||||
|
||||
float xpos = input.position.x + glyph.bearing.x * scale;
|
||||
float ypos = input.position.y - (glyph.size.y - glyph.bearing.y) * scale;
|
||||
|
||||
float w = glyph.size.x * scale;
|
||||
float h = glyph.size.y * scale;
|
||||
|
||||
float4 coordinates[4] = {
|
||||
float4(xpos, ypos + h, 0, 0),
|
||||
float4(xpos, ypos, 0, 1),
|
||||
float4(xpos + w, ypos, 1, 0),
|
||||
float4(xpos + w, ypos + h, 1, 1)
|
||||
};
|
||||
float4 vertex = coordinates[input.vertexId];
|
||||
VertexStageOutput output;
|
||||
output.uvCoords = vertex.zw;
|
||||
output.position = mul(viewData.projectionMatrix, float4(vertex.xy, 0, 1));
|
||||
output.glyphIndex = input.glyphIndex;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(
|
||||
float4 position : SV_Position,
|
||||
float2 uvCoords : TEXCOORD,
|
||||
uint glyphIndex : GLYPHINDEX
|
||||
) : SV_Target
|
||||
{
|
||||
return glyphTextures[glyphIndex].Sample(glyphSampler, uvCoords);
|
||||
}
|
||||
@@ -17,7 +17,6 @@ VertexStageOutput vertexMain(uint vertexId : SV_VertexID)
|
||||
VertexStageOutput output;
|
||||
output.uvCoords = coordinates[vertexId];
|
||||
output.position = float4(output.uvCoords * 2 - 1, 1, 1);
|
||||
output.position.y = -output.position.y;
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
slangc ForwardPlus.slang -target spirv -entry vertexMain -profile vs_6_0 -o vertex.spv -I lib/ -D USE_INSTANCING=0 -D NUM_MATERIAL_TEXCOORDS=1
|
||||
slangc ForwardPlus.slang -target spirv -entry fragmentMain -profile ps_6_0 -o fragment.spv -I lib/ -D USE_INSTANCING=0 -D NUM_MATERIAL_TEXCOORDS=1
|
||||
slangc TextPass.slang -target glsl -entry vertexMain -profile vs_6_0 -o vertex.glsl -I lib/ -D INDEX_VIEW_PARAMS=0
|
||||
slangc TextPass.slang -target glsl -entry fragmentMain -profile ps_6_0 -o fragment.glsl -I lib/ -D INDEX_VIEW_PARAMS=0
|
||||
@@ -0,0 +1,20 @@
|
||||
#version 450
|
||||
layout(row_major) uniform;
|
||||
layout(row_major) buffer;
|
||||
|
||||
#line 61 0
|
||||
layout(location = 0)
|
||||
out vec4 _S1;
|
||||
|
||||
|
||||
#line 61
|
||||
void main()
|
||||
{
|
||||
|
||||
#line 61
|
||||
_S1 = vec4(float(0), float(1), float(0), float(1));
|
||||
|
||||
#line 61
|
||||
return;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,114 @@
|
||||
#version 450
|
||||
layout(row_major) uniform;
|
||||
layout(row_major) buffer;
|
||||
|
||||
#line 7 0
|
||||
struct GlyphData_0
|
||||
{
|
||||
vec2 bearing_0;
|
||||
vec2 size_0;
|
||||
};
|
||||
|
||||
|
||||
layout(std430, binding = 1) readonly buffer _S1 {
|
||||
GlyphData_0 _data[];
|
||||
} glyphData_0;
|
||||
|
||||
#line 1
|
||||
struct ViewParameter_0
|
||||
{
|
||||
mat4x4 projectionMatrix_0;
|
||||
};
|
||||
|
||||
|
||||
#line 5
|
||||
layout(binding = 0)
|
||||
layout(std140) uniform _S2
|
||||
{
|
||||
ViewParameter_0 _data;
|
||||
} gViewParams_0;
|
||||
|
||||
#line 5
|
||||
layout(location = 0)
|
||||
out vec2 _S3;
|
||||
|
||||
|
||||
#line 5
|
||||
layout(location = 1)
|
||||
out uint _S4;
|
||||
|
||||
|
||||
#line 5
|
||||
layout(location = 0)
|
||||
in uint _S5;
|
||||
|
||||
|
||||
#line 5
|
||||
layout(location = 1)
|
||||
in vec2 _S6;
|
||||
|
||||
|
||||
#line 5
|
||||
layout(location = 2)
|
||||
in float _S7;
|
||||
|
||||
|
||||
#line 20
|
||||
struct VertexStageInput_0
|
||||
{
|
||||
uint glyphIndex_0;
|
||||
vec2 position_0;
|
||||
float scale_0;
|
||||
uint vertexId_0;
|
||||
};
|
||||
|
||||
struct VertexStageOutput_0
|
||||
{
|
||||
vec4 position_1;
|
||||
vec2 uvCoords_0;
|
||||
uint glyphIndex_1;
|
||||
};
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
#line 36
|
||||
VertexStageInput_0 _S8 = VertexStageInput_0(_S5, _S6, _S7, uint(gl_VertexIndex));
|
||||
|
||||
GlyphData_0 glyph_0 = ((glyphData_0)._data[(_S8.glyphIndex_0)]);
|
||||
|
||||
float xpos_0 = _S8.position_0.x + glyph_0.bearing_0.x * _S8.scale_0;
|
||||
float ypos_0 = _S8.position_0.y - (glyph_0.size_0.y - glyph_0.bearing_0.y) * _S8.scale_0;
|
||||
|
||||
float w_0 = glyph_0.size_0.x * _S8.scale_0;
|
||||
|
||||
|
||||
vec4 coordinates_0[4] = { vec4(xpos_0, ypos_0 + glyph_0.size_0.y * _S8.scale_0, float(0), float(0)), vec4(xpos_0, ypos_0, float(0), float(1)), vec4(xpos_0 + w_0, ypos_0, float(1), float(0)), vec4(xpos_0 + w_0, ypos_0 + w_0, float(1), float(1)) };
|
||||
|
||||
#line 46
|
||||
vec4 vertex_0 = coordinates_0[_S8.vertexId_0];
|
||||
|
||||
#line 53
|
||||
VertexStageOutput_0 output_0;
|
||||
output_0.uvCoords_0 = vertex_0.zw;
|
||||
vec4 _S9 = (((vec4(vertex_0.xy, float(0), float(1))) * (gViewParams_0._data.projectionMatrix_0)));
|
||||
|
||||
#line 55
|
||||
output_0.position_1 = _S9;
|
||||
output_0.glyphIndex_1 = _S8.glyphIndex_0;
|
||||
VertexStageOutput_0 _S10 = output_0;
|
||||
|
||||
#line 57
|
||||
gl_Position = _S10.position_1;
|
||||
|
||||
#line 57
|
||||
_S3 = _S10.uvCoords_0;
|
||||
|
||||
#line 57
|
||||
_S4 = _S10.glyphIndex_1;
|
||||
|
||||
#line 57
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "FontAsset.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#define TTF_FONT_PARSER_IMPLEMENTATION
|
||||
#include "ttfParser.h"
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include "Window/WindowManager.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -31,20 +32,30 @@ void FontAsset::save()
|
||||
|
||||
void FontAsset::load()
|
||||
{
|
||||
TTFFontParser::FontData font_data;
|
||||
int8_t error = TTFFontParser::parse_file(getFullPath().c_str(), &font_data, [](void*, void*, int){}, nullptr);
|
||||
assert(!error);
|
||||
for(auto pair : font_data.glyphs)
|
||||
FT_Library ft;
|
||||
assert(!FT_Init_FreeType(&ft));
|
||||
FT_Face face;
|
||||
assert(!FT_New_Face(ft, getFullPath().c_str(), 0, &face));
|
||||
FT_Set_Pixel_Sizes(face, 0, 48);
|
||||
for(uint8 c = 0; c < 128; ++c)
|
||||
{
|
||||
const TTFFontParser::Glyph& glyphData = pair.second;
|
||||
Glyph& glyph = glyphs[pair.first];
|
||||
glyph.advance = glyphData.advance_width;
|
||||
std::memcpy(glyph.boundingBox, glyphData.bounding_box, sizeof(glyphData.bounding_box));
|
||||
glyph.center = Vector2(glyphData.glyph_center.x, glyphData.glyph_center.y);
|
||||
glyph.index = glyphData.glyph_index;
|
||||
glyph.leftSideBearing = glyphData.left_side_bearing;
|
||||
glyph.numContours = glyphData.num_contours;
|
||||
Array<float> curveTextureData;
|
||||
|
||||
Gfx::PGraphics graphics = WindowManager::getGraphics();
|
||||
if(FT_Load_Char(face, c, FT_LOAD_RENDER))
|
||||
{
|
||||
std::cout << "error loading " << (char)c << std::endl;
|
||||
}
|
||||
TextureCreateInfo imageData;
|
||||
imageData.format = Gfx::SE_FORMAT_R8_UINT;
|
||||
imageData.width = face->glyph->bitmap.width;
|
||||
imageData.height = face->glyph->bitmap.rows;
|
||||
imageData.resourceData.data = face->glyph->bitmap.buffer;
|
||||
imageData.resourceData.size = imageData.width * imageData.height;
|
||||
Glyph& glyph = glyphs[c];
|
||||
glyph.texture = graphics->createTexture2D(imageData);
|
||||
glyph.size = IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
||||
glyph.bearing = IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
|
||||
glyph.advance = face->glyph->advance.x;
|
||||
}
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft);
|
||||
}
|
||||
@@ -13,18 +13,16 @@ public:
|
||||
virtual ~FontAsset();
|
||||
virtual void save() override;
|
||||
virtual void load() override;
|
||||
private:
|
||||
|
||||
struct Glyph
|
||||
{
|
||||
int16 index;
|
||||
int16 numContours;
|
||||
uint16 advance;
|
||||
int16 leftSideBearing;
|
||||
int16 boundingBox[4];
|
||||
Vector2 center;
|
||||
Gfx::PTexture2D curveTexture;
|
||||
Gfx::PTexture2D bandTexture;
|
||||
Gfx::PTexture2D texture;
|
||||
IVector2 size;
|
||||
IVector2 bearing;
|
||||
uint32 advance;
|
||||
};
|
||||
const Map<uint32, Glyph> getGlyphData() const { return glyphs; }
|
||||
private:
|
||||
Map<uint32, Glyph> glyphs;
|
||||
};
|
||||
DECLARE_REF(FontAsset)
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "Graphics/Vulkan/VulkanGraphicsEnums.h"
|
||||
#include "ktx.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <stb_image.h>
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
#include "ktx.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
|
||||
+28
-25
@@ -198,7 +198,7 @@ public:
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
Map()
|
||||
constexpr Map() noexcept
|
||||
: root(-1)
|
||||
, beginIt(-1)
|
||||
, endIt(-1)
|
||||
@@ -207,8 +207,7 @@ public:
|
||||
, comp(Compare())
|
||||
{
|
||||
}
|
||||
explicit Map(const Compare& comp,
|
||||
const Allocator& alloc = Allocator())
|
||||
constexpr explicit Map(const Compare& comp, const Allocator& alloc = Allocator()) noexcept(noexcept(Allocator()))
|
||||
: nodeContainer(alloc)
|
||||
, root(-1)
|
||||
, beginIt(-1)
|
||||
@@ -218,7 +217,7 @@ public:
|
||||
, comp(comp)
|
||||
{
|
||||
}
|
||||
explicit Map(const Allocator& alloc)
|
||||
constexpr explicit Map(const Allocator& alloc) noexcept(noexcept(Compare))
|
||||
: nodeContainer(alloc)
|
||||
, root(-1)
|
||||
, beginIt(-1)
|
||||
@@ -228,7 +227,7 @@ public:
|
||||
, comp(Compare())
|
||||
{
|
||||
}
|
||||
Map(const Map& other)
|
||||
constexpr Map(const Map& other)
|
||||
: nodeContainer(other.nodeContainer)
|
||||
, root(other.root)
|
||||
, _size(other._size)
|
||||
@@ -236,18 +235,18 @@ public:
|
||||
{
|
||||
markIteratorsDirty();
|
||||
}
|
||||
Map(Map&& other)
|
||||
: nodeContainer(other.nodeContainer)
|
||||
constexpr Map(Map&& other) noexcept
|
||||
: nodeContainer(std::move(other.nodeContainer))
|
||||
, root(std::move(other.root))
|
||||
, _size(std::move(other._size))
|
||||
, comp(std::move(other.comp))
|
||||
{
|
||||
markIteratorsDirty();
|
||||
}
|
||||
~Map()
|
||||
constexpr ~Map() noexcept
|
||||
{
|
||||
}
|
||||
Map& operator=(const Map& other)
|
||||
constexpr Map& operator=(const Map& other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
@@ -259,7 +258,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Map& operator=(Map&& other)
|
||||
constexpr Map& operator=(Map&& other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
@@ -271,7 +270,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline mapped_type& operator[](const key_type& key)
|
||||
constexpr mapped_type& operator[](const key_type& key)
|
||||
{
|
||||
root = splay(root, key);
|
||||
if (!isValid(root)
|
||||
@@ -284,7 +283,7 @@ public:
|
||||
markIteratorsDirty();
|
||||
return getNode(root)->pair.value;
|
||||
}
|
||||
inline mapped_type& operator[](key_type&& key)
|
||||
constexpr mapped_type& operator[](key_type&& key)
|
||||
{
|
||||
root = splay(root, std::move(key));
|
||||
if (!isValid(root)
|
||||
@@ -297,7 +296,7 @@ public:
|
||||
markIteratorsDirty();
|
||||
return getNode(root)->pair.value;
|
||||
}
|
||||
iterator find(const key_type& key)
|
||||
constexpr iterator find(const key_type& key)
|
||||
{
|
||||
root = splay(root, key);
|
||||
refreshIterators();
|
||||
@@ -309,7 +308,7 @@ public:
|
||||
}
|
||||
return iterator(root, &nodeContainer);
|
||||
}
|
||||
iterator find(key_type&& key)
|
||||
constexpr iterator find(key_type&& key)
|
||||
{
|
||||
root = splay(root, std::move(key));
|
||||
refreshIterators();
|
||||
@@ -321,30 +320,34 @@ public:
|
||||
}
|
||||
return iterator(root, &nodeContainer);
|
||||
}
|
||||
iterator erase(const key_type& key)
|
||||
constexpr iterator erase(const key_type& key)
|
||||
{
|
||||
root = remove(root, key);
|
||||
refreshIterators();
|
||||
return iterator(root, &nodeContainer);
|
||||
}
|
||||
iterator erase(K&& key)
|
||||
constexpr iterator erase(key_type&& key)
|
||||
{
|
||||
root = remove(root, std::move(key));
|
||||
refreshIterators();
|
||||
return iterator(root, &nodeContainer);
|
||||
}
|
||||
void clear()
|
||||
constexpr void clear()
|
||||
{
|
||||
nodeContainer.clear();
|
||||
root = -1;
|
||||
_size = 0;
|
||||
markIteratorsDirty();
|
||||
}
|
||||
bool exists(key_type&& key)
|
||||
constexpr bool exists(const key_type& key)
|
||||
{
|
||||
return find(std::forward<K>(key)) != endIt;
|
||||
return find(key) != endIt;
|
||||
}
|
||||
iterator begin()
|
||||
constexpr bool exists(key_type&& key)
|
||||
{
|
||||
return find(std::move(key)) != endIt;
|
||||
}
|
||||
constexpr iterator begin()
|
||||
{
|
||||
if(iteratorsDirty)
|
||||
{
|
||||
@@ -352,7 +355,7 @@ public:
|
||||
}
|
||||
return beginIt;
|
||||
}
|
||||
iterator end()
|
||||
constexpr iterator end()
|
||||
{
|
||||
if(iteratorsDirty)
|
||||
{
|
||||
@@ -360,7 +363,7 @@ public:
|
||||
}
|
||||
return endIt;
|
||||
}
|
||||
iterator begin() const
|
||||
constexpr iterator begin() const
|
||||
{
|
||||
if(iteratorsDirty)
|
||||
{
|
||||
@@ -368,7 +371,7 @@ public:
|
||||
}
|
||||
return beginIt;
|
||||
}
|
||||
iterator end() const
|
||||
constexpr iterator end() const
|
||||
{
|
||||
if(iteratorsDirty)
|
||||
{
|
||||
@@ -376,11 +379,11 @@ public:
|
||||
}
|
||||
return endIt;
|
||||
}
|
||||
bool empty() const
|
||||
constexpr bool empty() const
|
||||
{
|
||||
return nodeContainer.empty();
|
||||
}
|
||||
size_type size() const
|
||||
constexpr size_type size() const
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "Containers/Array.h"
|
||||
#include "VertexShaderInput.h"
|
||||
#include "ShaderCompiler.h"
|
||||
#include "ktx.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
|
||||
@@ -1404,6 +1404,19 @@ typedef enum SeDescriptorType
|
||||
SE_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||
} SeDescriptorType;
|
||||
|
||||
typedef enum SeDescriptorBindingFlagBits {
|
||||
SE_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0x00000001,
|
||||
SE_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002,
|
||||
SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0x00000004,
|
||||
SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0x00000008,
|
||||
SE_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = SE_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
|
||||
SE_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = SE_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
|
||||
SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
|
||||
SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT,
|
||||
SE_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||
} SeDescriptorBindingFlagBits;
|
||||
typedef SeFlags SeDescriptorBindingFlags;
|
||||
|
||||
typedef enum SeAttachmentLoadOp
|
||||
{
|
||||
SE_ATTACHMENT_LOAD_OP_LOAD = 0,
|
||||
|
||||
@@ -50,73 +50,63 @@ struct ViewportCreateInfo
|
||||
// doesnt own the data, only proxy it
|
||||
struct BulkResourceData
|
||||
{
|
||||
uint32 size;
|
||||
uint8 *data;
|
||||
uint32 size = 0;
|
||||
uint8 *data = nullptr;
|
||||
Gfx::QueueType owner = Gfx::QueueType::GRAPHICS;
|
||||
BulkResourceData()
|
||||
: size(0), data(nullptr), owner(Gfx::QueueType::GRAPHICS)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct TextureCreateInfo
|
||||
{
|
||||
BulkResourceData resourceData;
|
||||
uint32 width;
|
||||
uint32 height;
|
||||
uint32 depth;
|
||||
bool bArray;
|
||||
uint32 arrayLayers;
|
||||
uint32 mipLevels;
|
||||
uint32 samples;
|
||||
Gfx::SeFormat format;
|
||||
Gfx::SeImageUsageFlagBits usage;
|
||||
TextureCreateInfo()
|
||||
: resourceData(), 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)
|
||||
{
|
||||
}
|
||||
BulkResourceData resourceData = BulkResourceData();
|
||||
uint32 width = 1;
|
||||
uint32 height = 1;
|
||||
uint32 depth = 1;
|
||||
bool bArray = false;
|
||||
uint32 arrayLayers = 1;
|
||||
uint32 mipLevels = 1;
|
||||
uint32 samples = 1;
|
||||
Gfx::SeFormat format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT;
|
||||
Gfx::SeImageUsageFlagBits usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT;
|
||||
};
|
||||
struct SamplerCreateInfo
|
||||
{
|
||||
Gfx::SeSamplerCreateFlags flags;
|
||||
Gfx::SeFilter magFilter;
|
||||
Gfx::SeFilter minFilter;
|
||||
Gfx::SeSamplerMipmapMode mipmapMode;
|
||||
Gfx::SeSamplerAddressMode addressModeU;
|
||||
Gfx::SeSamplerAddressMode addressModeV;
|
||||
Gfx::SeSamplerAddressMode addressModeW;
|
||||
float mipLodBias;
|
||||
uint32 anisotropyEnable;
|
||||
float maxAnisotropy;
|
||||
uint32 compareEnable;
|
||||
Gfx::SeCompareOp compareOp;
|
||||
float minLod;
|
||||
float maxLod;
|
||||
Gfx::SeBorderColor borderColor;
|
||||
uint32 unnormalizedCoordinates;
|
||||
};
|
||||
struct VertexBufferCreateInfo
|
||||
{
|
||||
BulkResourceData resourceData;
|
||||
BulkResourceData resourceData = BulkResourceData();
|
||||
// bytes per vertex
|
||||
uint32 vertexSize;
|
||||
uint32 numVertices;
|
||||
VertexBufferCreateInfo()
|
||||
: resourceData(), vertexSize(0), numVertices(0)
|
||||
{
|
||||
}
|
||||
uint32 vertexSize = 0;
|
||||
uint32 numVertices = 0;
|
||||
};
|
||||
struct IndexBufferCreateInfo
|
||||
{
|
||||
BulkResourceData resourceData;
|
||||
Gfx::SeIndexType indexType;
|
||||
IndexBufferCreateInfo()
|
||||
: resourceData(), indexType(Gfx::SeIndexType::SE_INDEX_TYPE_UINT16)
|
||||
{
|
||||
}
|
||||
BulkResourceData resourceData = BulkResourceData();
|
||||
Gfx::SeIndexType indexType = Gfx::SeIndexType::SE_INDEX_TYPE_UINT16;
|
||||
};
|
||||
struct UniformBufferCreateInfo
|
||||
{
|
||||
BulkResourceData resourceData;
|
||||
uint8 bDynamic : 1;
|
||||
UniformBufferCreateInfo()
|
||||
: resourceData(), bDynamic(0)
|
||||
{
|
||||
}
|
||||
BulkResourceData resourceData = BulkResourceData();
|
||||
uint8 bDynamic : 1 = 0;
|
||||
};
|
||||
struct StructuredBufferCreateInfo
|
||||
{
|
||||
BulkResourceData resourceData;
|
||||
uint8 bDynamic: 1;
|
||||
StructuredBufferCreateInfo()
|
||||
: resourceData(), bDynamic(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct ShaderCreateInfo
|
||||
{
|
||||
@@ -138,13 +128,6 @@ struct SePushConstantRange
|
||||
};
|
||||
struct VertexElement
|
||||
{
|
||||
VertexElement(){}
|
||||
//VertexElement(uint8 attributeIndex, SeFormat vertexFormat, uint8 offset)
|
||||
// : attributeIndex(attributeIndex), vertexFormat(vertexFormat), offset(offset)
|
||||
//{}
|
||||
VertexElement(uint8 streamIndex, uint8 offset, SeFormat vertexFormat, uint8 attributeIndex, uint8 stride)
|
||||
: streamIndex(streamIndex), offset(offset), vertexFormat(vertexFormat), attributeIndex(attributeIndex), stride(stride)
|
||||
{}
|
||||
uint8 streamIndex;
|
||||
uint8 offset;
|
||||
SeFormat vertexFormat;
|
||||
@@ -152,6 +135,7 @@ struct VertexElement
|
||||
uint8 stride;
|
||||
uint8 bInstanced = 0;
|
||||
};
|
||||
static_assert(std::is_aggregate_v<VertexElement>);
|
||||
struct RasterizationState
|
||||
{
|
||||
uint8 depthClampEnable : 1;
|
||||
|
||||
@@ -93,17 +93,17 @@ ShaderCollection& ShaderMap::createShaders(
|
||||
|
||||
return collection;
|
||||
}
|
||||
void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount)
|
||||
void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount, SeDescriptorBindingFlags bindingFlags)
|
||||
{
|
||||
if (descriptorBindings.size() <= bindingIndex)
|
||||
{
|
||||
descriptorBindings.resize(bindingIndex + 1);
|
||||
}
|
||||
DescriptorBinding binding;
|
||||
DescriptorBinding& binding = descriptorBindings[bindingIndex];
|
||||
binding.binding = bindingIndex;
|
||||
binding.descriptorType = type;
|
||||
binding.descriptorCount = arrayCount;
|
||||
descriptorBindings[bindingIndex] = binding;
|
||||
binding.bindingFlags = bindingFlags;
|
||||
}
|
||||
|
||||
PDescriptorSet DescriptorLayout::allocateDescriptorSet()
|
||||
|
||||
@@ -160,16 +160,10 @@ public:
|
||||
: binding(other.binding), descriptorType(other.descriptorType), descriptorCount(other.descriptorCount), shaderStages(other.shaderStages)
|
||||
{
|
||||
}
|
||||
void operator=(const DescriptorBinding &other)
|
||||
{
|
||||
binding = other.binding;
|
||||
descriptorType = other.descriptorType;
|
||||
descriptorCount = other.descriptorCount;
|
||||
shaderStages = other.shaderStages;
|
||||
}
|
||||
uint32_t binding;
|
||||
SeDescriptorType descriptorType;
|
||||
uint32_t descriptorCount;
|
||||
SeDescriptorBindingFlags bindingFlags = 0;
|
||||
SeShaderStageFlags shaderStages;
|
||||
};
|
||||
DEFINE_REF(DescriptorBinding)
|
||||
@@ -196,6 +190,7 @@ public:
|
||||
virtual void updateBuffer(uint32 binding, PStructuredBuffer structuredBuffer) = 0;
|
||||
virtual void updateSampler(uint32 binding, PSamplerState samplerState) = 0;
|
||||
virtual void updateTexture(uint32 binding, PTexture texture, PSamplerState samplerState = nullptr) = 0;
|
||||
virtual void updateTextureArray(uint32_t binding, Array<PTexture> texture) = 0;
|
||||
virtual bool operator<(PDescriptorSet other) = 0;
|
||||
|
||||
virtual uint32 getSetIndex() const = 0;
|
||||
@@ -224,7 +219,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
virtual void create() = 0;
|
||||
virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1);
|
||||
virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1, SeDescriptorBindingFlags bindingFlags = 0);
|
||||
virtual void reset();
|
||||
virtual PDescriptorSet allocateDescriptorSet();
|
||||
const Array<DescriptorBinding> &getBindings() const { return descriptorBindings; }
|
||||
@@ -557,6 +552,7 @@ public:
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) = 0;
|
||||
virtual void bindVertexBuffer(const Array<VertexInputStream>& streams) = 0;
|
||||
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0;
|
||||
virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 0;
|
||||
virtual void draw(const MeshBatchElement& data) = 0;
|
||||
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) = 0;
|
||||
std::string name;
|
||||
@@ -571,6 +567,7 @@ public:
|
||||
virtual void bindPipeline(Gfx::PComputePipeline pipeline) = 0;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) = 0;
|
||||
virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 0;
|
||||
virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) = 0;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
@@ -11,5 +11,7 @@ target_sources(Engine
|
||||
RenderGraph.h
|
||||
RenderGraph.cpp
|
||||
RenderPass.h
|
||||
TextPass.h
|
||||
TextPass.cpp
|
||||
UIPass.h
|
||||
UIPass.cpp)
|
||||
@@ -0,0 +1,200 @@
|
||||
#include "TextPass.h"
|
||||
#include "RenderGraph.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Graphics/VertexShaderInput.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
TextPass::TextPass(Gfx::PGraphics graphics, Gfx::PViewport viewport, Gfx::PRenderTargetAttachment attachment)
|
||||
: RenderPass(graphics, viewport)
|
||||
, renderTarget(attachment)
|
||||
{
|
||||
}
|
||||
|
||||
TextPass::~TextPass()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MainJob TextPass::beginFrame()
|
||||
{
|
||||
for(TextRender& render : passData.texts)
|
||||
{
|
||||
FontData& fontData = getFontData(render.font);
|
||||
TextResources& resources = textResources.add();
|
||||
Array<GlyphInstanceData> instanceData;
|
||||
float x = render.position.x;
|
||||
float y = render.position.y;
|
||||
for(uint32 c : render.text)
|
||||
{
|
||||
instanceData.add(GlyphInstanceData{
|
||||
.glyphIndex = fontData.characterToGlyphIndex[c],
|
||||
.position = Vector2(x, y)
|
||||
});
|
||||
x += (fontData.characterAdvance[c] >> 6) * render.scale;
|
||||
}
|
||||
VertexBufferCreateInfo vbInfo;
|
||||
vbInfo.numVertices = static_cast<uint32>(instanceData.size());
|
||||
vbInfo.vertexSize = sizeof(GlyphInstanceData);
|
||||
vbInfo.resourceData.data = reinterpret_cast<uint8*>(instanceData.data());
|
||||
vbInfo.resourceData.size = static_cast<uint32>(instanceData.size());
|
||||
resources.vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
|
||||
resources.descriptorSet = descriptorLayout->allocateDescriptorSet();
|
||||
resources.descriptorSet->updateBuffer(0, projectionBuffer);
|
||||
resources.descriptorSet->updateSampler(1, glyphSampler);
|
||||
resources.descriptorSet->updateBuffer(2, fontData.structuredBuffer);
|
||||
resources.descriptorSet->writeChanges();
|
||||
|
||||
resources.textureArraySet = descriptorLayout->allocateDescriptorSet();
|
||||
resources.textureArraySet->updateTextureArray(0, fontData.textures);
|
||||
|
||||
resources.textureArraySet->writeChanges();
|
||||
resources.scale = render.scale;
|
||||
}
|
||||
co_return;
|
||||
}
|
||||
|
||||
MainJob TextPass::render()
|
||||
{
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Array<Gfx::PRenderCommand> commands;
|
||||
for(TextResources& resources : textResources)
|
||||
{
|
||||
Gfx::PRenderCommand command = graphics->createRenderCommand("TextPassCommand");
|
||||
command->setViewport(viewport);
|
||||
command->bindPipeline(pipeline);
|
||||
|
||||
command->bindVertexBuffer({VertexInputStream(0, 0, resources.vertexBuffer)});
|
||||
|
||||
command->pushConstants(pipelineLayout, Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float), &resources.scale);
|
||||
command->draw(4, static_cast<uint32>(resources.vertexBuffer->getNumVertices()), 0, 0);
|
||||
commands.add(command);
|
||||
}
|
||||
graphics->executeCommands(commands);
|
||||
graphics->endRenderPass();
|
||||
co_return;
|
||||
}
|
||||
|
||||
MainJob TextPass::endFrame()
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
void TextPass::publishOutputs()
|
||||
{
|
||||
}
|
||||
|
||||
void TextPass::createRenderPass()
|
||||
{
|
||||
depthAttachment = resources->requestRenderTarget("UIPASS_DEPTH");
|
||||
std::ifstream codeStream("./shaders/TextPass.slang", std::ios::ate);
|
||||
auto fileSize = codeStream.tellg();
|
||||
codeStream.seekg(0);
|
||||
Array<char> buffer(static_cast<uint32>(fileSize));
|
||||
codeStream.read(buffer.data(), fileSize);
|
||||
|
||||
ShaderCreateInfo createInfo;
|
||||
createInfo.shaderCode.add(std::string(buffer.data()));
|
||||
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
|
||||
createInfo.name = "TextVertex";
|
||||
createInfo.entryPoint = "vertexMain";
|
||||
vertexShader = graphics->createVertexShader(createInfo);
|
||||
|
||||
createInfo.name = "TextFragment";
|
||||
createInfo.entryPoint = "fragmentMain";
|
||||
fragmentShader = graphics->createFragmentShader(createInfo);
|
||||
Array<Gfx::VertexElement> elements;
|
||||
elements.add({
|
||||
.streamIndex = 0,
|
||||
.offset = offsetof(GlyphInstanceData, glyphIndex),
|
||||
.vertexFormat = Gfx::SE_FORMAT_R32_UINT,
|
||||
.attributeIndex = 0,
|
||||
.stride = sizeof(GlyphInstanceData),
|
||||
.bInstanced = 1
|
||||
});
|
||||
elements.add({
|
||||
.streamIndex = 0,
|
||||
.offset = offsetof(GlyphInstanceData, position),
|
||||
.vertexFormat = Gfx::SE_FORMAT_R32G32_SFLOAT,
|
||||
.attributeIndex = 1,
|
||||
.stride = sizeof(GlyphInstanceData),
|
||||
.bInstanced = 1
|
||||
});
|
||||
declaration = graphics->createVertexDeclaration(elements);
|
||||
|
||||
descriptorLayout = graphics->createDescriptorLayout("TextDescriptor");
|
||||
descriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
descriptorLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
|
||||
descriptorLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, 128, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT);
|
||||
descriptorLayout->create();
|
||||
|
||||
textureArrayLayout = graphics->createDescriptorLayout("TextureArray");
|
||||
textureArrayLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 128, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT);
|
||||
textureArrayLayout->create();
|
||||
|
||||
Matrix4 projectionMatrix = glm::ortho(0.f, (float)viewport->getSizeX(), 0.f, (float)viewport->getSizeY());
|
||||
projectionBuffer = graphics->createUniformBuffer({
|
||||
.resourceData = {
|
||||
.size = sizeof(Matrix4),
|
||||
.data = (uint8*)&projectionMatrix,
|
||||
},
|
||||
.bDynamic = false,
|
||||
});
|
||||
|
||||
glyphSampler = graphics->createSamplerState({
|
||||
.magFilter = Gfx::SE_FILTER_LINEAR,
|
||||
.minFilter = Gfx::SE_FILTER_LINEAR,
|
||||
.addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
|
||||
});
|
||||
|
||||
pipelineLayout = graphics->createPipelineLayout();
|
||||
pipelineLayout->addDescriptorLayout(0, descriptorLayout);
|
||||
pipelineLayout->addDescriptorLayout(1, textureArrayLayout);
|
||||
pipelineLayout->addPushConstants({
|
||||
.stageFlags = Gfx::SE_SHADER_STAGE_VERTEX_BIT,
|
||||
.offset = 0,
|
||||
.size = sizeof(float)});
|
||||
pipelineLayout->create();
|
||||
|
||||
Gfx::PRenderTargetLayout layout = new Gfx::RenderTargetLayout(renderTarget, depthAttachment);
|
||||
renderPass = graphics->createRenderPass(layout, viewport);
|
||||
|
||||
GraphicsPipelineCreateInfo pipelineInfo;
|
||||
pipelineInfo.vertexDeclaration = declaration;
|
||||
pipelineInfo.vertexShader = vertexShader;
|
||||
pipelineInfo.fragmentShader = fragmentShader;
|
||||
pipelineInfo.renderPass = renderPass;
|
||||
pipelineInfo.pipelineLayout = pipelineLayout;
|
||||
pipelineInfo.rasterizationState.cullMode = Gfx::SE_CULL_MODE_NONE;
|
||||
pipelineInfo.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
|
||||
pipeline = graphics->createGraphicsPipeline(pipelineInfo);
|
||||
}
|
||||
TextPass::FontData& TextPass::getFontData(PFontAsset font)
|
||||
{
|
||||
if(fontData.exists(font))
|
||||
{
|
||||
return fontData[font];
|
||||
}
|
||||
const Map<uint32, FontAsset::Glyph>& fontGlyphs = font->getGlyphData();
|
||||
FontData& fd = fontData[font];
|
||||
Array<GlyphData> buffer;
|
||||
buffer.reserve(fontGlyphs.size());
|
||||
for(const auto& [key, value] : fontGlyphs)
|
||||
{
|
||||
fd.characterToGlyphIndex[key] = static_cast<uint32>(buffer.size());
|
||||
fd.characterAdvance[key] = value.advance;
|
||||
fd.textures.add(value.texture);
|
||||
GlyphData& gd = buffer.add();
|
||||
gd.bearing = value.bearing;
|
||||
gd.size = value.size;
|
||||
}
|
||||
StructuredBufferCreateInfo bufferInfo;
|
||||
bufferInfo.bDynamic = false;
|
||||
bufferInfo.resourceData.data = reinterpret_cast<uint8*>(buffer.data());
|
||||
bufferInfo.resourceData.size = static_cast<uint32>(buffer.size());
|
||||
fd.structuredBuffer = graphics->createStructuredBuffer(bufferInfo);
|
||||
return fontData[font];
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
#include "RenderPass.h"
|
||||
#include "UI/RenderHierarchy.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "Asset/FontAsset.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_NAME_REF(Gfx, Texture2D)
|
||||
DECLARE_NAME_REF(Gfx, RenderTargetAttachment)
|
||||
DECLARE_NAME_REF(Gfx, StructuredBuffer)
|
||||
struct TextRender
|
||||
{
|
||||
std::string text;
|
||||
PFontAsset font;
|
||||
Vector4 textColor;
|
||||
Vector2 position;
|
||||
float scale;
|
||||
};
|
||||
struct TextPassData
|
||||
{
|
||||
Array<TextRender> texts;
|
||||
};
|
||||
|
||||
class TextPass : public RenderPass<TextPassData>
|
||||
{
|
||||
public:
|
||||
TextPass(Gfx::PGraphics graphics, Gfx::PViewport viewport, Gfx::PRenderTargetAttachment renderTarget);
|
||||
virtual ~TextPass();
|
||||
virtual MainJob beginFrame() override;
|
||||
virtual MainJob render() override;
|
||||
virtual MainJob endFrame() override;
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
private:
|
||||
struct GlyphData
|
||||
{
|
||||
Vector2 bearing;
|
||||
Vector2 size;
|
||||
};
|
||||
struct GlyphInstanceData
|
||||
{
|
||||
uint32 glyphIndex;
|
||||
Vector2 position;
|
||||
};
|
||||
struct FontData
|
||||
{
|
||||
Gfx::PStructuredBuffer structuredBuffer;
|
||||
Array<Gfx::PTexture> textures;
|
||||
Map<uint32, uint32> characterToGlyphIndex;
|
||||
// Logically this should be part of GlyphData,
|
||||
// but because GlyphData mirrors shader data and we need
|
||||
// the advance on the CPU, we need this in a separate structure
|
||||
Map<uint32, uint32> characterAdvance;
|
||||
};
|
||||
FontData& getFontData(PFontAsset font);
|
||||
Map<PFontAsset, FontData> fontData;
|
||||
|
||||
struct TextResources
|
||||
{
|
||||
Gfx::PDescriptorSet descriptorSet;
|
||||
Gfx::PDescriptorSet textureArraySet;
|
||||
Gfx::PVertexBuffer vertexBuffer;
|
||||
float scale;
|
||||
};
|
||||
Array<TextResources> textResources;
|
||||
|
||||
Gfx::PRenderTargetAttachment renderTarget;
|
||||
Gfx::PRenderTargetAttachment depthAttachment;
|
||||
Gfx::PTexture2D depthBuffer;
|
||||
|
||||
Gfx::PDescriptorLayout descriptorLayout;
|
||||
Gfx::PDescriptorLayout textureArrayLayout;
|
||||
|
||||
Gfx::PUniformBuffer projectionBuffer;
|
||||
Gfx::PSamplerState glyphSampler;
|
||||
|
||||
Gfx::PVertexDeclaration declaration;
|
||||
Gfx::PVertexShader vertexShader;
|
||||
Gfx::PFragmentShader fragmentShader;
|
||||
Gfx::PPipelineLayout pipelineLayout;
|
||||
Gfx::PGraphicsPipeline pipeline;
|
||||
};
|
||||
DEFINE_REF(TextPass);
|
||||
} // namespace Seele
|
||||
@@ -290,6 +290,13 @@ void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
|
||||
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
|
||||
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, cast(buf->getIndexType()));
|
||||
}
|
||||
|
||||
void RenderCommand::pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
vkCmdPushConstants(handle, layout.cast<PipelineLayout>()->getHandle(), stage, offset, size, data);
|
||||
}
|
||||
|
||||
void RenderCommand::draw(const MeshBatchElement& data)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
@@ -386,6 +393,12 @@ void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptor
|
||||
delete[] sets;
|
||||
}
|
||||
|
||||
void ComputeCommand::pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
vkCmdPushConstants(handle, layout.cast<PipelineLayout>()->getHandle(), stage, offset, size, data);
|
||||
}
|
||||
|
||||
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
|
||||
@@ -89,6 +89,7 @@ public:
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets) override;
|
||||
virtual void bindVertexBuffer(const Array<VertexInputStream>& streams) override;
|
||||
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
|
||||
virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) override;
|
||||
virtual void draw(const MeshBatchElement& data) override;
|
||||
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) override;
|
||||
private:
|
||||
@@ -121,6 +122,7 @@ public:
|
||||
virtual void bindPipeline(Gfx::PComputePipeline pipeline) override;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet set) override;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) override;
|
||||
virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) override;
|
||||
virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) override;
|
||||
private:
|
||||
PComputePipeline pipeline;
|
||||
|
||||
@@ -29,6 +29,7 @@ void DescriptorLayout::create()
|
||||
return;
|
||||
}
|
||||
bindings.resize(descriptorBindings.size());
|
||||
Array<VkDescriptorBindingFlags> bindingFlags(descriptorBindings.size());
|
||||
for (size_t i = 0; i < descriptorBindings.size(); ++i)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding &binding = bindings[i];
|
||||
@@ -38,9 +39,16 @@ void DescriptorLayout::create()
|
||||
binding.descriptorType = cast(rhiBinding.descriptorType);
|
||||
binding.stageFlags = rhiBinding.shaderStages;
|
||||
binding.pImmutableSamplers = nullptr;
|
||||
bindingFlags[i] = rhiBinding.bindingFlags;
|
||||
}
|
||||
VkDescriptorSetLayoutCreateInfo createInfo =
|
||||
init::DescriptorSetLayoutCreateInfo(bindings.data(), (uint32)bindings.size());
|
||||
VkDescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo = {};
|
||||
bindingFlagsInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO;
|
||||
bindingFlagsInfo.pNext = nullptr;
|
||||
bindingFlagsInfo.bindingCount = static_cast<uint32>(bindingFlags.size());
|
||||
bindingFlagsInfo.pBindingFlags = bindingFlags.data();
|
||||
createInfo.pNext = &bindingFlagsInfo;
|
||||
VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
|
||||
|
||||
allocator = new DescriptorAllocator(graphics, *this);
|
||||
@@ -188,20 +196,54 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::
|
||||
imageInfo.sampler = vulkanSampler->sampler;
|
||||
}
|
||||
imageInfos.add(imageInfo);
|
||||
VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
if(samplerState != nullptr)
|
||||
{
|
||||
descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
}
|
||||
else if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT)
|
||||
{
|
||||
descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
}
|
||||
VkWriteDescriptorSet writeDescriptor =
|
||||
init::WriteDescriptorSet(
|
||||
setHandle,
|
||||
samplerState != nullptr ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
descriptorType,
|
||||
binding,
|
||||
&imageInfos.back());
|
||||
if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT)
|
||||
{
|
||||
writeDescriptor.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
}
|
||||
|
||||
writeDescriptors.add(writeDescriptor);
|
||||
|
||||
cachedData[binding] = vulkanTexture;
|
||||
}
|
||||
void DescriptorSet::updateTextureArray(uint32_t binding, Array<Gfx::PTexture> textures)
|
||||
{
|
||||
// maybe make this a parameter?
|
||||
uint32 arrayElement = 0;
|
||||
for(const auto& gfxTexture : textures)
|
||||
{
|
||||
TextureHandle* vulkanTexture = TextureBase::cast(gfxTexture);
|
||||
imageInfos.add(
|
||||
init::DescriptorImageInfo(
|
||||
VK_NULL_HANDLE,
|
||||
vulkanTexture->getView(),
|
||||
cast(vulkanTexture->getLayout())));
|
||||
|
||||
VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT)
|
||||
{
|
||||
descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
}
|
||||
VkWriteDescriptorSet& write = writeDescriptors.add(
|
||||
init::WriteDescriptorSet(
|
||||
setHandle,
|
||||
descriptorType,
|
||||
binding,
|
||||
&imageInfos.back()
|
||||
));
|
||||
write.dstArrayElement = arrayElement++;
|
||||
}
|
||||
}
|
||||
|
||||
bool DescriptorSet::operator<(Gfx::PDescriptorSet other)
|
||||
{
|
||||
@@ -281,6 +323,20 @@ void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorS
|
||||
VkDescriptorSetLayout layoutHandle = layout.getHandle();
|
||||
VkDescriptorSetAllocateInfo allocInfo =
|
||||
init::DescriptorSetAllocateInfo(poolHandle, &layoutHandle, 1);
|
||||
VkDescriptorSetVariableDescriptorCountAllocateInfo setCounts = {};
|
||||
setCounts.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO;
|
||||
setCounts.pNext = nullptr;
|
||||
setCounts.descriptorSetCount = 1;
|
||||
uint32 counts = 0;
|
||||
for(const auto& binding : layout.bindings)
|
||||
{
|
||||
if(binding.binding & Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)
|
||||
{
|
||||
counts = binding.descriptorCount;
|
||||
}
|
||||
}
|
||||
setCounts.pDescriptorCounts = &counts;
|
||||
allocInfo.pNext = &setCounts;
|
||||
|
||||
for(uint32 setIndex = 0; setIndex < cachedHandles.size(); ++setIndex)
|
||||
{
|
||||
|
||||
@@ -12,11 +12,10 @@ public:
|
||||
DescriptorLayout(PGraphics graphics, const std::string& name);
|
||||
virtual ~DescriptorLayout();
|
||||
virtual void create();
|
||||
inline VkDescriptorSetLayout getHandle() const
|
||||
constexpr VkDescriptorSetLayout getHandle() const
|
||||
{
|
||||
return layoutHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 hash;
|
||||
PGraphics graphics;
|
||||
@@ -72,6 +71,7 @@ public:
|
||||
virtual void updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer);
|
||||
virtual void updateSampler(uint32_t binding, Gfx::PSamplerState samplerState);
|
||||
virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState sampler = nullptr);
|
||||
virtual void updateTextureArray(uint32_t binding, Array<Gfx::PTexture> texture);
|
||||
virtual bool operator<(Gfx::PDescriptorSet other);
|
||||
|
||||
inline bool isCurrentlyBound() const
|
||||
|
||||
@@ -204,11 +204,27 @@ Gfx::PComputePipeline Graphics::createComputePipeline(const ComputePipelineCreat
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
Gfx::PSamplerState Graphics::createSamplerState(const SamplerCreateInfo&)
|
||||
Gfx::PSamplerState Graphics::createSamplerState(const SamplerCreateInfo& createInfo)
|
||||
{
|
||||
PSamplerState sampler = new SamplerState(); // TODO: proper sampler creation
|
||||
PSamplerState sampler = new SamplerState();
|
||||
VkSamplerCreateInfo vkInfo =
|
||||
init::SamplerCreateInfo();
|
||||
vkInfo.addressModeU = cast(createInfo.addressModeU);
|
||||
vkInfo.addressModeV = cast(createInfo.addressModeV);
|
||||
vkInfo.addressModeW = cast(createInfo.addressModeW);
|
||||
vkInfo.anisotropyEnable = createInfo.anisotropyEnable;
|
||||
vkInfo.borderColor = cast(createInfo.borderColor);
|
||||
vkInfo.compareEnable = createInfo.compareEnable;
|
||||
vkInfo.compareOp = cast(createInfo.compareOp);
|
||||
vkInfo.flags = createInfo.flags;
|
||||
vkInfo.magFilter = cast(createInfo.magFilter);
|
||||
vkInfo.maxAnisotropy = createInfo.maxAnisotropy;
|
||||
vkInfo.maxLod = createInfo.maxLod;
|
||||
vkInfo.minFilter = cast(createInfo.minFilter);
|
||||
vkInfo.minLod = createInfo.minLod;
|
||||
vkInfo.mipLodBias = createInfo.mipLodBias;
|
||||
vkInfo.mipmapMode = cast(createInfo.mipmapMode);
|
||||
vkInfo.unnormalizedCoordinates = createInfo.unnormalizedCoordinates;
|
||||
VK_CHECK(vkCreateSampler(handle, &vkInfo, nullptr, &sampler->sampler));
|
||||
return sampler;
|
||||
}
|
||||
@@ -537,6 +553,15 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
||||
queueInfos.data(),
|
||||
(uint32)queueInfos.size(),
|
||||
&features);
|
||||
|
||||
VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexing = {};
|
||||
std::memset(&descriptorIndexing, 0, sizeof(descriptorIndexing));
|
||||
descriptorIndexing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES;
|
||||
descriptorIndexing.shaderSampledImageArrayNonUniformIndexing = VK_TRUE;
|
||||
descriptorIndexing.runtimeDescriptorArray = VK_TRUE;
|
||||
descriptorIndexing.descriptorBindingVariableDescriptorCount = VK_TRUE;
|
||||
descriptorIndexing.descriptorBindingPartiallyBound = VK_TRUE;
|
||||
deviceInfo.pNext = &descriptorIndexing;
|
||||
#if ENABLE_VALIDATION
|
||||
VkDeviceDiagnosticsConfigCreateInfoNV crashDiagInfo;
|
||||
crashDiagInfo.sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV;
|
||||
|
||||
@@ -1421,3 +1421,134 @@ Gfx::SeClearValue Seele::Vulkan::cast(const VkClearValue& clear)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
VkSamplerAddressMode Seele::Vulkan::cast(const Gfx::SeSamplerAddressMode &mode)
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case SE_SAMPLER_ADDRESS_MODE_REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case SE_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
case SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
|
||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
|
||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
case SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
|
||||
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
|
||||
default:
|
||||
return VK_SAMPLER_ADDRESS_MODE_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
Gfx::SeSamplerAddressMode Seele::Vulkan::cast(const VkSamplerAddressMode &mode)
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case VK_SAMPLER_ADDRESS_MODE_REPEAT:
|
||||
return SE_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
|
||||
return SE_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
|
||||
return SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
|
||||
return SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
|
||||
return SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
|
||||
default:
|
||||
return SE_SAMPLER_ADDRESS_MODE_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
VkBorderColor Seele::Vulkan::cast(const Gfx::SeBorderColor &color)
|
||||
{
|
||||
switch(color)
|
||||
{
|
||||
case SE_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
|
||||
return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
case SE_BORDER_COLOR_INT_TRANSPARENT_BLACK:
|
||||
return VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
|
||||
case SE_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
|
||||
return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
|
||||
case SE_BORDER_COLOR_INT_OPAQUE_BLACK:
|
||||
return VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||
case SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
|
||||
return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
case SE_BORDER_COLOR_INT_OPAQUE_WHITE:
|
||||
return VK_BORDER_COLOR_INT_OPAQUE_WHITE;
|
||||
default:
|
||||
return VK_BORDER_COLOR_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
Gfx::SeBorderColor Seele::Vulkan::cast(const VkBorderColor &color)
|
||||
{
|
||||
switch(color)
|
||||
{
|
||||
case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
|
||||
return SE_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
|
||||
return SE_BORDER_COLOR_INT_TRANSPARENT_BLACK;
|
||||
case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
|
||||
return SE_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
|
||||
case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
|
||||
return SE_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||
case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
|
||||
return SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
|
||||
return SE_BORDER_COLOR_INT_OPAQUE_WHITE;
|
||||
default:
|
||||
return SE_BORDER_COLOR_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
|
||||
VkFilter Seele::Vulkan::cast(const Gfx::SeFilter &filter)
|
||||
{
|
||||
switch(filter)
|
||||
{
|
||||
case SE_FILTER_NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SE_FILTER_LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
case SE_FILTER_CUBIC_IMG:
|
||||
return VK_FILTER_CUBIC_IMG;
|
||||
default:
|
||||
return VK_FILTER_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
Gfx::SeFilter Seele::Vulkan::cast(const VkFilter &filter)
|
||||
{
|
||||
switch(filter)
|
||||
{
|
||||
case VK_FILTER_NEAREST:
|
||||
return SE_FILTER_NEAREST;
|
||||
case VK_FILTER_LINEAR:
|
||||
return SE_FILTER_LINEAR;
|
||||
case VK_FILTER_CUBIC_IMG:
|
||||
return SE_FILTER_CUBIC_IMG;
|
||||
default:
|
||||
return SE_FILTER_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
|
||||
VkSamplerMipmapMode Seele::Vulkan::cast(const Gfx::SeSamplerMipmapMode &filter)
|
||||
{
|
||||
switch(filter)
|
||||
{
|
||||
case SE_SAMPLER_MIPMAP_MODE_NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SE_SAMPLER_MIPMAP_MODE_LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
default:
|
||||
return VK_SAMPLER_MIPMAP_MODE_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
Gfx::SeSamplerMipmapMode Seele::Vulkan::cast(const VkSamplerMipmapMode &filter)
|
||||
{
|
||||
switch(filter)
|
||||
{
|
||||
case VK_SAMPLER_MIPMAP_MODE_NEAREST:
|
||||
return SE_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case VK_SAMPLER_MIPMAP_MODE_LINEAR:
|
||||
return SE_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
default:
|
||||
return SE_SAMPLER_MIPMAP_MODE_MAX_ENUM;
|
||||
}
|
||||
}
|
||||
@@ -54,5 +54,13 @@ VkCompareOp cast(const Gfx::SeCompareOp &op);
|
||||
Gfx::SeCompareOp cast(const VkCompareOp &op);
|
||||
VkClearValue cast(const Gfx::SeClearValue &clear);
|
||||
Gfx::SeClearValue cast(const VkClearValue &clear);
|
||||
VkSamplerAddressMode cast(const Gfx::SeSamplerAddressMode &mode);
|
||||
Gfx::SeSamplerAddressMode cast(const VkSamplerAddressMode &mode);
|
||||
VkBorderColor cast(const Gfx::SeBorderColor &color);
|
||||
Gfx::SeBorderColor cast(const VkBorderColor &color);
|
||||
VkFilter cast(const Gfx::SeFilter &filter);
|
||||
Gfx::SeFilter cast(const VkFilter &filter);
|
||||
VkSamplerMipmapMode cast(const Gfx::SeSamplerMipmapMode &filter);
|
||||
Gfx::SeSamplerMipmapMode cast(const VkSamplerMipmapMode &filter);
|
||||
} // namespace Vulkan
|
||||
} // namespace Seele
|
||||
@@ -116,8 +116,7 @@ void MaterialAsset::load()
|
||||
{
|
||||
PSamplerParameter p = new SamplerParameter(param.key(), 0, bindingCounter);
|
||||
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
|
||||
SamplerCreateInfo createInfo;
|
||||
p->data = WindowManager::getGraphics()->createSamplerState(createInfo);
|
||||
p->data = WindowManager::getGraphics()->createSamplerState({});
|
||||
parameters.add(p);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,17 +2,29 @@
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Scene/Actor/Actor.h"
|
||||
#include "Window.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
InspectorView::InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo)
|
||||
: View(graphics, window, createInfo, "InspectorView")
|
||||
, uiPass(UIPass(graphics, viewport, new Gfx::SwapchainAttachment(window->getGfxHandle())))
|
||||
, textPass(TextPass(graphics, viewport, new Gfx::SwapchainAttachment(window->getGfxHandle())))
|
||||
{
|
||||
AssetRegistry::importFile("./fonts/Calibri.ttf");
|
||||
PRenderGraphResources resources = new RenderGraphResources();
|
||||
uiPass.setResources(resources);
|
||||
textPass.setResources(resources);
|
||||
uiPass.publishOutputs();
|
||||
textPass.publishOutputs();
|
||||
uiPass.createRenderPass();
|
||||
textPass.createRenderPass();
|
||||
TextRender& render = textPassData.texts.add();
|
||||
render.font = AssetRegistry::findFont("Calibri");
|
||||
render.text = "Seele Engine";
|
||||
render.position = Vector2(0.5f, 0.5f);
|
||||
render.scale = 1.0f;
|
||||
render.textColor = Vector4(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
InspectorView::~InspectorView()
|
||||
@@ -31,19 +43,21 @@ Job InspectorView::update()
|
||||
|
||||
void InspectorView::commitUpdate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InspectorView::prepareRender()
|
||||
{
|
||||
|
||||
textPass.updateViewFrame(textPassData);
|
||||
}
|
||||
|
||||
MainJob InspectorView::render()
|
||||
{
|
||||
return uiPass.beginFrame()
|
||||
.then(textPass.beginFrame())
|
||||
.then(uiPass.render())
|
||||
.then(uiPass.endFrame());
|
||||
.then(textPass.render())
|
||||
.then(uiPass.endFrame())
|
||||
.then(textPass.endFrame());
|
||||
}
|
||||
|
||||
void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "View.h"
|
||||
#include "Graphics/RenderPass/RenderGraph.h"
|
||||
#include "Graphics/RenderPass/UIPass.h"
|
||||
#include "Graphics/RenderPass/TextPass.h"
|
||||
#include "UI/Elements/Panel.h"
|
||||
|
||||
namespace Seele
|
||||
@@ -22,8 +23,10 @@ public:
|
||||
void selectActor();
|
||||
protected:
|
||||
UIPass uiPass;
|
||||
TextPass textPass;
|
||||
|
||||
UIPassData uiPassData;
|
||||
TextPassData textPassData;
|
||||
|
||||
UI::PPanel rootPanel;
|
||||
PActor selectedActor;
|
||||
|
||||
@@ -20,7 +20,6 @@ Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const Viewpo
|
||||
{
|
||||
scene = new Scene(graphics);
|
||||
scene->addActor(activeCamera);
|
||||
AssetRegistry::importFile("./fonts/GLSNECB.ttf");
|
||||
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Body_Diffuse.png");
|
||||
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Body_Lightmap.png");
|
||||
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Face_Diffuse.png");
|
||||
|
||||
+4
-136
@@ -19,7 +19,7 @@ int main()
|
||||
mainWindowInfo.pixelFormat = Gfx::SE_FORMAT_B8G8R8A8_UNORM;
|
||||
auto window = windowManager->addWindow(mainWindowInfo);
|
||||
ViewportCreateInfo sceneViewInfo;
|
||||
sceneViewInfo.sizeX = 1280;
|
||||
sceneViewInfo.sizeX = 680;
|
||||
sceneViewInfo.sizeY = 720;
|
||||
sceneViewInfo.offsetX = 0;
|
||||
sceneViewInfo.offsetY = 0;
|
||||
@@ -31,144 +31,12 @@ int main()
|
||||
inspectorViewInfo.sizeY = 720;
|
||||
inspectorViewInfo.offsetX = 640;
|
||||
inspectorViewInfo.offsetY = 0;
|
||||
//PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo);
|
||||
//window->addView(inspectorView);
|
||||
PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo);
|
||||
window->addView(inspectorView);
|
||||
sceneView->setFocused();
|
||||
|
||||
window->render();
|
||||
|
||||
getGlobalThreadPool().mainLoop();
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
#include <coroutine>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
struct Return;
|
||||
struct Promise
|
||||
{
|
||||
Promise()
|
||||
{
|
||||
handle = std::coroutine_handle<Promise>::from_promise(*this);
|
||||
numRefs = 0;
|
||||
}
|
||||
Return get_return_object();
|
||||
std::suspend_always initial_suspend() noexcept { return {}; }
|
||||
std::suspend_always final_suspend() noexcept { return {}; }
|
||||
void return_void() {}
|
||||
void unhandled_exception() {}
|
||||
void resume() { handle.resume(); }
|
||||
void addRef()
|
||||
{
|
||||
numRefs++;
|
||||
}
|
||||
void removeRef()
|
||||
{
|
||||
numRefs--;
|
||||
if(numRefs == 0)
|
||||
{
|
||||
if(handle.done())
|
||||
{
|
||||
handle.destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
std::coroutine_handle<Promise> handle;
|
||||
uint64_t numRefs;
|
||||
};
|
||||
|
||||
struct Return
|
||||
{
|
||||
using promise_type = Promise;
|
||||
Return(Promise* promise)
|
||||
: promise(promise)
|
||||
{
|
||||
promise->addRef();
|
||||
}
|
||||
Return(const Return& other)
|
||||
{
|
||||
promise = other.promise;
|
||||
if(promise != nullptr)
|
||||
{
|
||||
promise->addRef();
|
||||
}
|
||||
}
|
||||
Return(Return&& other)
|
||||
{
|
||||
promise = other.promise;
|
||||
other.promise = nullptr;
|
||||
}
|
||||
~Return()
|
||||
{
|
||||
promise->removeRef();
|
||||
}
|
||||
Return& operator=(const Return& other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
if(promise != nullptr)
|
||||
{
|
||||
promise->removeRef();
|
||||
}
|
||||
promise = other.promise;
|
||||
if(promise != nullptr)
|
||||
{
|
||||
promise->addRef();
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Return& operator=(Return&& other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
if(promise != nullptr)
|
||||
{
|
||||
promise->removeRef();
|
||||
}
|
||||
promise = other.promise;
|
||||
}
|
||||
}
|
||||
Promise* promise;
|
||||
};
|
||||
|
||||
|
||||
Return Promise::get_return_object(){
|
||||
return {this};
|
||||
}
|
||||
|
||||
Return coro1()
|
||||
{
|
||||
std::cout << "coro1" << std::endl;
|
||||
co_return;
|
||||
}
|
||||
|
||||
Return coro2()
|
||||
{
|
||||
std::cout << "coro2" << std::endl;
|
||||
co_return;
|
||||
}
|
||||
|
||||
Return coroAll(std::vector<Return> coros)
|
||||
{
|
||||
for(auto coro : coros)
|
||||
{
|
||||
coro.promise->resume();
|
||||
}
|
||||
co_return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<Return> returns{coro1(), coro2()};
|
||||
std::thread t = std::thread([returns](){
|
||||
coroAll(returns);
|
||||
});
|
||||
t.join();
|
||||
}*/
|
||||
}
|
||||
Reference in New Issue
Block a user