From 32fd10bd083ade9d160968afb7d014868f0d6ce2 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Sun, 29 Sep 2024 23:55:14 -0500 Subject: [PATCH 1/2] VideoBackends:Metal: Log file on failed pipeline compile --- .../VideoBackends/Metal/MTLObjectCache.mm | 61 ++++++++++++++++++- Source/Core/VideoBackends/Metal/MTLShader.h | 1 + 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/Metal/MTLObjectCache.mm b/Source/Core/VideoBackends/Metal/MTLObjectCache.mm index 5d29f06e88..db0e338ae5 100644 --- a/Source/Core/VideoBackends/Metal/MTLObjectCache.mm +++ b/Source/Core/VideoBackends/Metal/MTLObjectCache.mm @@ -17,6 +17,7 @@ #include "VideoCommon/AbstractPipeline.h" #include "VideoCommon/NativeVertexFormat.h" #include "VideoCommon/VertexShaderGen.h" +#include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoConfig.h" MRCOwned> Metal::g_device; @@ -445,10 +446,66 @@ public: error:&err]; if (err) { - PanicAlertFmt("Failed to compile pipeline for {} and {}: {}", + static int counter; + std::string filename = VideoBackendBase::BadShaderFilename("pipeline", counter++); + FILE* file = fopen(filename.c_str(), "w"); + if (file) + { + fmt::println(file, "=============== Error ==============="); + fmt::println(file, "{}", [[err localizedDescription] UTF8String]); + fmt::println(file, "============== Pipeline ============="); + fmt::println(file, "VS: {}", [[[desc vertexFunction] label] UTF8String]); + fmt::println(file, "PS: {}", [[[desc fragmentFunction] label] UTF8String]); + fmt::println(file, "Color Format: {}", static_cast(fs.color_texture_format.Value())); + fmt::println(file, "Depth Format: {}", static_cast(fs.depth_texture_format.Value())); + fmt::println(file, "Sample Count: {}", fs.samples); + if (u32 cnt = fs.additional_color_attachment_count) + fmt::println(file, "Additional Color Attachments: {}", cnt); + if (bs.colorupdate && bs.alphaupdate) + fmt::println(file, "Write Color, Alpha"); + else if (bs.colorupdate) + fmt::println(file, "Write Color"); + else if (bs.alphaupdate) + fmt::println(file, "Write Alpha"); + else + fmt::println(file, "Write None"); + if (bs.blendenable) + { + auto print_blend = [file](const char* name, SrcBlendFactor src, DstBlendFactor dst, + bool subtract) { + if (subtract) + fmt::println(file, "{}: dst * {} - src * {}", name, dst, src); + else + fmt::println(file, "{}: src * {} + dst * {}", name, src, dst); + }; + print_blend("Color Blend", bs.srcfactor, bs.dstfactor, bs.subtract); + print_blend("Alpha Blend", bs.srcfactoralpha, bs.dstfactoralpha, bs.subtractAlpha); + fmt::println(file, "Blend Dual Source: {}", bs.usedualsrc ? "true" : "false"); + } + else + { + fmt::println(file, "Blend Disabled"); + } + if (const Shader* vs = static_cast(config.vertex_shader)) + { + fmt::println(file, "========= Vertex Shader MSL ========="); + fmt::println(file, "{}", vs->GetMSL()); + } + if (const Shader* ps = static_cast(config.pixel_shader)) + { + fmt::println(file, "========== Pixel Shader MSL ========="); + fmt::println(file, "{}", ps->GetMSL()); + } + fclose(file); + } + + std::string file_msg = file ? fmt::format("Details were written to {}", filename) : + "Failed to write detailed info"; + + PanicAlertFmt("Failed to compile pipeline for {} and {}: {}\n{}", [[[desc vertexFunction] label] UTF8String], [[[desc fragmentFunction] label] UTF8String], - [[err localizedDescription] UTF8String]); + [[err localizedDescription] UTF8String], file_msg); return std::make_pair(nullptr, PipelineReflection()); } diff --git a/Source/Core/VideoBackends/Metal/MTLShader.h b/Source/Core/VideoBackends/Metal/MTLShader.h index 018346bb6d..dca9d97931 100644 --- a/Source/Core/VideoBackends/Metal/MTLShader.h +++ b/Source/Core/VideoBackends/Metal/MTLShader.h @@ -19,6 +19,7 @@ public: ~Shader(); id GetShader() const { return m_shader; } + const std::string& GetMSL() const { return m_msl; } BinaryData GetBinary() const override; private: From 1454934a07b233693291c5eba297e13811e496ab Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Mon, 30 Sep 2024 23:35:27 -0500 Subject: [PATCH 2/2] VideoBackends:Metal: Use standardized C++ features over clang builtins --- Source/Core/VideoBackends/Metal/MTLObjectCache.h | 2 +- Source/Core/VideoBackends/Metal/MTLStateTracker.mm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/Metal/MTLObjectCache.h b/Source/Core/VideoBackends/Metal/MTLObjectCache.h index f47a513116..81d77e894b 100644 --- a/Source/Core/VideoBackends/Metal/MTLObjectCache.h +++ b/Source/Core/VideoBackends/Metal/MTLObjectCache.h @@ -83,7 +83,7 @@ public: id GetSampler(SamplerSelector sel) { - if (__builtin_expect(!m_samplers[sel.value], false)) + if (!m_samplers[sel.value]) [[unlikely]] m_samplers[sel.value] = CreateSampler(sel); return m_samplers[sel.value]; } diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm index b67c4162b1..e9abbaee33 100644 --- a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm +++ b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm @@ -144,7 +144,7 @@ Metal::StateTracker::Map Metal::StateTracker::AllocateForTextureUpload(size_t am CPUBuffer& buffer = m_texture_upload_buffer; u64 last_draw = m_last_finished_draw.load(std::memory_order_acquire); bool needs_new = buffer.usage.PrepareForAllocation(last_draw, amt); - if (__builtin_expect(needs_new, false)) + if (needs_new) [[unlikely]] { // Orphan buffer size_t newsize = std::max(buffer.usage.Size() * 2, 4096); @@ -187,7 +187,7 @@ std::pair Metal::StateTracker::Preallocate(UploadBuffer buffer_id } buffer.last_upload = 0; } - if (__builtin_expect(needs_new, false)) + if (needs_new) [[unlikely]] { // Orphan buffer size_t newsize = std::max(buffer.usage.Size() * 2, 4096);