From 16cb00c521cae6e93ec49d10e15b575b7bc4857e Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Fri, 5 Feb 2021 23:11:23 -0300
Subject: shader: Add pools and rename files

---
 src/shader_recompiler/frontend/maxwell/opcodes.cpp | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 src/shader_recompiler/frontend/maxwell/opcodes.cpp

(limited to 'src/shader_recompiler/frontend/maxwell/opcodes.cpp')

diff --git a/src/shader_recompiler/frontend/maxwell/opcodes.cpp b/src/shader_recompiler/frontend/maxwell/opcodes.cpp
new file mode 100644
index 0000000000..12ddf2ac95
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/opcodes.cpp
@@ -0,0 +1,26 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <array>
+
+#include "shader_recompiler/exception.h"
+#include "shader_recompiler/frontend/maxwell/opcodes.h"
+
+namespace Shader::Maxwell {
+namespace {
+constexpr std::array NAME_TABLE{
+#define INST(name, cute, encode) #cute,
+#include "maxwell.inc"
+#undef INST
+};
+} // Anonymous namespace
+
+const char* NameOf(Opcode opcode) {
+    if (static_cast<size_t>(opcode) >= NAME_TABLE.size()) {
+        throw InvalidArgument("Invalid opcode with raw value {}", static_cast<int>(opcode));
+    }
+    return NAME_TABLE[static_cast<size_t>(opcode)];
+}
+
+} // namespace Shader::Maxwell
-- 
cgit v1.2.3-70-g09d2


From b7764c3a796e53ac74009bc7d7cd153c64b6d743 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Thu, 27 May 2021 17:51:00 -0300
Subject: shader: Handle host exceptions

---
 src/shader_recompiler/exception.h                  | 40 ++++++++++++++++----
 src/shader_recompiler/frontend/maxwell/opcodes.cpp |  2 +-
 src/shader_recompiler/frontend/maxwell/program.cpp |  1 +
 .../frontend/maxwell/translate/translate.cpp       | 13 +++++--
 src/video_core/renderer_opengl/gl_rasterizer.cpp   |  4 +-
 src/video_core/renderer_opengl/gl_shader_cache.cpp | 43 +++++++++++++---------
 src/video_core/renderer_opengl/gl_shader_cache.h   |  5 +--
 .../renderer_vulkan/vk_pipeline_cache.cpp          | 35 ++++++++++++------
 8 files changed, 98 insertions(+), 45 deletions(-)

(limited to 'src/shader_recompiler/frontend/maxwell/opcodes.cpp')

diff --git a/src/shader_recompiler/exception.h b/src/shader_recompiler/exception.h
index 6fe620801d..013d7b1bfe 100644
--- a/src/shader_recompiler/exception.h
+++ b/src/shader_recompiler/exception.h
@@ -5,38 +5,62 @@
 #pragma once
 
 #include <stdexcept>
+#include <string>
+#include <string_view>
 #include <utility>
 
 #include <fmt/format.h>
 
 namespace Shader {
 
-class LogicError : public std::logic_error {
+class Exception : public std::exception {
+public:
+    explicit Exception(std::string message_) noexcept : message{std::move(message_)} {}
+
+    const char* what() const override {
+        return message.c_str();
+    }
+
+    void Prepend(std::string_view prepend) {
+        message.insert(0, prepend);
+    }
+
+    void Append(std::string_view append) {
+        message += append;
+    }
+
+private:
+    std::string message;
+};
+
+class LogicError : public Exception {
 public:
     template <typename... Args>
     LogicError(const char* message, Args&&... args)
-        : std::logic_error{fmt::format(message, std::forward<Args>(args)...)} {}
+        : Exception{fmt::format(message, std::forward<Args>(args)...)} {}
 };
 
-class RuntimeError : public std::runtime_error {
+class RuntimeError : public Exception {
 public:
     template <typename... Args>
     RuntimeError(const char* message, Args&&... args)
-        : std::runtime_error{fmt::format(message, std::forward<Args>(args)...)} {}
+        : Exception{fmt::format(message, std::forward<Args>(args)...)} {}
 };
 
-class NotImplementedException : public std::logic_error {
+class NotImplementedException : public Exception {
 public:
     template <typename... Args>
     NotImplementedException(const char* message, Args&&... args)
-        : std::logic_error{fmt::format(message, std::forward<Args>(args)...)} {}
+        : Exception{fmt::format(message, std::forward<Args>(args)...)} {
+        Append(" is not implemented");
+    }
 };
 
-class InvalidArgument : public std::invalid_argument {
+class InvalidArgument : public Exception {
 public:
     template <typename... Args>
     InvalidArgument(const char* message, Args&&... args)
-        : std::invalid_argument{fmt::format(message, std::forward<Args>(args)...)} {}
+        : Exception{fmt::format(message, std::forward<Args>(args)...)} {}
 };
 
 } // namespace Shader
diff --git a/src/shader_recompiler/frontend/maxwell/opcodes.cpp b/src/shader_recompiler/frontend/maxwell/opcodes.cpp
index 12ddf2ac95..ccc40c20c1 100644
--- a/src/shader_recompiler/frontend/maxwell/opcodes.cpp
+++ b/src/shader_recompiler/frontend/maxwell/opcodes.cpp
@@ -10,7 +10,7 @@
 namespace Shader::Maxwell {
 namespace {
 constexpr std::array NAME_TABLE{
-#define INST(name, cute, encode) #cute,
+#define INST(name, cute, encode) cute,
 #include "maxwell.inc"
 #undef INST
 };
diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp
index ccdab1dad1..900fc7ab1b 100644
--- a/src/shader_recompiler/frontend/maxwell/program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/program.cpp
@@ -7,6 +7,7 @@
 #include <ranges>
 #include <vector>
 
+#include "shader_recompiler/exception.h"
 #include "shader_recompiler/frontend/ir/basic_block.h"
 #include "shader_recompiler/frontend/ir/post_order.h"
 #include "shader_recompiler/frontend/maxwell/program.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/translate.cpp b/src/shader_recompiler/frontend/maxwell/translate/translate.cpp
index 0f4e7a251a..8e3c4c5d5c 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/translate.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/translate.cpp
@@ -30,16 +30,21 @@ void Translate(Environment& env, IR::Block* block, u32 location_begin, u32 locat
     TranslatorVisitor visitor{env, *block};
     for (Location pc = location_begin; pc != location_end; ++pc) {
         const u64 insn{env.ReadInstruction(pc.Offset())};
-        const Opcode opcode{Decode(insn)};
-        switch (opcode) {
+        try {
+            const Opcode opcode{Decode(insn)};
+            switch (opcode) {
 #define INST(name, cute, mask)                                                                     \
     case Opcode::name:                                                                             \
         Invoke<&TranslatorVisitor::name>(visitor, pc, insn);                                       \
         break;
 #include "shader_recompiler/frontend/maxwell/maxwell.inc"
 #undef OPCODE
-        default:
-            throw LogicError("Invalid opcode {}", opcode);
+            default:
+                throw LogicError("Invalid opcode {}", opcode);
+            }
+        } catch (Exception& exception) {
+            exception.Prepend(fmt::format("Translate {}: ", Decode(insn)));
+            throw;
         }
     }
 }
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 5d4e80364a..54696d97de 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -221,7 +221,9 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
     SyncState();
 
     GraphicsPipeline* const pipeline{shader_cache.CurrentGraphicsPipeline()};
-
+    if (!pipeline) {
+        return;
+    }
     std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
     pipeline->Configure(is_indexed);
 
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 287f497b52..7d2ec4efa1 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -45,6 +45,7 @@ using VideoCommon::ComputeEnvironment;
 using VideoCommon::FileEnvironment;
 using VideoCommon::GenericEnvironment;
 using VideoCommon::GraphicsEnvironment;
+using VideoCommon::SerializePipeline;
 
 template <typename Container>
 auto MakeSpan(Container& container) {
@@ -327,10 +328,11 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
         workers.QueueWork(
             [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
                 ctx->pools.ReleaseContents();
-                auto pipeline{CreateComputePipeline(ctx->pools, key, env, false)};
-
+                auto pipeline{CreateComputePipeline(ctx->pools, key, env)};
                 std::lock_guard lock{state.mutex};
-                compute_cache.emplace(key, std::move(pipeline));
+                if (pipeline) {
+                    compute_cache.emplace(key, std::move(pipeline));
+                }
                 ++state.built;
                 if (state.has_loaded) {
                     callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
@@ -348,10 +350,11 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
                     env_ptrs.push_back(&env);
                 }
                 ctx->pools.ReleaseContents();
-                auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)};
-
+                auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs))};
                 std::lock_guard lock{state.mutex};
-                graphics_cache.emplace(key, std::move(pipeline));
+                if (pipeline) {
+                    graphics_cache.emplace(key, std::move(pipeline));
+                }
                 ++state.built;
                 if (state.has_loaded) {
                     callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
@@ -419,8 +422,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline() {
     GetGraphicsEnvironments(environments, graphics_key.unique_hashes);
 
     main_pools.ReleaseContents();
-    auto pipeline{CreateGraphicsPipeline(main_pools, graphics_key, environments.Span(), true)};
-    if (shader_cache_filename.empty()) {
+    auto pipeline{CreateGraphicsPipeline(main_pools, graphics_key, environments.Span())};
+    if (!pipeline || shader_cache_filename.empty()) {
         return pipeline;
     }
     boost::container::static_vector<const GenericEnvironment*, Maxwell::MaxShaderProgram> env_ptrs;
@@ -429,13 +432,13 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline() {
             env_ptrs.push_back(&environments.envs[index]);
         }
     }
-    VideoCommon::SerializePipeline(graphics_key, env_ptrs, shader_cache_filename);
+    SerializePipeline(graphics_key, env_ptrs, shader_cache_filename);
     return pipeline;
 }
 
 std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
-    ShaderPools& pools, const GraphicsPipelineKey& key, std::span<Shader::Environment* const> envs,
-    bool build_in_parallel) {
+    ShaderPools& pools, const GraphicsPipelineKey& key,
+    std::span<Shader::Environment* const> envs) try {
     LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash());
     size_t env_index{};
     u32 total_storage_buffers{};
@@ -492,6 +495,10 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
         device, texture_cache, buffer_cache, gpu_memory, maxwell3d, program_manager, state_tracker,
         std::move(source_program), std::move(assembly_programs), infos,
         key.xfb_enabled != 0 ? &key.xfb_state : nullptr);
+
+} catch (Shader::Exception& exception) {
+    LOG_ERROR(Render_OpenGL, "{}", exception.what());
+    return nullptr;
 }
 
 std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
@@ -502,18 +509,17 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
     env.SetCachedSize(shader->size_bytes);
 
     main_pools.ReleaseContents();
-    auto pipeline{CreateComputePipeline(main_pools, key, env, true)};
-    if (!shader_cache_filename.empty()) {
-        VideoCommon::SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env},
-                                       shader_cache_filename);
+    auto pipeline{CreateComputePipeline(main_pools, key, env)};
+    if (!pipeline || shader_cache_filename.empty()) {
+        return pipeline;
     }
+    SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env}, shader_cache_filename);
     return pipeline;
 }
 
 std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools& pools,
                                                                     const ComputePipelineKey& key,
-                                                                    Shader::Environment& env,
-                                                                    bool build_in_parallel) {
+                                                                    Shader::Environment& env) try {
     LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash());
 
     Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()};
@@ -540,6 +546,9 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools&
     return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, gpu_memory,
                                              kepler_compute, program_manager, program.info,
                                              std::move(source_program), std::move(asm_program));
+} catch (Shader::Exception& exception) {
+    LOG_ERROR(Render_OpenGL, "{}", exception.what());
+    return nullptr;
 }
 
 } // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index 16175318b6..cf74d34e4d 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -65,15 +65,14 @@ private:
 
     std::unique_ptr<GraphicsPipeline> CreateGraphicsPipeline(
         ShaderPools& pools, const GraphicsPipelineKey& key,
-        std::span<Shader::Environment* const> envs, bool build_in_parallel);
+        std::span<Shader::Environment* const> envs);
 
     std::unique_ptr<ComputePipeline> CreateComputePipeline(const ComputePipelineKey& key,
                                                            const VideoCommon::ShaderInfo* shader);
 
     std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderPools& pools,
                                                            const ComputePipelineKey& key,
-                                                           Shader::Environment& env,
-                                                           bool build_in_parallel);
+                                                           Shader::Environment& env);
 
     Core::Frontend::EmuWindow& emu_window;
     const Device& device;
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index f86bf9c306..b6998e37ce 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -303,6 +303,9 @@ GraphicsPipeline* PipelineCache::CurrentGraphicsPipeline() {
     if (is_new) {
         pipeline = CreateGraphicsPipeline();
     }
+    if (!pipeline) {
+        return nullptr;
+    }
     if (current_pipeline) {
         current_pipeline->AddTransition(pipeline.get());
     }
@@ -362,9 +365,10 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
         workers.QueueWork([this, key, env = std::move(env), &state, &callback]() mutable {
             ShaderPools pools;
             auto pipeline{CreateComputePipeline(pools, key, env, false)};
-
             std::lock_guard lock{state.mutex};
-            compute_cache.emplace(key, std::move(pipeline));
+            if (pipeline) {
+                compute_cache.emplace(key, std::move(pipeline));
+            }
             ++state.built;
             if (state.has_loaded) {
                 callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
@@ -405,7 +409,7 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
 
 std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
     ShaderPools& pools, const GraphicsPipelineCacheKey& key,
-    std::span<Shader::Environment* const> envs, bool build_in_parallel) {
+    std::span<Shader::Environment* const> envs, bool build_in_parallel) try {
     LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash());
     size_t env_index{0};
     std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs;
@@ -458,6 +462,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
     return std::make_unique<GraphicsPipeline>(
         maxwell3d, gpu_memory, scheduler, buffer_cache, texture_cache, device, descriptor_pool,
         update_descriptor_queue, thread_worker, render_pass_cache, key, std::move(modules), infos);
+
+} catch (const Shader::Exception& exception) {
+    LOG_ERROR(Render_Vulkan, "{}", exception.what());
+    return nullptr;
 }
 
 std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline() {
@@ -466,7 +474,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline() {
 
     main_pools.ReleaseContents();
     auto pipeline{CreateGraphicsPipeline(main_pools, graphics_key, environments.Span(), true)};
-    if (pipeline_cache_filename.empty()) {
+    if (!pipeline || pipeline_cache_filename.empty()) {
         return pipeline;
     }
     serialization_thread.QueueWork([this, key = graphics_key, envs = std::move(environments.envs)] {
@@ -477,7 +485,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline() {
                 env_ptrs.push_back(&envs[index]);
             }
         }
-        VideoCommon::SerializePipeline(key, env_ptrs, pipeline_cache_filename);
+        SerializePipeline(key, env_ptrs, pipeline_cache_filename);
     });
     return pipeline;
 }
@@ -491,18 +499,19 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
 
     main_pools.ReleaseContents();
     auto pipeline{CreateComputePipeline(main_pools, key, env, true)};
-    if (!pipeline_cache_filename.empty()) {
-        serialization_thread.QueueWork([this, key, env = std::move(env)] {
-            VideoCommon::SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env},
-                                           pipeline_cache_filename);
-        });
+    if (!pipeline || pipeline_cache_filename.empty()) {
+        return pipeline;
     }
+    serialization_thread.QueueWork([this, key, env = std::move(env)] {
+        SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env},
+                          pipeline_cache_filename);
+    });
     return pipeline;
 }
 
 std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
     ShaderPools& pools, const ComputePipelineCacheKey& key, Shader::Environment& env,
-    bool build_in_parallel) {
+    bool build_in_parallel) try {
     LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash());
 
     Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()};
@@ -517,6 +526,10 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
     Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
     return std::make_unique<ComputePipeline>(device, descriptor_pool, update_descriptor_queue,
                                              thread_worker, program.info, std::move(spv_module));
+
+} catch (const Shader::Exception& exception) {
+    LOG_ERROR(Render_Vulkan, "{}", exception.what());
+    return nullptr;
 }
 
 } // namespace Vulkan
-- 
cgit v1.2.3-70-g09d2