Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 83 additions & 55 deletions 62_CAD/DrawResourcesFiller.cpp

Large diffs are not rendered by default.

36 changes: 18 additions & 18 deletions 62_CAD/DrawResourcesFiller.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ using namespace nbl::video;
using namespace nbl::core;
using namespace nbl::asset;

static_assert(sizeof(DrawObject) == 16u);
static_assert(sizeof(MainObject) == 20u);
static_assert(sizeof(DrawObject) == 8u);
static_assert(sizeof(MainObject) == 8u);
static_assert(sizeof(LineStyle) == 88u);

// ! DrawResourcesFiller
Expand Down Expand Up @@ -109,7 +109,7 @@ struct DrawResourcesFiller
// auto-submission level 0 resources (settings that mainObj references)
CPUGeneratedResource<LineStyle> lineStyles;
CPUGeneratedResource<DTMSettings> dtmSettings;
CPUGeneratedResource<float64_t3x3> customProjections;
CPUGeneratedResource<float64_t2x3> customProjections;
CPUGeneratedResource<WorldClipRect> customClipRects;

// auto-submission level 1 buffers (mainObj that drawObjs references, if all drawObjs+idxBuffer+geometryInfo doesn't fit into mem this will be broken down into many)
Expand Down Expand Up @@ -229,7 +229,7 @@ struct DrawResourcesFiller

//! Draws a fixed-geometry polyline using a custom transformation.
//! TODO: Change `polyline` input to an ID referencing a possibly cached instance in our buffers, allowing reuse and avoiding redundant uploads.
void drawFixedGeometryPolyline(const CPolylineBase& polyline, const LineStyleInfo& lineStyleInfo, const float64_t3x3& transformation, TransformationType transformationType, SIntendedSubmitInfo& intendedNextSubmit);
void drawFixedGeometryPolyline(const CPolylineBase& polyline, const LineStyleInfo& lineStyleInfo, const float64_t2x3& transformation, TransformationType transformationType, SIntendedSubmitInfo& intendedNextSubmit);

/// Use this in a begin/endMainObject scope when you want to draw different polylines that should essentially be a single main object (no self-blending between components of a single main object)
/// WARNING: make sure this function is called within begin/endMainObject scope
Expand Down Expand Up @@ -267,7 +267,7 @@ struct DrawResourcesFiller
const float32_t4& foregroundColor,
const float32_t4& backgroundColor,
const HatchFillPattern fillPattern,
const float64_t3x3& transformation,
const float64_t2x3& transformation,
TransformationType transformationType,
SIntendedSubmitInfo& intendedNextSubmit);

Expand All @@ -276,15 +276,15 @@ struct DrawResourcesFiller
const Hatch& hatch,
const float32_t4& color,
const HatchFillPattern fillPattern,
const float64_t3x3& transformation,
const float64_t2x3& transformation,
TransformationType transformationType,
SIntendedSubmitInfo& intendedNextSubmit);

// ! Solid Fill Fixed-geometry Hatch
void drawFixedGeometryHatch(
const Hatch& hatch,
const float32_t4& color,
const float64_t3x3& transformation,
const float64_t2x3& transformation,
TransformationType transformationType,
SIntendedSubmitInfo& intendedNextSubmit);

Expand Down Expand Up @@ -490,13 +490,13 @@ struct DrawResourcesFiller
void beginMainObject(MainObjectType type, TransformationType transformationType = TransformationType::TT_NORMAL);
void endMainObject();

void pushCustomProjection(const float64_t3x3& projection);
void pushCustomProjection(const float64_t2x3& projection);
void popCustomProjection();

void pushCustomClipRect(const WorldClipRect& clipRect);
void popCustomClipRect();

const std::deque<float64_t3x3>& getCustomProjectionStack() const { return activeProjections; }
const std::deque<float64_t2x3>& getCustomProjectionStack() const { return activeProjections; }
const std::deque<WorldClipRect>& getCustomClipRectsStack() const { return activeClipRects; }

smart_refctd_ptr<IGPUImageView> getMSDFsTextureArray() { return msdfTextureArray; }
Expand Down Expand Up @@ -719,7 +719,7 @@ struct DrawResourcesFiller
uint32_t addDTMSettings_SubmitIfNeeded(const DTMSettingsInfo& dtmSettings, SIntendedSubmitInfo& intendedNextSubmit);

/// Attempts to add custom projection to gpu resources. If it fails to do, due to resource limitations, auto-submits and tries again.
uint32_t addCustomProjection_SubmitIfNeeded(const float64_t3x3& projection, SIntendedSubmitInfo& intendedNextSubmit);
uint32_t addCustomProjection_SubmitIfNeeded(const float64_t2x3& projection, SIntendedSubmitInfo& intendedNextSubmit);

/// Attempts to add custom clip to gpu resources. If it fails to do, due to resource limitations, auto-submits and tries again.
uint32_t addCustomClipRect_SubmitIfNeeded(const WorldClipRect& clipRect, SIntendedSubmitInfo& intendedNextSubmit);
Expand Down Expand Up @@ -748,7 +748,7 @@ struct DrawResourcesFiller
* @param transformationType The type of transformation to apply (e.g., TT_NORMAL or TT_FIXED_SCREENSPACE_SIZE).
*
*/
float64_t3x3 getFixedGeometryFinalTransformationMatrix(const float64_t3x3& transformation, TransformationType transformationType) const;
float64_t2x3 getFixedGeometryFinalTransformationMatrix(const float64_t2x3& transformation, TransformationType transformationType) const;

/// Attempts to upload as many draw objects as possible within the given polyline section considering resource limitations
void addPolylineObjects_Internal(const CPolylineBase& polyline, const CPolylineBase::SectionInfo& section, uint32_t& currentObjectInSection, uint32_t mainObjIdx);
Expand Down Expand Up @@ -859,7 +859,7 @@ struct DrawResourcesFiller

// Invalidate all the clip projection addresses because activeProjections buffer got reset
for (auto& addr : activeProjectionIndices)
addr = InvalidCustomProjectionIndex;
addr = MainObject::getInvalidCustomTransformationIndex();
}

void resetCustomClipRects()
Expand All @@ -868,19 +868,19 @@ struct DrawResourcesFiller

// Invalidate all the clip projection addresses because activeProjections buffer got reset
for (auto& addr : activeClipRectIndices)
addr = InvalidCustomClipRectIndex;
addr = MainObject::getInvalidCustomClipRectIndex();
}

void resetLineStyles()
{
resourcesCollection.lineStyles.vector.clear();
activeLineStyleIndex = InvalidStyleIdx;
activeLineStyleIndex = MainObject::getInvalidLineStyleIndex();
}

void resetDTMSettings()
{
resourcesCollection.dtmSettings.vector.clear();
activeDTMSettingsIndex = InvalidDTMSettingsIdx;
activeDTMSettingsIndex = MainObject::getInvalidDtmSettingsIndex();
}

// MSDF Hashing and Caching Internal Functions
Expand Down Expand Up @@ -991,18 +991,18 @@ struct DrawResourcesFiller

// Active Resources we need to keep track of and push to resources buffer if needed.
LineStyleInfo activeLineStyle;
uint32_t activeLineStyleIndex = InvalidStyleIdx;
uint32_t activeLineStyleIndex = MainObject::getInvalidLineStyleIndex();

DTMSettingsInfo activeDTMSettings;
uint32_t activeDTMSettingsIndex = InvalidDTMSettingsIdx;
uint32_t activeDTMSettingsIndex = MainObject::getInvalidDtmSettingsIndex();

MainObjectType activeMainObjectType;
TransformationType activeMainObjectTransformationType;

uint32_t activeMainObjectIndex = InvalidMainObjectIdx;

// The ClipRects & Projections are stack, because user can push/pop ClipRects & Projections in any order
std::deque<float64_t3x3> activeProjections; // stack of projections stored so we can resubmit them if geometry buffer got reset.
std::deque<float64_t2x3> activeProjections; // stack of projections stored so we can resubmit them if geometry buffer got reset.
std::deque<uint32_t> activeProjectionIndices; // stack of projection gpu addresses in geometry buffer. to keep track of them in push/pops

std::deque<WorldClipRect> activeClipRects; // stack of clips stored so we can resubmit them if geometry buffer got reset.
Expand Down
41 changes: 33 additions & 8 deletions 62_CAD/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ constexpr std::array<float, (uint32_t)ExampleMode::CASE_COUNT> cameraExtents =
10.0 // CASE_12
};

constexpr ExampleMode mode = ExampleMode::CASE_2;
constexpr ExampleMode mode = ExampleMode::CASE_10;

class Camera2D
{
Expand Down Expand Up @@ -3290,10 +3290,9 @@ class ComputerAidedDesign final : public nbl::examples::SimpleWindowedApplicatio
}
else if (mode == ExampleMode::CASE_6)
{
float64_t3x3 customProjection = float64_t3x3{
float64_t2x3 customProjection = float64_t2x3{
1.0, 0.0, cos(m_timeElapsed * 0.0005) * 100.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
0.0, 1.0, 0.0
};

/// [NOTE]: We set minClip and maxClip (in default worldspace) in such a way that minClip.y > maxClip.y so that minClipNDC.y < maxClipNDC.y
Expand Down Expand Up @@ -3752,7 +3751,7 @@ class ComputerAidedDesign final : public nbl::examples::SimpleWindowedApplicatio

LineStyleInfo style = {};
style.screenSpaceLineWidth = 4.0f;
style.color = float32_t4(0.619f, 0.325f, 0.709f, 0.5f);
style.color = float32_t4(0.2f, 0.2f, 0.2f, 0.5f);

for (uint32_t i = 0; i < 128u; ++i)
{
Expand Down Expand Up @@ -3809,7 +3808,7 @@ class ComputerAidedDesign final : public nbl::examples::SimpleWindowedApplicatio
0.0, 0.0, 1.0
};

float64_t2 scale = float64_t2{ 100.0, 100.0 };
float64_t2 scale = float64_t2{ 10.0, 10.0 };
float64_t3x3 scaleMat =
{
scale.x, 0.0, 0.0,
Expand All @@ -3821,8 +3820,34 @@ class ComputerAidedDesign final : public nbl::examples::SimpleWindowedApplicatio
polyline.addLinePoints(line0);
polyline.addLinePoints(line1);
polyline.preprocessPolylineWithStyle(style);
// drawResourcesFiller.drawPolyline(polyline, intendedNextSubmit);
drawResourcesFiller.drawFixedGeometryPolyline(polyline, style, transformation, TransformationType::TT_FIXED_SCREENSPACE_SIZE, intendedNextSubmit);
//drawResourcesFiller.drawPolyline(polyline, intendedNextSubmit);
//drawResourcesFiller.drawFixedGeometryPolyline(polyline, style, transformation, TransformationType::TT_FIXED_SCREENSPACE_SIZE, intendedNextSubmit);

constexpr int MarkerCount = 1000000;
for (int i = 0; i < MarkerCount; ++i)
{
translateMat =
{
1.0, 0.0, static_cast<float64_t>(i) / static_cast<float64_t>(MarkerCount*0.2),
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
};

const float64_t rotationAngle = (core::radians(360.0) / static_cast<float64_t>(MarkerCount)) * static_cast<float64_t>(i) * 10.0;
dir = float64_t2{ std::cos(rotationAngle), std::sin(rotationAngle) };
rotateMat =
{
dir.x, -dir.y, 0.0,
dir.y, dir.x, 0.0,
0.0, 0.0, 1.0
};

transformation = nbl::hlsl::mul(rotateMat, translateMat);

transformation = nbl::hlsl::mul(rotateMat, nbl::hlsl::mul(translateMat, scaleMat));

drawResourcesFiller.drawFixedGeometryPolyline(polyline, style, float64_t2x3(transformation[0], transformation[1]), TransformationType::TT_FIXED_SCREENSPACE_SIZE, intendedNextSubmit);
}
}
}
else if (mode == ExampleMode::CASE_11)
Expand Down
95 changes: 78 additions & 17 deletions 62_CAD/shaders/globals.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <nbl/builtin/hlsl/cpp_compat/matrix.hlsl>
#include <nbl/builtin/hlsl/shapes/beziers.hlsl>
#include <nbl/builtin/hlsl/tgmath.hlsl>
#include <nbl/builtin/hlsl/utils/bitfield.hlsl>
#include <nbl/builtin/hlsl/math/linalg/basic.hlsl>

#ifdef __HLSL_VERSION
#include <nbl/builtin/hlsl/math/equations/quadratic.hlsl>
Expand All @@ -28,6 +30,7 @@ using pfloat64_t2 = nbl::hlsl::vector<float64_t, 2>;
using pfloat64_t3 = nbl::hlsl::vector<float64_t, 3>;
#endif

using pfloat64_t2x3 = portable_matrix_t2x3<pfloat64_t>;
using pfloat64_t3x3 = portable_matrix_t3x3<pfloat64_t>;

struct PushConstants
Expand Down Expand Up @@ -144,24 +147,74 @@ enum TransformationType
TT_FIXED_SCREENSPACE_SIZE
};

template <typename T, uint32_t Bits>
struct IndexLimits
{
// The universal invalid marker (all 1s for the given bit width)
NBL_CONSTEXPR_STATIC T Invalid = (Bits >= sizeof(T) * 8)
? ~T(0)
: (T(1) << Bits) - T(1);

// The highest valid index is one less than the invalid marker
NBL_CONSTEXPR_STATIC T MaxIndexable = Invalid - T(1);
};

// Consists of multiple DrawObjects
// [IDEA]: In GPU-driven rendering, to save mem for MainObject data fetching: many of these can be shared amongst different main objects, we could find these styles, settings, etc indices with upper_bound
// [TODO]: pack indices and members of mainObject and DrawObject + enforce max size for autosubmit --> but do it only after the mainobject definition is finalized in gpu-driven rendering work
struct MainObject
{
uint32_t styleIdx;
uint32_t dtmSettingsIdx;
uint32_t customProjectionIndex;
uint32_t customClipRectIndex;
uint32_t transformationType; // todo pack later, it's just 2 possible values atm
uint32_t packedData;
uint32_t customTransformationIndex; // needs at least 24 bits

using LineStyleIdxOrDtmSettingsIdxField = utils::BitField<uint32_t, 0, 16>; // 65,536 distinct lineStyles or dtmSettings is more than enough for an n4ce frame, but make sure auto submit in drawresources filler plays nice and doesn't exceed this value
using CustomClipRectIndexField = utils::BitField<uint32_t, 16, 14>; // these are associated with the number of clipping rects or dwgs one could have in a frame. from experience they'll always be less than 10, 32,768 is more than enough
using TransformationTypeField = utils::BitField<uint32_t, 30, 1>; // todo pack later, it's just 2 possible values atm
using UseDtmSettingsField = utils::BitField<uint32_t, 31, 1>; // this bit indicates if MainObject uses DTM settings

uint32_t getLineStyleIndex() { return LineStyleIdxOrDtmSettingsIdxField::get(packedData); }
void setLineStyleIndex(uint32_t styleIdx) { packedData = LineStyleIdxOrDtmSettingsIdxField::set(packedData, styleIdx); }

uint32_t getDtmSettingsIndex() { return LineStyleIdxOrDtmSettingsIdxField::get(packedData); }
void setDtmSettingsIndex(uint32_t dtmSettingsIdx) { packedData = LineStyleIdxOrDtmSettingsIdxField::set(packedData, dtmSettingsIdx); }

uint32_t getCustomClipRectIndex() { return CustomClipRectIndexField::get(packedData); }
void setCustomClipRectIndex(uint32_t customClipRectIndexField) { packedData = CustomClipRectIndexField::set(packedData, customClipRectIndexField); }

uint32_t getTransformationType() { return TransformationTypeField::get(packedData); }
void setTransformationType(uint32_t transformationTypeField) { packedData = TransformationTypeField::set(packedData, transformationTypeField); }

bool isUsingDtmSettings() { return (bool)UseDtmSettingsField::get(packedData); }
void setDtmSettingsFlag(bool isUsingDtmSettings) { packedData = UseDtmSettingsField::set(packedData, (uint32_t)isUsingDtmSettings); }

static uint32_t getInvalidLineStyleIndex() { return IndexLimits<uint32_t, LineStyleIdxOrDtmSettingsIdxField::BitCount>::Invalid; }
static uint32_t getInvalidDtmSettingsIndex() { return getInvalidLineStyleIndex(); }
static uint32_t getInvalidCustomClipRectIndex() { return IndexLimits<uint32_t, CustomClipRectIndexField::BitCount>::Invalid; }
static uint32_t getInvalidCustomTransformationIndex() { return nbl::hlsl::numeric_limits<uint32_t>::max; }

static uint32_t getMaxIndexableLineStyles() { return IndexLimits<uint32_t, LineStyleIdxOrDtmSettingsIdxField::BitCount>::MaxIndexable; }
static uint32_t getMaxIndexableDtmSettings() { return getMaxIndexableLineStyles(); }
static uint32_t getMaxIndexableCustomClipRects() { return IndexLimits<uint32_t, CustomClipRectIndexField::BitCount>::MaxIndexable; }
static uint32_t getMaxIndexableCustomTransformations() { return nbl::hlsl::numeric_limits<uint32_t>::max - 1u; }
};

struct DrawObject
{
uint32_t type_subsectionIdx; // packed two uint16 into uint32
uint32_t mainObjIndex;
uint64_t geometryAddress;
uint32_t packedData;
uint32_t geometryAddress; // geometry has 8 byte alignment, max 34GB of data to reference

using TypeField = utils::BitField<uint32_t, 0, 4>; // 16 different object types
using SubsectionField = utils::BitField<uint32_t, 4, 2>; // 4 max subsections
using MainObjField = utils::BitField<uint32_t, 6, 26>; // 67M main objects max

ObjectType getType() { return (ObjectType)TypeField::get(packedData); }
void setType(ObjectType objType) { packedData = TypeField::set(packedData, (uint32_t)objType); }

uint32_t getSubsectionIdx() { return SubsectionField::get(packedData); }
void setSubsectionIdx(uint32_t subsectionIdx) { packedData = SubsectionField::set(packedData, subsectionIdx); }

uint32_t getMainObjIndex() { return MainObjField::get(packedData); }
void setMainObjIndex(uint32_t mainObjIdx) { packedData = MainObjField::set(packedData, mainObjIdx); }
};

// Goes into geometry buffer, needs to be aligned by 8
Expand Down Expand Up @@ -549,12 +602,8 @@ inline bool operator==(const DTMSettings& lhs, const DTMSettings& rhs)
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t ImagesBindingArraySize = 128;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t MainObjectIdxBits = 24u; // It will be packed next to alpha in a texture
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t AlphaBits = 32u - MainObjectIdxBits;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t MaxIndexableMainObjects = (1u << MainObjectIdxBits) - 1u;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t InvalidStyleIdx = nbl::hlsl::numeric_limits<uint32_t>::max;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t InvalidDTMSettingsIdx = nbl::hlsl::numeric_limits<uint32_t>::max;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t InvalidMainObjectIdx = MaxIndexableMainObjects;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t InvalidCustomProjectionIndex = nbl::hlsl::numeric_limits<uint32_t>::max;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t InvalidCustomClipRectIndex = nbl::hlsl::numeric_limits<uint32_t>::max;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t MaxIndexableMainObjects = IndexLimits<uint32_t, MainObjectIdxBits>::MaxIndexable;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t InvalidMainObjectIdx = IndexLimits<uint32_t, MainObjectIdxBits>::Invalid;
NBL_CONSTEXPR_INLINE_NSPC_SCOPE_VAR uint32_t InvalidTextureIndex = nbl::hlsl::numeric_limits<uint32_t>::max;

// Hatches
Expand Down Expand Up @@ -606,7 +655,19 @@ DTMSettings loadDTMSettings(const uint32_t index)
}
pfloat64_t3x3 loadCustomProjection(const uint32_t index)
{
return vk::RawBufferLoad<pfloat64_t3x3>(globals.pointers.customProjections + index * sizeof(pfloat64_t3x3), 8u);
pfloat64_t2x3 matrix2x3 = vk::RawBufferLoad<pfloat64_t2x3>(globals.pointers.customProjections + index * sizeof(pfloat64_t2x3), 8u);

pfloat64_t3x3 output;
output.rows[0].setComponent(0, matrix2x3.rows[0].getComponent(0));
output.rows[0].setComponent(1, matrix2x3.rows[0].getComponent(1));
output.rows[0].setComponent(2, matrix2x3.rows[0].getComponent(2));
output.rows[1].setComponent(0, matrix2x3.rows[1].getComponent(0));
output.rows[1].setComponent(1, matrix2x3.rows[1].getComponent(1));
output.rows[1].setComponent(2, matrix2x3.rows[1].getComponent(2));
output.rows[2].setComponent(0, nbl::hlsl::_static_cast<pfloat64_t>(0.0));
output.rows[2].setComponent(1, nbl::hlsl::_static_cast<pfloat64_t>(0.0));
output.rows[2].setComponent(2, nbl::hlsl::_static_cast<pfloat64_t>(1.0));
return output;
}
WorldClipRect loadCustomClipRect(const uint32_t index)
{
Expand All @@ -618,15 +679,15 @@ MainObject loadMainObject(const uint32_t index)
}
DrawObject loadDrawObject(const uint32_t index)
{
return vk::RawBufferLoad<DrawObject>(globals.pointers.drawObjects + index * sizeof(DrawObject), 8u);
return vk::RawBufferLoad<DrawObject>(globals.pointers.drawObjects + index * sizeof(DrawObject), 4u);
}
#else
static_assert(alignof(LineStyle)==4u);
static_assert(alignof(DTMSettings)==4u);
static_assert(alignof(pfloat64_t3x3)==8u);
static_assert(alignof(WorldClipRect)==8u);
static_assert(alignof(MainObject)==4u);
static_assert(alignof(DrawObject)==8u);
static_assert(alignof(DrawObject)==4u);
#endif


Expand Down
Loading