aboutsummaryrefslogtreecommitdiff
path: root/src/verifier.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/verifier.cc')
-rw-r--r--src/verifier.cc214
1 files changed, 204 insertions, 10 deletions
diff --git a/src/verifier.cc b/src/verifier.cc
index c36923d..2f65320 100644
--- a/src/verifier.cc
+++ b/src/verifier.cc
@@ -16,15 +16,153 @@
#include <cmath>
#include <string>
+#include <vector>
+
+#include "src/command.h"
namespace amber {
namespace {
-const float kEpsilon = 0.002f;
+const double kEpsilon = 0.000001;
+const double kDefaultTexelTolerance = 0.002;
+
+// It returns true if the difference is within the given error.
+// If |is_tolerance_percent| is true, the actual tolerance will be
+// relative value i.e., |tolerance| * fabs(real - expected).
+// Otherwise, this method uses the absolute value i.e., |tolerance|.
+bool IsEqualWithTolerance(const double real,
+ const double expected,
+ double tolerance,
+ const bool is_tolerance_percent = true) {
+ double difference = std::fabs(real - expected);
+ if (difference == 0.0)
+ return true;
+ if (is_tolerance_percent)
+ tolerance *= difference;
+ return difference < tolerance;
+}
-bool IsFloatPixelEqualInt(float pixel, uint8_t expected) {
- // TODO(jaebaek): Change kEpsilon to tolerance.
- return std::fabs(pixel - static_cast<float>(expected) / 255.0f) < kEpsilon;
+template <typename T>
+Result CheckValue(const ProbeSSBOCommand* command,
+ const uint8_t* memory,
+ const std::vector<Value>& values) {
+ const auto comp = command->GetComparator();
+ const auto& tolerance = command->GetTolerances();
+ const T* ptr = reinterpret_cast<const T*>(memory);
+ for (size_t i = 0; i < values.size(); ++i) {
+ const T val = values[i].IsInteger() ? static_cast<T>(values[i].AsUint64())
+ : static_cast<T>(values[i].AsDouble());
+ switch (comp) {
+ case ProbeSSBOCommand::Comparator::kEqual:
+ if (values[i].IsInteger()) {
+ if (static_cast<uint64_t>(*ptr) != static_cast<uint64_t>(val)) {
+ return Result("Verifier failed: " + std::to_string(*ptr) +
+ " == " + std::to_string(val) + ", at index " +
+ std::to_string(i));
+ }
+ } else {
+ if (!IsEqualWithTolerance(static_cast<const double>(*ptr),
+ static_cast<const double>(val), kEpsilon)) {
+ return Result("Verifier failed: " + std::to_string(*ptr) +
+ " == " + std::to_string(val) + ", at index " +
+ std::to_string(i));
+ }
+ }
+ break;
+ case ProbeSSBOCommand::Comparator::kNotEqual:
+ if (values[i].IsInteger()) {
+ if (static_cast<uint64_t>(*ptr) == static_cast<uint64_t>(val)) {
+ return Result("Verifier failed: " + std::to_string(*ptr) +
+ " != " + std::to_string(val) + ", at index " +
+ std::to_string(i));
+ }
+ } else {
+ if (IsEqualWithTolerance(static_cast<const double>(*ptr),
+ static_cast<const double>(val), kEpsilon)) {
+ return Result("Verifier failed: " + std::to_string(*ptr) +
+ " != " + std::to_string(val) + ", at index " +
+ std::to_string(i));
+ }
+ }
+ break;
+ case ProbeSSBOCommand::Comparator::kFuzzyEqual:
+ if (!IsEqualWithTolerance(
+ static_cast<const double>(*ptr), static_cast<const double>(val),
+ command->HasTolerances() ? tolerance[0].value : kEpsilon,
+ command->HasTolerances() ? tolerance[0].is_percent : true)) {
+ return Result("Verifier failed: " + std::to_string(*ptr) +
+ " ~= " + std::to_string(val) + ", at index " +
+ std::to_string(i));
+ }
+ break;
+ case ProbeSSBOCommand::Comparator::kLess:
+ if (*ptr >= val) {
+ return Result("Verifier failed: " + std::to_string(*ptr) + " < " +
+ std::to_string(val) + ", at index " +
+ std::to_string(i));
+ }
+ break;
+ case ProbeSSBOCommand::Comparator::kLessOrEqual:
+ if (*ptr > val) {
+ return Result("Verifier failed: " + std::to_string(*ptr) +
+ " <= " + std::to_string(val) + ", at index " +
+ std::to_string(i));
+ }
+ break;
+ case ProbeSSBOCommand::Comparator::kGreater:
+ if (*ptr <= val) {
+ return Result("Verifier failed: " + std::to_string(*ptr) + " > " +
+ std::to_string(val) + ", at index " +
+ std::to_string(i));
+ }
+ break;
+ case ProbeSSBOCommand::Comparator::kGreaterOrEqual:
+ if (*ptr < val) {
+ return Result("Verifier failed: " + std::to_string(*ptr) +
+ " >= " + std::to_string(val) + ", at index " +
+ std::to_string(i));
+ }
+ break;
+ }
+ ++ptr;
+ }
+ return {};
+}
+
+void SetupToleranceForTexels(const ProbeCommand* command,
+ double* tolerance,
+ bool* is_tolerance_percent) {
+ if (command->HasTolerances()) {
+ const auto& tol = command->GetTolerances();
+ if (tol.size() == 4) {
+ tolerance[0] = tol[0].value;
+ tolerance[1] = tol[1].value;
+ tolerance[2] = tol[2].value;
+ tolerance[3] = tol[3].value;
+ is_tolerance_percent[0] = tol[0].is_percent;
+ is_tolerance_percent[1] = tol[1].is_percent;
+ is_tolerance_percent[2] = tol[2].is_percent;
+ is_tolerance_percent[3] = tol[3].is_percent;
+ } else {
+ tolerance[0] = tol[0].value;
+ tolerance[1] = tol[0].value;
+ tolerance[2] = tol[0].value;
+ tolerance[3] = tol[0].value;
+ is_tolerance_percent[0] = tol[0].is_percent;
+ is_tolerance_percent[1] = tol[0].is_percent;
+ is_tolerance_percent[2] = tol[0].is_percent;
+ is_tolerance_percent[3] = tol[0].is_percent;
+ }
+ } else {
+ tolerance[0] = kDefaultTexelTolerance;
+ tolerance[1] = kDefaultTexelTolerance;
+ tolerance[2] = kDefaultTexelTolerance;
+ tolerance[3] = kDefaultTexelTolerance;
+ is_tolerance_percent[0] = false;
+ is_tolerance_percent[1] = false;
+ is_tolerance_percent[2] = false;
+ is_tolerance_percent[3] = false;
+ }
}
} // namespace
@@ -65,6 +203,10 @@ Result Verifier::Probe(const ProbeCommand* command,
std::to_string(frame_width) + "," + std::to_string(frame_height) + ")");
}
+ double tolerance[4] = {};
+ bool is_tolerance_percent[4] = {};
+ SetupToleranceForTexels(command, tolerance, is_tolerance_percent);
+
// TODO(jaebaek): Support all VkFormat
const uint8_t* ptr = static_cast<const uint8_t*>(buf);
uint32_t count_of_invalid_pixels = 0;
@@ -74,11 +216,23 @@ Result Verifier::Probe(const ProbeCommand* command,
const uint8_t* p = ptr + stride * frame_width * (j + y) + stride * x;
for (uint32_t i = 0; i < width; ++i) {
// TODO(jaebaek): Get actual pixel values based on frame buffer formats.
- if (!IsFloatPixelEqualInt(command->GetR(), p[stride * i]) ||
- !IsFloatPixelEqualInt(command->GetG(), p[stride * i + 1]) ||
- !IsFloatPixelEqualInt(command->GetB(), p[stride * i + 2]) ||
+ if (!IsEqualWithTolerance(
+ static_cast<const double>(command->GetR()),
+ static_cast<const double>(p[stride * i]) / 255.0, tolerance[0],
+ is_tolerance_percent[0]) ||
+ !IsEqualWithTolerance(
+ static_cast<const double>(command->GetG()),
+ static_cast<const double>(p[stride * i + 1]) / 255.0,
+ tolerance[1], is_tolerance_percent[1]) ||
+ !IsEqualWithTolerance(
+ static_cast<const double>(command->GetB()),
+ static_cast<const double>(p[stride * i + 2]) / 255.0,
+ tolerance[2], is_tolerance_percent[2]) ||
(command->IsRGBA() &&
- !IsFloatPixelEqualInt(command->GetA(), p[stride * i + 3]))) {
+ !IsEqualWithTolerance(
+ static_cast<const double>(command->GetA()),
+ static_cast<const double>(p[stride * i + 3]) / 255.0,
+ tolerance[3], is_tolerance_percent[3]))) {
if (!count_of_invalid_pixels) {
first_invalid_i = i;
first_invalid_j = j;
@@ -114,8 +268,48 @@ Result Verifier::Probe(const ProbeCommand* command,
return {};
}
-Result Verifier::ProbeSSBO(const ProbeSSBOCommand*, size_t, const void*) {
- return Result("Verifier::ProbeSSBO Not Implemented");
+Result Verifier::ProbeSSBO(const ProbeSSBOCommand* command,
+ size_t size_in_bytes,
+ const void* cpu_memory) {
+ const auto& values = command->GetValues();
+ const auto& datum_type = command->GetDatumType();
+ size_t bytes_per_elem = datum_type.SizeInBytes() / datum_type.RowCount() /
+ datum_type.ColumnCount();
+ size_t offset = static_cast<size_t>(command->GetOffset());
+
+ if (values.size() * bytes_per_elem + offset > size_in_bytes) {
+ return Result(
+ "Verifier::ProbeSSBO has more expected values than SSBO size");
+ }
+
+ if (offset % bytes_per_elem != 0) {
+ return Result(
+ "Verifier::ProbeSSBO given offset is not multiple of bytes_per_elem");
+ }
+
+ const uint8_t* ptr = static_cast<const uint8_t*>(cpu_memory) + offset;
+ if (datum_type.IsInt8())
+ return CheckValue<int8_t>(command, ptr, values);
+ if (datum_type.IsUint8())
+ return CheckValue<uint8_t>(command, ptr, values);
+ if (datum_type.IsInt16())
+ return CheckValue<int16_t>(command, ptr, values);
+ if (datum_type.IsUint16())
+ return CheckValue<uint16_t>(command, ptr, values);
+ if (datum_type.IsInt32())
+ return CheckValue<int32_t>(command, ptr, values);
+ if (datum_type.IsUint32())
+ return CheckValue<uint32_t>(command, ptr, values);
+ if (datum_type.IsInt64())
+ return CheckValue<int64_t>(command, ptr, values);
+ if (datum_type.IsUint64())
+ return CheckValue<uint64_t>(command, ptr, values);
+ if (datum_type.IsFloat())
+ return CheckValue<float>(command, ptr, values);
+ if (datum_type.IsDouble())
+ return CheckValue<double>(command, ptr, values);
+
+ return Result("Verifier::ProbeSSBO unknown datum type");
}
} // namespace amber