Compare commits

..

No commits in common. "214ae33246484054472b689cc5e905bbddebaa6b" and "b86a27531b88fb9cf065943386d6395b6695047e" have entirely different histories.

12 changed files with 128 additions and 204 deletions

View File

@ -95,14 +95,13 @@ void Image::Copy(const Image& other) {
} }
bool Image::CreateMip(const Image& other) { bool Image::CreateMip(const Image& other) {
if (other.width_ <= 1 || other.height_ <= 1 || if (other.width_ <= 1 || other.height_ <= 1 || other.GetFormat() != kRGBA32)
other.GetFormat() != ImageFormat::kRGBA32)
return false; return false;
// Reduce the dimensions. // Reduce the dimensions.
width_ = std::max(other.width_ >> 1, 1); width_ = std::max(other.width_ >> 1, 1);
height_ = std::max(other.height_ >> 1, 1); height_ = std::max(other.height_ >> 1, 1);
format_ = ImageFormat::kRGBA32; format_ = kRGBA32;
buffer_.reset((uint8_t*)AlignedAlloc(GetSize(), 16)); buffer_.reset((uint8_t*)AlignedAlloc(GetSize(), 16));
// If the width isn't perfectly divisable with two, then we end up skewing // If the width isn't perfectly divisable with two, then we end up skewing
@ -215,12 +214,21 @@ bool Image::Load(const std::string& file_name) {
return !!buffer_; return !!buffer_;
} }
bool Image::IsCompressed() const {
return IsCompressedFormat(format_);
}
size_t Image::GetSize() const { size_t Image::GetSize() const {
return GetImageSize(width_, height_, format_); switch (format_) {
case kRGBA32:
return width_ * height_ * 4;
case kDXT1:
case kATC:
return ((width_ + 3) / 4) * ((height_ + 3) / 4) * 8;
case kDXT5:
case kATCIA:
return ((width_ + 3) / 4) * ((height_ + 3) / 4) * 16;
case kETC1:
return (width_ * height_ * 4) / 8;
default:
return 0;
}
} }
void Image::ConvertToPow2() { void Image::ConvertToPow2() {
@ -267,25 +275,25 @@ bool Image::Compress() {
switch (tc->format()) { switch (tc->format()) {
case TextureCompressor::kFormatATC: case TextureCompressor::kFormatATC:
format_ = ImageFormat::kATC; format_ = kATC;
break; break;
case TextureCompressor::kFormatATCIA: case TextureCompressor::kFormatATCIA:
format_ = ImageFormat::kATCIA; format_ = kATCIA;
break; break;
case TextureCompressor::kFormatDXT1: case TextureCompressor::kFormatDXT1:
format_ = ImageFormat::kDXT1; format_ = kDXT1;
break; break;
case TextureCompressor::kFormatDXT5: case TextureCompressor::kFormatDXT5:
format_ = ImageFormat::kDXT5; format_ = kDXT5;
break; break;
case TextureCompressor::kFormatETC1: case TextureCompressor::kFormatETC1:
format_ = ImageFormat::kETC1; format_ = kETC1;
break; break;
default: default:
return false; return false;
} }
LOG(0) << "Compressing image. Format: " << ImageFormatToString(format_); LOG(0) << "Compressing image. Format: " << format_;
unsigned compressedSize = GetSize(); unsigned compressedSize = GetSize();
uint8_t* compressedBuffer = uint8_t* compressedBuffer =

View File

@ -6,12 +6,13 @@
#include "base/mem.h" #include "base/mem.h"
#include "base/vecmath.h" #include "base/vecmath.h"
#include "engine/renderer/renderer_types.h"
namespace eng { namespace eng {
class Image { class Image {
public: public:
enum Format { kRGBA32, kDXT1, kDXT5, kETC1, kATC, kATCIA };
Image(); Image();
Image(const Image& other); Image(const Image& other);
~Image(); ~Image();
@ -30,8 +31,8 @@ class Image {
int GetWidth() const { return width_; } int GetWidth() const { return width_; }
int GetHeight() const { return height_; } int GetHeight() const { return height_; }
ImageFormat GetFormat() const { return format_; } Format GetFormat() const { return format_; }
bool IsCompressed() const; bool IsCompressed() const { return format_ > kRGBA32; }
size_t GetSize() const; size_t GetSize() const;
@ -50,7 +51,7 @@ class Image {
base::AlignedMemPtr<uint8_t[]> buffer_; base::AlignedMemPtr<uint8_t[]> buffer_;
int width_ = 0; int width_ = 0;
int height_ = 0; int height_ = 0;
ImageFormat format_ = ImageFormat::kRGBA32; Format format_ = kRGBA32;
}; };
} // namespace eng } // namespace eng

View File

@ -102,8 +102,6 @@ void Engine::Initialize() {
thread_pool_.Initialize(); thread_pool_.Initialize();
imgui_backend_.Initialize(IsMobile(), GetRootPath());
platform_->CreateMainWindow(); platform_->CreateMainWindow();
CreateRendererInternal(RendererType::kVulkan); CreateRendererInternal(RendererType::kVulkan);
@ -121,6 +119,8 @@ void Engine::Initialize() {
CreateRenderResources(); CreateRenderResources();
WaitForAsyncWork(); WaitForAsyncWork();
imgui_backend_.Initialize();
CHECK(game_->Initialize()) << "Failed to initialize the game."; CHECK(game_->Initialize()) << "Failed to initialize the game.";
} }

View File

@ -1,10 +1,14 @@
#include "engine/imgui_backend.h" #include "engine/imgui_backend.h"
#include "base/log.h" #include "base/log.h"
#include "engine/asset/image.h"
#include "engine/asset/shader_source.h" #include "engine/asset/shader_source.h"
#include "engine/engine.h"
#include "engine/input_event.h" #include "engine/input_event.h"
#include "engine/platform/asset_file.h" #include "engine/platform/asset_file.h"
#include "engine/renderer/renderer.h" #include "engine/renderer/renderer.h"
#include "engine/renderer/shader.h"
#include "engine/renderer/texture.h"
#include "third_party/imgui/imgui.h" #include "third_party/imgui/imgui.h"
using namespace base; using namespace base;
@ -15,11 +19,11 @@ namespace {
const char vertex_description[] = "p2f;t2f;c4b"; const char vertex_description[] = "p2f;t2f;c4b";
} // namespace } // namespace
ImguiBackend::ImguiBackend() = default; ImguiBackend::ImguiBackend() : shader_{std::make_unique<Shader>(nullptr)} {}
ImguiBackend::~ImguiBackend() = default; ImguiBackend::~ImguiBackend() = default;
void ImguiBackend::Initialize(bool is_mobile, std::string root_path) { void ImguiBackend::Initialize() {
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
ImGui::GetIO().IniFilename = nullptr; ImGui::GetIO().IniFilename = nullptr;
@ -29,11 +33,12 @@ void ImguiBackend::Initialize(bool is_mobile, std::string root_path) {
size_t buffer_size = 0; size_t buffer_size = 0;
auto buffer = AssetFile::ReadWholeFile("engine/RobotoMono-Regular.ttf", auto buffer = AssetFile::ReadWholeFile("engine/RobotoMono-Regular.ttf",
root_path.c_str(), &buffer_size); Engine::Get().GetRootPath().c_str(),
&buffer_size);
if (buffer) { if (buffer) {
ImFontConfig font_cfg = ImFontConfig(); ImFontConfig font_cfg = ImFontConfig();
font_cfg.FontDataOwnedByAtlas = false; font_cfg.FontDataOwnedByAtlas = false;
float size_pixels = is_mobile ? 64 : 32; float size_pixels = Engine::Get().IsMobile() ? 64 : 32;
ImGui::GetIO().Fonts->AddFontFromMemoryTTF(buffer.get(), (int)buffer_size, ImGui::GetIO().Fonts->AddFontFromMemoryTTF(buffer.get(), (int)buffer_size,
size_pixels, &font_cfg); size_pixels, &font_cfg);
ImGui::GetIO().Fonts->Build(); ImGui::GetIO().Fonts->Build();
@ -43,45 +48,54 @@ void ImguiBackend::Initialize(bool is_mobile, std::string root_path) {
// Arbitrary scale-up for mobile devices. // Arbitrary scale-up for mobile devices.
// TODO: Put some effort into DPI awareness. // TODO: Put some effort into DPI awareness.
if (is_mobile) if (Engine::Get().IsMobile())
ImGui::GetStyle().ScaleAllSizes(2.0f); ImGui::GetStyle().ScaleAllSizes(2.0f);
}
void ImguiBackend::Shutdown() { Engine::Get().SetImageSource(
ImGui::DestroyContext(); "imgui_atlas",
for (auto& id : geometries_) []() -> std::unique_ptr<Image> {
renderer_->DestroyGeometry(id);
geometries_.clear();
renderer_->DestroyTexture(font_atlas_);
renderer_->DestroyShader(shader_);
}
void ImguiBackend::CreateRenderResources(Renderer* renderer) {
renderer_ = renderer;
geometries_.clear();
// Avoid flickering by using the geometries form the last frame if available.
if (ImGui::GetCurrentContext() && ImGui::GetDrawData())
Render();
// Create the shader.
auto source = std::make_unique<ShaderSource>();
if (source->Load("engine/imgui.glsl")) {
shader_ = renderer_->CreateShader(std::move(source), vertex_description_,
kPrimitive_Triangles, false);
} else {
LOG(0) << "Could not create imgui shader.";
}
// Create a texture for the font atlas.
unsigned char* pixels; unsigned char* pixels;
int width, height; int width, height;
ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
LOG(0) << "Font atlas size: " << width << ", " << height; LOG(0) << "Font atlas size: " << width << ", " << height;
font_atlas_ = renderer_->CreateTexture(); auto image = std::make_unique<Image>();
renderer_->UpdateTexture(font_atlas_, width, height, ImageFormat::kRGBA32, image->Create(width, height);
width * height * 4, pixels); memcpy(image->GetBuffer(), pixels, width * height * 4);
ImGui::GetIO().Fonts->SetTexID((ImTextureID)(intptr_t)font_atlas_); return image;
},
true);
Engine::Get().RefreshImage("imgui_atlas");
ImGui::GetIO().Fonts->SetTexID(
(ImTextureID)(intptr_t)Engine::Get().AcquireTexture("imgui_atlas"));
}
void ImguiBackend::Shutdown() {
for (auto& id : geometries_)
renderer_->DestroyGeometry(id);
geometries_.clear();
ImGui::DestroyContext();
shader_.reset();
}
void ImguiBackend::CreateRenderResources(Renderer* renderer) {
renderer_ = renderer;
shader_->SetRenderer(renderer);
geometries_.clear();
if (ImGui::GetCurrentContext() && ImGui::GetDrawData())
Render();
auto source = std::make_unique<ShaderSource>();
if (source->Load("engine/imgui.glsl")) {
VertexDescription vd;
if (!ParseVertexDescription(vertex_description, vd)) {
DLOG(0) << "Failed to parse vertex description.";
} else {
shader_->Create(std::move(source), vd, kPrimitive_Triangles, false);
}
} else {
LOG(0) << "Could not create imgui shader.";
}
} }
std::unique_ptr<InputEvent> ImguiBackend::OnInputEvent( std::unique_ptr<InputEvent> ImguiBackend::OnInputEvent(
@ -119,7 +133,6 @@ void ImguiBackend::NewFrame(float delta_time) {
void ImguiBackend::Render() { void ImguiBackend::Render() {
ImGui::Render(); ImGui::Render();
// Create a geometry for each draw list and upload the vertex data.
ImDrawData* draw_data = ImGui::GetDrawData(); ImDrawData* draw_data = ImGui::GetDrawData();
if ((int)geometries_.size() < draw_data->CmdListsCount) if ((int)geometries_.size() < draw_data->CmdListsCount)
geometries_.resize(draw_data->CmdListsCount, 0); geometries_.resize(draw_data->CmdListsCount, 0);
@ -147,9 +160,9 @@ void ImguiBackend::Draw() {
draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x,
draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y + draw_data->DisplaySize.y,
draw_data->DisplayPos.y); draw_data->DisplayPos.y);
renderer_->ActivateShader(shader_); shader_->Activate();
renderer_->SetUniform(shader_, "projection", proj); shader_->SetUniform("projection", proj);
renderer_->UploadUniforms(shader_); shader_->UploadUniforms();
for (int n = 0; n < draw_data->CmdListsCount; n++) { for (int n = 0; n < draw_data->CmdListsCount; n++) {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
@ -158,8 +171,7 @@ void ImguiBackend::Draw() {
if (pcmd->ClipRect.z <= pcmd->ClipRect.x || if (pcmd->ClipRect.z <= pcmd->ClipRect.x ||
pcmd->ClipRect.w <= pcmd->ClipRect.y) pcmd->ClipRect.w <= pcmd->ClipRect.y)
continue; continue;
uint64_t texture_id = reinterpret_cast<uintptr_t>(pcmd->GetTexID()); reinterpret_cast<Texture*>(pcmd->GetTexID())->Activate(0);
renderer_->ActivateTexture(texture_id, 0);
renderer_->SetScissor(int(pcmd->ClipRect.x), int(pcmd->ClipRect.y), renderer_->SetScissor(int(pcmd->ClipRect.x), int(pcmd->ClipRect.y),
int(pcmd->ClipRect.z - pcmd->ClipRect.x), int(pcmd->ClipRect.z - pcmd->ClipRect.x),
int(pcmd->ClipRect.w - pcmd->ClipRect.y)); int(pcmd->ClipRect.w - pcmd->ClipRect.y));

View File

@ -9,6 +9,7 @@
namespace eng { namespace eng {
class InputEvent; class InputEvent;
class Shader;
class Renderer; class Renderer;
class ImguiBackend { class ImguiBackend {
@ -16,7 +17,7 @@ class ImguiBackend {
ImguiBackend(); ImguiBackend();
~ImguiBackend(); ~ImguiBackend();
void Initialize(bool is_mobile, std::string root_path); void Initialize();
void Shutdown(); void Shutdown();
void CreateRenderResources(Renderer* renderer); void CreateRenderResources(Renderer* renderer);
@ -30,8 +31,7 @@ class ImguiBackend {
private: private:
VertexDescription vertex_description_; VertexDescription vertex_description_;
std::vector<uint64_t> geometries_; std::vector<uint64_t> geometries_;
uint64_t shader_ = 0; std::unique_ptr<Shader> shader_;
uint64_t font_atlas_ = 0;
Renderer* renderer_ = nullptr; Renderer* renderer_ = nullptr;
}; };

View File

@ -17,8 +17,6 @@
using namespace base; using namespace base;
namespace eng {
namespace { namespace {
constexpr GLenum kGlPrimitive[eng::kPrimitive_Max] = {GL_TRIANGLES, constexpr GLenum kGlPrimitive[eng::kPrimitive_Max] = {GL_TRIANGLES,
@ -33,6 +31,8 @@ const std::string kAttributeNames[eng::kAttribType_Max] = {
} // namespace } // namespace
namespace eng {
RendererOpenGL::RendererOpenGL(base::Closure context_lost_cb) RendererOpenGL::RendererOpenGL(base::Closure context_lost_cb)
: Renderer(context_lost_cb) {} : Renderer(context_lost_cb) {}
@ -251,63 +251,55 @@ uint64_t RendererOpenGL::CreateTexture() {
void RendererOpenGL::UpdateTexture(uint64_t resource_id, void RendererOpenGL::UpdateTexture(uint64_t resource_id,
std::unique_ptr<Image> image) { std::unique_ptr<Image> image) {
UpdateTexture(resource_id, image->GetWidth(), image->GetHeight(),
image->GetFormat(), image->GetSize(), image->GetBuffer());
}
void RendererOpenGL::UpdateTexture(uint64_t resource_id,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) {
auto it = textures_.find(resource_id); auto it = textures_.find(resource_id);
if (it == textures_.end()) if (it == textures_.end())
return; return;
glBindTexture(GL_TEXTURE_2D, it->second); glBindTexture(GL_TEXTURE_2D, it->second);
if (IsCompressedFormat(format)) { if (image->IsCompressed()) {
GLenum gl_format = 0; GLenum format = 0;
switch (format) { switch (image->GetFormat()) {
case ImageFormat::kDXT1: case Image::kDXT1:
gl_format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
break; break;
case ImageFormat::kDXT5: case Image::kDXT5:
gl_format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break; break;
case ImageFormat::kETC1: case Image::kETC1:
gl_format = GL_ETC1_RGB8_OES; format = GL_ETC1_RGB8_OES;
break; break;
#if defined(__ANDROID__) #if defined(__ANDROID__)
case ImageFormat::kATC: case Image::kATC:
gl_format = GL_ATC_RGB_AMD; format = GL_ATC_RGB_AMD;
break; break;
case ImageFormat::kATCIA: case Image::kATCIA:
gl_format = GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD; format = GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD;
break; break;
#endif #endif
default: default:
NOTREACHED() << "- Unhandled texture format: " NOTREACHED() << "- Unhandled texure format: " << image->GetFormat();
<< ImageFormatToString(format);
} }
glCompressedTexImage2D(GL_TEXTURE_2D, 0, gl_format, width, height, 0, glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, image->GetWidth(),
data_size, image_data); image->GetHeight(), 0, image->GetSize(),
image->GetBuffer());
// On some devices the first glCompressedTexImage2D call after context-lost // On some devices the first glCompressedTexImage2D call after context-lost
// returns GL_INVALID_VALUE for some reason. // returns GL_INVALID_VALUE for some reason.
GLenum err = glGetError(); GLenum err = glGetError();
if (err == GL_INVALID_VALUE) { if (err == GL_INVALID_VALUE) {
glCompressedTexImage2D(GL_TEXTURE_2D, 0, gl_format, width, height, 0, glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, image->GetWidth(),
data_size, image_data); image->GetHeight(), 0, image->GetSize(),
image->GetBuffer());
err = glGetError(); err = glGetError();
} }
if (err != GL_NO_ERROR) if (err != GL_NO_ERROR)
LOG(0) << "GL ERROR after glCompressedTexImage2D: " << (int)err; LOG(0) << "GL ERROR after glCompressedTexImage2D: " << (int)err;
} else { } else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->GetWidth(),
GL_UNSIGNED_BYTE, image_data); image->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
image->GetBuffer());
} }
} }

View File

@ -55,12 +55,6 @@ class RendererOpenGL final : public Renderer {
uint64_t CreateTexture() final; uint64_t CreateTexture() final;
void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final; void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final;
void UpdateTexture(uint64_t resource_id,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) final;
void DestroyTexture(uint64_t resource_id) final; void DestroyTexture(uint64_t resource_id) final;
void ActivateTexture(uint64_t resource_id, uint64_t texture_unit) final; void ActivateTexture(uint64_t resource_id, uint64_t texture_unit) final;

View File

@ -63,12 +63,6 @@ class Renderer {
virtual uint64_t CreateTexture() = 0; virtual uint64_t CreateTexture() = 0;
virtual void UpdateTexture(uint64_t resource_id, virtual void UpdateTexture(uint64_t resource_id,
std::unique_ptr<Image> image) = 0; std::unique_ptr<Image> image) = 0;
virtual void UpdateTexture(uint64_t resource_id,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) = 0;
virtual void DestroyTexture(uint64_t resource_id) = 0; virtual void DestroyTexture(uint64_t resource_id) = 0;
virtual void ActivateTexture(uint64_t resource_id, uint64_t texture_unit) = 0; virtual void ActivateTexture(uint64_t resource_id, uint64_t texture_unit) = 0;

View File

@ -14,60 +14,6 @@ const char kLayoutDelimiter[] = ";/ \t";
namespace eng { namespace eng {
const char* ImageFormatToString(ImageFormat format) {
switch (format) {
case ImageFormat::kRGBA32:
return "RGBA32";
case ImageFormat::kDXT1:
return "DXT1";
case ImageFormat::kDXT5:
return "DXT5";
case ImageFormat::kETC1:
return "ETC1";
case ImageFormat::kATC:
return "ATC";
case ImageFormat::kATCIA:
return "ATCIA";
default:
NOTREACHED() << "Unknown image format: " << static_cast<int>(format);
return nullptr;
}
}
bool IsCompressedFormat(ImageFormat format) {
switch (format) {
case ImageFormat::kRGBA32:
return false;
case ImageFormat::kDXT1:
case ImageFormat::kDXT5:
case ImageFormat::kETC1:
case ImageFormat::kATC:
case ImageFormat::kATCIA:
return true;
default:
NOTREACHED() << "Unknown image format: " << static_cast<int>(format);
return false;
}
}
size_t GetImageSize(int width, int height, ImageFormat format) {
switch (format) {
case ImageFormat::kRGBA32:
return width * height * 4;
case ImageFormat::kDXT1:
case ImageFormat::kATC:
return ((width + 3) / 4) * ((height + 3) / 4) * 8;
case ImageFormat::kDXT5:
case ImageFormat::kATCIA:
return ((width + 3) / 4) * ((height + 3) / 4) * 16;
case ImageFormat::kETC1:
return (width * height * 4) / 8;
default:
NOTREACHED() << "Unknown image format: " << static_cast<int>(format);
return 0;
}
}
size_t GetVertexSize(const VertexDescription& vertex_description) { size_t GetVertexSize(const VertexDescription& vertex_description) {
size_t size = 0; size_t size = 0;
for (auto& attr : vertex_description) { for (auto& attr : vertex_description) {

View File

@ -7,8 +7,6 @@
namespace eng { namespace eng {
enum class ImageFormat { kRGBA32, kDXT1, kDXT5, kETC1, kATC, kATCIA };
enum Primitive { enum Primitive {
kPrimitive_Invalid = -1, kPrimitive_Invalid = -1,
kPrimitive_Triangles, kPrimitive_Triangles,
@ -43,14 +41,7 @@ using DataTypeSize = size_t;
using VertexDescription = using VertexDescription =
std::vector<std::tuple<AttribType, DataType, ElementCount, DataTypeSize>>; std::vector<std::tuple<AttribType, DataType, ElementCount, DataTypeSize>>;
const char* ImageFormatToString(ImageFormat format);
bool IsCompressedFormat(ImageFormat format);
size_t GetImageSize(int width, int height, ImageFormat format);
size_t GetVertexSize(const VertexDescription& vertex_description); size_t GetVertexSize(const VertexDescription& vertex_description);
size_t GetIndexSize(DataType index_description); size_t GetIndexSize(DataType index_description);
bool ParseVertexDescription(const std::string& vd_str, VertexDescription& out); bool ParseVertexDescription(const std::string& vd_str, VertexDescription& out);

View File

@ -23,8 +23,6 @@
using namespace base; using namespace base;
namespace eng {
namespace { namespace {
// Synchronized with glslang/StandAlone/ResourceLimits.cpp which was removed // Synchronized with glslang/StandAlone/ResourceLimits.cpp which was removed
@ -150,12 +148,12 @@ using VertexInputDescription =
std::pair<std::vector<VkVertexInputBindingDescription>, std::pair<std::vector<VkVertexInputBindingDescription>,
std::vector<VkVertexInputAttributeDescription>>; std::vector<VkVertexInputAttributeDescription>>;
constexpr VkPrimitiveTopology kVkPrimitiveType[kPrimitive_Max] = { constexpr VkPrimitiveTopology kVkPrimitiveType[eng::kPrimitive_Max] = {
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
}; };
constexpr VkFormat kVkDataType[kDataType_Max][4] = { constexpr VkFormat kVkDataType[eng::kDataType_Max][4] = {
{ {
VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM,
VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8_UNORM,
@ -279,7 +277,8 @@ std::vector<uint8_t> CompileGlsl(EShLanguage stage,
return ret; return ret;
} }
VertexInputDescription GetVertexInputDescription(const VertexDescription& vd) { VertexInputDescription GetVertexInputDescription(
const eng::VertexDescription& vd) {
unsigned vertex_offset = 0; unsigned vertex_offset = 0;
unsigned location = 0; unsigned location = 0;
@ -306,13 +305,13 @@ VertexInputDescription GetVertexInputDescription(const VertexDescription& vd) {
return std::make_pair(std::move(bindings), std::move(attributes)); return std::make_pair(std::move(bindings), std::move(attributes));
} }
VkIndexType GetIndexType(DataType data_type) { VkIndexType GetIndexType(eng::DataType data_type) {
switch (data_type) { switch (data_type) {
case kDataType_Invalid: case eng::kDataType_Invalid:
return VK_INDEX_TYPE_NONE_KHR; return VK_INDEX_TYPE_NONE_KHR;
case kDataType_UInt: case eng::kDataType_UInt:
return VK_INDEX_TYPE_UINT32; return VK_INDEX_TYPE_UINT32;
case kDataType_UShort: case eng::kDataType_UShort:
return VK_INDEX_TYPE_UINT16; return VK_INDEX_TYPE_UINT16;
default: default:
break; break;
@ -321,21 +320,21 @@ VkIndexType GetIndexType(DataType data_type) {
return VK_INDEX_TYPE_NONE_KHR; return VK_INDEX_TYPE_NONE_KHR;
} }
VkFormat GetImageFormat(ImageFormat format) { VkFormat GetImageFormat(eng::Image::Format format) {
switch (format) { switch (format) {
case ImageFormat::kRGBA32: case eng::Image::kRGBA32:
return VK_FORMAT_R8G8B8A8_UNORM; return VK_FORMAT_R8G8B8A8_UNORM;
case ImageFormat::kDXT1: case eng::Image::kDXT1:
return VK_FORMAT_BC1_RGB_UNORM_BLOCK; return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
case ImageFormat::kDXT5: case eng::Image::kDXT5:
return VK_FORMAT_BC3_UNORM_BLOCK; return VK_FORMAT_BC3_UNORM_BLOCK;
case ImageFormat::kETC1: case eng::Image::kETC1:
case ImageFormat::kATC: case eng::Image::kATC:
case ImageFormat::kATCIA: case eng::Image::kATCIA:
default: default:
break; break;
} }
NOTREACHED() << "Invalid format: " << ImageFormatToString(format); NOTREACHED() << "Invalid format: " << format;
return VK_FORMAT_R8G8B8A8_UNORM; return VK_FORMAT_R8G8B8A8_UNORM;
} }
@ -372,6 +371,8 @@ std::pair<int, int> GetNumBlocksForImageFormat(VkFormat format,
} // namespace } // namespace
namespace eng {
RendererVulkan::RendererVulkan(base::Closure context_lost_cb) RendererVulkan::RendererVulkan(base::Closure context_lost_cb)
: Renderer(context_lost_cb) {} : Renderer(context_lost_cb) {}
@ -558,27 +559,16 @@ uint64_t RendererVulkan::CreateTexture() {
void RendererVulkan::UpdateTexture(uint64_t resource_id, void RendererVulkan::UpdateTexture(uint64_t resource_id,
std::unique_ptr<Image> image) { std::unique_ptr<Image> image) {
UpdateTexture(resource_id, image->GetWidth(), image->GetHeight(),
image->GetFormat(), image->GetSize(), image->GetBuffer());
task_runner_.Delete(HERE, std::move(image));
semaphore_.release();
}
void RendererVulkan::UpdateTexture(uint64_t resource_id,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) {
auto it = textures_.find(resource_id); auto it = textures_.find(resource_id);
if (it == textures_.end()) if (it == textures_.end())
return; return;
VkImageLayout old_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkImageLayout old_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkFormat vk_format = GetImageFormat(format); VkFormat format = GetImageFormat(image->GetFormat());
if (it->second.view != VK_NULL_HANDLE && if (it->second.view != VK_NULL_HANDLE &&
(it->second.width != width || it->second.height != height)) { (it->second.width != image->GetWidth() ||
it->second.height != image->GetHeight())) {
// Size mismatch. Recreate the texture. // Size mismatch. Recreate the texture.
FreeImage(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));
@ -587,12 +577,12 @@ void RendererVulkan::UpdateTexture(uint64_t resource_id,
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, AllocateImage(it->second.image, it->second.view, it->second.desc_set,
vk_format, width, height, 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);
old_layout = VK_IMAGE_LAYOUT_UNDEFINED; old_layout = VK_IMAGE_LAYOUT_UNDEFINED;
it->second.width = width; it->second.width = image->GetWidth();
it->second.height = height; it->second.height = image->GetHeight();
} }
task_runner_.PostTask( task_runner_.PostTask(
@ -602,9 +592,10 @@ void RendererVulkan::UpdateTexture(uint64_t resource_id,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT,
old_layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)); old_layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL));
task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateImage, this, task_runner_.PostTask(
std::get<0>(it->second.image), HERE, std::bind(&RendererVulkan::UpdateImage, this,
vk_format, image_data, width, height)); std::get<0>(it->second.image), format, image->GetBuffer(),
image->GetWidth(), image->GetHeight()));
task_runner_.PostTask( task_runner_.PostTask(
HERE, HERE,
std::bind(&RendererVulkan::ImageMemoryBarrier, this, std::bind(&RendererVulkan::ImageMemoryBarrier, this,
@ -615,6 +606,7 @@ void RendererVulkan::UpdateTexture(uint64_t resource_id,
0, VK_ACCESS_SHADER_READ_BIT, 0, VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
task_runner_.Delete(HERE, std::move(image));
semaphore_.release(); semaphore_.release();
} }

View File

@ -55,12 +55,6 @@ class RendererVulkan final : public Renderer {
uint64_t CreateTexture() final; uint64_t CreateTexture() final;
void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final; void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final;
void UpdateTexture(uint64_t resource_id,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) final;
void DestroyTexture(uint64_t resource_id) final; void DestroyTexture(uint64_t resource_id) final;
void ActivateTexture(uint64_t resource_id, uint64_t texture_unit) final; void ActivateTexture(uint64_t resource_id, uint64_t texture_unit) final;