utils: add precond/postcond macro guarded by feature flags
We link the behavior of certain precondition/postcondition checks to feature flag states. - If provided *flag* is true, then this macro will assert when the *condition* is false. - If provided *flag* is fase, then this macro will output a warning when the condition is false. - If the condition is true, then neither of the above will happen These two macros will enable us to provide less restrictive behavior for certain correctness assertions, allowing clients to modify their before enabling these assertions by default.
This commit is contained in:
@@ -1235,20 +1235,13 @@ bool FEngine::destroy(const FMaterialInstance* p) {
|
||||
size_t const primitiveCount = rcm.getPrimitiveCount(ri, 0);
|
||||
for (size_t j = 0; j < primitiveCount; j++) {
|
||||
auto const* const mi = rcm.getMaterialInstanceAt(ri, 0, j);
|
||||
if (features.engine.debug.assert_material_instance_in_use) {
|
||||
FILAMENT_CHECK_PRECONDITION(mi != p)
|
||||
<< "destroying MaterialInstance \""
|
||||
<< mi->getName() << "\" which is still in use by Renderable (entity="
|
||||
<< entity.getId() << ", instance="
|
||||
<< ri.asValue() << ", index=" << j << ")";
|
||||
} else {
|
||||
if (UTILS_UNLIKELY(mi == p)) {
|
||||
LOG(ERROR) << "destroying MaterialInstance \"" << mi->getName()
|
||||
<< "\" which is still in use by Renderable (entity="
|
||||
<< entity.getId() << ", instance=" << ri.asValue()
|
||||
<< ", index=" << j << ")";
|
||||
}
|
||||
}
|
||||
auto const& featureFlags = features.engine.debug;
|
||||
FILAMENT_FLAG_GUARDED_CHECK_PRECONDITION(
|
||||
mi != p,
|
||||
featureFlags.assert_material_instance_in_use)
|
||||
<< "destroying MaterialInstance \"" << mi->getName()
|
||||
<< "\" which is still in use by Renderable (entity=" << entity.getId()
|
||||
<< ", instance=" << ri.asValue() << ", index=" << j << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,16 +391,11 @@ void FMaterial::terminate(FEngine& engine) {
|
||||
auto const& materialInstanceResourceList = engine.getMaterialInstanceResourceList();
|
||||
auto pos = materialInstanceResourceList.find(this);
|
||||
if (UTILS_LIKELY(pos != materialInstanceResourceList.cend())) {
|
||||
if (engine.features.engine.debug.assert_destroy_material_before_material_instance) {
|
||||
FILAMENT_CHECK_PRECONDITION(pos->second.empty())
|
||||
<< "destroying material \"" << this->getName().c_str_safe() << "\" but "
|
||||
<< pos->second.size() << " instances still alive.";
|
||||
} else {
|
||||
if (UTILS_UNLIKELY(!pos->second.empty())) {
|
||||
LOG(ERROR) << "destroying material \"" << this->getName().c_str_safe() << "\" but "
|
||||
<< pos->second.size() << " instances still alive.";
|
||||
}
|
||||
}
|
||||
auto const& featureFlags = engine.features.engine.debug;
|
||||
FILAMENT_FLAG_GUARDED_CHECK_PRECONDITION(pos->second.empty(),
|
||||
featureFlags.assert_destroy_material_before_material_instance)
|
||||
<< "destroying material \"" << this->getName().c_str_safe() << "\" but "
|
||||
<< pos->second.size() << " instances still alive.";
|
||||
}
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
|
||||
@@ -158,12 +158,11 @@ VertexBuffer* VertexBuffer::Builder::build(Engine& engine) {
|
||||
|
||||
static_assert(DOCUMENTED_MAX_VERTEX_BUFFER_COUNT <= MAX_VERTEX_BUFFER_COUNT);
|
||||
|
||||
if (downcast(engine).features.engine.debug.assert_vertex_buffer_count_exceeds_8) {
|
||||
FILAMENT_CHECK_PRECONDITION(mImpl->mBufferCount <= DOCUMENTED_MAX_VERTEX_BUFFER_COUNT)
|
||||
<< "bufferCount cannot be more than " << DOCUMENTED_MAX_VERTEX_BUFFER_COUNT;
|
||||
} else if (mImpl->mBufferCount > DOCUMENTED_MAX_VERTEX_BUFFER_COUNT) {
|
||||
LOG(WARNING) << "bufferCount cannot be more than " << DOCUMENTED_MAX_VERTEX_BUFFER_COUNT;
|
||||
}
|
||||
auto const& featureFlags = static_cast<FEngine*>(&engine)->features.engine.debug;
|
||||
FILAMENT_FLAG_GUARDED_CHECK_PRECONDITION(
|
||||
mImpl->mBufferCount <= DOCUMENTED_MAX_VERTEX_BUFFER_COUNT,
|
||||
featureFlags.assert_vertex_buffer_count_exceeds_8)
|
||||
<< "bufferCount cannot be more than " << DOCUMENTED_MAX_VERTEX_BUFFER_COUNT;
|
||||
|
||||
// Next we check if any unused buffer slots have been allocated. This helps prevent errors
|
||||
// because uploading to an unused slot can trigger undefined behavior in the backend.
|
||||
@@ -177,15 +176,10 @@ VertexBuffer* VertexBuffer::Builder::build(Engine& engine) {
|
||||
<< "attribute " << j << " offset=" << attributes[j].offset
|
||||
<< " is not multiple of 4";
|
||||
|
||||
FEngine* fengine = static_cast<FEngine*>(&engine);
|
||||
if (fengine->features.engine.debug.assert_vertex_buffer_attribute_stride_mult_of_4) {
|
||||
FILAMENT_CHECK_PRECONDITION((attributes[j].stride & 0x3u) == 0)
|
||||
<< "attribute " << j << " stride=" << attributes[j].stride
|
||||
<< " is not multiple of 4";
|
||||
} else if ((attributes[j].stride & 0x3u) != 0) {
|
||||
LOG(WARNING) << "attribute " << j << " stride=" << attributes[j].stride
|
||||
<< " is not multiple of 4";
|
||||
}
|
||||
FILAMENT_FLAG_GUARDED_CHECK_PRECONDITION((attributes[j].stride & 0x3u) == 0,
|
||||
featureFlags.assert_vertex_buffer_attribute_stride_mult_of_4)
|
||||
<< "attribute " << j << " stride=" << +attributes[j].stride
|
||||
<< " is not multiple of 4";
|
||||
|
||||
if (engine.getActiveFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0) {
|
||||
FILAMENT_CHECK_PRECONDITION(!(attributes[j].flags & Attribute::FLAG_INTEGER_TARGET))
|
||||
|
||||
@@ -544,6 +544,27 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PanicType>
|
||||
class FlagGuardedStream : public PanicStream {
|
||||
public:
|
||||
FlagGuardedStream(bool enable, char const* function, char const* file, int line,
|
||||
char const* condition)
|
||||
: PanicStream(function, file, line, condition),
|
||||
mEnablePanic(enable) {}
|
||||
~FlagGuardedStream() noexcept(false) {
|
||||
if (mEnablePanic) {
|
||||
PanicType::panic(mFunction, mFile, mLine, mLiteral, mStream.c_str());
|
||||
} else {
|
||||
logWarning();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void logWarning() noexcept;
|
||||
|
||||
bool mEnablePanic;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
@@ -582,6 +603,20 @@ public:
|
||||
FILAMENT_CHECK_CONDITION_IMPL(condition) FILAMENT_PANIC_IMPL(#condition, ArithmeticPanic)
|
||||
#endif
|
||||
|
||||
#define FILAMENT_FLAG_GUARDED_PANIC_IMPL(flag, condition, TYPE) \
|
||||
::utils::details::FlagGuardedStream<::utils::TYPE>(flag, PANIC_FUNCTION, PANIC_FILE(__FILE__), \
|
||||
__LINE__, #condition)
|
||||
|
||||
#ifndef FILAMENT_FLAG_GUARDED_CHECK_PRECONDITION
|
||||
#define FILAMENT_FLAG_GUARDED_CHECK_PRECONDITION(condition, flag) \
|
||||
FILAMENT_CHECK_CONDITION_IMPL(condition) FILAMENT_FLAG_GUARDED_PANIC_IMPL(flag, condition, PreconditionPanic)
|
||||
#endif
|
||||
|
||||
#ifndef FILAMENT_FLAG_GUARDED_CHECK_POSTCONDITION
|
||||
#define FILAMENT_FLAG_GUARDED_CHECK_POSTCONDITION(condition, flag) \
|
||||
FILAMENT_CHECK_CONDITION_IMPL(condition) FILAMENT_FLAG_GUARDED_PANIC_IMPL(flag, condition, PostconditionPanic)
|
||||
#endif
|
||||
|
||||
#define PANIC_PRECONDITION_IMPL(cond, format, ...) \
|
||||
::utils::PreconditionPanic::panic(PANIC_FUNCTION, \
|
||||
PANIC_FILE(__FILE__), __LINE__, #cond, format, ##__VA_ARGS__)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <utils/CallStack.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Logger.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
@@ -352,6 +353,17 @@ PanicStream& PanicStream::operator<<(std::string_view const& value) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename PanicType>
|
||||
void FlagGuardedStream<PanicType>::logWarning() noexcept {
|
||||
LOG(WARNING) << "Failed [" << mLiteral << "]" << "\n file=" << mFile
|
||||
<< "\n function=" << mFunction << "\n line=" << mLine << "\n info=\""
|
||||
<< mStream.c_str() << "\"";
|
||||
|
||||
}
|
||||
|
||||
template void FlagGuardedStream<PreconditionPanic>::logWarning() noexcept;
|
||||
template void FlagGuardedStream<PostconditionPanic>::logWarning() noexcept;
|
||||
|
||||
} // namespace details
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user