Compare commits

..

No commits in common. "daa3a8c06f375d5002159e7cbf343b71982fce27" and "5ca5ed763a99293a926f59759fee6ff3c32c7a14" have entirely different histories.

29 changed files with 287 additions and 296 deletions

View File

@ -26,4 +26,3 @@ 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,5 +1,9 @@
#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;
@ -13,25 +17,19 @@ 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 = random2(i); float a = random(i);
float b = random2(i + vec2(1.0, 0.0)); float b = random(i + vec2(1.0, 0.0));
float c = random2(i + vec2(0.0, 1.0)); float c = random(i + vec2(0.0, 1.0));
float d = random2(i + vec2(1.0, 1.0)); float d = random(i + vec2(1.0, 1.0));
vec2 u = smoothstep(0.0, 1.0, f); vec2 u = smoothstep(0.0, 1.0, f);
@ -54,7 +52,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;
vec3 result = vec3(0.); mediump 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,5 +1,9 @@
#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;
@ -31,7 +35,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;
vec3 result = vec3(0.); mediump 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="17" android:versionCode="16"
android:versionName="1.0.2"> android:versionName="1.0.1">
<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.7f, rnd.Rand()) * (1 - weights[0]), c += {Lerp(0.1f, 0.5f, rnd.Rand()) * (1 - weights[0]),
Lerp(0.1f, 0.7f, rnd.Rand()) * (1 - weights[1]), Lerp(0.1f, 0.5f, rnd.Rand()) * (1 - weights[1]),
Lerp(0.1f, 0.7f, rnd.Rand()) * (1 - weights[2]), 1}; Lerp(0.1f, 0.5f, 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(-1); player_.TakeDamage(-3);
total_enemies_ = 23.0897f * log((float)wave_ + 1.0f) - 10.0f; total_enemies_ = 20.0f + 23.0897f * log((float)wave_);
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,7 +489,6 @@ 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 final : public eng::Game { class Demo : public eng::Game {
public: public:
Demo(); Demo();
~Demo() final; ~Demo() override;
bool Initialize() final; bool Initialize() override;
void Update(float delta_time) final; void Update(float delta_time) override;
void ContextLost() final; void ContextLost() override;
void LostFocus() final; void LostFocus() override;
void GainedFocus(bool from_interstitial_ad) final; void GainedFocus(bool from_interstitial_ad) override;
void AddScore(size_t score); void AddScore(size_t score);

View File

@ -148,8 +148,7 @@ void Enemy::Update(float delta_time) {
if (it->chromatic_aberration_active_) { if (it->chromatic_aberration_active_) {
it->sprite.SetCustomUniform( it->sprite.SetCustomUniform(
"aberration_offset", "aberration_offset", Lerp(0.0f, 0.01f, chromatic_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 &&
@ -407,8 +406,6 @@ bool Enemy::IsBossAlive() const {
} }
void Enemy::PauseProgress() { void Enemy::PauseProgress() {
DeselectTarget(kDamageType_Green);
DeselectTarget(kDamageType_Blue);
progress_paused_ = true; progress_paused_ = true;
} }
@ -787,7 +784,8 @@ 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 = 41.1283f * log((float)game->wave()) - 20.0f; e.total_health = e.hit_points =
-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 =
@ -1082,7 +1080,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(60.0f, 80.0f, rnd.Rand()); seconds_to_next_power_up_ = Lerp(1.3f * 60.0f, 1.8f * 60.0f, rnd.Rand());
} }
} }
@ -1102,6 +1100,9 @@ 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.2"; constexpr char kVersionStr[] = "Version 1.0.1";
constexpr char kMenuOption[Menu::kOption_Max][10] = {"continue", "start", constexpr char kMenuOption[Menu::kOption_Max][10] = {"continue", "start",
"credits", "exit"}; "credits", "exit"};
@ -81,12 +81,7 @@ 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. selected_option_ = (Option)i;
if (i == kExit)
click_.SetEndCallback(
[&, i]() -> void { selected_option_ = (Option)i; });
else
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, 20.0f); warmup_animator_[i].SetRotation(M_PI * 2, 8.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) final {} void SetFrame(size_t frame) override {}
size_t GetFrame() const final { return 0; } size_t GetFrame() const override { return 0; }
size_t GetNumFrames() const final { return 0; } size_t GetNumFrames() const override { return 0; }
void SetColor(const base::Vector4f& color) final { nebula_color_ = color; } void SetColor(const base::Vector4f& color) override { nebula_color_ = color; }
base::Vector4f GetColor() const final { return nebula_color_; } base::Vector4f GetColor() const override { return nebula_color_; }
// Drawable interface. // Drawable interface.
void Draw(float frame_frac) final; void Draw(float frame_frac) override;
void ContextLost(); void ContextLost();

View File

@ -180,13 +180,9 @@ 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;
@ -252,8 +248,6 @@ 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,8 +120,6 @@ 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 final : public oboe::AudioStreamCallback { class StreamCallback : public oboe::AudioStreamCallback {
public: public:
StreamCallback(AudioOboe* audio); StreamCallback(AudioOboe* audio);
~StreamCallback() final; ~StreamCallback() override;
oboe::DataCallbackResult onAudioReady(oboe::AudioStream* oboe_stream, oboe::DataCallbackResult onAudioReady(oboe::AudioStream* oboe_stream,
void* audio_data, void* audio_data,
int32_t num_frames) final; int32_t num_frames) override;
void onErrorAfterClose(oboe::AudioStream* oboe_stream, void onErrorAfterClose(oboe::AudioStream* oboe_stream,
oboe::Result error) final; oboe::Result error) override;
private: private:
AudioOboe* audio_; AudioOboe* audio_;

View File

@ -222,27 +222,31 @@ 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) {
if (textures_.contains(asset_name) && textures_[asset_name].use_count > 0) { Texture* texture;
DLOG << "Texture in use: " << asset_name; auto it = textures_.find(asset_name);
return; if (it != textures_.end()) {
texture = it->second.texture.get();
it->second.create_image = create_image;
it->second.persistent = persistent;
} else {
auto& t = textures_[asset_name] = {CreateRenderResource<Texture>(),
create_image, persistent, 0};
texture = t.texture.get();
} }
auto& t = textures_[asset_name] = {CreateRenderResource<Texture>(),
create_image, persistent, 0};
if (persistent) { if (persistent) {
auto image = create_image(); auto image = create_image();
if (image) if (image)
t.texture->Update(std::move(image)); 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)
@ -253,23 +257,22 @@ 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; if (!it->second.texture->IsValid())
return nullptr; RefreshImage(it->first);
it->second.use_count++;
return it->second.texture.get();
} }
if (!it->second.texture->IsValid()) auto& t = textures_[asset_name] = {CreateRenderResource<Texture>(), nullptr,
RefreshImage(it->first); false, 1};
it->second.use_count++; return t.texture.get();
return it->second.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--;
@ -507,7 +510,10 @@ 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);
lines.push_back(renderer_->GetDebugName()); // line = "cmd: ";
// 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 final : public GameFactoryBase { class GameFactory : public GameFactoryBase {
public: public:
~GameFactory() final = default; ~GameFactory() override = default;
private: private:
using GameType = Type; using GameType = Type;
std::unique_ptr<Game> CreateGame() final { std::unique_ptr<Game> CreateGame() override {
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,10 +33,8 @@ 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 final : public Animatable { class ImageQuad : public Animatable {
public: public:
ImageQuad(); ImageQuad();
~ImageQuad() final; ~ImageQuad() override;
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 final : public Animatable {
} }
// Animatable interface. // Animatable interface.
void SetFrame(size_t frame) final; void SetFrame(size_t frame) override;
size_t GetFrame() const final { return current_frame_; } size_t GetFrame() const override { return current_frame_; }
size_t GetNumFrames() const final; size_t GetNumFrames() const override;
void SetColor(const base::Vector4f& color) final { color_ = color; } void SetColor(const base::Vector4f& color) override { color_ = color; }
base::Vector4f GetColor() const final { return color_; } base::Vector4f GetColor() const override { return color_; }
// Drawable interface. // Drawable interface.
void Draw(float frame_frac) final; void Draw(float frame_frac) override;
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,6 +7,8 @@
#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 {
@ -29,13 +31,11 @@ void Platform::InitializeCommon() {
throw internal_error; throw internal_error;
} }
auto context = std::make_unique<VulkanContext>(); #if defined(VULKAN_RENDERER)
if (context->Initialize()) { renderer_ = std::make_unique<RendererVulkan>();
renderer_ = std::make_unique<RendererVulkan>(std::move(context)); #else
} else { renderer_ = std::make_unique<RendererOpenGL>();
LOG << "Failed to initialize Vulkan context. Fallback to OpenGL."; #endif
renderer_ = std::make_unique<RendererOpenGL>();
}
} }
void Platform::ShutdownCommon() { void Platform::ShutdownCommon() {

View File

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

View File

@ -92,8 +92,6 @@ 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,7 +18,6 @@
#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;
@ -346,7 +345,7 @@ std::pair<int, int> GetBlockSizeForImageFormat(VkFormat format) {
default: default:
break; break;
} }
NOTREACHED << "Invalid format: " << string_VkFormat(format); NOTREACHED << "Invalid format: " << format;
return {0, 0}; return {0, 0};
} }
@ -362,7 +361,7 @@ std::pair<int, int> GetNumBlocksForImageFormat(VkFormat format,
default: default:
break; break;
} }
NOTREACHED << "Invalid format: " << string_VkFormat(format); NOTREACHED << "Invalid format: " << format;
return {width, height}; return {width, height};
} }
@ -370,8 +369,7 @@ std::pair<int, int> GetNumBlocksForImageFormat(VkFormat format,
namespace eng { namespace eng {
RendererVulkan::RendererVulkan(std::unique_ptr<VulkanContext> context) RendererVulkan::RendererVulkan() = default;
: context_{std::move(context)} {}
RendererVulkan::~RendererVulkan() = default; RendererVulkan::~RendererVulkan() = default;
@ -468,13 +466,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.
FreeImage(std::move(it->second.image), it->second.view, FreeTexture(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) {
AllocateImage(it->second.image, it->second.view, it->second.desc_set, CreateTexture(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);
@ -516,8 +514,8 @@ void RendererVulkan::DestroyTexture(uint64_t resource_id) {
if (it == textures_.end()) if (it == textures_.end())
return; return;
FreeImage(std::move(it->second.image), it->second.view, FreeTexture(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);
} }
@ -707,7 +705,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;
@ -828,7 +826,7 @@ void RendererVulkan::UploadUniforms(uint64_t resource_id) {
} }
void RendererVulkan::PrepareForDrawing() { void RendererVulkan::PrepareForDrawing() {
context_->PrepareBuffers(); context_.PrepareBuffers();
DrawListBegin(); DrawListBegin();
} }
@ -840,20 +838,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++) {
@ -861,20 +859,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 " << string_VkResult(err); DLOG << "vkCreateCommandPool failed with error " << std::to_string(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 " << string_VkResult(err); DLOG << "vkCreateCommandPool failed with error " << std::to_string(err);
return false; return false;
} }
@ -890,7 +888,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 "
<< string_VkResult(err); << std::to_string(err);
continue; continue;
} }
@ -899,7 +897,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 "
<< string_VkResult(err); << std::to_string(err);
continue; continue;
} }
} }
@ -920,10 +918,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 err = vkCreateDescriptorSetLayout(device_, &ds_layout_info, nullptr, VkResult res = vkCreateDescriptorSetLayout(device_, &ds_layout_info, nullptr,
&descriptor_set_layout_); &descriptor_set_layout_);
if (err) { if (res) {
DLOG << "Error (" << string_VkResult(err) DLOG << "Error (" << std::to_string(res)
<< ") creating descriptor set layout for set"; << ") creating descriptor set layout for set";
return false; return false;
} }
@ -949,9 +947,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;
err = vkCreateSampler(device_, &sampler_info, nullptr, &sampler_); res = vkCreateSampler(device_, &sampler_info, nullptr, &sampler_);
if (err) { if (res) {
DLOG << "vkCreateSampler failed with error " << string_VkResult(err); DLOG << "vkCreateSampler failed with error " << std::to_string(res);
return false; return false;
} }
@ -973,7 +971,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_ && context_lost_cb_) { if (context_lost_cb_) {
LOG << "Context lost."; LOG << "Context lost.";
context_lost_cb_(); context_lost_cb_();
} }
@ -986,7 +984,6 @@ 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();
@ -1014,8 +1011,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();
} }
@ -1023,8 +1020,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);
@ -1038,14 +1035,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 " << string_VkResult(err); DLOG << "vkBeginCommandBuffer failed with error " << std::to_string(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 " << string_VkResult(err); DLOG << "vkBeginCommandBuffer failed with error " << std::to_string(err);
return; return;
} }
@ -1063,7 +1060,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);
@ -1076,11 +1073,11 @@ 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 " << string_VkResult(err); DLOG << "vkBeginCommandBuffer failed with error " << std::to_string(err);
return; return;
} }
context_->AppendCommandBuffer(frames_[current_frame_].setup_command_buffer, context_.AppendCommandBuffer(frames_[current_frame_].setup_command_buffer,
true); true);
} }
void RendererVulkan::FreePendingResources(int frame) { void RendererVulkan::FreePendingResources(int frame) {
@ -1289,7 +1286,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 " << string_VkResult(err); DLOG << "vmaCreateBuffer failed with error " << std::to_string(err);
return false; return false;
} }
@ -1327,11 +1324,11 @@ RendererVulkan::DescPool* RendererVulkan::AllocateDescriptorPool() {
descriptor_pool_create_info.pPoolSizes = &sizes; descriptor_pool_create_info.pPoolSizes = &sizes;
VkDescriptorPool desc_pool; VkDescriptorPool desc_pool;
VkResult err = vkCreateDescriptorPool(device_, &descriptor_pool_create_info, VkResult res = vkCreateDescriptorPool(device_, &descriptor_pool_create_info,
nullptr, &desc_pool); nullptr, &desc_pool);
if (err) { if (res) {
DLOG << "vkCreateDescriptorPool failed with error " DLOG << "vkCreateDescriptorPool failed with error "
<< string_VkResult(err); << std::to_string(res);
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
} }
@ -1387,7 +1384,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 " << string_VkResult(err); << ", error " << std::to_string(err);
return false; return false;
} }
@ -1461,7 +1458,7 @@ void RendererVulkan::BufferMemoryBarrier(VkBuffer buffer,
&buffer_mem_barrier, 0, nullptr); &buffer_mem_barrier, 0, nullptr);
} }
bool RendererVulkan::AllocateImage(Buffer<VkImage>& image, bool RendererVulkan::CreateTexture(Buffer<VkImage>& image,
VkImageView& view, VkImageView& view,
DescSet& desc_set, DescSet& desc_set,
VkFormat format, VkFormat format,
@ -1503,7 +1500,7 @@ bool RendererVulkan::AllocateImage(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 " << string_VkResult(err); DLOG << "vmaCreateImage failed with error " << std::to_string(err);
return false; return false;
} }
@ -1529,7 +1526,7 @@ bool RendererVulkan::AllocateImage(Buffer<VkImage>& image,
if (err) { if (err) {
vmaDestroyImage(allocator_, vk_image, allocation); vmaDestroyImage(allocator_, vk_image, allocation);
DLOG << "vkCreateImageView failed with error " << string_VkResult(err); DLOG << "vkCreateImageView failed with error " << std::to_string(err);
return false; return false;
} }
@ -1546,11 +1543,11 @@ bool RendererVulkan::AllocateImage(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;
err = vkAllocateDescriptorSets(device_, &descriptor_set_allocate_info, VkResult res = vkAllocateDescriptorSets(
&descriptor_set); device_, &descriptor_set_allocate_info, &descriptor_set);
if (err) { if (res) {
--std::get<1>(*desc_pool); --std::get<1>(*desc_pool);
DLOG << "Cannot allocate descriptor sets, error " << string_VkResult(err); DLOG << "Cannot allocate descriptor sets, error " << std::to_string(res);
return false; return false;
} }
@ -1578,9 +1575,9 @@ bool RendererVulkan::AllocateImage(Buffer<VkImage>& image,
return true; return true;
} }
void RendererVulkan::FreeImage(Buffer<VkImage> image, void RendererVulkan::FreeTexture(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(
std::make_tuple(std::move(image), image_view)); std::make_tuple(std::move(image), image_view));
frames_[current_frame_].desc_sets_to_destroy.push_back(std::move(desc_set)); frames_[current_frame_].desc_sets_to_destroy.push_back(std::move(desc_set));
@ -1907,8 +1904,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_;
@ -1974,7 +1971,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;
@ -2033,13 +2030,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,62 +20,63 @@ namespace eng {
class Image; class Image;
class RendererVulkan final : public Renderer { class RendererVulkan : public Renderer {
public: public:
RendererVulkan(std::unique_ptr<VulkanContext> context); RendererVulkan();
~RendererVulkan() final; ~RendererVulkan() override;
#if defined(__ANDROID__) #if defined(__ANDROID__)
bool Initialize(ANativeWindow* window) final; bool Initialize(ANativeWindow* window) override;
#elif defined(__linux__) #elif defined(__linux__)
bool Initialize(Display* display, Window window) final; bool Initialize(Display* display, Window window) override;
#endif #endif
void Shutdown() final; void Shutdown() override;
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final; uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) override;
void DestroyGeometry(uint64_t resource_id) final; void DestroyGeometry(uint64_t resource_id) override;
void Draw(uint64_t resource_id) final; void Draw(uint64_t resource_id) override;
uint64_t CreateTexture() final; uint64_t CreateTexture() override;
void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final; void UpdateTexture(uint64_t resource_id,
void DestroyTexture(uint64_t resource_id) final; std::unique_ptr<Image> image) override;
void ActivateTexture(uint64_t resource_id) final; void DestroyTexture(uint64_t resource_id) override;
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) final; bool enable_depth_test) override;
void DestroyShader(uint64_t resource_id) final; void DestroyShader(uint64_t resource_id) override;
void ActivateShader(uint64_t resource_id) final; void ActivateShader(uint64_t resource_id) override;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Vector2f& val) final; const base::Vector2f& val) override;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Vector3f& val) final; const base::Vector3f& val) override;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Vector4f& val) final; const base::Vector4f& val) override;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
const base::Matrix4f& val) final; const base::Matrix4f& val) override;
void SetUniform(uint64_t resource_id, void SetUniform(uint64_t resource_id,
const std::string& name, const std::string& name,
float val) final; float val) override;
void SetUniform(uint64_t resource_id, const std::string& name, int val) final; void SetUniform(uint64_t resource_id,
void UploadUniforms(uint64_t resource_id) final; const std::string& name,
int val) override;
void UploadUniforms(uint64_t resource_id) override;
void PrepareForDrawing() final; void PrepareForDrawing() override;
void Present() final; void Present() override;
size_t GetAndResetFPS() final; size_t GetAndResetFPS() override;
const char* GetDebugName() final { return "Vulkan"; }
#if defined(__linux__) && !defined(__ANDROID__) #if defined(__linux__) && !defined(__ANDROID__)
XVisualInfo* GetXVisualInfo(Display* display) final; XVisualInfo* GetXVisualInfo(Display* display) override;
#endif #endif
private: private:
@ -154,9 +155,7 @@ class RendererVulkan final : 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;
bool context_lost_ = false; VulkanContext context_;
std::unique_ptr<VulkanContext> context_;
VmaAllocator allocator_ = nullptr; VmaAllocator allocator_ = nullptr;
@ -225,7 +224,7 @@ class RendererVulkan final : public Renderer {
VkAccessFlags src_access, VkAccessFlags src_access,
VkAccessFlags dst_sccess); VkAccessFlags dst_sccess);
bool AllocateImage(Buffer<VkImage>& image, bool CreateTexture(Buffer<VkImage>& image,
VkImageView& view, VkImageView& view,
DescSet& desc_set, DescSet& desc_set,
VkFormat format, VkFormat format,
@ -233,9 +232,9 @@ class RendererVulkan final : public Renderer {
int height, int height,
VkImageUsageFlags usage, VkImageUsageFlags usage,
VmaMemoryUsage mapping); VmaMemoryUsage mapping);
void FreeImage(Buffer<VkImage> image, void FreeTexture(Buffer<VkImage> image,
VkImageView image_view, VkImageView image_view,
DescSet desc_set); DescSet desc_set);
void UpdateImage(VkImage image, void UpdateImage(VkImage image,
VkFormat format, VkFormat format,
const uint8_t* data, const uint8_t* data,

View File

@ -12,7 +12,11 @@ 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_->CreateWindow(window, screen_width_, screen_height_)) { if (!context_.Initialize()) {
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,7 +12,11 @@ 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_->CreateWindow(display, window, screen_width_, screen_height_)) { if (!context_.Initialize()) {
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,6 +58,7 @@ 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;
@ -214,8 +215,7 @@ 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: " DLOG << "vkEnumerateInstanceLayerProperties failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -228,8 +228,7 @@ 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: " DLOG << "vkEnumerateInstanceLayerProperties failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -285,8 +284,7 @@ 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: " DLOG << "vkEnumerateInstanceExtensionProperties failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -296,8 +294,7 @@ 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: " DLOG << "vkEnumerateInstanceExtensionProperties failed. Error: " << err;
<< 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++) {
@ -412,7 +409,7 @@ bool VulkanContext::CreatePhysicalDevice() {
return false; return false;
} }
if (err) { if (err) {
DLOG << "vkCreateInstance failed. Error: " << string_VkResult(err); DLOG << "vkCreateInstance failed. Error: " << err;
return false; return false;
} }
} }
@ -422,8 +419,7 @@ 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: " DLOG << "vkEnumeratePhysicalDevices failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -436,8 +432,7 @@ 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: " DLOG << "vkEnumeratePhysicalDevices failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
// Grab the first physical device for now. // Grab the first physical device for now.
@ -452,8 +447,7 @@ 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: " DLOG << "vkEnumerateDeviceExtensionProperties failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -463,8 +457,7 @@ 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: " DLOG << "vkEnumerateDeviceExtensionProperties failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -608,7 +601,7 @@ bool VulkanContext::CreateDevice() {
} }
err = vkCreateDevice(gpu_, &sdevice, nullptr, &device_); err = vkCreateDevice(gpu_, &sdevice, nullptr, &device_);
if (err) { if (err) {
DLOG << "vkCreateDevice failed. Error: " << string_VkResult(err); DLOG << "vkCreateDevice failed. Error: " << err;
return false; return false;
} }
return true; return true;
@ -686,16 +679,14 @@ 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: " DLOG << "GetPhysicalDeviceSurfaceFormatsKHR failed. Error: " << err;
<< 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: " DLOG << "GetPhysicalDeviceSurfaceFormatsKHR failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -753,26 +744,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: " << string_VkResult(err); DLOG << "vkCreateFence failed. Error: " << 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: " << string_VkResult(err); DLOG << "vkCreateSemaphore failed. Error: " << 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: " << string_VkResult(err); DLOG << "vkCreateSemaphore failed. Error: " << 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: " << string_VkResult(err); DLOG << "vkCreateSemaphore failed. Error: " << err;
return false; return false;
} }
} }
@ -797,7 +788,10 @@ void VulkanContext::DestroyWindow() {
} }
VkFramebuffer VulkanContext::GetFramebuffer() { VkFramebuffer VulkanContext::GetFramebuffer() {
return window_.swapchain_image_resources[window_.current_buffer].frame_buffer; return buffers_prepared_
? window_.swapchain_image_resources[window_.current_buffer]
.frame_buffer
: VK_NULL_HANDLE;
} }
bool VulkanContext::CleanUpSwapChain(Window* window) { bool VulkanContext::CleanUpSwapChain(Window* window) {
@ -844,8 +838,7 @@ 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: " DLOG << "GetPhysicalDeviceSurfaceCapabilitiesKHR failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -853,8 +846,7 @@ 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: " DLOG << "GetPhysicalDeviceSurfacePresentModesKHR failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -863,8 +855,7 @@ 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: " DLOG << "GetPhysicalDeviceSurfacePresentModesKHR failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -1011,7 +1002,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: " << string_VkResult(err); DLOG << "CreateSwapchainKHR failed. Error: " << err;
return false; return false;
} }
@ -1019,7 +1010,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: " << string_VkResult(err); DLOG << "CreateSwapchainKHR failed. Error: " << err;
return false; return false;
} }
@ -1036,7 +1027,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: " << string_VkResult(err); DLOG << "GetSwapchainImagesKHR failed. Error: " << err;
return false; return false;
} }
@ -1073,7 +1064,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: " << string_VkResult(err); DLOG << "vkCreateImageView failed. Error: " << err;
return false; return false;
} }
} }
@ -1157,7 +1148,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: " << string_VkResult(err); DLOG << "vkCreateRenderPass failed. Error: " << err;
return false; return false;
} }
@ -1182,7 +1173,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: " << string_VkResult(err); DLOG << "vkCreateFramebuffer failed. Error: " << err;
return false; return false;
} }
} }
@ -1200,7 +1191,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: " << string_VkResult(err); DLOG << "vkCreateCommandPool failed. Error: " << err;
return false; return false;
} }
@ -1216,8 +1207,7 @@ 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: " DLOG << "vkAllocateCommandBuffers failed. Error: " << err;
<< string_VkResult(err);
return false; return false;
} }
@ -1231,7 +1221,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: " << string_VkResult(err); DLOG << "vkBeginCommandBuffer failed. Error: " << err;
return false; return false;
} }
@ -1255,7 +1245,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: " << string_VkResult(err); DLOG << "vkEndCommandBuffer failed. Error: " << err;
return false; return false;
} }
} }
@ -1294,7 +1284,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: " << string_VkResult(err); DLOG << "vkCreateImage failed. Error: " << err;
return false; return false;
} }
@ -1326,7 +1316,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: " << string_VkResult(err); DLOG << "vkAllocateMemory failed. Error: " << err;
return false; return false;
} }
@ -1396,7 +1386,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: " << string_VkResult(err); DLOG << "vkQueueSubmit failed. Error: " << err;
return; return;
} }
@ -1431,20 +1421,23 @@ 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, recreating."; DLOG << "Swapchain is out of date.";
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 if (err != VK_SUCCESS) { } else {
DLOG << "AcquireNextImageKHR failed. Error: " << string_VkResult(err); if (err) {
return false; DLOG << "AcquireNextImageKHR failed. Error: " << err;
return false;
}
} }
} while (err != VK_SUCCESS); } while (err != VK_SUCCESS);
buffers_prepared_ = true;
return true; return true;
} }
@ -1477,7 +1470,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: " << string_VkResult(err); DLOG << "vkQueueSubmit failed. Error: " << err;
return false; return false;
} }
@ -1508,7 +1501,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: " << string_VkResult(err); DLOG << "vkQueueSubmit failed. Error: " << err;
return false; return false;
} }
} }
@ -1555,10 +1548,11 @@ 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: " << string_VkResult(err); DLOG << "QueuePresentKHR failed. Error: " << err;
return false; return false;
} }
buffers_prepared_ = false;
return true; return true;
} }

View File

@ -96,6 +96,8 @@ 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 final : public Animatable { class SolidQuad : public Animatable {
public: public:
SolidQuad() = default; SolidQuad() = default;
~SolidQuad() final = default; ~SolidQuad() override = default;
// Animatable interface. // Animatable interface.
void SetFrame(size_t frame) final {} void SetFrame(size_t frame) override {}
size_t GetFrame() const final { return 0; } size_t GetFrame() const override { return 0; }
size_t GetNumFrames() const final { return 0; } size_t GetNumFrames() const override { return 0; }
void SetColor(const base::Vector4f& color) final { color_ = color; } void SetColor(const base::Vector4f& color) override { color_ = color; }
base::Vector4f GetColor() const final { return color_; } base::Vector4f GetColor() const override { return color_; }
// Drawable interface. // Drawable interface.
void Draw(float frame_frac) final; void Draw(float frame_frac) override;
private: private:
base::Vector4f color_ = {1, 1, 1, 1}; base::Vector4f color_ = {1, 1, 1, 1};