[VK, MacOS] Fix strict output type mismatch on Metal (MK8D/TOTK fix) (#3414)

Metal validation requires fragment shader output types to strictly match the render target format (e.g., writing float to RGBA32Uint is invalid).

This commit:
1. Adds color_output_types to RuntimeInfo.
2. Detects Integer/SignedInteger render targets in the Vulkan backend (MoltenVK only).
3. Updates the SPIR-V emitter to declare the correct output type (Uint/Sint) and bitcast values accordingly.

This fixes the VK_ERROR_INITIALIZATION_FAILED crash on macOS.

Co-authored-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3414
Co-authored-by: rayman30 <silentbitdev@gmail.com>
Co-committed-by: rayman30 <silentbitdev@gmail.com>
This commit is contained in:
rayman30 2026-01-29 17:24:36 +01:00 committed by crueter
parent 025bc799f7
commit 643f11d972
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
4 changed files with 42 additions and 4 deletions

View file

@ -39,6 +39,7 @@
#include "video_core/shader_cache.h"
#include "video_core/shader_environment.h"
#include "video_core/shader_notify.h"
#include "video_core/surface.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
@ -238,6 +239,22 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
info.alpha_test_func = MaxwellToCompareFunction(
key.state.UnpackComparisonOp(key.state.alpha_test_func.Value()));
info.alpha_test_reference = std::bit_cast<float>(key.state.alpha_test_ref);
if (device.IsMoltenVK()) {
for (size_t i = 0; i < 8; ++i) {
const auto format = static_cast<Tegra::RenderTargetFormat>(key.state.color_formats[i]);
const auto pixel_format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(format);
if (VideoCore::Surface::IsPixelFormatInteger(pixel_format)) {
if (VideoCore::Surface::IsPixelFormatSignedInteger(pixel_format)) {
info.color_output_types[i] = Shader::AttributeType::SignedInt;
} else {
info.color_output_types[i] = Shader::AttributeType::UnsignedInt;
}
} else {
info.color_output_types[i] = Shader::AttributeType::Float;
}
}
}
break;
default:
break;