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
53 changes: 39 additions & 14 deletions scripts/generateShaderIncludes.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,49 @@
#!/bin/sh

# dash-compatible and space-safe shader include generator. @Rtur2003
SHADERS_SRC="./src/render/shaders/glsl"
SHADERS_OUT="./src/render/shaders"
SHADERS_HPP="${SHADERS_OUT}/Shaders.hpp"

echo "-- Generating shader includes"

if [ ! -d ./src/render/shaders ]; then
mkdir ./src/render/shaders
if [ ! -d "${SHADERS_SRC}" ]; then
echo "!! No shader sources in ${SHADERS_SRC}"
exit 1
fi

echo '#pragma once' > ./src/render/shaders/Shaders.hpp
echo '#include <map>' >> ./src/render/shaders/Shaders.hpp
echo 'static const std::map<std::string, std::string> SHADERS = {' >> ./src/render/shaders/Shaders.hpp

for filename in `ls ${SHADERS_SRC}`; do
echo "-- ${filename}"

{ echo 'R"#('; cat ${SHADERS_SRC}/${filename}; echo ')#"'; } > ./src/render/shaders/${filename}.inc
echo "{\"${filename}\"," >> ./src/render/shaders/Shaders.hpp
echo "#include \"./${filename}.inc\"" >> ./src/render/shaders/Shaders.hpp
echo "}," >> ./src/render/shaders/Shaders.hpp
mkdir -p "${SHADERS_OUT}"

{
echo '#pragma once'
echo '#include <map>'
echo 'static const std::map<std::string, std::string> SHADERS = {'
} > "${SHADERS_HPP}"

found=0
for file in "${SHADERS_SRC}"/*; do
[ -f "${file}" ] || continue
found=1
filename=$(basename -- "${file}")
echo "-- ${filename}"

{
echo 'R"#('
cat "${file}"
echo ')#"'
} > "${SHADERS_OUT}/${filename}.inc"

{
printf '{ "%s",\n' "${filename}"
printf '#include "./%s.inc"\n' "${filename}"
printf "},\n"
} >> "${SHADERS_HPP}"
done

echo '};' >> ./src/render/shaders/Shaders.hpp
if [ "${found}" -eq 0 ]; then
echo "!! No shader files found in ${SHADERS_SRC}"
rm -f "${SHADERS_HPP}"
exit 1
fi

echo '};' >> "${SHADERS_HPP}"
47 changes: 27 additions & 20 deletions src/helpers/time/Time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ static s_ns timediff(const s_ns& a, const s_ns& b) {
if (a.second >= b.second)
d.second = a.second - b.second;
else {
d.second = b.second - a.second;
d.second = TIMESPEC_NSEC_PER_SEC + a.second - b.second;
d.first -= 1;
}

Expand All @@ -33,6 +33,15 @@ static s_ns timeadd(const s_ns& a, const s_ns& b) {
return d;
}

static s_ns normalizeTimespec(const s_ns& raw) {
s_ns out = raw;
if (out.second >= TIMESPEC_NSEC_PER_SEC) {
out.first += out.second / TIMESPEC_NSEC_PER_SEC;
out.second %= TIMESPEC_NSEC_PER_SEC;
}
return out;
}

Time::steady_tp Time::steadyNow() {
return chr::steady_clock::now();
}
Expand All @@ -57,7 +66,7 @@ uint64_t Time::millis(const system_tp& tp) {

s_ns Time::secNsec(const system_tp& tp) {
const uint64_t sec = chr::duration_cast<chr::seconds>(tp.time_since_epoch()).count();
const chr::steady_clock::duration nsecdur = tp - chr::system_clock::time_point(chr::seconds(sec));
const chr::system_clock::duration nsecdur = tp - chr::system_clock::time_point(chr::seconds(sec));
return std::make_pair<>(sec, chr::duration_cast<chr::nanoseconds>(nsecdur).count());
}

Expand All @@ -79,20 +88,13 @@ Time::steady_tp Time::fromTimespec(const timespec* ts) {
stdReal = Time::secNsec(nowSys);

// timespec difference, REAL - MONO
s_ns diff;
diff.first = real.tv_sec - mono.tv_sec;
if (real.tv_nsec >= mono.tv_nsec)
diff.second = real.tv_nsec - mono.tv_nsec;
else {
diff.second = mono.tv_nsec - real.tv_nsec;
diff.first -= 1;
}
s_ns diff = timediff({real.tv_sec, real.tv_nsec}, {mono.tv_sec, mono.tv_nsec});

// STD difference, REAL - MONO
s_ns diff2 = timediff(stdReal, stdSteady);

s_ns diffFinal;
s_ns monotime = {ts->tv_sec, ts->tv_nsec};
s_ns monotime = normalizeTimespec({ts->tv_sec, ts->tv_nsec});

if (diff.first >= diff2.first || (diff.first == diff2.first && diff.second >= diff2.second))
diffFinal = timediff(diff, diff2);
Expand All @@ -114,20 +116,13 @@ struct timespec Time::toTimespec(const steady_tp& tp) {
stdReal = Time::secNsec(nowSys);

// timespec difference, REAL - MONO
s_ns diff;
diff.first = real.tv_sec - mono.tv_sec;
if (real.tv_nsec >= mono.tv_nsec)
diff.second = real.tv_nsec - mono.tv_nsec;
else {
diff.second = mono.tv_nsec - real.tv_nsec;
diff.first -= 1;
}
s_ns diff = timediff({real.tv_sec, real.tv_nsec}, {mono.tv_sec, mono.tv_nsec});

// STD difference, REAL - MONO
s_ns diff2 = timediff(stdReal, stdSteady);

s_ns diffFinal;
s_ns tpTime = secNsec(tp);
s_ns tpTime = normalizeTimespec(secNsec(tp));

if (diff.first >= diff2.first || (diff.first == diff2.first && diff.second >= diff2.second))
diffFinal = timediff(diff, diff2);
Expand All @@ -137,3 +132,15 @@ struct timespec Time::toTimespec(const steady_tp& tp) {
auto sum = timeadd(tpTime, diffFinal);
return timespec{.tv_sec = sum.first, .tv_nsec = sum.second};
}

namespace Time::detail {

sec_nsec diff(const sec_nsec& newer, const sec_nsec& older) {
return timediff(newer, older);
}

sec_nsec normalize(const sec_nsec& raw) {
return normalizeTimespec(raw);
}

}
10 changes: 9 additions & 1 deletion src/helpers/time/Time.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ namespace Time {
uint64_t millis(const system_tp& tp);
std::pair<uint64_t, uint64_t> secNsec(const steady_tp& tp);
std::pair<uint64_t, uint64_t> secNsec(const system_tp& tp);
};

namespace detail {
using sec_nsec = std::pair<uint64_t, uint64_t>;

// Exposed for tests to verify borrow handling in timespec math. @Rtur2003
sec_nsec diff(const sec_nsec& newer, const sec_nsec& older);
sec_nsec normalize(const sec_nsec& raw);
}
};
40 changes: 40 additions & 0 deletions tests/helpers/Time.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <gtest/gtest.h>
#include <helpers/time/Time.hpp>
#include <chrono>

TEST(HelpersTime, HandlesNanosecondBorrowInDiff) {
const Time::detail::sec_nsec later{5, 5};
const Time::detail::sec_nsec earlier{4, 999'999'900};

const auto delta = Time::detail::diff(later, earlier);

EXPECT_EQ(delta.first, 0u);
EXPECT_EQ(delta.second, 105u);
}

TEST(HelpersTime, SteadyRoundtripWithinTolerance) {
using namespace std::chrono_literals;

const auto now = Time::steadyNow();
const auto ts = Time::toTimespec(now);
const auto roundtrip = Time::fromTimespec(&ts);
const auto diff = roundtrip > now ? (roundtrip - now) : (now - roundtrip);
const auto diffMillis = std::chrono::duration_cast<std::chrono::milliseconds>(diff).count();

// Allow a small drift for conversions and scheduling jitter.
EXPECT_LT(diffMillis, 50) << "Roundtrip drift exceeded tolerance";
}

TEST(HelpersTime, SystemRoundtripWithinTolerance) {
using namespace std::chrono_literals;

const auto now = Time::systemNow();
const auto parts = Time::secNsec(now);
const auto reconstructed = std::chrono::system_clock::time_point(std::chrono::seconds(parts.first)) +
std::chrono::nanoseconds(parts.second);

const auto diff = reconstructed > now ? (reconstructed - now) : (now - reconstructed);
const auto diffMillis = std::chrono::duration_cast<std::chrono::milliseconds>(diff).count();

EXPECT_LT(diffMillis, 1) << "System clock reconstruction drifted too far";
}
54 changes: 54 additions & 0 deletions tests/helpers/TimeDiff.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <gtest/gtest.h>
#include <helpers/time/Time.hpp>

TEST(HelpersTime, DiffBorrowsNanoseconds) {
const Time::detail::sec_nsec newer{5, 1};
const Time::detail::sec_nsec older{4, 999'999'999};

const auto diff = Time::detail::diff(newer, older);

EXPECT_EQ(diff.first, 0u);
EXPECT_EQ(diff.second, 2u);
}

TEST(HelpersTime, DiffWithoutBorrow) {
const Time::detail::sec_nsec newer{3, 500};
const Time::detail::sec_nsec older{2, 250};

const auto diff = Time::detail::diff(newer, older);

EXPECT_EQ(diff.first, 1u);
EXPECT_EQ(diff.second, 250u);
}

TEST(HelpersTime, NormalizesTimespecNsecOverflow) {
const Time::detail::sec_nsec raw{1u, 2'000'000'050u};

const auto normalized = Time::detail::normalize(raw);

EXPECT_EQ(normalized.first, 3u);
EXPECT_EQ(normalized.second, 50u);
}

TEST(HelpersTime, SecNsecSteadyFixedPoint) {
using namespace std::chrono;
using namespace std::chrono_literals;
const Time::steady_tp tp{steady_clock::duration{1s + 5000ns}};

const auto secNsec = Time::secNsec(tp);

EXPECT_EQ(secNsec.first, 1);
EXPECT_EQ(secNsec.second, 5000);
}

TEST(HelpersTime, SecNsecSystemFixedPoint) {
using namespace std::chrono;
using namespace std::chrono_literals;
// 5000ns keeps compatibility with coarser system_clock periods (e.g. microseconds).
const Time::system_tp tp{system_clock::duration{2s + 5000ns}};

const auto secNsec = Time::secNsec(tp);

EXPECT_EQ(secNsec.first, 2u);
EXPECT_EQ(secNsec.second, 5000u);
}