Compare commits

...

5 Commits

Author SHA1 Message Date
Attila Uygun daa3a8c06f Try Vulkan renderer first, fallback to OpenGL if it fails. 2023-05-16 22:07:52 +02:00
Attila Uygun 449ac3f386 Update version 2023-05-16 22:07:52 +02:00
Attila Uygun beba055645 Stringify error values 2023-05-16 22:07:52 +02:00
Attila Uygun 0a2f1bd7c3 Miscellaneous changes and improvements 2023-05-16 22:07:52 +02:00
Attila Uygun 58cc270e24 Use final and override appropriately 2023-05-16 08:46:50 +02:00
29 changed files with 296 additions and 287 deletions

View File

@ -26,3 +26,4 @@ cd build/android
[spirv-reflect](https://github.com/KhronosGroup/SPIRV-Reflect), [spirv-reflect](https://github.com/KhronosGroup/SPIRV-Reflect),
[vma](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator), [vma](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator),
[vulkan-sdk](https://vulkan.lunarg.com) [vulkan-sdk](https://vulkan.lunarg.com)
[volk](https://github.com/zeux/volk)

View File

@ -1,9 +1,5 @@
#ifdef GL_ES #ifdef GL_ES
precision highp float; precision highp float;
#else
#define lowp
#define mediump
#define highp
#endif #endif
IN(0) vec2 tex_coord_0; IN(0) vec2 tex_coord_0;
@ -17,19 +13,25 @@ UNIFORM_END
FRAG_COLOR_OUT(frag_color) FRAG_COLOR_OUT(frag_color)
const float PHI = 1.61803398874989484820459; // Golden Ratio
float random(vec2 p) { float random(vec2 p) {
float sd = sin(dot(p, vec2(54.90898, 18.233))); float sd = sin(dot(p, vec2(54.90898, 18.233)));
return fract(sd * 2671.6182); return fract(sd * 2671.6182);
} }
float random2(in vec2 xy) {
return fract(tan(distance(xy * PHI, xy)) * (xy.x + 0.1));
}
float nebula(in vec2 p) { float nebula(in vec2 p) {
vec2 i = floor(p); vec2 i = floor(p);
vec2 f = fract(p); vec2 f = fract(p);
float a = random(i); float a = random2(i);
float b = random(i + vec2(1.0, 0.0)); float b = random2(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0)); float c = random2(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0)); float d = random2(i + vec2(1.0, 1.0));
vec2 u = smoothstep(0.0, 1.0, f); vec2 u = smoothstep(0.0, 1.0, f);
@ -52,7 +54,7 @@ float stars(in vec2 p, float num_cells, float size) {
void main() { void main() {
vec2 layer1_coord = tex_coord_0 + PARAM(sky_offset); vec2 layer1_coord = tex_coord_0 + PARAM(sky_offset);
vec2 layer2_coord = tex_coord_0 + PARAM(sky_offset) * 0.7; vec2 layer2_coord = tex_coord_0 + PARAM(sky_offset) * 0.7;
mediump vec3 result = vec3(0.); vec3 result = vec3(0.);
float c = nebula(layer2_coord * 3.0) * 0.35 - 0.05; float c = nebula(layer2_coord * 3.0) * 0.35 - 0.05;
result += PARAM(nebula_color) * floor(c * 60.0) / 60.0; result += PARAM(nebula_color) * floor(c * 60.0) / 60.0;

View File

@ -1,9 +1,5 @@
#ifdef GL_ES #ifdef GL_ES
precision highp float; precision highp float;
#else
#define lowp
#define mediump
#define highp
#endif #endif
IN(0) vec2 tex_coord_0; IN(0) vec2 tex_coord_0;
@ -35,7 +31,7 @@ float stars(in vec2 p, float num_cells, float size) {
void main() { void main() {
vec2 layer1_coord = tex_coord_0 + PARAM(sky_offset); vec2 layer1_coord = tex_coord_0 + PARAM(sky_offset);
vec2 layer2_coord = tex_coord_0 + PARAM(sky_offset) * 0.7; vec2 layer2_coord = tex_coord_0 + PARAM(sky_offset) * 0.7;
mediump vec3 result = vec3(0.); vec3 result = vec3(0.);
float c = stars(layer1_coord, 8.0, 0.05); float c = stars(layer1_coord, 8.0, 0.05);
result += vec3(0.97, 0.74, 0.74) * c; result += vec3(0.97, 0.74, 0.74) * c;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="16" android:versionCode="17"
android:versionName="1.0.1"> android:versionName="1.0.2">
<application <application
android:allowBackup="false" android:allowBackup="false"

View File

@ -447,9 +447,9 @@ void Demo::StartNextStage(bool boss) {
Vector4f c = {Lerp(0.75f, 0.95f, rnd.Rand()) * weights[0], Vector4f c = {Lerp(0.75f, 0.95f, rnd.Rand()) * weights[0],
Lerp(0.75f, 0.95f, rnd.Rand()) * weights[1], Lerp(0.75f, 0.95f, rnd.Rand()) * weights[1],
Lerp(0.75f, 0.95f, rnd.Rand()) * weights[2], 1}; Lerp(0.75f, 0.95f, rnd.Rand()) * weights[2], 1};
c += {Lerp(0.1f, 0.5f, rnd.Rand()) * (1 - weights[0]), c += {Lerp(0.1f, 0.7f, rnd.Rand()) * (1 - weights[0]),
Lerp(0.1f, 0.5f, rnd.Rand()) * (1 - weights[1]), Lerp(0.1f, 0.7f, rnd.Rand()) * (1 - weights[1]),
Lerp(0.1f, 0.5f, rnd.Rand()) * (1 - weights[2]), 1}; Lerp(0.1f, 0.7f, rnd.Rand()) * (1 - weights[2]), 1};
sky_.SwitchColor(c); sky_.SwitchColor(c);
++wave_; ++wave_;
@ -457,9 +457,9 @@ void Demo::StartNextStage(bool boss) {
hud_.SetProgress(1); hud_.SetProgress(1);
if (boss_fight_) if (boss_fight_)
player_.TakeDamage(-3); player_.TakeDamage(-1);
total_enemies_ = 20.0f + 23.0897f * log((float)wave_); total_enemies_ = 23.0897f * log((float)wave_ + 1.0f) - 10.0f;
last_num_enemies_killed_ = 0; last_num_enemies_killed_ = 0;
boss_fight_ = false; boss_fight_ = false;
DLOG << "wave: " << wave_ << " total_enemies_: " << total_enemies_; DLOG << "wave: " << wave_ << " total_enemies_: " << total_enemies_;
@ -489,6 +489,7 @@ void Demo::Dimmer(bool enable) {
dimmer_.SetColor(kBgColor * Vector4f(0, 0, 0, 0)); dimmer_.SetColor(kBgColor * Vector4f(0, 0, 0, 0));
dimmer_animator_.SetBlending(kBgColor, kFadeSpeed); dimmer_animator_.SetBlending(kBgColor, kFadeSpeed);
dimmer_animator_.Play(Animator::kBlending, false); dimmer_animator_.Play(Animator::kBlending, false);
dimmer_animator_.SetEndCallback(Animator::kBlending, nullptr);
dimmer_animator_.SetVisible(true); dimmer_animator_.SetVisible(true);
} else if (!enable && dimmer_active_) { } else if (!enable && dimmer_active_) {
dimmer_active_ = false; dimmer_active_ = false;

View File

@ -18,20 +18,20 @@
// #define LOAD_TEST // #define LOAD_TEST
class Demo : public eng::Game { class Demo final : public eng::Game {
public: public:
Demo(); Demo();
~Demo() override; ~Demo() final;
bool Initialize() override; bool Initialize() final;
void Update(float delta_time) override; void Update(float delta_time) final;
void ContextLost() override; void ContextLost() final;
void LostFocus() override; void LostFocus() final;
void GainedFocus(bool from_interstitial_ad) override; void GainedFocus(bool from_interstitial_ad) final;
void AddScore(size_t score); void AddScore(size_t score);

View File

@ -148,7 +148,8 @@ void Enemy::Update(float delta_time) {
if (it->chromatic_aberration_active_) { if (it->chromatic_aberration_active_) {
it->sprite.SetCustomUniform( it->sprite.SetCustomUniform(
"aberration_offset", Lerp(0.0f, 0.01f, chromatic_aberration_offset_)); "aberration_offset",
Lerp(0.0f, 0.015f, chromatic_aberration_offset_));
} }
#if defined(LOAD_TEST) #if defined(LOAD_TEST)
else if (it->kill_timer <= 0 && else if (it->kill_timer <= 0 &&
@ -406,6 +407,8 @@ bool Enemy::IsBossAlive() const {
} }
void Enemy::PauseProgress() { void Enemy::PauseProgress() {
DeselectTarget(kDamageType_Green);
DeselectTarget(kDamageType_Blue);
progress_paused_ = true; progress_paused_ = true;
} }
@ -784,8 +787,7 @@ void Enemy::SpawnBoss() {
auto& e = enemies_.emplace_front(); auto& e = enemies_.emplace_front();
e.enemy_type = kEnemyType_Boss; e.enemy_type = kEnemyType_Boss;
e.damage_type = kDamageType_Any; e.damage_type = kDamageType_Any;
e.total_health = e.hit_points = e.total_health = e.hit_points = 41.1283f * log((float)game->wave()) - 20.0f;
-15.0845f + 41.1283f * log((float)game->wave());
DLOG << " Boss health: " << e.total_health; DLOG << " Boss health: " << e.total_health;
Vector2f hit_box_pos = Vector2f hit_box_pos =
@ -1080,7 +1082,7 @@ void Enemy::UpdateWave(float delta_time) {
SpawnUnit(kEnemyType_PowerUp, kDamageType_Any, pos, 6); SpawnUnit(kEnemyType_PowerUp, kDamageType_Any, pos, 6);
} }
seconds_since_last_power_up_ = 0; seconds_since_last_power_up_ = 0;
seconds_to_next_power_up_ = Lerp(1.3f * 60.0f, 1.8f * 60.0f, rnd.Rand()); seconds_to_next_power_up_ = Lerp(60.0f, 80.0f, rnd.Rand());
} }
} }
@ -1100,9 +1102,6 @@ void Enemy::UpdateBoss(float delta_time) {
if (boss_spawn_factor < 0.1f) if (boss_spawn_factor < 0.1f)
boss_spawn_factor = 0.1f; boss_spawn_factor = 0.1f;
DLOG << "boss_spawn_time_: " << boss_spawn_time_
<< " boss_spawn_factor: " << boss_spawn_factor;
EnemyType enemy_type = kEnemyType_Invalid; EnemyType enemy_type = kEnemyType_Invalid;
for (int i = 0; i < kEnemyType_Unit_Last + 1; ++i) { for (int i = 0; i < kEnemyType_Unit_Last + 1; ++i) {

View File

@ -22,7 +22,7 @@ using namespace eng;
namespace { namespace {
constexpr char kVersionStr[] = "Version 1.0.1"; constexpr char kVersionStr[] = "Version 1.0.2";
constexpr char kMenuOption[Menu::kOption_Max][10] = {"continue", "start", constexpr char kMenuOption[Menu::kOption_Max][10] = {"continue", "start",
"credits", "exit"}; "credits", "exit"};
@ -81,6 +81,11 @@ bool Menu::Initialize() {
items_[i].select_item_cb_ = [&, i]() -> void { items_[i].select_item_cb_ = [&, i]() -> void {
items_[i].text_animator.SetEndCallback(Animator::kBlending, nullptr); items_[i].text_animator.SetEndCallback(Animator::kBlending, nullptr);
// Wait until click sound ends before exiting.
if (i == kExit)
click_.SetEndCallback(
[&, i]() -> void { selected_option_ = (Option)i; });
else
selected_option_ = (Option)i; selected_option_ = (Option)i;
}; };
items_[i].text_animator.Attach(&items_[i].text); items_[i].text_animator.Attach(&items_[i].text);

View File

@ -288,7 +288,7 @@ void Player::SetupWeapons() {
weapon_[i].SetFrame(wepon_warmup_frame[i]); weapon_[i].SetFrame(wepon_warmup_frame[i]);
warmup_animator_[i].SetFrames(wepon_warmup_frame_count, wepon_anim_speed); warmup_animator_[i].SetFrames(wepon_warmup_frame_count, wepon_anim_speed);
warmup_animator_[i].SetRotation(M_PI * 2, 8.0f); warmup_animator_[i].SetRotation(M_PI * 2, 20.0f);
warmup_animator_[i].Attach(&weapon_[i]); warmup_animator_[i].Attach(&weapon_[i]);
warmup_animator_[i].Play(Animator::kRotation, true); warmup_animator_[i].Play(Animator::kRotation, true);

View File

@ -27,14 +27,14 @@ class SkyQuad : public eng::Animatable {
void Update(float delta_time); void Update(float delta_time);
// Animatable interface. // Animatable interface.
void SetFrame(size_t frame) override {} void SetFrame(size_t frame) final {}
size_t GetFrame() const override { return 0; } size_t GetFrame() const final { return 0; }
size_t GetNumFrames() const override { return 0; } size_t GetNumFrames() const final { return 0; }
void SetColor(const base::Vector4f& color) override { nebula_color_ = color; } void SetColor(const base::Vector4f& color) final { nebula_color_ = color; }
base::Vector4f GetColor() const override { return nebula_color_; } base::Vector4f GetColor() const final { return nebula_color_; }
// Drawable interface. // Drawable interface.
void Draw(float frame_frac) override; void Draw(float frame_frac) final;
void ContextLost(); void ContextLost();

View File

@ -180,9 +180,13 @@ void Animator::Update(float delta_time) {
UpdateAnimTime(delta_time, kFrames, frame_speed_, frame_time_, frame_cb_); UpdateAnimTime(delta_time, kFrames, frame_speed_, frame_time_, frame_cb_);
if (play_flags_ & kTimer) if (play_flags_ & kTimer)
UpdateAnimTime(delta_time, kTimer, timer_speed_, timer_time_, timer_cb_); UpdateAnimTime(delta_time, kTimer, timer_speed_, timer_time_, timer_cb_);
did_evaluate_ = false;
} }
void Animator::Evaluate(float frame_frac_time) { void Animator::Evaluate(float frame_frac_time) {
did_evaluate_ = true;
Vector2f pos = {0, 0}; Vector2f pos = {0, 0};
if (play_flags_ & kMovement) { if (play_flags_ & kMovement) {
float time = movement_time_ + movement_speed_ * frame_frac_time; float time = movement_time_ + movement_speed_ * frame_frac_time;
@ -248,6 +252,8 @@ void Animator::UpdateAnimTime(float delta_time,
if (loop_flags_ & anim) { if (loop_flags_ & anim) {
anim_time = fmod(anim_time, 1.0f); anim_time = fmod(anim_time, 1.0f);
} else { } else {
if (!did_evaluate_)
Evaluate(0);
anim_time = 0; anim_time = 0;
play_flags_ &= ~anim; play_flags_ &= ~anim;
if (cb) { if (cb) {

View File

@ -120,6 +120,8 @@ class Animator {
base::Closure pending_cb_; base::Closure pending_cb_;
Flags inside_cb_ = kNone; Flags inside_cb_ = kNone;
bool did_evaluate_ = false;
void UpdateAnimTime(float delta_time, void UpdateAnimTime(float delta_time,
int anim, int anim,
float anim_speed, float anim_speed,

View File

@ -25,17 +25,17 @@ class AudioOboe : public AudioBase {
int GetHardwareSampleRate(); int GetHardwareSampleRate();
private: private:
class StreamCallback : public oboe::AudioStreamCallback { class StreamCallback final : public oboe::AudioStreamCallback {
public: public:
StreamCallback(AudioOboe* audio); StreamCallback(AudioOboe* audio);
~StreamCallback() override; ~StreamCallback() final;
oboe::DataCallbackResult onAudioReady(oboe::AudioStream* oboe_stream, oboe::DataCallbackResult onAudioReady(oboe::AudioStream* oboe_stream,
void* audio_data, void* audio_data,
int32_t num_frames) override; int32_t num_frames) final;
void onErrorAfterClose(oboe::AudioStream* oboe_stream, void onErrorAfterClose(oboe::AudioStream* oboe_stream,
oboe::Result error) override; oboe::Result error) final;
private: private:
AudioOboe* audio_; AudioOboe* audio_;

View File

@ -222,31 +222,27 @@ void Engine::SetImageSource(const std::string& asset_name,
void Engine::SetImageSource(const std::string& asset_name, void Engine::SetImageSource(const std::string& asset_name,
CreateImageCB create_image, CreateImageCB create_image,
bool persistent) { bool persistent) {
Texture* texture; if (textures_.contains(asset_name) && textures_[asset_name].use_count > 0) {
auto it = textures_.find(asset_name); DLOG << "Texture in use: " << asset_name;
if (it != textures_.end()) { return;
texture = it->second.texture.get(); }
it->second.create_image = create_image;
it->second.persistent = persistent;
} else {
auto& t = textures_[asset_name] = {CreateRenderResource<Texture>(), auto& t = textures_[asset_name] = {CreateRenderResource<Texture>(),
create_image, persistent, 0}; create_image, persistent, 0};
texture = t.texture.get();
}
if (persistent) { if (persistent) {
auto image = create_image(); auto image = create_image();
if (image) if (image)
texture->Update(std::move(image)); t.texture->Update(std::move(image));
else
texture->Destroy();
} }
} }
void Engine::RefreshImage(const std::string& asset_name) { void Engine::RefreshImage(const std::string& asset_name) {
auto it = textures_.find(asset_name); auto it = textures_.find(asset_name);
if (it == textures_.end()) if (it == textures_.end()) {
DLOG << "Texture not found: " << asset_name;
return; return;
}
auto image = it->second.create_image(); auto image = it->second.create_image();
if (image) if (image)
@ -257,22 +253,23 @@ void Engine::RefreshImage(const std::string& asset_name) {
Texture* Engine::AcquireTexture(const std::string& asset_name) { Texture* Engine::AcquireTexture(const std::string& asset_name) {
auto it = textures_.find(asset_name); auto it = textures_.find(asset_name);
if (it != textures_.end()) { if (it == textures_.end()) {
DLOG << "Texture not found: " << asset_name;
return nullptr;
}
if (!it->second.texture->IsValid()) if (!it->second.texture->IsValid())
RefreshImage(it->first); RefreshImage(it->first);
it->second.use_count++; it->second.use_count++;
return it->second.texture.get(); return it->second.texture.get();
}
auto& t = textures_[asset_name] = {CreateRenderResource<Texture>(), nullptr,
false, 1};
return t.texture.get();
} }
void Engine::ReleaseTexture(const std::string& asset_name) { void Engine::ReleaseTexture(const std::string& asset_name) {
auto it = textures_.find(asset_name); auto it = textures_.find(asset_name);
if (it == textures_.end()) if (it == textures_.end()) {
DLOG << "Texture not found: " << asset_name;
return; return;
}
DCHECK(it->second.use_count > 0); DCHECK(it->second.use_count > 0);
it->second.use_count--; it->second.use_count--;
@ -510,10 +507,7 @@ std::unique_ptr<Image> Engine::PrintStats() {
line = "fps: "; line = "fps: ";
line += std::to_string(fps_); line += std::to_string(fps_);
lines.push_back(line); lines.push_back(line);
// line = "cmd: "; lines.push_back(renderer_->GetDebugName());
// line += std::to_string(renderer_->global_queue_size() +
// renderer_->render_queue_size());
// lines.push_back(line);
constexpr int margin = 5; constexpr int margin = 5;
int line_height = system_font_->GetLineHeight(); int line_height = system_font_->GetLineHeight();

View File

@ -38,14 +38,14 @@ class GameFactoryBase {
}; };
template <typename Type> template <typename Type>
class GameFactory : public GameFactoryBase { class GameFactory final : public GameFactoryBase {
public: public:
~GameFactory() override = default; ~GameFactory() final = default;
private: private:
using GameType = Type; using GameType = Type;
std::unique_ptr<Game> CreateGame() override { std::unique_ptr<Game> CreateGame() final {
return std::make_unique<GameType>(); return std::make_unique<GameType>();
} }
}; };

View File

@ -6,9 +6,9 @@
#include "base/interpolation.h" #include "base/interpolation.h"
#include "base/log.h" #include "base/log.h"
#include "base/misc.h" #include "base/misc.h"
#include "third_party/texture_compressor/texture_compressor.h"
#include "engine/engine.h" #include "engine/engine.h"
#include "engine/platform/asset_file.h" #include "engine/platform/asset_file.h"
#include "third_party/texture_compressor/texture_compressor.h"
// This 3rd party library is written in C and uses malloc, which means that we // This 3rd party library is written in C and uses malloc, which means that we
// have to do the same. // have to do the same.

View File

@ -33,8 +33,10 @@ void ImageQuad::Create(const std::string& asset_name,
} }
void ImageQuad::Destory() { void ImageQuad::Destory() {
if (texture_) {
Engine::Get().ReleaseTexture(asset_name_); Engine::Get().ReleaseTexture(asset_name_);
texture_ = nullptr; texture_ = nullptr;
}
} }
void ImageQuad::AutoScale() { void ImageQuad::AutoScale() {

View File

@ -14,10 +14,10 @@ namespace eng {
class Shader; class Shader;
class Texture; class Texture;
class ImageQuad : public Animatable { class ImageQuad final : public Animatable {
public: public:
ImageQuad(); ImageQuad();
~ImageQuad() override; ~ImageQuad() final;
void Create(const std::string& asset_name, void Create(const std::string& asset_name,
std::array<int, 2> num_frames = {1, 1}, std::array<int, 2> num_frames = {1, 1},
@ -36,14 +36,14 @@ class ImageQuad : public Animatable {
} }
// Animatable interface. // Animatable interface.
void SetFrame(size_t frame) override; void SetFrame(size_t frame) final;
size_t GetFrame() const override { return current_frame_; } size_t GetFrame() const final { return current_frame_; }
size_t GetNumFrames() const override; size_t GetNumFrames() const final;
void SetColor(const base::Vector4f& color) override { color_ = color; } void SetColor(const base::Vector4f& color) final { color_ = color; }
base::Vector4f GetColor() const override { return color_; } base::Vector4f GetColor() const final { return color_; }
// Drawable interface. // Drawable interface.
void Draw(float frame_frac) override; void Draw(float frame_frac) final;
private: private:
using UniformValue = std::variant<base::Vector2f, using UniformValue = std::variant<base::Vector2f,

View File

@ -3,9 +3,9 @@
#include <string.h> #include <string.h>
#include "base/log.h" #include "base/log.h"
#include "third_party/jsoncpp/json.h"
#include "engine/engine.h" #include "engine/engine.h"
#include "engine/platform/asset_file.h" #include "engine/platform/asset_file.h"
#include "third_party/jsoncpp/json.h"
namespace eng { namespace eng {

View File

@ -7,8 +7,6 @@
#include "engine/renderer/opengl/renderer_opengl.h" #include "engine/renderer/opengl/renderer_opengl.h"
#include "engine/renderer/vulkan/renderer_vulkan.h" #include "engine/renderer/vulkan/renderer_vulkan.h"
#define VULKAN_RENDERER
using namespace base; using namespace base;
namespace eng { namespace eng {
@ -31,11 +29,13 @@ void Platform::InitializeCommon() {
throw internal_error; throw internal_error;
} }
#if defined(VULKAN_RENDERER) auto context = std::make_unique<VulkanContext>();
renderer_ = std::make_unique<RendererVulkan>(); if (context->Initialize()) {
#else renderer_ = std::make_unique<RendererVulkan>(std::move(context));
} else {
LOG << "Failed to initialize Vulkan context. Fallback to OpenGL.";
renderer_ = std::make_unique<RendererOpenGL>(); renderer_ = std::make_unique<RendererOpenGL>();
#endif }
} }
void Platform::ShutdownCommon() { void Platform::ShutdownCommon() {

View File

@ -35,63 +35,62 @@ namespace eng {
struct RenderCommand; struct RenderCommand;
class RendererOpenGL : public Renderer { class RendererOpenGL final : public Renderer {
public: public:
RendererOpenGL(); RendererOpenGL();
~RendererOpenGL() override; ~RendererOpenGL() final;
#if defined(__ANDROID__) #if defined(__ANDROID__)
bool Initialize(ANativeWindow* window) override; bool Initialize(ANativeWindow* window) final;
#elif defined(__linux__) #elif defined(__linux__)
bool Initialize(Display* display, Window window) override; bool Initialize(Display* display, Window window) final;
#endif #endif
void Shutdown() override; void Shutdown() final;
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) override; uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final;
void DestroyGeometry(uint64_t resource_id) override; void DestroyGeometry(uint64_t resource_id) final;
void Draw(uint64_t resource_id) override; void Draw(uint64_t resource_id) final;
uint64_t CreateTexture() override; uint64_t CreateTexture() final;
void UpdateTexture(uint64_t resource_id, void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final;
std::unique_ptr<Image> image) override; void DestroyTexture(uint64_t resource_id) final;
void DestroyTexture(uint64_t resource_id) override; void ActivateTexture(uint64_t resource_id) final;
void ActivateTexture(uint64_t resource_id) override;
uint64_t CreateShader(std::unique_ptr<ShaderSource> source, uint64_t CreateShader(std::unique_ptr<ShaderSource> source,
const VertexDescripton& vertex_description, const VertexDescripton& vertex_description,
Primitive primitive, Primitive primitive,
bool enable_depth_test) override; bool enable_depth_test) final;
void DestroyShader(uint64_t resource_id) override; void DestroyShader(uint64_t resource_id) final;
void ActivateShader(uint64_t resource_id) override; void ActivateShader(uint64_t resource_id) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Vector2f& val) override; const base::Vector2f& val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Vector3f& val) override; const base::Vector3f& val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Vector4f& val) override; const base::Vector4f& val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Matrix4f& val) override; const base::Matrix4f& val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
float val) override; float val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id, const std::string& name, int val) final;
const std::string& name, void UploadUniforms(uint64_t resource_id) final {}
int val) override;
void UploadUniforms(uint64_t resource_id) override {}
void PrepareForDrawing() override {} void PrepareForDrawing() final {}
void Present() override; void Present() final;
size_t GetAndResetFPS() override; size_t GetAndResetFPS() final;
const char* GetDebugName() final { return "OpenGL"; }
#if defined(__linux__) && !defined(__ANDROID__) #if defined(__linux__) && !defined(__ANDROID__)
XVisualInfo* GetXVisualInfo(Display* display) override; XVisualInfo* GetXVisualInfo(Display* display) final;
#endif #endif
private: private:

View File

@ -92,6 +92,8 @@ class Renderer {
virtual size_t GetAndResetFPS() = 0; virtual size_t GetAndResetFPS() = 0;
virtual const char* GetDebugName() = 0;
#if defined(__linux__) && !defined(__ANDROID__) #if defined(__linux__) && !defined(__ANDROID__)
virtual XVisualInfo* GetXVisualInfo(Display* display) = 0; virtual XVisualInfo* GetXVisualInfo(Display* display) = 0;
#endif #endif

View File

@ -18,6 +18,7 @@
#include "third_party/glslang/glslang/Include/Types.h" #include "third_party/glslang/glslang/Include/Types.h"
#include "third_party/glslang/glslang/Public/ShaderLang.h" #include "third_party/glslang/glslang/Public/ShaderLang.h"
#include "third_party/spirv-reflect/spirv_reflect.h" #include "third_party/spirv-reflect/spirv_reflect.h"
#include "third_party/vulkan/vk_enum_string_helper.h"
using namespace base; using namespace base;
@ -345,7 +346,7 @@ std::pair<int, int> GetBlockSizeForImageFormat(VkFormat format) {
default: default:
break; break;
} }
NOTREACHED << "Invalid format: " << format; NOTREACHED << "Invalid format: " << string_VkFormat(format);
return {0, 0}; return {0, 0};
} }
@ -361,7 +362,7 @@ std::pair<int, int> GetNumBlocksForImageFormat(VkFormat format,
default: default:
break; break;
} }
NOTREACHED << "Invalid format: " << format; NOTREACHED << "Invalid format: " << string_VkFormat(format);
return {width, height}; return {width, height};
} }
@ -369,7 +370,8 @@ std::pair<int, int> GetNumBlocksForImageFormat(VkFormat format,
namespace eng { namespace eng {
RendererVulkan::RendererVulkan() = default; RendererVulkan::RendererVulkan(std::unique_ptr<VulkanContext> context)
: context_{std::move(context)} {}
RendererVulkan::~RendererVulkan() = default; RendererVulkan::~RendererVulkan() = default;
@ -466,13 +468,13 @@ void RendererVulkan::UpdateTexture(uint64_t resource_id,
(it->second.width != image->GetWidth() || (it->second.width != image->GetWidth() ||
it->second.height != image->GetHeight())) { it->second.height != image->GetHeight())) {
// Size mismatch. Recreate the texture. // Size mismatch. Recreate the texture.
FreeTexture(std::move(it->second.image), it->second.view, FreeImage(std::move(it->second.image), it->second.view,
std::move(it->second.desc_set)); std::move(it->second.desc_set));
it->second = {}; it->second = {};
} }
if (it->second.view == VK_NULL_HANDLE) { if (it->second.view == VK_NULL_HANDLE) {
CreateTexture(it->second.image, it->second.view, it->second.desc_set, AllocateImage(it->second.image, it->second.view, it->second.desc_set,
format, image->GetWidth(), image->GetHeight(), format, image->GetWidth(), image->GetHeight(),
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VMA_MEMORY_USAGE_GPU_ONLY); VMA_MEMORY_USAGE_GPU_ONLY);
@ -514,7 +516,7 @@ void RendererVulkan::DestroyTexture(uint64_t resource_id) {
if (it == textures_.end()) if (it == textures_.end())
return; return;
FreeTexture(std::move(it->second.image), it->second.view, FreeImage(std::move(it->second.image), it->second.view,
std::move(it->second.desc_set)); std::move(it->second.desc_set));
textures_.erase(it); textures_.erase(it);
} }
@ -705,7 +707,7 @@ uint64_t RendererVulkan::CreateShader(
pipeline_info.pDepthStencilState = &depth_stencil; pipeline_info.pDepthStencilState = &depth_stencil;
pipeline_info.pDynamicState = &dynamic_state_create_info; pipeline_info.pDynamicState = &dynamic_state_create_info;
pipeline_info.layout = shader.pipeline_layout; pipeline_info.layout = shader.pipeline_layout;
pipeline_info.renderPass = context_.GetRenderPass(); pipeline_info.renderPass = context_->GetRenderPass();
pipeline_info.subpass = 0; pipeline_info.subpass = 0;
pipeline_info.basePipelineHandle = VK_NULL_HANDLE; pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
@ -826,7 +828,7 @@ void RendererVulkan::UploadUniforms(uint64_t resource_id) {
} }
void RendererVulkan::PrepareForDrawing() { void RendererVulkan::PrepareForDrawing() {
context_.PrepareBuffers(); context_->PrepareBuffers();
DrawListBegin(); DrawListBegin();
} }
@ -838,20 +840,20 @@ void RendererVulkan::Present() {
bool RendererVulkan::InitializeInternal() { bool RendererVulkan::InitializeInternal() {
glslang::InitializeProcess(); glslang::InitializeProcess();
device_ = context_.GetDevice(); device_ = context_->GetDevice();
// Allocate one extra frame to ensure it's unused at any time without having // Allocate one extra frame to ensure it's unused at any time without having
// to use a fence. // to use a fence.
int frame_count = context_.GetSwapchainImageCount() + 1; int frame_count = context_->GetSwapchainImageCount() + 1;
frames_.resize(frame_count); frames_.resize(frame_count);
frames_drawn_ = frame_count; frames_drawn_ = frame_count;
// Initialize allocator // Initialize allocator
VmaAllocatorCreateInfo allocator_info; VmaAllocatorCreateInfo allocator_info;
memset(&allocator_info, 0, sizeof(VmaAllocatorCreateInfo)); memset(&allocator_info, 0, sizeof(VmaAllocatorCreateInfo));
allocator_info.physicalDevice = context_.GetPhysicalDevice(); allocator_info.physicalDevice = context_->GetPhysicalDevice();
allocator_info.device = device_; allocator_info.device = device_;
allocator_info.instance = context_.GetInstance(); allocator_info.instance = context_->GetInstance();
vmaCreateAllocator(&allocator_info, &allocator_); vmaCreateAllocator(&allocator_info, &allocator_);
for (size_t i = 0; i < frames_.size(); i++) { for (size_t i = 0; i < frames_.size(); i++) {
@ -859,20 +861,20 @@ bool RendererVulkan::InitializeInternal() {
VkCommandPoolCreateInfo cmd_pool_info; VkCommandPoolCreateInfo cmd_pool_info;
cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
cmd_pool_info.pNext = nullptr; cmd_pool_info.pNext = nullptr;
cmd_pool_info.queueFamilyIndex = context_.GetGraphicsQueue(); cmd_pool_info.queueFamilyIndex = context_->GetGraphicsQueue();
cmd_pool_info.flags = 0; cmd_pool_info.flags = 0;
VkResult err = vkCreateCommandPool(device_, &cmd_pool_info, nullptr, VkResult err = vkCreateCommandPool(device_, &cmd_pool_info, nullptr,
&frames_[i].setup_command_pool); &frames_[i].setup_command_pool);
if (err) { if (err) {
DLOG << "vkCreateCommandPool failed with error " << std::to_string(err); DLOG << "vkCreateCommandPool failed with error " << string_VkResult(err);
return false; return false;
} }
err = vkCreateCommandPool(device_, &cmd_pool_info, nullptr, err = vkCreateCommandPool(device_, &cmd_pool_info, nullptr,
&frames_[i].draw_command_pool); &frames_[i].draw_command_pool);
if (err) { if (err) {
DLOG << "vkCreateCommandPool failed with error " << std::to_string(err); DLOG << "vkCreateCommandPool failed with error " << string_VkResult(err);
return false; return false;
} }
@ -888,7 +890,7 @@ bool RendererVulkan::InitializeInternal() {
&frames_[i].setup_command_buffer); &frames_[i].setup_command_buffer);
if (err) { if (err) {
DLOG << "vkAllocateCommandBuffers failed with error " DLOG << "vkAllocateCommandBuffers failed with error "
<< std::to_string(err); << string_VkResult(err);
continue; continue;
} }
@ -897,7 +899,7 @@ bool RendererVulkan::InitializeInternal() {
&frames_[i].draw_command_buffer); &frames_[i].draw_command_buffer);
if (err) { if (err) {
DLOG << "vkAllocateCommandBuffers failed with error " DLOG << "vkAllocateCommandBuffers failed with error "
<< std::to_string(err); << string_VkResult(err);
continue; continue;
} }
} }
@ -918,10 +920,10 @@ bool RendererVulkan::InitializeInternal() {
ds_layout_info.bindingCount = 1; ds_layout_info.bindingCount = 1;
ds_layout_info.pBindings = &ds_layout_binding; ds_layout_info.pBindings = &ds_layout_binding;
VkResult res = vkCreateDescriptorSetLayout(device_, &ds_layout_info, nullptr, VkResult err = vkCreateDescriptorSetLayout(device_, &ds_layout_info, nullptr,
&descriptor_set_layout_); &descriptor_set_layout_);
if (res) { if (err) {
DLOG << "Error (" << std::to_string(res) DLOG << "Error (" << string_VkResult(err)
<< ") creating descriptor set layout for set"; << ") creating descriptor set layout for set";
return false; return false;
} }
@ -947,9 +949,9 @@ bool RendererVulkan::InitializeInternal() {
sampler_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; sampler_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
sampler_info.unnormalizedCoordinates = VK_FALSE; sampler_info.unnormalizedCoordinates = VK_FALSE;
res = vkCreateSampler(device_, &sampler_info, nullptr, &sampler_); err = vkCreateSampler(device_, &sampler_info, nullptr, &sampler_);
if (res) { if (err) {
DLOG << "vkCreateSampler failed with error " << std::to_string(res); DLOG << "vkCreateSampler failed with error " << string_VkResult(err);
return false; return false;
} }
@ -971,7 +973,7 @@ bool RendererVulkan::InitializeInternal() {
// Begin the first command buffer for the first frame. // Begin the first command buffer for the first frame.
BeginFrame(); BeginFrame();
if (context_lost_cb_) { if (context_lost_ && context_lost_cb_) {
LOG << "Context lost."; LOG << "Context lost.";
context_lost_cb_(); context_lost_cb_();
} }
@ -984,6 +986,7 @@ void RendererVulkan::Shutdown() {
LOG << "Shutting down renderer."; LOG << "Shutting down renderer.";
DestroyAllResources(); DestroyAllResources();
context_lost_ = true;
quit_.store(true, std::memory_order_relaxed); quit_.store(true, std::memory_order_relaxed);
semaphore_.release(); semaphore_.release();
@ -1011,8 +1014,8 @@ void RendererVulkan::Shutdown() {
current_staging_buffer_ = 0; current_staging_buffer_ = 0;
staging_buffer_used_ = false; staging_buffer_used_ = false;
context_.DestroyWindow(); context_->DestroyWindow();
context_.Shutdown(); context_->Shutdown();
glslang::FinalizeProcess(); glslang::FinalizeProcess();
} }
@ -1020,8 +1023,8 @@ void RendererVulkan::Shutdown() {
void RendererVulkan::BeginFrame() { void RendererVulkan::BeginFrame() {
FreePendingResources(current_frame_); FreePendingResources(current_frame_);
context_.AppendCommandBuffer(frames_[current_frame_].setup_command_buffer); context_->AppendCommandBuffer(frames_[current_frame_].setup_command_buffer);
context_.AppendCommandBuffer(frames_[current_frame_].draw_command_buffer); context_->AppendCommandBuffer(frames_[current_frame_].draw_command_buffer);
vkResetCommandPool(device_, frames_[current_frame_].setup_command_pool, 0); vkResetCommandPool(device_, frames_[current_frame_].setup_command_pool, 0);
vkResetCommandPool(device_, frames_[current_frame_].draw_command_pool, 0); vkResetCommandPool(device_, frames_[current_frame_].draw_command_pool, 0);
@ -1035,14 +1038,14 @@ void RendererVulkan::BeginFrame() {
VkResult err = vkBeginCommandBuffer( VkResult err = vkBeginCommandBuffer(
frames_[current_frame_].setup_command_buffer, &cmdbuf_begin); frames_[current_frame_].setup_command_buffer, &cmdbuf_begin);
if (err) { if (err) {
DLOG << "vkBeginCommandBuffer failed with error " << std::to_string(err); DLOG << "vkBeginCommandBuffer failed with error " << string_VkResult(err);
return; return;
} }
err = vkBeginCommandBuffer(frames_[current_frame_].draw_command_buffer, err = vkBeginCommandBuffer(frames_[current_frame_].draw_command_buffer,
&cmdbuf_begin); &cmdbuf_begin);
if (err) { if (err) {
DLOG << "vkBeginCommandBuffer failed with error " << std::to_string(err); DLOG << "vkBeginCommandBuffer failed with error " << string_VkResult(err);
return; return;
} }
@ -1060,7 +1063,7 @@ void RendererVulkan::BeginFrame() {
void RendererVulkan::FlushSetupBuffer() { void RendererVulkan::FlushSetupBuffer() {
vkEndCommandBuffer(frames_[current_frame_].setup_command_buffer); vkEndCommandBuffer(frames_[current_frame_].setup_command_buffer);
context_.Flush(false); context_->Flush(false);
vkResetCommandPool(device_, frames_[current_frame_].setup_command_pool, 0); vkResetCommandPool(device_, frames_[current_frame_].setup_command_pool, 0);
@ -1073,10 +1076,10 @@ void RendererVulkan::FlushSetupBuffer() {
VkResult err = vkBeginCommandBuffer( VkResult err = vkBeginCommandBuffer(
frames_[current_frame_].setup_command_buffer, &cmdbuf_begin); frames_[current_frame_].setup_command_buffer, &cmdbuf_begin);
if (err) { if (err) {
DLOG << "vkBeginCommandBuffer failed with error " << std::to_string(err); DLOG << "vkBeginCommandBuffer failed with error " << string_VkResult(err);
return; return;
} }
context_.AppendCommandBuffer(frames_[current_frame_].setup_command_buffer, context_->AppendCommandBuffer(frames_[current_frame_].setup_command_buffer,
true); true);
} }
@ -1286,7 +1289,7 @@ bool RendererVulkan::InsertStagingBuffer() {
&std::get<0>(block.buffer), &std::get<0>(block.buffer),
&std::get<1>(block.buffer), &block.alloc_info); &std::get<1>(block.buffer), &block.alloc_info);
if (err) { if (err) {
DLOG << "vmaCreateBuffer failed with error " << std::to_string(err); DLOG << "vmaCreateBuffer failed with error " << string_VkResult(err);
return false; return false;
} }
@ -1324,11 +1327,11 @@ RendererVulkan::DescPool* RendererVulkan::AllocateDescriptorPool() {
descriptor_pool_create_info.pPoolSizes = &sizes; descriptor_pool_create_info.pPoolSizes = &sizes;
VkDescriptorPool desc_pool; VkDescriptorPool desc_pool;
VkResult res = vkCreateDescriptorPool(device_, &descriptor_pool_create_info, VkResult err = vkCreateDescriptorPool(device_, &descriptor_pool_create_info,
nullptr, &desc_pool); nullptr, &desc_pool);
if (res) { if (err) {
DLOG << "vkCreateDescriptorPool failed with error " DLOG << "vkCreateDescriptorPool failed with error "
<< std::to_string(res); << string_VkResult(err);
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
} }
@ -1384,7 +1387,7 @@ bool RendererVulkan::AllocateBuffer(Buffer<VkBuffer>& buffer,
&vk_buffer, &allocation, nullptr); &vk_buffer, &allocation, nullptr);
if (err) { if (err) {
DLOG << "Can't create buffer of size: " << std::to_string(size) DLOG << "Can't create buffer of size: " << std::to_string(size)
<< ", error " << std::to_string(err); << ", error " << string_VkResult(err);
return false; return false;
} }
@ -1458,7 +1461,7 @@ void RendererVulkan::BufferMemoryBarrier(VkBuffer buffer,
&buffer_mem_barrier, 0, nullptr); &buffer_mem_barrier, 0, nullptr);
} }
bool RendererVulkan::CreateTexture(Buffer<VkImage>& image, bool RendererVulkan::AllocateImage(Buffer<VkImage>& image,
VkImageView& view, VkImageView& view,
DescSet& desc_set, DescSet& desc_set,
VkFormat format, VkFormat format,
@ -1500,7 +1503,7 @@ bool RendererVulkan::CreateTexture(Buffer<VkImage>& image,
VkResult err = vmaCreateImage(allocator_, &image_create_info, &allocInfo, VkResult err = vmaCreateImage(allocator_, &image_create_info, &allocInfo,
&vk_image, &allocation, nullptr); &vk_image, &allocation, nullptr);
if (err) { if (err) {
DLOG << "vmaCreateImage failed with error " << std::to_string(err); DLOG << "vmaCreateImage failed with error " << string_VkResult(err);
return false; return false;
} }
@ -1526,7 +1529,7 @@ bool RendererVulkan::CreateTexture(Buffer<VkImage>& image,
if (err) { if (err) {
vmaDestroyImage(allocator_, vk_image, allocation); vmaDestroyImage(allocator_, vk_image, allocation);
DLOG << "vkCreateImageView failed with error " << std::to_string(err); DLOG << "vkCreateImageView failed with error " << string_VkResult(err);
return false; return false;
} }
@ -1543,11 +1546,11 @@ bool RendererVulkan::CreateTexture(Buffer<VkImage>& image,
descriptor_set_allocate_info.pSetLayouts = &descriptor_set_layout_; descriptor_set_allocate_info.pSetLayouts = &descriptor_set_layout_;
VkDescriptorSet descriptor_set; VkDescriptorSet descriptor_set;
VkResult res = vkAllocateDescriptorSets( err = vkAllocateDescriptorSets(device_, &descriptor_set_allocate_info,
device_, &descriptor_set_allocate_info, &descriptor_set); &descriptor_set);
if (res) { if (err) {
--std::get<1>(*desc_pool); --std::get<1>(*desc_pool);
DLOG << "Cannot allocate descriptor sets, error " << std::to_string(res); DLOG << "Cannot allocate descriptor sets, error " << string_VkResult(err);
return false; return false;
} }
@ -1575,7 +1578,7 @@ bool RendererVulkan::CreateTexture(Buffer<VkImage>& image,
return true; return true;
} }
void RendererVulkan::FreeTexture(Buffer<VkImage> image, void RendererVulkan::FreeImage(Buffer<VkImage> image,
VkImageView image_view, VkImageView image_view,
DescSet desc_set) { DescSet desc_set) {
frames_[current_frame_].images_to_destroy.push_back( frames_[current_frame_].images_to_destroy.push_back(
@ -1904,8 +1907,8 @@ void RendererVulkan::DrawListBegin() {
VkRenderPassBeginInfo render_pass_begin; VkRenderPassBeginInfo render_pass_begin;
render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin.pNext = nullptr; render_pass_begin.pNext = nullptr;
render_pass_begin.renderPass = context_.GetRenderPass(); render_pass_begin.renderPass = context_->GetRenderPass();
render_pass_begin.framebuffer = context_.GetFramebuffer(); render_pass_begin.framebuffer = context_->GetFramebuffer();
render_pass_begin.renderArea.extent.width = screen_width_; render_pass_begin.renderArea.extent.width = screen_width_;
render_pass_begin.renderArea.extent.height = screen_height_; render_pass_begin.renderArea.extent.height = screen_height_;
@ -1971,7 +1974,7 @@ void RendererVulkan::SwapBuffers() {
vkEndCommandBuffer(frames_[current_frame_].setup_command_buffer); vkEndCommandBuffer(frames_[current_frame_].setup_command_buffer);
vkEndCommandBuffer(frames_[current_frame_].draw_command_buffer); vkEndCommandBuffer(frames_[current_frame_].draw_command_buffer);
context_.SwapBuffers(); context_->SwapBuffers();
current_frame_ = (current_frame_ + 1) % frames_.size(); current_frame_ = (current_frame_ + 1) % frames_.size();
active_pipeline_ = VK_NULL_HANDLE; active_pipeline_ = VK_NULL_HANDLE;
@ -2030,13 +2033,13 @@ bool RendererVulkan::SetUniformInternal(ShaderVulkan& shader,
bool RendererVulkan::IsFormatSupported(VkFormat format) { bool RendererVulkan::IsFormatSupported(VkFormat format) {
VkFormatProperties properties; VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(context_.GetPhysicalDevice(), format, vkGetPhysicalDeviceFormatProperties(context_->GetPhysicalDevice(), format,
&properties); &properties);
return properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; return properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
} }
size_t RendererVulkan::GetAndResetFPS() { size_t RendererVulkan::GetAndResetFPS() {
return context_.GetAndResetFPS(); return context_->GetAndResetFPS();
} }
void RendererVulkan::DestroyAllResources() { void RendererVulkan::DestroyAllResources() {

View File

@ -20,63 +20,62 @@ namespace eng {
class Image; class Image;
class RendererVulkan : public Renderer { class RendererVulkan final : public Renderer {
public: public:
RendererVulkan(); RendererVulkan(std::unique_ptr<VulkanContext> context);
~RendererVulkan() override; ~RendererVulkan() final;
#if defined(__ANDROID__) #if defined(__ANDROID__)
bool Initialize(ANativeWindow* window) override; bool Initialize(ANativeWindow* window) final;
#elif defined(__linux__) #elif defined(__linux__)
bool Initialize(Display* display, Window window) override; bool Initialize(Display* display, Window window) final;
#endif #endif
void Shutdown() override; void Shutdown() final;
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) override; uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final;
void DestroyGeometry(uint64_t resource_id) override; void DestroyGeometry(uint64_t resource_id) final;
void Draw(uint64_t resource_id) override; void Draw(uint64_t resource_id) final;
uint64_t CreateTexture() override; uint64_t CreateTexture() final;
void UpdateTexture(uint64_t resource_id, void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final;
std::unique_ptr<Image> image) override; void DestroyTexture(uint64_t resource_id) final;
void DestroyTexture(uint64_t resource_id) override; void ActivateTexture(uint64_t resource_id) final;
void ActivateTexture(uint64_t resource_id) override;
uint64_t CreateShader(std::unique_ptr<ShaderSource> source, uint64_t CreateShader(std::unique_ptr<ShaderSource> source,
const VertexDescripton& vertex_description, const VertexDescripton& vertex_description,
Primitive primitive, Primitive primitive,
bool enable_depth_test) override; bool enable_depth_test) final;
void DestroyShader(uint64_t resource_id) override; void DestroyShader(uint64_t resource_id) final;
void ActivateShader(uint64_t resource_id) override; void ActivateShader(uint64_t resource_id) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Vector2f& val) override; const base::Vector2f& val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Vector3f& val) override; const base::Vector3f& val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Vector4f& val) override; const base::Vector4f& val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Matrix4f& val) override; const base::Matrix4f& val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
float val) override; float val) final;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id, const std::string& name, int val) final;
const std::string& name, void UploadUniforms(uint64_t resource_id) final;
int val) override;
void UploadUniforms(uint64_t resource_id) override;
void PrepareForDrawing() override; void PrepareForDrawing() final;
void Present() override; void Present() final;
size_t GetAndResetFPS() override; size_t GetAndResetFPS() final;
const char* GetDebugName() final { return "Vulkan"; }
#if defined(__linux__) && !defined(__ANDROID__) #if defined(__linux__) && !defined(__ANDROID__)
XVisualInfo* GetXVisualInfo(Display* display) override; XVisualInfo* GetXVisualInfo(Display* display) final;
#endif #endif
private: private:
@ -155,7 +154,9 @@ class RendererVulkan : public Renderer {
std::unordered_map<uint64_t, TextureVulkan> textures_; std::unordered_map<uint64_t, TextureVulkan> textures_;
uint64_t last_resource_id_ = 0; uint64_t last_resource_id_ = 0;
VulkanContext context_; bool context_lost_ = false;
std::unique_ptr<VulkanContext> context_;
VmaAllocator allocator_ = nullptr; VmaAllocator allocator_ = nullptr;
@ -224,7 +225,7 @@ class RendererVulkan : public Renderer {
VkAccessFlags src_access, VkAccessFlags src_access,
VkAccessFlags dst_sccess); VkAccessFlags dst_sccess);
bool CreateTexture(Buffer<VkImage>& image, bool AllocateImage(Buffer<VkImage>& image,
VkImageView& view, VkImageView& view,
DescSet& desc_set, DescSet& desc_set,
VkFormat format, VkFormat format,
@ -232,7 +233,7 @@ class RendererVulkan : public Renderer {
int height, int height,
VkImageUsageFlags usage, VkImageUsageFlags usage,
VmaMemoryUsage mapping); VmaMemoryUsage mapping);
void FreeTexture(Buffer<VkImage> image, void FreeImage(Buffer<VkImage> image,
VkImageView image_view, VkImageView image_view,
DescSet desc_set); DescSet desc_set);
void UpdateImage(VkImage image, void UpdateImage(VkImage image,

View File

@ -12,11 +12,7 @@ bool RendererVulkan::Initialize(ANativeWindow* window) {
screen_width_ = ANativeWindow_getWidth(window); screen_width_ = ANativeWindow_getWidth(window);
screen_height_ = ANativeWindow_getHeight(window); screen_height_ = ANativeWindow_getHeight(window);
if (!context_.Initialize()) { if (!context_->CreateWindow(window, screen_width_, screen_height_)) {
LOG << "Failed to initialize Vulkan context.";
return false;
}
if (!context_.CreateWindow(window, screen_width_, screen_height_)) {
LOG << "Vulkan context failed to create window."; LOG << "Vulkan context failed to create window.";
return false; return false;
} }

View File

@ -12,11 +12,7 @@ bool RendererVulkan::Initialize(Display* display, Window window) {
screen_width_ = xwa.width; screen_width_ = xwa.width;
screen_height_ = xwa.height; screen_height_ = xwa.height;
if (!context_.Initialize()) { if (!context_->CreateWindow(display, window, screen_width_, screen_height_)) {
LOG << "Failed to initialize Vulkan context.";
return false;
}
if (!context_.CreateWindow(display, window, screen_width_, screen_height_)) {
LOG << "Vulkan context failed to create window."; LOG << "Vulkan context failed to create window.";
return false; return false;
} }

View File

@ -58,7 +58,6 @@ void VulkanContext::Shutdown() {
vkDestroyDevice(device_, nullptr); vkDestroyDevice(device_, nullptr);
device_ = VK_NULL_HANDLE; device_ = VK_NULL_HANDLE;
} }
buffers_prepared_ = false;
queues_initialized_ = false; queues_initialized_ = false;
separate_present_queue_ = false; separate_present_queue_ = false;
swapchain_image_count_ = 0; swapchain_image_count_ = 0;
@ -215,7 +214,8 @@ bool VulkanContext::CreateValidationLayers() {
uint32_t instance_layer_count = 0; uint32_t instance_layer_count = 0;
err = vkEnumerateInstanceLayerProperties(&instance_layer_count, nullptr); err = vkEnumerateInstanceLayerProperties(&instance_layer_count, nullptr);
if (err) { if (err) {
DLOG << "vkEnumerateInstanceLayerProperties failed. Error: " << err; DLOG << "vkEnumerateInstanceLayerProperties failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -228,7 +228,8 @@ bool VulkanContext::CreateValidationLayers() {
err = vkEnumerateInstanceLayerProperties(&instance_layer_count, err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
instance_layers.get()); instance_layers.get());
if (err) { if (err) {
DLOG << "vkEnumerateInstanceLayerProperties failed. Error: " << err; DLOG << "vkEnumerateInstanceLayerProperties failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -284,7 +285,8 @@ bool VulkanContext::InitializeExtensions() {
err = vkEnumerateInstanceExtensionProperties( err = vkEnumerateInstanceExtensionProperties(
nullptr, &instance_extension_count, nullptr); nullptr, &instance_extension_count, nullptr);
if (err) { if (err) {
DLOG << "vkEnumerateInstanceExtensionProperties failed. Error: " << err; DLOG << "vkEnumerateInstanceExtensionProperties failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -294,7 +296,8 @@ bool VulkanContext::InitializeExtensions() {
err = vkEnumerateInstanceExtensionProperties( err = vkEnumerateInstanceExtensionProperties(
nullptr, &instance_extension_count, instance_extensions.get()); nullptr, &instance_extension_count, instance_extensions.get());
if (err) { if (err) {
DLOG << "vkEnumerateInstanceExtensionProperties failed. Error: " << err; DLOG << "vkEnumerateInstanceExtensionProperties failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
for (uint32_t i = 0; i < instance_extension_count; i++) { for (uint32_t i = 0; i < instance_extension_count; i++) {
@ -409,7 +412,7 @@ bool VulkanContext::CreatePhysicalDevice() {
return false; return false;
} }
if (err) { if (err) {
DLOG << "vkCreateInstance failed. Error: " << err; DLOG << "vkCreateInstance failed. Error: " << string_VkResult(err);
return false; return false;
} }
} }
@ -419,7 +422,8 @@ bool VulkanContext::CreatePhysicalDevice() {
// Make initial call to query gpu_count. // Make initial call to query gpu_count.
VkResult err = vkEnumeratePhysicalDevices(instance_, &gpu_count, nullptr); VkResult err = vkEnumeratePhysicalDevices(instance_, &gpu_count, nullptr);
if (err) { if (err) {
DLOG << "vkEnumeratePhysicalDevices failed. Error: " << err; DLOG << "vkEnumeratePhysicalDevices failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -432,7 +436,8 @@ bool VulkanContext::CreatePhysicalDevice() {
err = err =
vkEnumeratePhysicalDevices(instance_, &gpu_count, physical_devices.get()); vkEnumeratePhysicalDevices(instance_, &gpu_count, physical_devices.get());
if (err) { if (err) {
DLOG << "vkEnumeratePhysicalDevices failed. Error: " << err; DLOG << "vkEnumeratePhysicalDevices failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
// Grab the first physical device for now. // Grab the first physical device for now.
@ -447,7 +452,8 @@ bool VulkanContext::CreatePhysicalDevice() {
err = vkEnumerateDeviceExtensionProperties(gpu_, nullptr, err = vkEnumerateDeviceExtensionProperties(gpu_, nullptr,
&device_extension_count, nullptr); &device_extension_count, nullptr);
if (err) { if (err) {
DLOG << "vkEnumerateDeviceExtensionProperties failed. Error: " << err; DLOG << "vkEnumerateDeviceExtensionProperties failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -457,7 +463,8 @@ bool VulkanContext::CreatePhysicalDevice() {
err = vkEnumerateDeviceExtensionProperties( err = vkEnumerateDeviceExtensionProperties(
gpu_, nullptr, &device_extension_count, device_extensions.get()); gpu_, nullptr, &device_extension_count, device_extensions.get());
if (err) { if (err) {
DLOG << "vkEnumerateDeviceExtensionProperties failed. Error: " << err; DLOG << "vkEnumerateDeviceExtensionProperties failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -601,7 +608,7 @@ bool VulkanContext::CreateDevice() {
} }
err = vkCreateDevice(gpu_, &sdevice, nullptr, &device_); err = vkCreateDevice(gpu_, &sdevice, nullptr, &device_);
if (err) { if (err) {
DLOG << "vkCreateDevice failed. Error: " << err; DLOG << "vkCreateDevice failed. Error: " << string_VkResult(err);
return false; return false;
} }
return true; return true;
@ -679,14 +686,16 @@ bool VulkanContext::InitializeQueues(VkSurfaceKHR surface) {
VkResult err = VkResult err =
GetPhysicalDeviceSurfaceFormatsKHR(gpu_, surface, &format_count, nullptr); GetPhysicalDeviceSurfaceFormatsKHR(gpu_, surface, &format_count, nullptr);
if (err) { if (err) {
DLOG << "GetPhysicalDeviceSurfaceFormatsKHR failed. Error: " << err; DLOG << "GetPhysicalDeviceSurfaceFormatsKHR failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
auto surf_formats = std::make_unique<VkSurfaceFormatKHR[]>(format_count); auto surf_formats = std::make_unique<VkSurfaceFormatKHR[]>(format_count);
err = GetPhysicalDeviceSurfaceFormatsKHR(gpu_, surface, &format_count, err = GetPhysicalDeviceSurfaceFormatsKHR(gpu_, surface, &format_count,
surf_formats.get()); surf_formats.get());
if (err) { if (err) {
DLOG << "GetPhysicalDeviceSurfaceFormatsKHR failed. Error: " << err; DLOG << "GetPhysicalDeviceSurfaceFormatsKHR failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -744,26 +753,26 @@ bool VulkanContext::CreateSemaphores() {
for (uint32_t i = 0; i < kFrameLag; i++) { for (uint32_t i = 0; i < kFrameLag; i++) {
err = vkCreateFence(device_, &fence_ci, nullptr, &fences_[i]); err = vkCreateFence(device_, &fence_ci, nullptr, &fences_[i]);
if (err) { if (err) {
DLOG << "vkCreateFence failed. Error: " << err; DLOG << "vkCreateFence failed. Error: " << string_VkResult(err);
return false; return false;
} }
err = vkCreateSemaphore(device_, &semaphoreCreateInfo, nullptr, err = vkCreateSemaphore(device_, &semaphoreCreateInfo, nullptr,
&image_acquired_semaphores_[i]); &image_acquired_semaphores_[i]);
if (err) { if (err) {
DLOG << "vkCreateSemaphore failed. Error: " << err; DLOG << "vkCreateSemaphore failed. Error: " << string_VkResult(err);
return false; return false;
} }
err = vkCreateSemaphore(device_, &semaphoreCreateInfo, nullptr, err = vkCreateSemaphore(device_, &semaphoreCreateInfo, nullptr,
&draw_complete_semaphores_[i]); &draw_complete_semaphores_[i]);
if (err) { if (err) {
DLOG << "vkCreateSemaphore failed. Error: " << err; DLOG << "vkCreateSemaphore failed. Error: " << string_VkResult(err);
return false; return false;
} }
if (separate_present_queue_) { if (separate_present_queue_) {
err = vkCreateSemaphore(device_, &semaphoreCreateInfo, nullptr, err = vkCreateSemaphore(device_, &semaphoreCreateInfo, nullptr,
&image_ownership_semaphores_[i]); &image_ownership_semaphores_[i]);
if (err) { if (err) {
DLOG << "vkCreateSemaphore failed. Error: " << err; DLOG << "vkCreateSemaphore failed. Error: " << string_VkResult(err);
return false; return false;
} }
} }
@ -788,10 +797,7 @@ void VulkanContext::DestroyWindow() {
} }
VkFramebuffer VulkanContext::GetFramebuffer() { VkFramebuffer VulkanContext::GetFramebuffer() {
return buffers_prepared_ return window_.swapchain_image_resources[window_.current_buffer].frame_buffer;
? window_.swapchain_image_resources[window_.current_buffer]
.frame_buffer
: VK_NULL_HANDLE;
} }
bool VulkanContext::CleanUpSwapChain(Window* window) { bool VulkanContext::CleanUpSwapChain(Window* window) {
@ -838,7 +844,8 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = GetPhysicalDeviceSurfaceCapabilitiesKHR(gpu_, window->surface, err = GetPhysicalDeviceSurfaceCapabilitiesKHR(gpu_, window->surface,
&surf_capabilities); &surf_capabilities);
if (err) { if (err) {
DLOG << "GetPhysicalDeviceSurfaceCapabilitiesKHR failed. Error: " << err; DLOG << "GetPhysicalDeviceSurfaceCapabilitiesKHR failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -846,7 +853,8 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = GetPhysicalDeviceSurfacePresentModesKHR(gpu_, window->surface, err = GetPhysicalDeviceSurfacePresentModesKHR(gpu_, window->surface,
&present_mode_count, nullptr); &present_mode_count, nullptr);
if (err) { if (err) {
DLOG << "GetPhysicalDeviceSurfacePresentModesKHR failed. Error: " << err; DLOG << "GetPhysicalDeviceSurfacePresentModesKHR failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -855,7 +863,8 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = GetPhysicalDeviceSurfacePresentModesKHR( err = GetPhysicalDeviceSurfacePresentModesKHR(
gpu_, window->surface, &present_mode_count, present_modes.get()); gpu_, window->surface, &present_mode_count, present_modes.get());
if (err) { if (err) {
DLOG << "GetPhysicalDeviceSurfacePresentModesKHR failed. Error: " << err; DLOG << "GetPhysicalDeviceSurfacePresentModesKHR failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -1002,7 +1011,7 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = CreateSwapchainKHR(device_, &swapchain_ci, nullptr, &window->swapchain); err = CreateSwapchainKHR(device_, &swapchain_ci, nullptr, &window->swapchain);
if (err) { if (err) {
DLOG << "CreateSwapchainKHR failed. Error: " << err; DLOG << "CreateSwapchainKHR failed. Error: " << string_VkResult(err);
return false; return false;
} }
@ -1010,7 +1019,7 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = GetSwapchainImagesKHR(device_, window->swapchain, &sp_image_count, err = GetSwapchainImagesKHR(device_, window->swapchain, &sp_image_count,
nullptr); nullptr);
if (err) { if (err) {
DLOG << "CreateSwapchainKHR failed. Error: " << err; DLOG << "CreateSwapchainKHR failed. Error: " << string_VkResult(err);
return false; return false;
} }
@ -1027,7 +1036,7 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = GetSwapchainImagesKHR(device_, window->swapchain, err = GetSwapchainImagesKHR(device_, window->swapchain,
&swapchain_image_count_, swapchain_images.get()); &swapchain_image_count_, swapchain_images.get());
if (err) { if (err) {
DLOG << "GetSwapchainImagesKHR failed. Error: " << err; DLOG << "GetSwapchainImagesKHR failed. Error: " << string_VkResult(err);
return false; return false;
} }
@ -1064,7 +1073,7 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = vkCreateImageView(device_, &color_image_view, nullptr, err = vkCreateImageView(device_, &color_image_view, nullptr,
&window->swapchain_image_resources[i].view); &window->swapchain_image_resources[i].view);
if (err) { if (err) {
DLOG << "vkCreateImageView failed. Error: " << err; DLOG << "vkCreateImageView failed. Error: " << string_VkResult(err);
return false; return false;
} }
} }
@ -1148,7 +1157,7 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = vkCreateRenderPass(device_, &rp_info, nullptr, &window->render_pass); err = vkCreateRenderPass(device_, &rp_info, nullptr, &window->render_pass);
if (err) { if (err) {
DLOG << "vkCreateRenderPass failed. Error: " << err; DLOG << "vkCreateRenderPass failed. Error: " << string_VkResult(err);
return false; return false;
} }
@ -1173,7 +1182,7 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
device_, &fb_info, nullptr, device_, &fb_info, nullptr,
&window->swapchain_image_resources[i].frame_buffer); &window->swapchain_image_resources[i].frame_buffer);
if (err) { if (err) {
DLOG << "vkCreateFramebuffer failed. Error: " << err; DLOG << "vkCreateFramebuffer failed. Error: " << string_VkResult(err);
return false; return false;
} }
} }
@ -1191,7 +1200,7 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = vkCreateCommandPool(device_, &present_cmd_pool_info, nullptr, err = vkCreateCommandPool(device_, &present_cmd_pool_info, nullptr,
&window->present_cmd_pool); &window->present_cmd_pool);
if (err) { if (err) {
DLOG << "vkCreateCommandPool failed. Error: " << err; DLOG << "vkCreateCommandPool failed. Error: " << string_VkResult(err);
return false; return false;
} }
@ -1207,7 +1216,8 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
device_, &present_cmd_info, device_, &present_cmd_info,
&window->swapchain_image_resources[i].graphics_to_present_cmd); &window->swapchain_image_resources[i].graphics_to_present_cmd);
if (err) { if (err) {
DLOG << "vkAllocateCommandBuffers failed. Error: " << err; DLOG << "vkAllocateCommandBuffers failed. Error: "
<< string_VkResult(err);
return false; return false;
} }
@ -1221,7 +1231,7 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
window->swapchain_image_resources[i].graphics_to_present_cmd, window->swapchain_image_resources[i].graphics_to_present_cmd,
&cmd_buf_info); &cmd_buf_info);
if (err) { if (err) {
DLOG << "vkBeginCommandBuffer failed. Error: " << err; DLOG << "vkBeginCommandBuffer failed. Error: " << string_VkResult(err);
return false; return false;
} }
@ -1245,7 +1255,7 @@ bool VulkanContext::UpdateSwapChain(Window* window) {
err = vkEndCommandBuffer( err = vkEndCommandBuffer(
window->swapchain_image_resources[i].graphics_to_present_cmd); window->swapchain_image_resources[i].graphics_to_present_cmd);
if (err) { if (err) {
DLOG << "vkEndCommandBuffer failed. Error: " << err; DLOG << "vkEndCommandBuffer failed. Error: " << string_VkResult(err);
return false; return false;
} }
} }
@ -1284,7 +1294,7 @@ bool VulkanContext::CreateDepthImage(Window* window) {
VkResult err = VkResult err =
vkCreateImage(device_, &depth_image_ci, nullptr, &window->depth_image); vkCreateImage(device_, &depth_image_ci, nullptr, &window->depth_image);
if (err) { if (err) {
DLOG << "vkCreateImage failed. Error: " << err; DLOG << "vkCreateImage failed. Error: " << string_VkResult(err);
return false; return false;
} }
@ -1316,7 +1326,7 @@ bool VulkanContext::CreateDepthImage(Window* window) {
err = vkAllocateMemory(device_, &alloc_info, nullptr, err = vkAllocateMemory(device_, &alloc_info, nullptr,
&window->depth_image_memory); &window->depth_image_memory);
if (err) { if (err) {
DLOG << "vkAllocateMemory failed. Error: " << err; DLOG << "vkAllocateMemory failed. Error: " << string_VkResult(err);
return false; return false;
} }
@ -1386,7 +1396,7 @@ void VulkanContext::Flush(bool all) {
vkQueueSubmit(graphics_queue_, 1, &submit_info, VK_NULL_HANDLE); vkQueueSubmit(graphics_queue_, 1, &submit_info, VK_NULL_HANDLE);
command_buffers_[0] = nullptr; command_buffers_[0] = nullptr;
if (err) { if (err) {
DLOG << "vkQueueSubmit failed. Error: " << err; DLOG << "vkQueueSubmit failed. Error: " << string_VkResult(err);
return; return;
} }
@ -1421,23 +1431,20 @@ bool VulkanContext::PrepareBuffers() {
if (err == VK_ERROR_OUT_OF_DATE_KHR) { if (err == VK_ERROR_OUT_OF_DATE_KHR) {
// swapchain is out of date (e.g. the window was resized) and must be // swapchain is out of date (e.g. the window was resized) and must be
// recreated: // recreated:
DLOG << "Swapchain is out of date."; DLOG << "Swapchain is out of date, recreating.";
UpdateSwapChain(&window_); UpdateSwapChain(&window_);
} else if (err == VK_SUBOPTIMAL_KHR) { } else if (err == VK_SUBOPTIMAL_KHR) {
DLOG << "Swapchain is suboptimal.";
// swapchain is not as optimal as it could be, but the platform's // swapchain is not as optimal as it could be, but the platform's
// presentation engine will still present the image correctly. // presentation engine will still present the image correctly.
DLOG << "Swapchain is suboptimal, recreating.";
UpdateSwapChain(&window_);
break; break;
} else { } else if (err != VK_SUCCESS) {
if (err) { DLOG << "AcquireNextImageKHR failed. Error: " << string_VkResult(err);
DLOG << "AcquireNextImageKHR failed. Error: " << err;
return false; return false;
} }
}
} while (err != VK_SUCCESS); } while (err != VK_SUCCESS);
buffers_prepared_ = true;
return true; return true;
} }
@ -1470,7 +1477,7 @@ bool VulkanContext::SwapBuffers() {
submit_info.pSignalSemaphores = &draw_complete_semaphores_[frame_index_]; submit_info.pSignalSemaphores = &draw_complete_semaphores_[frame_index_];
err = vkQueueSubmit(graphics_queue_, 1, &submit_info, fences_[frame_index_]); err = vkQueueSubmit(graphics_queue_, 1, &submit_info, fences_[frame_index_]);
if (err) { if (err) {
DLOG << "vkQueueSubmit failed. Error: " << err; DLOG << "vkQueueSubmit failed. Error: " << string_VkResult(err);
return false; return false;
} }
@ -1501,7 +1508,7 @@ bool VulkanContext::SwapBuffers() {
submit_info.pSignalSemaphores = &image_ownership_semaphores_[frame_index_]; submit_info.pSignalSemaphores = &image_ownership_semaphores_[frame_index_];
err = vkQueueSubmit(present_queue_, 1, &submit_info, null_fence); err = vkQueueSubmit(present_queue_, 1, &submit_info, null_fence);
if (err) { if (err) {
DLOG << "vkQueueSubmit failed. Error: " << err; DLOG << "vkQueueSubmit failed. Error: " << string_VkResult(err);
return false; return false;
} }
} }
@ -1548,11 +1555,10 @@ bool VulkanContext::SwapBuffers() {
// presentation engine will still present the image correctly. // presentation engine will still present the image correctly.
DLOG << "Swapchain is Suboptimal."; DLOG << "Swapchain is Suboptimal.";
} else if (err) { } else if (err) {
DLOG << "QueuePresentKHR failed. Error: " << err; DLOG << "QueuePresentKHR failed. Error: " << string_VkResult(err);
return false; return false;
} }
buffers_prepared_ = false;
return true; return true;
} }

View File

@ -96,8 +96,6 @@ class VulkanContext {
uint32_t queue_family_count_ = 0; uint32_t queue_family_count_ = 0;
std::unique_ptr<VkQueueFamilyProperties[]> queue_props_ = nullptr; std::unique_ptr<VkQueueFamilyProperties[]> queue_props_ = nullptr;
bool buffers_prepared_ = false;
bool queues_initialized_ = false; bool queues_initialized_ = false;
bool separate_present_queue_ = false; bool separate_present_queue_ = false;

View File

@ -5,20 +5,20 @@
namespace eng { namespace eng {
class SolidQuad : public Animatable { class SolidQuad final : public Animatable {
public: public:
SolidQuad() = default; SolidQuad() = default;
~SolidQuad() override = default; ~SolidQuad() final = default;
// Animatable interface. // Animatable interface.
void SetFrame(size_t frame) override {} void SetFrame(size_t frame) final {}
size_t GetFrame() const override { return 0; } size_t GetFrame() const final { return 0; }
size_t GetNumFrames() const override { return 0; } size_t GetNumFrames() const final { return 0; }
void SetColor(const base::Vector4f& color) override { color_ = color; } void SetColor(const base::Vector4f& color) final { color_ = color; }
base::Vector4f GetColor() const override { return color_; } base::Vector4f GetColor() const final { return color_; }
// Drawable interface. // Drawable interface.
void Draw(float frame_frac) override; void Draw(float frame_frac) final;
private: private:
base::Vector4f color_ = {1, 1, 1, 1}; base::Vector4f color_ = {1, 1, 1, 1};