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();
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);
}
CreateTextureCompressors();
system_font_ = std::make_unique<Font>();
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() {
platform_->Exit();
}
@ -488,6 +495,28 @@ bool Engine::IsMobile() const {
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() {
CreateRenderResources();

View File

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

View File

@ -22,6 +22,25 @@ 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() {
LOG << "Initializing platform.";

View File

@ -45,6 +45,8 @@ class Platform {
void Exit();
Renderer* SwitchRenderer(bool vulkan);
void Vibrate(int duration);
void ShowInterstitialAd();
@ -121,6 +123,8 @@ class Platform {
void InitializeCommon();
void ShutdownCommon();
bool InitializeRenderer();
Platform(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";
if (app->window != NULL) {
platform->SetFrameRate(60);
bool res = platform->renderer_->Initialize(app->window);
bool res = platform->InitializeRenderer();
CHECK(res) << "Failed to initialize "
<< platform->renderer_->GetDebugName() << " renderer.";
}
@ -314,7 +314,7 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) {
if (width != ANativeWindow_getWidth(app->window) ||
height != ANativeWindow_getHeight(app->window)) {
platform->renderer_->Shutdown();
bool res = platform->renderer_->Initialize(platform->app_->window);
bool res = platform->InitializeRenderer();
CHECK(res) << "Failed to initialize "
<< platform->renderer_->GetDebugName() << " renderer.";
}
@ -439,6 +439,10 @@ void Platform::SetFrameRate(float frame_rate) {
}
}
bool Platform::InitializeRenderer() {
return renderer_->Initialize(app_->window);
}
} // namespace eng
void android_main(android_app* app) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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