validate Engine in all Builder::build() methods
We now assert if the Engine given is invalid, which would happen if it was used after being destroyed. Builder::build() is a reasonable place for this since it's generally not in the critical path.
This commit is contained in:
committed by
Mathias Agopian
parent
2fa08123a0
commit
2548da9aed
@@ -94,29 +94,50 @@ FEngine* FEngine::create(Backend backend, Platform* platform, void* sharedGLCont
|
||||
instance->mOwnPlatform = true;
|
||||
}
|
||||
instance->mDriver = platform->createDriver(sharedGLContext);
|
||||
instance->init();
|
||||
instance->execute();
|
||||
return instance;
|
||||
} else {
|
||||
// start the driver thread
|
||||
instance->mDriverThread = std::thread(&FEngine::loop, instance);
|
||||
|
||||
// wait for the driver to be ready
|
||||
instance->mDriverBarrier.await();
|
||||
|
||||
if (UTILS_UNLIKELY(!instance->mDriver)) {
|
||||
// something went horribly wrong during driver initialization
|
||||
instance->mDriverThread.join();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// start the driver thread
|
||||
instance->mDriverThread = std::thread(&FEngine::loop, instance);
|
||||
|
||||
// wait for the driver to be ready
|
||||
instance->mDriverBarrier.await();
|
||||
|
||||
if (UTILS_UNLIKELY(!instance->mDriver)) {
|
||||
// something went horribly wrong during driver initialization
|
||||
instance->mDriverThread.join();
|
||||
return nullptr;
|
||||
// Add this Engine to the list of active Engines
|
||||
{ // scope for the lock
|
||||
std::unique_ptr<FEngine> engine(instance);
|
||||
std::lock_guard<std::mutex> guard(sEnginesLock);
|
||||
Engine* handle = engine.get();
|
||||
sEngines[handle] = std::move(engine);
|
||||
}
|
||||
|
||||
// now we can initialize the largest part of the engine
|
||||
instance->init();
|
||||
|
||||
if (!UTILS_HAS_THREADING) {
|
||||
instance->execute();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void FEngine::assertValid(Engine const& engine) {
|
||||
bool valid;
|
||||
{ // scope for the lock
|
||||
std::lock_guard<std::mutex> guard(sEnginesLock);
|
||||
auto const& engines = sEngines;
|
||||
auto const& pos = engines.find(&engine);
|
||||
valid = pos != engines.end();
|
||||
}
|
||||
ASSERT_POSTCONDITION(valid,
|
||||
"Using an Engine instance (@ %p) after it's been destroyed", &engine);
|
||||
}
|
||||
|
||||
// these must be static because only a pointer is copied to the render stream
|
||||
// Note that these coordinates are specified in OpenGL clip space. Other backends can transform
|
||||
@@ -748,16 +769,7 @@ bool FEngine::execute() {
|
||||
using namespace details;
|
||||
|
||||
Engine* Engine::create(Backend backend, Platform* platform, void* sharedGLContext) {
|
||||
std::unique_ptr<FEngine> engine(FEngine::create(backend, platform, sharedGLContext));
|
||||
if (UTILS_UNLIKELY(!engine)) {
|
||||
// something went wrong during the driver or engine initialization
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(sEnginesLock);
|
||||
Engine* handle = engine.get();
|
||||
sEngines[handle] = std::move(engine);
|
||||
return handle;
|
||||
return FEngine::create(backend, platform, sharedGLContext);
|
||||
}
|
||||
|
||||
void Engine::destroy(Engine* engine) {
|
||||
|
||||
@@ -48,6 +48,7 @@ IndexBuffer::Builder& IndexBuffer::Builder::bufferType(IndexType indexType) noex
|
||||
}
|
||||
|
||||
IndexBuffer* IndexBuffer::Builder::build(Engine& engine) {
|
||||
FEngine::assertValid(engine);
|
||||
return upcast(engine).createIndexBuffer(*this);
|
||||
}
|
||||
|
||||
|
||||
@@ -148,6 +148,7 @@ IndirectLight::Builder& IndirectLight::Builder::rotation(mat3f const& rotation)
|
||||
}
|
||||
|
||||
IndirectLight* IndirectLight::Builder::build(Engine& engine) {
|
||||
FEngine::assertValid(engine);
|
||||
if (mImpl->mReflectionsMap) {
|
||||
if (!ASSERT_POSTCONDITION_NON_FATAL(
|
||||
mImpl->mReflectionsMap->getTarget() == Texture::Sampler::SAMPLER_CUBEMAP,
|
||||
|
||||
@@ -73,6 +73,7 @@ Material::Builder& Material::Builder::package(const void* payload, size_t size)
|
||||
}
|
||||
|
||||
Material* Material::Builder::build(Engine& engine) {
|
||||
FEngine::assertValid(engine);
|
||||
MaterialParser* materialParser = FMaterial::createParser(
|
||||
upcast(engine).getBackend(), mImpl->mPayload, mImpl->mSize);
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ RenderTarget::Builder& RenderTarget::Builder::layer(AttachmentPoint pt, uint32_t
|
||||
}
|
||||
|
||||
RenderTarget* RenderTarget::Builder::build(Engine& engine) {
|
||||
FEngine::assertValid(engine);
|
||||
using backend::TextureUsage;
|
||||
const FRenderTarget::Attachment& color = mImpl->mAttachments[COLOR];
|
||||
const FRenderTarget::Attachment& depth = mImpl->mAttachments[DEPTH];
|
||||
|
||||
@@ -69,6 +69,7 @@ Skybox::Builder& Skybox::Builder::showSun(bool show) noexcept {
|
||||
}
|
||||
|
||||
Skybox* Skybox::Builder::build(Engine& engine) {
|
||||
FEngine::assertValid(engine);
|
||||
FTexture* cubemap = upcast(mImpl->mEnvironmentMap);
|
||||
|
||||
if (!ASSERT_PRECONDITION_NON_FATAL(cubemap, "environment texture not set")) {
|
||||
|
||||
@@ -69,7 +69,7 @@ Stream::Builder& Stream::Builder::height(uint32_t height) noexcept {
|
||||
}
|
||||
|
||||
Stream* Stream::Builder::build(Engine& engine) {
|
||||
|
||||
FEngine::assertValid(engine);
|
||||
if (!ASSERT_PRECONDITION_NON_FATAL(!mImpl->mStream || !mImpl->mExternalTextureId,
|
||||
"One and only one of the stream or external texture can be specified")) {
|
||||
return nullptr;
|
||||
|
||||
@@ -92,6 +92,7 @@ Texture::Builder& Texture::Builder::usage(Texture::Usage usage) noexcept {
|
||||
}
|
||||
|
||||
Texture* Texture::Builder::build(Engine& engine) {
|
||||
FEngine::assertValid(engine);
|
||||
if (!ASSERT_POSTCONDITION_NON_FATAL(Texture::isTextureFormatSupported(engine, mImpl->mFormat),
|
||||
"Texture format %u not supported on this platform", mImpl->mFormat)) {
|
||||
return nullptr;
|
||||
|
||||
@@ -110,10 +110,10 @@ VertexBuffer::Builder& VertexBuffer::Builder::normalized(VertexAttribute attribu
|
||||
}
|
||||
|
||||
VertexBuffer* VertexBuffer::Builder::build(Engine& engine) {
|
||||
FEngine::assertValid(engine);
|
||||
if (!ASSERT_PRECONDITION_NON_FATAL(mImpl->mVertexCount > 0, "vertexCount cannot be 0")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!ASSERT_PRECONDITION_NON_FATAL(mImpl->mBufferCount > 0, "bufferCount cannot be 0")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ LightManager::Builder& LightManager::Builder::sunHaloFalloff(float haloFalloff)
|
||||
}
|
||||
|
||||
LightManager::Builder::Result LightManager::Builder::build(Engine& engine, Entity entity) {
|
||||
FEngine::assertValid(engine);
|
||||
upcast(engine).createLight(*this, entity);
|
||||
return Success;
|
||||
}
|
||||
|
||||
@@ -167,6 +167,7 @@ RenderableManager::Builder& RenderableManager::Builder::blendOrder(size_t index,
|
||||
}
|
||||
|
||||
RenderableManager::Builder::Result RenderableManager::Builder::build(Engine& engine, Entity entity) {
|
||||
FEngine::assertValid(engine);
|
||||
bool isEmpty = true;
|
||||
|
||||
if (!ASSERT_PRECONDITION_NON_FATAL(mImpl->mSkinningBoneCount <= CONFIG_MAX_BONE_COUNT,
|
||||
|
||||
@@ -132,6 +132,8 @@ public:
|
||||
static FEngine* create(Backend backend = Backend::DEFAULT,
|
||||
Platform* platform = nullptr, void* sharedGLContext = nullptr);
|
||||
|
||||
static void assertValid(Engine const& engine);
|
||||
|
||||
~FEngine() noexcept;
|
||||
|
||||
backend::Driver& getDriver() const noexcept { return *mDriver; }
|
||||
|
||||
Reference in New Issue
Block a user