Skip to content

Commit 7705a4d

Browse files
committed
Merge branch 'master' into cad-text-rendering-mip-maps
2 parents 4d256b8 + a39779f commit 7705a4d

File tree

10 files changed

+135
-45
lines changed

10 files changed

+135
-45
lines changed

3rdparty/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ add_library(Freetype::Freetype ALIAS freetype) # alias target for MSDFGEN not tr
3030

3131
# msdfgen
3232
set(MSDFGEN_USE_VCPKG OFF)
33+
set(MSDFGEN_USE_SKIA OFF)
3334
set(MSDFGEN_CORE_ONLY OFF) # if turned on then MSDFGEN will be built without dependencies like freetype or skia
3435
set(MSDFGEN_INSTALL OFF)
3536
set(MSDFGEN_BUILD_STANDALONE OFF)

include/nbl/ext/TextRendering/TextRendering.h

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77

88
#include "nabla.h"
99

10-
#include "nbl/video/utilities/CPropertyPool.h"
1110
#include <msdfgen/msdfgen.h>
1211
#include <ft2build.h>
13-
#include <nbl/ext/TextRendering/TextRendering.h>
1412
#include <nbl/builtin/hlsl/cpp_compat.hlsl>
1513
#include <nbl/builtin/hlsl/cpp_compat/matrix.hlsl>
1614
#include <nbl/builtin/hlsl/cpp_compat/vector.hlsl>
@@ -46,6 +44,12 @@ class TextRenderer : public nbl::core::IReferenceCounted
4644
auto error = FT_Init_FreeType(&m_ftLibrary);
4745
assert(!error);
4846
}
47+
48+
~TextRenderer()
49+
{
50+
auto error = FT_Done_FreeType(m_ftLibrary);
51+
assert(!error);
52+
}
4953

5054
// TODO: Remove these here, it's only used for customized tests such as building shapes for hatches
5155
const FT_Library& getFreetypeLibrary() const { return m_ftLibrary; }
@@ -59,11 +63,23 @@ class TextRenderer : public nbl::core::IReferenceCounted
5963
class FontFace : public nbl::core::IReferenceCounted
6064
{
6165
public:
66+
67+
// Face Global Metrics/Settings
68+
struct Metrics
69+
{
70+
// This value is the vertical distance between two consecutive baselines, expressed in font units. It is always positive.
71+
float64_t height;
72+
// The distance from the baseline to the highest or upper grid coordinate used to place an outline point. It is a positive value.
73+
float64_t ascent;
74+
// The distance from the baseline to the lowest grid coordinate used to place an outline point. this is almost always a negative value.
75+
float64_t descent;
76+
};
77+
6278
struct GlyphMetrics
6379
{
6480
// Offset that should be applied to the current baseline after this glyph is placed
6581
float64_t2 advance;
66-
// Offset that the image of the glyph should be placed from the current baseline start, horizontal refers to horizonral LTR or RTL Languages
82+
// Offset of the glyph's top left from the current baseline start, horizontal refers to horizonral LTR or RTL Languages
6783
float64_t2 horizontalBearing;
6884
// Size of the glyph in the text line
6985
float64_t2 size;
@@ -79,6 +95,12 @@ class FontFace : public nbl::core::IReferenceCounted
7995
m_hash = std::hash<std::string>{}(path);
8096
}
8197

98+
~FontFace()
99+
{
100+
auto error = FT_Done_Face(m_ftFace);
101+
assert(!error);
102+
}
103+
82104
static constexpr uint32_t InvalidGlyphIndex = ~0u;
83105

84106
uint32_t getGlyphIndex(wchar_t unicode)
@@ -91,7 +113,9 @@ class FontFace : public nbl::core::IReferenceCounted
91113
return FT_Get_Char_Index(m_ftFace, unicode);
92114
}
93115

94-
GlyphMetrics getGlyphMetricss(uint32_t glyphId);
116+
Metrics getMetrics() const;
117+
118+
GlyphMetrics getGlyphMetrics(uint32_t glyphId);
95119

96120
// returns the cpu buffer for the generated MSDF texture with "TextRenderer::MSDFTextureFormat" format
97121
// it will place the glyph in the center of msdfExtents considering the margin of msdfPixelRange
@@ -142,7 +166,7 @@ class GlyphShapeBuilder {
142166
void lineTo(const float64_t2 to)
143167
{
144168
if (to != lastPosition) {
145-
currentContour->addEdge(new msdfgen::LinearSegment(msdfPoint(lastPosition), msdfPoint(to)));
169+
currentContour->addEdge(msdfgen::EdgeHolder(msdfPoint(lastPosition), msdfPoint(to)));
146170
lastPosition = to;
147171
}
148172
}
@@ -151,15 +175,15 @@ class GlyphShapeBuilder {
151175
// [last position, control, end]
152176
void quadratic(const float64_t2 control, const float64_t2 to)
153177
{
154-
currentContour->addEdge(new msdfgen::QuadraticSegment(msdfPoint(lastPosition), msdfPoint(control), msdfPoint(to)));
178+
currentContour->addEdge(msdfgen::EdgeHolder(msdfPoint(lastPosition), msdfPoint(control), msdfPoint(to)));
155179
lastPosition = to;
156180
}
157181

158182
// Continue the last moveTo or lineTo with a cubic bezier:
159183
// [last position, control1, control2, end]
160184
void cubic(const float64_t2 control1, const float64_t2 control2, const float64_t2 to)
161185
{
162-
currentContour->addEdge(new msdfgen::CubicSegment(msdfPoint(lastPosition), msdfPoint(control1), msdfPoint(control2), msdfPoint(to)));
186+
currentContour->addEdge(msdfgen::EdgeHolder(msdfPoint(lastPosition), msdfPoint(control1), msdfPoint(control2), msdfPoint(to)));
163187
lastPosition = to;
164188
}
165189

include/nbl/video/utilities/SIntendedSubmitInfo.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,24 +130,36 @@ struct SIntendedSubmitInfo final : core::Uncopyable
130130

131131
// One thing you might notice is that this results in a few implicit Memory and Execution Dependencies
132132
// So there's a little bit of non-deterministic behaviour we won't fight (will not insert a barrier every time you "could-have" overflown)
133-
inline void overflowSubmit()
133+
inline IQueue::RESULT overflowSubmit()
134134
{
135135
auto cmdbuf = getScratchCommandBuffer();
136136
// first sumbit the already buffered up work
137137
cmdbuf->end();
138+
138139
// we only signal the scratch semaphore when overflowing
139140
const auto submit = popSubmit({});
140-
queue->submit(submit);
141+
IQueue::RESULT res = queue->submit(submit);
142+
if (res != IQueue::RESULT::SUCCESS)
143+
return res;
144+
141145
// We wait (stall) on the immediately preceeding submission, this could be improved in the future with multiple buffering of the commandbuffers
142146
{
143147
const ISemaphore::SWaitInfo info = {.semaphore=scratchSemaphore.semaphore,.value=scratchSemaphore.value};
144-
const_cast<ILogicalDevice*>(cmdbuf->getOriginDevice())->blockForSemaphores({&info,1});
148+
ISemaphore::WAIT_RESULT waitResult = const_cast<ILogicalDevice*>(cmdbuf->getOriginDevice())->blockForSemaphores({&info,1});
149+
if (waitResult != ISemaphore::WAIT_RESULT::SUCCESS)
150+
{
151+
assert(false);
152+
return IQueue::RESULT::OTHER_ERROR;
153+
}
145154
}
146155
// since all the commandbuffers have submitted already we only reuse the last one
147156
commandBuffers = {&commandBuffers.back(),1};
157+
158+
148159
// we will still signal the same set in the future
149160
cmdbuf->reset(IGPUCommandBuffer::RESET_FLAGS::RELEASE_RESOURCES_BIT);
150161
cmdbuf->begin(IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT);
162+
return res;
151163
}
152164

153165
// Error Text to Log/Display if you try to use an invalid `SIntendedSubmitInfo`

src/nbl/builtin/builtinDataGen.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
# Creates a c++ file for builtin resources that contains binary data of all resources
22

3-
# TODO: use argparse not this by-hand-shit
4-
5-
import sys, os, subprocess, json
3+
import argparse, os, subprocess, json
64
from datetime import datetime, timezone
75

8-
if len(sys.argv) < 8 :
9-
print(sys.argv[0] + " - Incorrect argument count")
10-
else:
11-
outputBuiltinPath = sys.argv[1]
12-
outputArchivePath = sys.argv[2]
13-
bundleAbsoluteEntryPath = sys.argv[3]
14-
resourcesFile = sys.argv[4]
15-
resourcesNamespace = sys.argv[5]
16-
correspondingHeaderFile = sys.argv[6]
17-
xxHash256Exe = sys.argv[7]
6+
7+
parser = argparse.ArgumentParser(description="Creates a c++ file for builtin resources that contains binary data of all resources")
8+
parser.add_argument('--outputBuiltinPath', required=True, help="output path of generated C++ builtin data source")
9+
parser.add_argument('--outputArchivePath', required=True, help="output path of generated C++ archive data source")
10+
parser.add_argument('--bundleAbsoluteEntryPath', required=True, help="\"absolute path\" for an archive which will store a given bundle of builtin resources")
11+
parser.add_argument('--resourcesFile', required=True, help="path to file containing resources list")
12+
parser.add_argument('--resourcesNamespace', required=True, help="a C++ namespace builtin resources will be wrapped into")
13+
parser.add_argument('--correspondingHeaderFile', required=True, help="filename of previosly generated header (via buitinHeaderGen.py)")
14+
parser.add_argument('--xxHash256Exe', default="", nargs='?', help="path to xxHash256 executable")
15+
16+
def execute(args):
17+
outputBuiltinPath = args.outputBuiltinPath
18+
outputArchivePath = args.outputArchivePath
19+
bundleAbsoluteEntryPath = args.bundleAbsoluteEntryPath
20+
resourcesFile = args.resourcesFile
21+
resourcesNamespace = args.resourcesNamespace
22+
correspondingHeaderFile = args.correspondingHeaderFile
23+
xxHash256Exe = args.xxHash256Exe
1824

1925
forceConstexprHash = True if not xxHash256Exe else False
2026

@@ -196,4 +202,9 @@
196202

197203
outp = open(outputArchivePath, "w+")
198204
outp.write(archiveSource)
199-
outp.close()
205+
outp.close()
206+
207+
208+
if __name__ == "__main__":
209+
args: argparse.Namespace = parser.parse_args()
210+
execute(args)

src/nbl/builtin/builtinHeaderGen.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
# Creates a header file for builtin resources
22

3-
# TODO: use argparse not this by-hand-shit
4-
5-
import sys, os
6-
7-
if len(sys.argv) < 8 :
8-
print(sys.argv[0] + " - Incorrect argument count")
9-
else:
10-
outputBuiltinPath = sys.argv[1]
11-
outputArchivePath = sys.argv[2]
12-
archiveBundlePath = sys.argv[3]
13-
resourcesFile = sys.argv[4]
14-
resourcesNamespace = sys.argv[5]
15-
guardSuffix = sys.argv[6]
16-
isSharedLibrary = True if sys.argv[7] == "True" else False
3+
import argparse, sys, os
4+
5+
6+
parser = argparse.ArgumentParser(description="Creates a c++ file for builtin resources that contains binary data of all resources")
7+
parser.add_argument('--outputBuiltinPath', required=True, help="output path of generated C++ builtin header source")
8+
parser.add_argument('--outputArchivePath', required=True, help="output path of generated C++ archive header source")
9+
parser.add_argument('--archiveBundlePath', required=True, help="path for an archive which will store a given bundle of builtin resources")
10+
parser.add_argument('--resourcesFile', required=True, help="path for a file which containins list of resources")
11+
parser.add_argument('--resourcesNamespace', required=True, help="a C++ namespace builtin resources will be wrapped into")
12+
parser.add_argument('--guardSuffix', required=True, help="include guard suffix name, for C header files")
13+
parser.add_argument('--isSharedLibrary', required=True, choices=["True", "False"])
14+
15+
def execute(args):
16+
outputBuiltinPath = args.outputBuiltinPath
17+
outputArchivePath = args.outputArchivePath
18+
archiveBundlePath = args.archiveBundlePath
19+
resourcesFile = args.resourcesFile
20+
resourcesNamespace = args.resourcesNamespace
21+
guardSuffix = args.guardSuffix
22+
isSharedLibrary = True if args.isSharedLibrary == "True" else False
1723

1824
NBL_BR_API = "NBL_BR_API" if isSharedLibrary else ""
1925

@@ -134,3 +140,7 @@ class {NBL_BR_API} CArchive final : public nbl::system::CFileArchive
134140
outp = open(outputArchivePath, "w+")
135141
outp.write(archiveHeader)
136142
outp.close()
143+
144+
if __name__ == "__main__":
145+
args: argparse.Namespace = parser.parse_args()
146+
execute(args)

src/nbl/builtin/utils.cmake

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,14 @@ function(ADD_CUSTOM_BUILTIN_RESOURCES _TARGET_NAME_ _BUNDLE_NAME_ _BUNDLE_SEARCH
133133
set(_NBL_BR_RUNTIME_HASH_ 1)
134134
endif()
135135

136+
set(NBL_BUILTIN_RESOURCES_COMMON_ARGS
137+
--resourcesFile "${NBL_RESOURCES_LIST_FILE}"
138+
--resourcesNamespace "${_NAMESPACE_}"
139+
)
140+
136141
add_custom_command(OUTPUT "${NBL_BUILTIN_RESOURCES_H}" "${NBL_BUILTIN_RESOURCE_DATA_CPP}" "${NBL_BUILTIN_DATA_ARCHIVE_H}" "${NBL_BUILTIN_DATA_ARCHIVE_CPP}"
137-
COMMAND "${_Python3_EXECUTABLE}" "${NBL_BUILTIN_HEADER_GEN_PY}" "${NBL_BUILTIN_RESOURCES_H}" "${NBL_BUILTIN_DATA_ARCHIVE_H}" "${_BUNDLE_ARCHIVE_ABSOLUTE_PATH_}" "${NBL_RESOURCES_LIST_FILE}" "${_NAMESPACE_}" "${_GUARD_SUFFIX_}" "${_SHARED_}"
138-
COMMAND "${_Python3_EXECUTABLE}" "${NBL_BUILTIN_DATA_GEN_PY}" "${NBL_BUILTIN_RESOURCE_DATA_CPP}" "${NBL_BUILTIN_DATA_ARCHIVE_CPP}" "${_BUNDLE_SEARCH_DIRECTORY_}/${_BUNDLE_ARCHIVE_ABSOLUTE_PATH_}" "${NBL_RESOURCES_LIST_FILE}" "${_NAMESPACE_}" "${NBL_BS_HEADER_FILENAME}" "$<${_NBL_BR_RUNTIME_HASH_}:$<TARGET_FILE:xxHash256>>"
142+
COMMAND "${_Python3_EXECUTABLE}" "${NBL_BUILTIN_HEADER_GEN_PY}" ${NBL_BUILTIN_RESOURCES_COMMON_ARGS} --outputBuiltinPath "${NBL_BUILTIN_RESOURCES_H}" --outputArchivePath "${NBL_BUILTIN_DATA_ARCHIVE_H}" --archiveBundlePath "${_BUNDLE_ARCHIVE_ABSOLUTE_PATH_}" --guardSuffix "${_GUARD_SUFFIX_}" --isSharedLibrary "${_SHARED_}"
143+
COMMAND "${_Python3_EXECUTABLE}" "${NBL_BUILTIN_DATA_GEN_PY}" ${NBL_BUILTIN_RESOURCES_COMMON_ARGS} --outputBuiltinPath "${NBL_BUILTIN_RESOURCE_DATA_CPP}" --outputArchivePath "${NBL_BUILTIN_DATA_ARCHIVE_CPP}" --bundleAbsoluteEntryPath "${_BUNDLE_SEARCH_DIRECTORY_}/${_BUNDLE_ARCHIVE_ABSOLUTE_PATH_}" --correspondingHeaderFile "${NBL_BS_HEADER_FILENAME}" --xxHash256Exe "$<${_NBL_BR_RUNTIME_HASH_}:$<TARGET_FILE:xxHash256>>"
139144
COMMENT "Generating \"${_TARGET_NAME_}\"'s sources & headers"
140145
DEPENDS ${NBL_DEPENDENCY_FILES}
141146
VERBATIM

src/nbl/ext/TextRendering/TextRendering.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
using namespace nbl;
32
using namespace nbl::core;
43
using namespace nbl::asset;
@@ -57,7 +56,16 @@ core::smart_refctd_ptr<ICPUBuffer> TextRenderer::generateShapeMSDF(msdfgen::Shap
5756

5857
constexpr double FreeTypeFontScaling = 1.0 / 64.0;
5958

60-
FontFace::GlyphMetrics FontFace::getGlyphMetricss(uint32_t glyphId)
59+
FontFace::Metrics FontFace::getMetrics() const
60+
{
61+
Metrics ret = {};
62+
ret.height = float64_t(m_ftFace->height) * FreeTypeFontScaling;
63+
ret.ascent = float64_t(m_ftFace->ascender) * FreeTypeFontScaling;
64+
ret.descent = float64_t(m_ftFace->descender) * FreeTypeFontScaling;
65+
return ret;
66+
}
67+
68+
FontFace::GlyphMetrics FontFace::getGlyphMetrics(uint32_t glyphId)
6169
{
6270
auto slot = getGlyphSlot(glyphId);
6371

@@ -177,4 +185,4 @@ msdfgen::Shape FontFace::generateGlyphShape(uint32_t glyphId)
177185

178186
}
179187
}
180-
}
188+
}

src/nbl/video/IGPUCommandBuffer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ bool IGPUCommandBuffer::reset(const core::bitflag<RESET_FLAGS> flags)
156156
{
157157
if (!canReset())
158158
{
159-
m_logger.log("Failed to reset command buffer.", system::ILogger::ELL_ERROR);
159+
m_logger.log("Failed to reset command buffer, state is: %d", system::ILogger::ELL_ERROR, (uint32_t)m_state);
160160
m_state = STATE::INVALID;
161161
return false;
162162
}

src/nbl/video/ILogicalDevice.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,10 @@ core::smart_refctd_ptr<IGPUBufferView> ILogicalDevice::createBufferView(const as
260260
core::smart_refctd_ptr<IGPUShader> ILogicalDevice::createShader(const SShaderCreationParameters& creationParams)
261261
{
262262
if (!creationParams.cpushader)
263+
{
264+
m_logger.log("No valid CPU Shader supplied",system::ILogger::ELL_ERROR);
263265
return nullptr;
266+
}
264267

265268
const asset::IShader::E_SHADER_STAGE shaderStage = creationParams.cpushader->getStage();
266269
const auto& features = getEnabledFeatures();
@@ -277,11 +280,17 @@ core::smart_refctd_ptr<IGPUShader> ILogicalDevice::createShader(const SShaderCre
277280
case IGPUShader::E_SHADER_STAGE::ESS_TESSELLATION_CONTROL: [[fallthrough]];
278281
case IGPUShader::E_SHADER_STAGE::ESS_TESSELLATION_EVALUATION:
279282
if (!features.tessellationShader)
283+
{
284+
m_logger.log("Cannot create IGPUShader for %p, Tessellation Shader feature not enabled!",system::ILogger::ELL_ERROR,creationParams.cpushader);
280285
return nullptr;
286+
}
281287
break;
282288
case IGPUShader::E_SHADER_STAGE::ESS_GEOMETRY:
283289
if (!features.geometryShader)
290+
{
291+
m_logger.log("Cannot create IGPUShader for %p, Geometry Shader feature not enabled!",system::ILogger::ELL_ERROR,creationParams.cpushader);
284292
return nullptr;
293+
}
285294
break;
286295
case IGPUShader::E_SHADER_STAGE::ESS_FRAGMENT: [[fallthrough]];
287296
case IGPUShader::E_SHADER_STAGE::ESS_COMPUTE:
@@ -298,10 +307,14 @@ core::smart_refctd_ptr<IGPUShader> ILogicalDevice::createShader(const SShaderCre
298307
case IGPUShader::E_SHADER_STAGE::ESS_INTERSECTION: [[fallthrough]];
299308
case IGPUShader::E_SHADER_STAGE::ESS_CALLABLE:
300309
if (!features.rayTracingPipeline)
310+
{
311+
m_logger.log("Cannot create IGPUShader for %p, Raytracing Pipeline feature not enabled!",system::ILogger::ELL_ERROR,creationParams.cpushader);
301312
return nullptr;
313+
}
302314
break;
303315
default:
304316
// Implicit unsupported stages or weird multi-bit stage enum values
317+
m_logger.log("Unknown Shader Stage %d",system::ILogger::ELL_ERROR,shaderStage);
305318
return nullptr;
306319
break;
307320
}
@@ -343,12 +356,18 @@ core::smart_refctd_ptr<IGPUShader> ILogicalDevice::createShader(const SShaderCre
343356
spirvShader = m_compilerSet->compileToSPIRV(creationParams.cpushader, commonCompileOptions);
344357

345358
if (!spirvShader)
359+
{
360+
m_logger.log("SPIR-V Compilation from non SPIR-V shader %p failed.",system::ILogger::ELL_ERROR,creationParams.cpushader);
346361
return nullptr;
362+
}
347363
}
348364

349365
auto spirv = spirvShader->getContent();
350366
if (!spirv)
367+
{
368+
m_logger.log("SPIR-V Compilation from non SPIR-V shader %p failed.",system::ILogger::ELL_ERROR,creationParams.cpushader);
351369
return nullptr;
370+
}
352371

353372
// for debugging
354373
if constexpr (true)

0 commit comments

Comments
 (0)