Skip to content
Merged
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
5 changes: 4 additions & 1 deletion .github/workflows/build-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,18 @@ jobs:
uses: DiligentGraphics/github-action/run-core-gpu-tests@v26
with:
mode: d3d12_sw
# Temporarily skip flaky RT2/RT4 until WARP and reference AS synchronization are fixed.
args: --gtest_filter=-RayTracingTest/RT2.*:RayTracingTest/RT4.*

- name: DiligentCoreAPITest D3D12 DXC
if: ${{ (success() || failure() && steps.build.outcome == 'success') && (matrix.name == 'Win10' || matrix.name == 'Win10-Ninja') }}
uses: DiligentGraphics/github-action/run-core-gpu-tests@v26
with:
mode: d3d12_sw
use-dxc: true
# Temporarily skip flaky RT2/RT4 until WARP and reference AS synchronization are fixed.
# Disable texture creation tests that are not relevant for DXC to save time
args: --gtest_filter=-TextureCreation*
args: --gtest_filter=-TextureCreation*:RayTracingTest/RT2.*:RayTracingTest/RT4.*

- name: DiligentCoreAPITest WebGPU
if: ${{ (success() || failure() && steps.build.outcome == 'success') && matrix.name == 'Win10' }}
Expand Down
42 changes: 21 additions & 21 deletions Common/interface/AdvancedMath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1371,16 +1371,16 @@ class Polygon2DTriangulator
m_VertTypes.resize(VertCount);
for (int i = 0; i < VertCount; ++i)
{
m_RemainingVertIds[i] = i;
m_RemainingVertIds[i] = static_cast<IndexType>(i);
m_VertTypes[i] = VertexType::Convexx;
}

auto CheckConvex = [&](int vert_id) {
const int RemainingVertCount = static_cast<int>(m_RemainingVertIds.size());

const int Idx0 = m_RemainingVertIds[WrapIndex(vert_id - 1, RemainingVertCount)];
const int Idx1 = m_RemainingVertIds[WrapIndex(vert_id + 0, RemainingVertCount)];
const int Idx2 = m_RemainingVertIds[WrapIndex(vert_id + 1, RemainingVertCount)];
const IndexType Idx0 = m_RemainingVertIds[WrapIndex(vert_id - 1, RemainingVertCount)];
const IndexType Idx1 = m_RemainingVertIds[WrapIndex(vert_id + 0, RemainingVertCount)];
const IndexType Idx2 = m_RemainingVertIds[WrapIndex(vert_id + 1, RemainingVertCount)];

const auto& V0 = Polygon[Idx0];
const auto& V1 = Polygon[Idx1];
Expand All @@ -1394,9 +1394,9 @@ class Polygon2DTriangulator
auto CheckEar = [&](int vert_id) {
const int RemainingVertCount = static_cast<int>(m_RemainingVertIds.size());

const int Idx0 = m_RemainingVertIds[WrapIndex(vert_id - 1, RemainingVertCount)];
const int Idx1 = m_RemainingVertIds[WrapIndex(vert_id + 0, RemainingVertCount)];
const int Idx2 = m_RemainingVertIds[WrapIndex(vert_id + 1, RemainingVertCount)];
const IndexType Idx0 = m_RemainingVertIds[WrapIndex(vert_id - 1, RemainingVertCount)];
const IndexType Idx1 = m_RemainingVertIds[WrapIndex(vert_id + 0, RemainingVertCount)];
const IndexType Idx2 = m_RemainingVertIds[WrapIndex(vert_id + 1, RemainingVertCount)];

VERIFY_EXPR(m_VertTypes[Idx1] == VertexType::Convexx);

Expand All @@ -1408,7 +1408,7 @@ class Polygon2DTriangulator
// Degenerate ears still need to be removable with collinear vertices.
const bool AllowEdges = GetWinding(V0, V1, V2) != 0;

for (const int Idx : m_RemainingVertIds)
for (const IndexType Idx : m_RemainingVertIds)
{
if (Idx == Idx0 || Idx == Idx1 || Idx == Idx2)
continue;
Expand Down Expand Up @@ -1443,13 +1443,13 @@ class Polygon2DTriangulator
// the triangle order produced by clipping the first ear repeatedly.
for (int i = 0; i < VertCount - 3; ++i)
{
m_Triangles.emplace_back(VertCount - 1);
m_Triangles.emplace_back(i);
m_Triangles.emplace_back(i + 1);
m_Triangles.emplace_back(static_cast<IndexType>(VertCount - 1));
m_Triangles.emplace_back(static_cast<IndexType>(i));
m_Triangles.emplace_back(static_cast<IndexType>(i + 1));
}
m_Triangles.emplace_back(VertCount - 3);
m_Triangles.emplace_back(VertCount - 2);
m_Triangles.emplace_back(VertCount - 1);
m_Triangles.emplace_back(static_cast<IndexType>(VertCount - 3));
m_Triangles.emplace_back(static_cast<IndexType>(VertCount - 2));
m_Triangles.emplace_back(static_cast<IndexType>(VertCount - 1));
return m_Triangles;
}

Expand All @@ -1470,7 +1470,7 @@ class Polygon2DTriangulator
int ear_vert_id = 0;
for (; ear_vert_id < RemainingVertCount; ++ear_vert_id)
{
const int Idx = m_RemainingVertIds[ear_vert_id];
const IndexType Idx = m_RemainingVertIds[ear_vert_id];
if (m_VertTypes[Idx] == VertexType::Ear)
break;
};
Expand All @@ -1482,9 +1482,9 @@ class Polygon2DTriangulator
ear_vert_id = 0;
}

const int Idx0 = m_RemainingVertIds[WrapIndex(ear_vert_id - 1, RemainingVertCount)];
const int Idx1 = m_RemainingVertIds[ear_vert_id];
const int Idx2 = m_RemainingVertIds[WrapIndex(ear_vert_id + 1, RemainingVertCount)];
const IndexType Idx0 = m_RemainingVertIds[WrapIndex(ear_vert_id - 1, RemainingVertCount)];
const IndexType Idx1 = m_RemainingVertIds[ear_vert_id];
const IndexType Idx2 = m_RemainingVertIds[WrapIndex(ear_vert_id + 1, RemainingVertCount)];

m_Triangles.emplace_back(Idx0);
m_Triangles.emplace_back(Idx1);
Expand All @@ -1495,8 +1495,8 @@ class Polygon2DTriangulator
// Update adjacent vertices
if (RemainingVertCount > 3)
{
const int IdxL = m_RemainingVertIds[WrapIndex(ear_vert_id - 1, RemainingVertCount)];
const int IdxR = m_RemainingVertIds[WrapIndex(ear_vert_id, RemainingVertCount)];
const IndexType IdxL = m_RemainingVertIds[WrapIndex(ear_vert_id - 1, RemainingVertCount)];
const IndexType IdxR = m_RemainingVertIds[WrapIndex(ear_vert_id, RemainingVertCount)];
// First check for convex vs reflex
m_VertTypes[IdxL] = CheckConvex(ear_vert_id - 1);
m_VertTypes[IdxR] = CheckConvex(ear_vert_id);
Expand Down Expand Up @@ -1541,7 +1541,7 @@ class Polygon2DTriangulator
std::vector<VertexType> m_VertTypes;

// Remaining vertices to process
std::vector<int> m_RemainingVertIds;
std::vector<IndexType> m_RemainingVertIds;
};


Expand Down
213 changes: 200 additions & 13 deletions Common/interface/ParsingTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
/// Parsing tools

#include <cstring>
#include <cmath>
#include <sstream>
#include <limits>
#include <vector>
#include <algorithm>
#include <optional>
#include <type_traits>

#include "../../Primitives/interface/BasicTypes.h"
#include "../../Primitives/interface/FlagEnum.h"
Expand Down Expand Up @@ -423,39 +425,224 @@ bool SkipString(const IteratorType& Start, const IteratorType& End, const char*
}
}

/// Parses an integer starting from the given position.
/// Parses a decimal integer starting from the given position.
///
/// \param[in] Start - starting position.
/// \param[in] End - end of the input string
/// \param[out] Value - parsed integer value.
/// \return position immediately following the last character of the number.
/// \param[in] Start - starting position; leading whitespace is not skipped.
/// \param[in] End - end of the input range.
/// \param[out] Value - parsed integer value, unchanged on failure.
/// \return The position immediately following the last digit, or Start if no
/// integer is found or its value cannot be represented by ValueType.
///
/// Accepts an optional sign. Negative values are rejected for unsigned types.
/// ValueType must be an integral type other than bool.
template <typename IteratorType, typename ValueType>
IteratorType ParseInteger(const IteratorType& Start, const IteratorType& End, ValueType& Value) noexcept
{
auto Pos = Start;
static_assert(std::is_integral<ValueType>::value && !std::is_same<ValueType, bool>::value,
"ValueType must be an integral type other than bool");

IteratorType Pos = Start;
if (Pos == End)
return Pos;
return Start;

const bool IsNegative = *Pos == '-';
if (IsNegative && !std::numeric_limits<ValueType>::is_signed)
return Start;

if (*Pos == '+' || *Pos == '-')
++Pos;

if (Pos == End || !IsNum(*Pos))
if (Pos == End || !IsDigit(*Pos))
return Start;

Value = 0;
while (Pos != End && IsNum(*Pos))
ValueType Number = 0;
while (Pos != End && IsDigit(*Pos))
{
Value = Value * 10 + (*Pos - '0');
const ValueType Digit = static_cast<ValueType>(*Pos - '0');
if (IsNegative)
{
// Accumulate negative values directly so that the minimum signed
// value never needs to be represented as a positive value.
if (Number < ((std::numeric_limits<ValueType>::min)() + Digit) / 10)
return Start;
Number = static_cast<ValueType>(Number * 10 - Digit);
}
else
{
if (Number > ((std::numeric_limits<ValueType>::max)() - Digit) / 10)
return Start;
Number = static_cast<ValueType>(Number * 10 + Digit);
}
++Pos;
}

if (IsNegative)
Value = -Value;
Value = Number;
return Pos;
}

/// Reads a decimal floating-point number starting from the given position.
///
/// \param[in] Start - starting position; leading whitespace is not skipped.
/// \param[in] End - end of the input range; no null terminator is required.
/// \param[out] Value - parsed value, unchanged on failure.
/// \return The position immediately following the number, or Start if no valid
/// number is found or its magnitude exceeds the finite ValueType range.
///
/// Accepts an optional sign, decimal digits with an optional decimal point,
/// and an optional e/E exponent. At least one digit is required before the
/// exponent, and an exponent marker must be followed by an optional sign and
/// at least one digit. NaN and infinity are not accepted. Conversion is
/// locale-independent and does not allocate memory. Underflow is accepted,
/// including signed zero. ValueType must be float or double.
template <typename IteratorType, typename ValueType>
IteratorType ReadFloat(const IteratorType& Start, const IteratorType& End, ValueType& Value) noexcept
{
static_assert(std::is_same<ValueType, float>::value || std::is_same<ValueType, double>::value,
"ValueType must be float or double");

// Retain 19 significant decimal digits for conversion to float or double without
// allocating a terminated string or depending on floating from_chars support.
if (Start == End)
{
return Start;
}
IteratorType Pos = Start;

// Parse the optional sign.
// -12.34e-5;
// ^
// Pos
const bool Negative = *Pos == '-';
if (*Pos == '-' || *Pos == '+')
{
++Pos;
}
Uint64 Mantissa = 0;
int Digits = 0;
Int64 Power = 0;
bool AnyDigit = false;

const auto ReadDigits = [&](bool IsFractional) {
while (Pos != End && IsDigit(*Pos))
{
AnyDigit = true;
if (Digits < 19)
{
Mantissa = Mantissa * 10 + static_cast<unsigned>(*Pos - '0');
if (Mantissa != 0)
{
++Digits;
}
if (IsFractional)
{
// Each retained fractional digit shifts the decimal point left.
--Power;
}
}
else if (!IsFractional)
{
// Discarded integer digits still contribute to the magnitude.
// Discarded fractional digits do not change the retained value.
++Power;
}
++Pos;
}
};

// Parse the integer part, which may be empty (e.g. ".5").
// -12.34e-5;
// ^
// Pos
ReadDigits(false);

// Parse the optional decimal point and fractional part.
// -12.34e-5;
// ^
// Pos
if (Pos != End && *Pos == '.')
{
++Pos;
// -12.34e-5;
// ^
// Pos
ReadDigits(true);
}
// A sign or decimal point alone does not form a number.
if (!AnyDigit)
{
return Start;
}

// Parse the optional exponent marker and sign.
// -12.34e-5;
// ^
// Pos
if (Pos != End && (*Pos == 'e' || *Pos == 'E'))
{
++Pos;
// -12.34e-5;
// ^
// Pos
bool NegativeExponent = false;
if (Pos != End && (*Pos == '-' || *Pos == '+'))
{
NegativeExponent = *Pos == '-';
++Pos;
}
// An exponent marker requires at least one exponent digit.
// -12.34e-5;
// ^
// Pos
if (Pos == End || !IsDigit(*Pos))
{
return Start;
}
Int64 Exponent = 0;
while (Pos != End && IsDigit(*Pos))
{
// Cap the exponent so additional digits cannot overflow Int64.
Exponent = (std::min)(Exponent * 10 + static_cast<Int64>(*Pos - '0'), Int64{1000000000});
++Pos;
}
Power += NegativeExponent ? -Exponent : Exponent;
}

// Pos now points past the number. Convert Mantissa * 10^Power.
// -12.34e-5;
// ^
// Pos
double Number = 0;
if (Mantissa != 0)
{
Number = static_cast<double>(Mantissa);
if (Power > std::numeric_limits<double>::max_exponent10 - 19)
{
// Normalize near the upper double limit to avoid overflowing the
// product through rounding of a large power of ten.
Number /= std::pow(10.0, Digits - 1);
Power += Digits - 1;
}
if (Power < std::numeric_limits<double>::min_exponent10)
{
// A subnormal result may still be representable even when 10^Power
// alone underflows. Apply the scale in two representable steps.
Number *= std::pow(10.0, static_cast<double>(Power - std::numeric_limits<double>::min_exponent10));
Number *= std::pow(10.0, std::numeric_limits<double>::min_exponent10);
}
else
{
Number *= std::pow(10.0, static_cast<double>(Power));
}
if (!std::isfinite(Number) || Number > (std::numeric_limits<ValueType>::max)())
{
return Start;
}
}
Value = static_cast<ValueType>(Negative ? -Number : Number);
return Pos;
}


/// Splits string into chunks separated by comments and delimiters.
///
/// \param [in] Start - start of the string to split.
Expand Down
Loading
Loading