Support for switching between renderers in run-time

This commit is contained in:
Attila Uygun 2023-05-22 12:17:23 +02:00
parent b7f1f7faa2
commit b160ae0bd3
11 changed files with 97 additions and 19 deletions

View File

@ -71,22 +71,7 @@ bool Engine::Initialize() {
LOG << "image scale factor: " << GetImageScaleFactor(); LOG << "image scale factor: " << GetImageScaleFactor();
if (renderer_->SupportsDXT5()) { CreateTextureCompressors();
tex_comp_alpha_ = TextureCompressor::Create(TextureCompressor::kFormatDXT5);
} else if (renderer_->SupportsATC()) {
tex_comp_alpha_ =
TextureCompressor::Create(TextureCompressor::kFormatATCIA);
}
if (renderer_->SupportsDXT1()) {
tex_comp_opaque_ =
TextureCompressor::Create(TextureCompressor::kFormatDXT1);
} else if (renderer_->SupportsATC()) {
tex_comp_opaque_ = TextureCompressor::Create(TextureCompressor::kFormatATC);
} else if (renderer_->SupportsETC1()) {
tex_comp_opaque_ =
TextureCompressor::Create(TextureCompressor::kFormatETC1);
}
system_font_ = std::make_unique<Font>(); system_font_ = std::make_unique<Font>();
system_font_->Load("engine/RobotoMono-Regular.ttf"); system_font_->Load("engine/RobotoMono-Regular.ttf");
@ -199,6 +184,28 @@ void Engine::RemoveAnimator(Animator* animator) {
} }
} }
void Engine::SwitchRenderer(bool vulkan) {
Renderer* new_renderer = platform_->SwitchRenderer(vulkan);
if (new_renderer == renderer_)
return;
renderer_ = new_renderer;
renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this));
CreateTextureCompressors();
for (auto& t : textures_)
t.second.texture->SetRenderer(renderer_);
for (auto& s : shaders_)
s.second.shader->SetRenderer(renderer_);
quad_->SetRenderer(renderer_);
pass_through_shader_->SetRenderer(renderer_);
solid_shader_->SetRenderer(renderer_);
ContextLost();
}
void Engine::Exit() { void Engine::Exit() {
platform_->Exit(); platform_->Exit();
} }
@ -488,6 +495,28 @@ bool Engine::IsMobile() const {
return platform_->mobile_device(); return platform_->mobile_device();
} }
void Engine::CreateTextureCompressors() {
tex_comp_alpha_.reset();
tex_comp_opaque_.reset();
if (renderer_->SupportsDXT5()) {
tex_comp_alpha_ = TextureCompressor::Create(TextureCompressor::kFormatDXT5);
} else if (renderer_->SupportsATC()) {
tex_comp_alpha_ =
TextureCompressor::Create(TextureCompressor::kFormatATCIA);
}
if (renderer_->SupportsDXT1()) {
tex_comp_opaque_ =
TextureCompressor::Create(TextureCompressor::kFormatDXT1);
} else if (renderer_->SupportsATC()) {
tex_comp_opaque_ = TextureCompressor::Create(TextureCompressor::kFormatATC);
} else if (renderer_->SupportsETC1()) {
tex_comp_opaque_ =
TextureCompressor::Create(TextureCompressor::kFormatETC1);
}
}
void Engine::ContextLost() { void Engine::ContextLost() {
CreateRenderResources(); CreateRenderResources();

View File

@ -55,6 +55,8 @@ class Engine {
void AddAnimator(Animator* animator); void AddAnimator(Animator* animator);
void RemoveAnimator(Animator* animator); void RemoveAnimator(Animator* animator);
void SwitchRenderer(bool vulkan);
void Exit(); void Exit();
// Convert size from pixels to viewport scale. // Convert size from pixels to viewport scale.
@ -222,6 +224,8 @@ class Engine {
base::Randomf random_; base::Randomf random_;
void CreateTextureCompressors();
void ContextLost(); void ContextLost();
bool CreateRenderResources(); bool CreateRenderResources();

View File

@ -22,6 +22,25 @@ Platform::Platform() = default;
Platform::~Platform() = default; Platform::~Platform() = default;
Renderer* Platform::SwitchRenderer(bool vulkan) {
DCHECK(renderer_);
if ((dynamic_cast<RendererVulkan*>(renderer_.get()) && vulkan) ||
(dynamic_cast<RendererOpenGL*>(renderer_.get()) && !vulkan))
return renderer_.get();
if (vulkan)
renderer_ = std::make_unique<RendererVulkan>();
else
renderer_ = std::make_unique<RendererOpenGL>();
bool result = InitializeRenderer();
CHECK(result) << "Failed to initialize " << renderer_->GetDebugName()
<< " renderer.";
LOG << "Switched to " << renderer_->GetDebugName() << " renderer.";
return renderer_.get();
}
void Platform::InitializeCommon() { void Platform::InitializeCommon() {
LOG << "Initializing platform."; LOG << "Initializing platform.";

View File

@ -45,6 +45,8 @@ class Platform {
void Exit(); void Exit();
Renderer* SwitchRenderer(bool vulkan);
void Vibrate(int duration); void Vibrate(int duration);
void ShowInterstitialAd(); void ShowInterstitialAd();
@ -121,6 +123,8 @@ class Platform {
void InitializeCommon(); void InitializeCommon();
void ShutdownCommon(); void ShutdownCommon();
bool InitializeRenderer();
Platform(const Platform&) = delete; Platform(const Platform&) = delete;
Platform& operator=(const Platform&) = delete; Platform& operator=(const Platform&) = delete;
}; };

View File

@ -295,7 +295,7 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) {
DLOG << "APP_CMD_INIT_WINDOW"; DLOG << "APP_CMD_INIT_WINDOW";
if (app->window != NULL) { if (app->window != NULL) {
platform->SetFrameRate(60); platform->SetFrameRate(60);
bool res = platform->renderer_->Initialize(app->window); bool res = platform->InitializeRenderer();
CHECK(res) << "Failed to initialize " CHECK(res) << "Failed to initialize "
<< platform->renderer_->GetDebugName() << " renderer."; << platform->renderer_->GetDebugName() << " renderer.";
} }
@ -314,7 +314,7 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) {
if (width != ANativeWindow_getWidth(app->window) || if (width != ANativeWindow_getWidth(app->window) ||
height != ANativeWindow_getHeight(app->window)) { height != ANativeWindow_getHeight(app->window)) {
platform->renderer_->Shutdown(); platform->renderer_->Shutdown();
bool res = platform->renderer_->Initialize(platform->app_->window); bool res = platform->InitializeRenderer();
CHECK(res) << "Failed to initialize " CHECK(res) << "Failed to initialize "
<< platform->renderer_->GetDebugName() << " renderer."; << platform->renderer_->GetDebugName() << " renderer.";
} }
@ -439,6 +439,10 @@ void Platform::SetFrameRate(float frame_rate) {
} }
} }
bool Platform::InitializeRenderer() {
return renderer_->Initialize(app_->window);
}
} // namespace eng } // namespace eng
void android_main(android_app* app) { void android_main(android_app* app) {

View File

@ -26,7 +26,7 @@ void Platform::Initialize() {
bool res = CreateWindow(800, 1205); bool res = CreateWindow(800, 1205);
CHECK(res) << "Failed to create window."; CHECK(res) << "Failed to create window.";
res = renderer_->Initialize(display_, window_); res = InitializeRenderer();
CHECK(res) << "Failed to initialize " << renderer_->GetDebugName() CHECK(res) << "Failed to initialize " << renderer_->GetDebugName()
<< " renderer."; << " renderer.";
@ -157,6 +157,10 @@ void Platform::DestroyWindow() {
} }
} }
bool Platform::InitializeRenderer() {
return renderer_->Initialize(display_, window_);
}
} // namespace eng } // namespace eng
int main(int argc, char** argv) { int main(int argc, char** argv) {

View File

@ -48,6 +48,7 @@ RendererOpenGL::RendererOpenGL() = default;
RendererOpenGL::~RendererOpenGL() { RendererOpenGL::~RendererOpenGL() {
Shutdown(); Shutdown();
OnDestroy();
} }
void RendererOpenGL::Shutdown() { void RendererOpenGL::Shutdown() {

View File

@ -165,6 +165,8 @@ class RendererOpenGL final : public Renderer {
bool InitCommon(); bool InitCommon();
void ShutdownInternal(); void ShutdownInternal();
void OnDestroy();
void ContextLost(); void ContextLost();
void DestroyAllResources(); void DestroyAllResources();

View File

@ -14,6 +14,10 @@ bool RendererOpenGL::Initialize(ANativeWindow* window) {
return StartRenderThread(); return StartRenderThread();
} }
void RendererOpenGL::OnDestroy() {
ndk_helper::GLContext::GetInstance()->Invalidate();
}
bool RendererOpenGL::InitInternal() { bool RendererOpenGL::InitInternal() {
ndk_helper::GLContext* gl_context = ndk_helper::GLContext::GetInstance(); ndk_helper::GLContext* gl_context = ndk_helper::GLContext::GetInstance();

View File

@ -18,6 +18,8 @@ bool RendererOpenGL::Initialize(Display* display, Window window) {
return StartRenderThread(); return StartRenderThread();
} }
void RendererOpenGL::OnDestroy() {}
bool RendererOpenGL::InitInternal() { bool RendererOpenGL::InitInternal() {
// Create the OpenGL context. // Create the OpenGL context.
glx_context_ = glx_context_ =

View File

@ -15,6 +15,11 @@ class RenderResource {
uint64_t resource_id() { return resource_id_; } uint64_t resource_id() { return resource_id_; }
void SetRenderer(Renderer* renderer) {
renderer_ = renderer;
resource_id_ = 0;
}
protected: protected:
uint64_t resource_id_ = 0; uint64_t resource_id_ = 0;
Renderer* renderer_ = nullptr; Renderer* renderer_ = nullptr;