From ccb6a9146c4358a6e6644758979ce8e84688b544 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Fri, 5 Feb 2016 15:59:07 -0600 Subject: [PATCH 1/6] Expose microcode data hash in Shader Return paths to files that were dumped from Dump --- src/xenia/gpu/shader.cc | 7 ++++++- src/xenia/gpu/shader.h | 8 ++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/xenia/gpu/shader.cc b/src/xenia/gpu/shader.cc index 3e0be41f9..cf8e43b9d 100644 --- a/src/xenia/gpu/shader.cc +++ b/src/xenia/gpu/shader.cc @@ -16,9 +16,11 @@ #include "xenia/base/math.h" #include "xenia/base/memory.h" #include "xenia/base/string.h" +#include "xenia/gpu/ucode.h" namespace xe { namespace gpu { +using namespace ucode; Shader::Shader(ShaderType shader_type, uint64_t ucode_data_hash, const uint32_t* ucode_dwords, size_t ucode_dword_count) @@ -38,7 +40,8 @@ std::string Shader::GetTranslatedBinaryString() const { return result; } -void Shader::Dump(const std::string& base_path, const char* path_prefix) { +std::pair Shader::Dump(const std::string& base_path, + const char* path_prefix) { // Ensure target path exists. auto target_path = xe::to_wstring(base_path); if (!target_path.empty()) { @@ -79,6 +82,8 @@ void Shader::Dump(const std::string& base_path, const char* path_prefix) { fwrite(ucode_data_.data(), 4, ucode_data_.size(), f); fclose(f); } + + return {std::string(txt_file_name), std::string(bin_file_name)}; } } // namespace gpu diff --git a/src/xenia/gpu/shader.h b/src/xenia/gpu/shader.h index 46f725475..ebe491d65 100644 --- a/src/xenia/gpu/shader.h +++ b/src/xenia/gpu/shader.h @@ -502,6 +502,7 @@ class Shader { // Microcode dwords in host endianness. const std::vector& ucode_data() const { return ucode_data_; } + uint64_t ucode_data_hash() const { return ucode_data_hash_; } const uint32_t* ucode_dwords() const { return ucode_data_.data(); } size_t ucode_dword_count() const { return ucode_data_.size(); } @@ -547,13 +548,12 @@ class Shader { // May be empty if the host does not support saving binaries. const std::vector& host_binary() const { return host_binary_; } - // Prepares the shader for use in the host graphics API. - virtual bool Prepare() { return is_valid_; } - // Dumps the shader to a file in the given path based on ucode hash. // Both the ucode binary and disassembled and translated shader will be // written. - void Dump(const std::string& base_path, const char* path_prefix); + // Returns the filename of the shader and the binary. + std::pair Dump(const std::string& base_path, + const char* path_prefix); protected: friend class ShaderTranslator; From 1066362ada6b45024999753c081b088b8b36647e Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Fri, 5 Feb 2016 16:00:50 -0600 Subject: [PATCH 2/6] ShaderTranslator::GatherAllBindingInformation --- src/xenia/gpu/shader_translator.cc | 37 ++++++++++++++++++++++++++++++ src/xenia/gpu/shader_translator.h | 3 +++ 2 files changed, 40 insertions(+) diff --git a/src/xenia/gpu/shader_translator.cc b/src/xenia/gpu/shader_translator.cc index 11affc7ea..4991833ab 100644 --- a/src/xenia/gpu/shader_translator.cc +++ b/src/xenia/gpu/shader_translator.cc @@ -1,3 +1,4 @@ +#include "shader_translator.h" /** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * @@ -57,6 +58,41 @@ void ShaderTranslator::Reset() { } } +bool ShaderTranslator::GatherAllBindingInformation(Shader* shader) { + // FIXME: This is kind of silly. + Reset(); + + shader_type_ = shader->type(); + ucode_dwords_ = shader->ucode_dwords(); + ucode_dword_count_ = shader->ucode_dword_count(); + + uint32_t max_cf_dword_index = static_cast(ucode_dword_count_); + for (uint32_t i = 0; i < max_cf_dword_index; i += 3) { + ControlFlowInstruction cf_a; + ControlFlowInstruction cf_b; + UnpackControlFlowInstructions(ucode_dwords_ + i, &cf_a, &cf_b); + if (IsControlFlowOpcodeExec(cf_a.opcode())) { + max_cf_dword_index = + std::min(max_cf_dword_index, cf_a.exec.address() * 3); + } + if (IsControlFlowOpcodeExec(cf_b.opcode())) { + max_cf_dword_index = + std::min(max_cf_dword_index, cf_b.exec.address() * 3); + } + + GatherBindingInformation(cf_a); + GatherBindingInformation(cf_b); + } + + shader->vertex_bindings_ = std::move(vertex_bindings_); + shader->texture_bindings_ = std::move(texture_bindings_); + for (size_t i = 0; i < xe::countof(writes_color_targets_); ++i) { + shader->writes_color_targets_[i] = writes_color_targets_[i]; + } + + return true; +} + bool ShaderTranslator::Translate(Shader* shader) { Reset(); @@ -79,6 +115,7 @@ bool ShaderTranslator::Translate(Shader* shader) { max_cf_dword_index = std::min(max_cf_dword_index, cf_b.exec.address() * 3); } + GatherBindingInformation(cf_a); GatherBindingInformation(cf_b); } diff --git a/src/xenia/gpu/shader_translator.h b/src/xenia/gpu/shader_translator.h index adf8f449d..d1d731926 100644 --- a/src/xenia/gpu/shader_translator.h +++ b/src/xenia/gpu/shader_translator.h @@ -26,6 +26,9 @@ class ShaderTranslator { public: virtual ~ShaderTranslator(); + // Gathers all vertex/texture bindings. Implicitly called in Translate. + // TODO: Move this functionality to Shader. + bool GatherAllBindingInformation(Shader* shader); bool Translate(Shader* shader); protected: From e9dd0ce9deea4b55d5b36e13424bdb8a9ff3a365 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Fri, 5 Feb 2016 16:02:14 -0600 Subject: [PATCH 3/6] GL4Shader load from binary support --- src/xenia/gpu/gl4/gl4_shader.cc | 43 ++++++++++++++++++++++++++++++--- src/xenia/gpu/gl4/gl4_shader.h | 5 ++-- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/xenia/gpu/gl4/gl4_shader.cc b/src/xenia/gpu/gl4/gl4_shader.cc index 52e2b9c4b..7f34b1957 100644 --- a/src/xenia/gpu/gl4/gl4_shader.cc +++ b/src/xenia/gpu/gl4/gl4_shader.cc @@ -51,6 +51,37 @@ bool GL4Shader::Prepare() { return success; } +bool GL4Shader::LoadFromBinary(const uint8_t* blob, GLenum binary_format, + size_t length) { + program_ = glCreateProgram(); + glProgramBinary(program_, binary_format, blob, GLsizei(length)); + + GLint link_status = 0; + glGetProgramiv(program_, GL_LINK_STATUS, &link_status); + if (!link_status) { + // Failed to link. Not fatal - just clean up so we can get generated later. + XELOGD("GL4Shader::LoadFromBinary failed. Log:\n%s", + GetProgramInfoLog().c_str()); + glDeleteProgram(program_); + program_ = 0; + + return false; + } + + // Build static vertex array descriptor. + if (!PrepareVertexArrayObject()) { + XELOGE("Unable to prepare vertex shader array object"); + return false; + } + + // Success! + host_binary_ = GetBinary(); + host_disassembly_ = GetHostDisasmNV(host_binary_); + + is_valid_ = true; + return true; +} + bool GL4Shader::PrepareVertexArrayObject() { glCreateVertexArrays(1, &vao_); @@ -211,7 +242,7 @@ std::string GL4Shader::GetProgramInfoLog() { return log; } -std::vector GL4Shader::GetBinary() { +std::vector GL4Shader::GetBinary(GLenum* binary_format) { std::vector binary; // Get program binary, if it's available. @@ -219,9 +250,13 @@ std::vector GL4Shader::GetBinary() { glGetProgramiv(program_, GL_PROGRAM_BINARY_LENGTH, &binary_length); if (binary_length) { binary.resize(binary_length); - GLenum binary_format; - glGetProgramBinary(program_, binary_length, &binary_length, &binary_format, - binary.data()); + GLenum binary_format_tmp = 0; + glGetProgramBinary(program_, binary_length, &binary_length, + &binary_format_tmp, binary.data()); + + if (binary_format) { + *binary_format = binary_format_tmp; + } } return binary; diff --git a/src/xenia/gpu/gl4/gl4_shader.h b/src/xenia/gpu/gl4/gl4_shader.h index 91b1e6098..1f884ebf2 100644 --- a/src/xenia/gpu/gl4/gl4_shader.h +++ b/src/xenia/gpu/gl4/gl4_shader.h @@ -29,7 +29,9 @@ class GL4Shader : public Shader { GLuint shader() const { return shader_; } GLuint vao() const { return vao_; } - bool Prepare() override; + bool Prepare(); + bool LoadFromBinary(const uint8_t* blob, GLenum binary_format, size_t length); + std::vector GetBinary(GLenum* binary_format = nullptr); protected: bool PrepareVertexArrayObject(); @@ -38,7 +40,6 @@ class GL4Shader : public Shader { std::string GetShaderInfoLog(); std::string GetProgramInfoLog(); - std::vector GetBinary(); static std::string GetHostDisasmNV(const std::vector& binary); GLuint program_ = 0; From 406ec8c6da7f4a248fffe144fc22ccabeb1e92b6 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Fri, 5 Feb 2016 16:11:00 -0600 Subject: [PATCH 4/6] GL4ShaderCache util class - caching to filesystem disabled by default --- src/xenia/gpu/gl4/gl4_gpu_flags.cc | 3 + src/xenia/gpu/gl4/gl4_gpu_flags.h | 1 + src/xenia/gpu/gl4/gl4_shader_cache.cc | 187 ++++++++++++++++++++++++++ src/xenia/gpu/gl4/gl4_shader_cache.h | 60 +++++++++ 4 files changed, 251 insertions(+) create mode 100644 src/xenia/gpu/gl4/gl4_shader_cache.cc create mode 100644 src/xenia/gpu/gl4/gl4_shader_cache.h diff --git a/src/xenia/gpu/gl4/gl4_gpu_flags.cc b/src/xenia/gpu/gl4/gl4_gpu_flags.cc index 213f38ca7..3844bfc95 100644 --- a/src/xenia/gpu/gl4/gl4_gpu_flags.cc +++ b/src/xenia/gpu/gl4/gl4_gpu_flags.cc @@ -12,3 +12,6 @@ DEFINE_bool(disable_framebuffer_readback, false, "Disable framebuffer readback."); DEFINE_bool(disable_textures, false, "Disable textures and use colors only."); +DEFINE_string(shader_cache_dir, "", + "GL4 Shader cache directory (relative to Xenia). Specify an " + "empty string to disable the cache."); diff --git a/src/xenia/gpu/gl4/gl4_gpu_flags.h b/src/xenia/gpu/gl4/gl4_gpu_flags.h index 31ef901a9..9f68287f9 100644 --- a/src/xenia/gpu/gl4/gl4_gpu_flags.h +++ b/src/xenia/gpu/gl4/gl4_gpu_flags.h @@ -14,6 +14,7 @@ DECLARE_bool(disable_framebuffer_readback); DECLARE_bool(disable_textures); +DECLARE_string(shader_cache_dir); #define FINE_GRAINED_DRAW_SCOPES 0 diff --git a/src/xenia/gpu/gl4/gl4_shader_cache.cc b/src/xenia/gpu/gl4/gl4_shader_cache.cc new file mode 100644 index 000000000..008c36d71 --- /dev/null +++ b/src/xenia/gpu/gl4/gl4_shader_cache.cc @@ -0,0 +1,187 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/gpu/gl4/gl4_shader_cache.h" + +#include + +#include "xenia/base/filesystem.h" +#include "xenia/base/logging.h" +#include "xenia/base/mapped_memory.h" +#include "xenia/gpu/glsl_shader_translator.h" +#include "xenia/gpu/gl4/gl4_gpu_flags.h" +#include "xenia/gpu/gl4/gl4_shader.h" +#include "xenia/gpu/gpu_flags.h" + +#include "third_party/xxhash/xxhash.h" + +namespace xe { +namespace gpu { +namespace gl4 { + +GL4ShaderCache::GL4ShaderCache(GlslShaderTranslator* shader_translator) + : shader_translator_(shader_translator) {} + +GL4ShaderCache::~GL4ShaderCache() {} + +void GL4ShaderCache::Reset() { + shader_map_.clear(); + all_shaders_.clear(); +} + +GL4Shader* GL4ShaderCache::LookupOrInsertShader(ShaderType shader_type, + const uint32_t* dwords, + uint32_t dword_count) { + // Hash the input memory and lookup the shader. + GL4Shader* shader_ptr = nullptr; + uint64_t hash = XXH64(dwords, dword_count * sizeof(uint32_t), 0); + auto it = shader_map_.find(hash); + if (it != shader_map_.end()) { + // Shader has been previously loaded. + // TODO(benvanik): compare bytes? Likelihood of collision is low. + shader_ptr = it->second; + } else { + // Check filesystem cache. + shader_ptr = FindCachedShader(shader_type, hash, dwords, dword_count); + if (shader_ptr) { + // Found! + XELOGGPU("Loaded %s shader from cache (hash: %.16" PRIX64 ")", + shader_type == ShaderType::kVertex ? "vertex" : "pixel", hash); + return shader_ptr; + } + + // Not found in cache - load from scratch. + auto shader = + std::make_unique(shader_type, hash, dwords, dword_count); + shader_ptr = shader.get(); + shader_map_.insert({hash, shader_ptr}); + all_shaders_.emplace_back(std::move(shader)); + + // Perform translation. + // If this fails the shader will be marked as invalid and ignored later. + if (shader_translator_->Translate(shader_ptr)) { + shader_ptr->Prepare(); + if (shader_ptr->is_valid()) { + CacheShader(shader_ptr); + + XELOGGPU("Generated %s shader at 0x%.16" PRIX64 " (%db):\n%s", + shader_type == ShaderType::kVertex ? "vertex" : "pixel", + dwords, dword_count * 4, + shader_ptr->ucode_disassembly().c_str()); + } + + // Dump shader files if desired. + if (!FLAGS_dump_shaders.empty()) { + shader_ptr->Dump(FLAGS_dump_shaders, "gl4"); + } + } else { + XELOGE("Shader failed translation"); + } + } + + return shader_ptr; +} + +void GL4ShaderCache::CacheShader(GL4Shader* shader) { + if (FLAGS_shader_cache_dir.empty()) { + // Cache disabled. + return; + } + + GLenum binary_format = 0; + auto binary = shader->GetBinary(&binary_format); + if (binary.size() == 0) { + // No binary returned. + return; + } + + auto cache_dir = xe::to_absolute_path(xe::to_wstring(FLAGS_shader_cache_dir)); + xe::filesystem::CreateFolder(cache_dir); + auto filename = + cache_dir + xe::format_string( + L"%.16" PRIX64 ".%s", shader->ucode_data_hash(), + shader->type() == ShaderType::kPixel ? L"frag" : L"vert"); + auto file = xe::filesystem::OpenFile(filename, "wb"); + if (!file) { + // Not fatal, but not too good. + return; + } + + std::vector cached_shader_mem; + // Resize this vector to the final filesize (- 1 to account for dummy array + // in CachedShader) + cached_shader_mem.resize(sizeof(CachedShader) + binary.size() - 1); + auto cached_shader = + reinterpret_cast(cached_shader_mem.data()); + cached_shader->magic = xe::byte_swap('XSHD'); + cached_shader->version = 0; // TODO + cached_shader->shader_type = uint8_t(shader->type()); + cached_shader->binary_len = uint32_t(binary.size()); + cached_shader->binary_format = binary_format; + std::memcpy(cached_shader->binary, binary.data(), binary.size()); + + fwrite(cached_shader_mem.data(), cached_shader_mem.size(), 1, file); + fclose(file); +} + +GL4Shader* GL4ShaderCache::FindCachedShader(ShaderType shader_type, + uint64_t hash, + const uint32_t* dwords, + uint32_t dword_count) { + if (FLAGS_shader_cache_dir.empty()) { + // Cache disabled. + return nullptr; + } + + auto cache_dir = xe::to_absolute_path(xe::to_wstring(FLAGS_shader_cache_dir)); + auto filename = + cache_dir + + xe::format_string(L"%.16" PRIX64 ".%s", hash, + shader_type == ShaderType::kPixel ? L"frag" : L"vert"); + if (!xe::filesystem::PathExists(filename)) { + return nullptr; + } + + // Shader is cached. Open it up. + auto map = xe::MappedMemory::Open(filename, MappedMemory::Mode::kRead); + if (!map) { + // Should not fail + assert_always(); + return nullptr; + } + + auto cached_shader = reinterpret_cast(map->data()); + // TODO: Compare versions + if (cached_shader->magic != xe::byte_swap('XSHD')) { + return nullptr; + } + + auto shader = + std::make_unique(shader_type, hash, dwords, dword_count); + + // Gather the binding points. + // TODO: Make Shader do this on construction. + // TODO: Regenerate microcode disasm/etc on load. + shader_translator_->GatherAllBindingInformation(shader.get()); + if (!shader->LoadFromBinary(cached_shader->binary, + cached_shader->binary_format, + cached_shader->binary_len)) { + // Failed to load from binary. + return nullptr; + } + + auto shader_ptr = shader.get(); + shader_map_.insert({hash, shader_ptr}); + all_shaders_.emplace_back(std::move(shader)); + return shader_ptr; +} + +} // namespace gl4 +} // namespace gpu +} // namespace xe \ No newline at end of file diff --git a/src/xenia/gpu/gl4/gl4_shader_cache.h b/src/xenia/gpu/gl4/gl4_shader_cache.h new file mode 100644 index 000000000..33155d2ed --- /dev/null +++ b/src/xenia/gpu/gl4/gl4_shader_cache.h @@ -0,0 +1,60 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_GPU_GL4_SHADER_CACHE_H_ +#define XENIA_GPU_GL4_SHADER_CACHE_H_ + +#include +#include +#include + +#include "xenia/gpu/xenos.h" + +namespace xe { +namespace gpu { +class GlslShaderTranslator; + +namespace gl4 { + +class GL4Shader; + +class GL4ShaderCache { + public: + GL4ShaderCache(GlslShaderTranslator* shader_translator); + ~GL4ShaderCache(); + + void Reset(); + GL4Shader* LookupOrInsertShader(ShaderType shader_type, + const uint32_t* dwords, uint32_t dword_count); + + private: + // Cached shader file format. + struct CachedShader { + uint32_t magic; + uint32_t version; // Version of the shader translator used. + uint8_t shader_type; // ShaderType enum + uint32_t binary_len; // Code length + uint32_t binary_format; // Binary format (from OpenGL) + uint8_t binary[1]; // Code + }; + + void CacheShader(GL4Shader* shader); + GL4Shader* FindCachedShader(ShaderType shader_type, uint64_t hash, + const uint32_t* dwords, uint32_t dword_count); + + GlslShaderTranslator* shader_translator_ = nullptr; + std::vector> all_shaders_; + std::unordered_map shader_map_; +}; + +} // namespace gl4 +} // namespace gpu +} // namespace xe + +#endif // XENIA_GPU_GL4_SHADER_CACHE_H_ \ No newline at end of file From 6cb7f0c23dd88908fc54b65e9e43429d872e0c0f Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Fri, 5 Feb 2016 16:14:35 -0600 Subject: [PATCH 5/6] GL4CommandProcessor: Use the new GL4ShaderCache --- src/xenia/gpu/gl4/gl4_command_processor.cc | 43 +++------------------- src/xenia/gpu/gl4/gl4_command_processor.h | 4 +- 2 files changed, 7 insertions(+), 40 deletions(-) diff --git a/src/xenia/gpu/gl4/gl4_command_processor.cc b/src/xenia/gpu/gl4/gl4_command_processor.cc index 31499a021..85de39460 100644 --- a/src/xenia/gpu/gl4/gl4_command_processor.cc +++ b/src/xenia/gpu/gl4/gl4_command_processor.cc @@ -56,7 +56,8 @@ GL4CommandProcessor::GL4CommandProcessor(GL4GraphicsSystem* graphics_system, : CommandProcessor(graphics_system, kernel_state), shader_translator_(GlslShaderTranslator::Dialect::kGL45), draw_batcher_(graphics_system_->register_file()), - scratch_buffer_(kScratchBufferCapacity, kScratchBufferAlignment) {} + scratch_buffer_(kScratchBufferCapacity, kScratchBufferAlignment), + shader_cache_(&shader_translator_) {} GL4CommandProcessor::~GL4CommandProcessor() = default; @@ -324,8 +325,7 @@ void GL4CommandProcessor::ShutdownContext() { scratch_buffer_.Shutdown(); all_pipelines_.clear(); - all_shaders_.clear(); - shader_cache_.clear(); + shader_cache_.Reset(); CommandProcessor::ShutdownContext(); } @@ -484,41 +484,8 @@ Shader* GL4CommandProcessor::LoadShader(ShaderType shader_type, uint32_t guest_address, const uint32_t* host_address, uint32_t dword_count) { - // Hash the input memory and lookup the shader. - GL4Shader* shader_ptr = nullptr; - uint64_t hash = XXH64(host_address, dword_count * sizeof(uint32_t), 0); - auto it = shader_cache_.find(hash); - if (it != shader_cache_.end()) { - // Found in the cache. - // TODO(benvanik): compare bytes? Likelyhood of collision is low. - shader_ptr = it->second; - } else { - // Not found in cache. - auto shader = std::make_unique(shader_type, hash, host_address, - dword_count); - shader_ptr = shader.get(); - shader_cache_.insert({hash, shader_ptr}); - all_shaders_.emplace_back(std::move(shader)); - - // Perform translation. - // If this fails the shader will be marked as invalid and ignored later. - if (shader_translator_.Translate(shader_ptr)) { - shader_ptr->Prepare(); - - // Dump shader files if desired. - if (!FLAGS_dump_shaders.empty()) { - shader_ptr->Dump(FLAGS_dump_shaders, "gl4"); - } - } else { - XELOGE("Shader failed translation"); - } - - XELOGGPU("Set %s shader at %0.8X (%db):\n%s", - shader_type == ShaderType::kVertex ? "vertex" : "pixel", - guest_address, dword_count * 4, - shader_ptr->ucode_disassembly().c_str()); - } - return shader_ptr; + return shader_cache_.LookupOrInsertShader(shader_type, host_address, + dword_count); } bool GL4CommandProcessor::IssueDraw(PrimitiveType prim_type, diff --git a/src/xenia/gpu/gl4/gl4_command_processor.h b/src/xenia/gpu/gl4/gl4_command_processor.h index 1d3d3e6c9..46bbd984d 100644 --- a/src/xenia/gpu/gl4/gl4_command_processor.h +++ b/src/xenia/gpu/gl4/gl4_command_processor.h @@ -23,6 +23,7 @@ #include "xenia/base/threading.h" #include "xenia/gpu/command_processor.h" #include "xenia/gpu/gl4/draw_batcher.h" +#include "xenia/gpu/gl4/gl4_shader_cache.h" #include "xenia/gpu/gl4/gl4_shader.h" #include "xenia/gpu/gl4/texture_cache.h" #include "xenia/gpu/glsl_shader_translator.h" @@ -131,8 +132,7 @@ class GL4CommandProcessor : public CommandProcessor { GLuint depth_target); GlslShaderTranslator shader_translator_; - std::vector> all_shaders_; - std::unordered_map shader_cache_; + GL4ShaderCache shader_cache_; CachedFramebuffer* active_framebuffer_ = nullptr; GLuint last_framebuffer_texture_ = 0; From a64e53fba6bf95852b1d09bc453de0199dcbbc17 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Fri, 5 Feb 2016 16:31:01 -0600 Subject: [PATCH 6/6] Fix include order. --- src/xenia/gpu/gl4/gl4_command_processor.h | 2 +- src/xenia/gpu/gl4/gl4_shader_cache.cc | 2 +- src/xenia/gpu/gl4/gl4_shader_cache.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/xenia/gpu/gl4/gl4_command_processor.h b/src/xenia/gpu/gl4/gl4_command_processor.h index 46bbd984d..13ac5f57f 100644 --- a/src/xenia/gpu/gl4/gl4_command_processor.h +++ b/src/xenia/gpu/gl4/gl4_command_processor.h @@ -23,8 +23,8 @@ #include "xenia/base/threading.h" #include "xenia/gpu/command_processor.h" #include "xenia/gpu/gl4/draw_batcher.h" -#include "xenia/gpu/gl4/gl4_shader_cache.h" #include "xenia/gpu/gl4/gl4_shader.h" +#include "xenia/gpu/gl4/gl4_shader_cache.h" #include "xenia/gpu/gl4/texture_cache.h" #include "xenia/gpu/glsl_shader_translator.h" #include "xenia/gpu/register_file.h" diff --git a/src/xenia/gpu/gl4/gl4_shader_cache.cc b/src/xenia/gpu/gl4/gl4_shader_cache.cc index 008c36d71..033ed1b5e 100644 --- a/src/xenia/gpu/gl4/gl4_shader_cache.cc +++ b/src/xenia/gpu/gl4/gl4_shader_cache.cc @@ -14,9 +14,9 @@ #include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/mapped_memory.h" -#include "xenia/gpu/glsl_shader_translator.h" #include "xenia/gpu/gl4/gl4_gpu_flags.h" #include "xenia/gpu/gl4/gl4_shader.h" +#include "xenia/gpu/glsl_shader_translator.h" #include "xenia/gpu/gpu_flags.h" #include "third_party/xxhash/xxhash.h" diff --git a/src/xenia/gpu/gl4/gl4_shader_cache.h b/src/xenia/gpu/gl4/gl4_shader_cache.h index 33155d2ed..7bac4c084 100644 --- a/src/xenia/gpu/gl4/gl4_shader_cache.h +++ b/src/xenia/gpu/gl4/gl4_shader_cache.h @@ -11,8 +11,8 @@ #define XENIA_GPU_GL4_SHADER_CACHE_H_ #include -#include #include +#include #include "xenia/gpu/xenos.h"