Compare commits

...
10 Commits
35 changed files with 1623 additions and 1226 deletions
@@ -3,6 +3,7 @@ name: Application Bug Report
description: Found a problem with the application itself (ie. bad file path handling, UX issue)? Help us improve it.
title: "[BUG]: "
labels: [Bug]
type: Bug
# assignees:
# - octocat
body:
@@ -3,6 +3,7 @@ name: Emulation Bug Report
description: Problem in a game (ie. graphical artifacts, crashes)? Help us improve it.
title: "[BUG]: "
labels: [Bug]
type: Bug
# assignees:
# - octocat
body:
@@ -3,6 +3,7 @@ name: Feature request
description: Suggest a new feature or improve an existing one
title: "[Feature Request]: "
labels: ["Enhancement / Feature Request", "FR: Awaiting Consideration"]
type: Feature Request
# assignees:
# - octocat
body:
@@ -0,0 +1,159 @@
From 4cf93f0f16b1503580cdb7ffdedb056321446677 Mon Sep 17 00:00:00 2001
From: squidbus <175574877+squidbus@users.noreply.github.com>
Date: Sat, 9 May 2026 16:53:22 -0700
Subject: [PATCH] Restore some checks for Mac1 GPUs.
---
MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 1 +
MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 34 +++++++++++--------
MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 2 +-
.../MoltenVK/GPUObjects/MVKPixelFormats.mm | 2 +-
4 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
index ba3914de5..8923d23f0 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
@@ -112,6 +112,7 @@ typedef struct MVKMTLDeviceCapabilities {
bool supportsApple8;
bool supportsApple9;
bool supportsApple10;
+ bool supportsMac1;
bool supportsMac2;
bool supportsMetal3;
bool supportsMetal4;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 2c930b004..2e212645a 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -110,7 +110,8 @@
#if MVK_XCODE_26
supportsApple10 = supportsGPUFam(Apple10, mtlDev);
#endif
- supportsMac2 = MVK_MACOS; // Incl Mac2 & MacCatalyst2
+ supportsMac1 = MVK_MACOS;
+ supportsMac2 = supportsGPUFam(Mac2, mtlDev) || supportsGPUFam(MacCatalyst2, mtlDev);
isAppleGPU = supportsApple1;
@@ -1547,7 +1548,7 @@
const auto placementHeapFlags = VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT |
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT |
VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
- if (!getMVKConfig().useMTLHeap && mvkIsAnyFlagEnabled(flags, placementHeapFlags)) {
+ if (!_metalFeatures.placementHeaps && mvkIsAnyFlagEnabled(flags, placementHeapFlags)) {
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
@@ -2456,9 +2457,10 @@
// AMD support for MTLHeap is buggy.
auto cfgUseMTLHeap = getMVKConfig().useMTLHeap;
- _metalFeatures.placementHeaps = (_properties.vendorID == kAMDVendorId
- ? cfgUseMTLHeap == MVK_CONFIG_USE_MTLHEAP_ALWAYS
- : cfgUseMTLHeap != MVK_CONFIG_USE_MTLHEAP_NEVER);
+ auto allowMTLHeap = (_properties.vendorID == kAMDVendorId
+ ? cfgUseMTLHeap == MVK_CONFIG_USE_MTLHEAP_ALWAYS
+ : cfgUseMTLHeap != MVK_CONFIG_USE_MTLHEAP_NEVER);
+ _metalFeatures.placementHeaps = allowMTLHeap && (supportsMTLGPUFamily(Apple2) || supportsMTLGPUFamily(Mac2));
_metalFeatures.multisampleArrayTextures = !MVK_TVOS || mvkOSVersionIsAtLeast(16.0);
// Dynamic vertex stride needs to have everything aligned - compiled with support for vertex stride calls, and supported by both runtime OS and GPU.
@@ -2467,7 +2469,7 @@
_metalFeatures.renderLinearTextures = _gpuCapabilities.supportsRenderLinearTextures;
- if (supportsMTLGPUFamily(Mac2)) {
+ if (supportsMTLGPUFamily(Mac1)) {
_metalFeatures.mtlBufferAlignment = 256;
_metalFeatures.mtlConstantBufferAlignment = 32;
_metalFeatures.mtlCopyBufferAlignment = 4;
@@ -2489,15 +2491,18 @@
_metalFeatures.presentModeImmediate = true;
_metalFeatures.nonUniformThreadgroups = true;
_metalFeatures.native3DCompressedTextures = true;
- _metalFeatures.multisampleLayeredRendering = _metalFeatures.layeredRendering;
+ _metalFeatures.simdPermute = true;
+ _metalFeatures.memoryBarriers = true;
+ }
+
+ if (supportsMTLGPUFamily(Mac2)) {
+ _metalFeatures.multisampleLayeredRendering = true;
_metalFeatures.stencilFeedback = true;
_metalFeatures.depthResolve = true;
_metalFeatures.stencilResolve = true;
- _metalFeatures.simdPermute = true;
_metalFeatures.quadPermute = true;
_metalFeatures.simdReduction = true;
- _metalFeatures.memoryBarriers = true;
- }
+ }
if (supportsMTLGPUFamily(Apple1)) {
_metalFeatures.mtlBufferAlignment = 64;
@@ -2798,7 +2803,7 @@
_features.shaderResourceMinLod = true;
}
- if (supportsMTLGPUFamily(Mac2)) {
+ if (supportsMTLGPUFamily(Mac1)) {
_features.occlusionQueryPrecise = true;
_features.imageCubeArray = true;
_features.tessellationShader = true;
@@ -2970,19 +2975,19 @@
if (supportsMTLGPUFamily(Apple3)) {
_properties.limits.optimalBufferCopyOffsetAlignment = 16;
- } else if (supportsMTLGPUFamily(Mac2)) {
+ } else if (supportsMTLGPUFamily(Mac1)) {
_properties.limits.optimalBufferCopyOffsetAlignment = 256;
} else {
_properties.limits.optimalBufferCopyOffsetAlignment = 64;
}
- if (supportsMTLGPUFamily(Apple4) || supportsMTLGPUFamily(Mac2)) {
+ if (supportsMTLGPUFamily(Apple4) || supportsMTLGPUFamily(Mac1)) {
_properties.limits.maxFragmentInputComponents = 124;
} else {
_properties.limits.maxFragmentInputComponents = 60;
}
- if (supportsMTLGPUFamily(Apple5) || supportsMTLGPUFamily(Mac2)) {
+ if (supportsMTLGPUFamily(Apple5) || supportsMTLGPUFamily(Mac1)) {
_properties.limits.maxTessellationGenerationLevel = 64;
_properties.limits.maxTessellationPatchSize = 32;
} else if (supportsMTLGPUFamily(Apple3)) {
@@ -3653,6 +3658,7 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope
if (supportsMTLGPUFamily(Apple2)) { logMsg += "\n\t\tGPU Family Apple 2"; } else
if (supportsMTLGPUFamily(Apple1)) { logMsg += "\n\t\tGPU Family Apple 1"; }
+ if (supportsMTLGPUFamily(Mac1)) { logMsg += "\n\t\tGPU Family Mac 1"; }
if (supportsMTLGPUFamily(Mac2)) { logMsg += "\n\t\tGPU Family Mac 2"; }
logMsg += "\n\t\tRead-Write Texture Tier ";
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index d2fdd4020..696ec4467 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -1382,7 +1382,7 @@ static MTLRegion getMTLRegion(const ImgRgn& imgRgn) {
const auto placementHeapFlags = VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT |
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT |
VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
- if (!getMVKConfig().useMTLHeap && mvkIsAnyFlagEnabled(pCreateInfo->flags, placementHeapFlags)) {
+ if (!getMetalFeatures().placementHeaps && mvkIsAnyFlagEnabled(pCreateInfo->flags, placementHeapFlags)) {
setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : MTLHeap must be enabled to create 2D-on-3D or block texel view compatible images."));
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
index d16d6c8f6..11ca10a03 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
@@ -1343,7 +1343,7 @@
addMTLVertexFormatDesc( UChar4Normalized_BGRA );
- if (gpuCaps.supportsApple5 || gpuCaps.supportsMac2) {
+ if (gpuCaps.supportsApple5 || gpuCaps.supportsMac1) {
addMTLVertexFormatDesc( FloatRG11B10 );
addMTLVertexFormatDesc( FloatRGB9E5 );
}
@@ -289,6 +289,8 @@ echo "Installing MoltenVK..."
rm -fr "MoltenVK-${MOLTENVK}"
tar xf "MoltenVK-$MOLTENVK.tar.gz"
cd "MoltenVK-${MOLTENVK}"
patch -p1 < "$SCRIPTDIR/4cf93f0f16b1503580cdb7ffdedb056321446677.patch"
patch -p1 < "$SCRIPTDIR/mvk-texture-swizzle.patch"
./fetchDependencies --macos
make macos MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=0 MVK_CONFIG_USE_METAL_PRIVATE_API=1
cp Package/Latest/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib "$INSTALLDIR/lib/"
@@ -78,7 +78,7 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz
6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e libjpeg-turbo-$LIBJPEGTURBO.tar.gz
cf38e0e28c7e5605942c4a77755349b0145804a397af37eb1fb4c77cb237f635 ffmpeg-$FFMPEG.tar.xz
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c MoltenVK-$MOLTENVK.tar.gz
5cd9495d9316cf6cc937bb328a7fd491c3248ef2469cfa42511f1039f6148aca KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
@@ -102,7 +102,7 @@ if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
-O "https://github.com/KhronosGroup/MoltenVK/archive/refs/tags/v$MOLTENVK.tar.gz" \
-O "https://github.com/KhronosGroup/MoltenVK/archive/v$MOLTENVK/MoltenVK-$MOLTENVK.tar.gz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
@@ -228,8 +228,10 @@ cd ..
# MoltenVK already builds universal binaries, nothing special to do here.
echo "Installing MoltenVK..."
rm -fr "MoltenVK-${MOLTENVK}"
tar xf "v$MOLTENVK.tar.gz"
tar xf "MoltenVK-$MOLTENVK.tar.gz"
cd "MoltenVK-${MOLTENVK}"
patch -p1 < "$SCRIPTDIR/4cf93f0f16b1503580cdb7ffdedb056321446677.patch"
patch -p1 < "$SCRIPTDIR/mvk-texture-swizzle.patch"
sed -i '' 's/xcodebuild "$@"/xcodebuild $XCODEBUILD_EXTRA_ARGS "$@"/g' fetchDependencies
sed -i '' 's/XCODEBUILD :=/XCODEBUILD ?=/g' Makefile
XCODEBUILD_EXTRA_ARGS="VALID_ARCHS=x86_64" ./fetchDependencies --macos
@@ -0,0 +1,139 @@
From f6be31a110761ea494a938d62473abc085ea447b Mon Sep 17 00:00:00 2001
From: TellowKrinkle <tellowkrinkle@gmail.com>
Date: Mon, 31 Aug 2026 02:52:38 -0500
Subject: [PATCH] Re-add native texture swizzle checks
---
MoltenVK/MoltenVK/API/mvk_deprecated_api.h | 2 +-
MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 3 +-
MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 51 ++++++++++++++++++-
.../MoltenVK/GPUObjects/MVKPixelFormats.mm | 3 ++
4 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/MoltenVK/MoltenVK/API/mvk_deprecated_api.h b/MoltenVK/MoltenVK/API/mvk_deprecated_api.h
index 74fef844..8d16f86c 100644
--- a/MoltenVK/MoltenVK/API/mvk_deprecated_api.h
+++ b/MoltenVK/MoltenVK/API/mvk_deprecated_api.h
@@ -118,7 +118,7 @@ typedef struct {
VkBool32 fences; /**< If true, Metal synchronization fences (MTLFence) are supported. Deprecated. Will always be true on all platforms. */
VkBool32 rasterOrderGroups; /**< If true, Raster order groups in fragment shaders are supported. */
VkBool32 native3DCompressedTextures; /**< If true, 3D compressed images are supported natively, without manual decompression. */
- VkBool32 nativeTextureSwizzle; /**< If true, component swizzle is supported natively, without manual swizzling in shaders. Deprecated. Will always be true on all platforms. */
+ VkBool32 nativeTextureSwizzle; /**< If true, component swizzle is supported natively, without manual swizzling in shaders. */
VkBool32 placementHeaps; /**< If true, MTLHeap objects support placement of resources. */
VkDeviceSize pushConstantSizeAlignment; /**< The alignment used internally when allocating memory for push constants. Must be PoT. */
uint32_t maxTextureLayers; /**< The maximum number of layers in an array texture. */
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index aaf5945b..c7da8256 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -2496,6 +2496,7 @@
_metalFeatures.stencilResolve = true;
_metalFeatures.quadPermute = true;
_metalFeatures.simdReduction = true;
+ _metalFeatures.nativeTextureSwizzle = true;
}
if (supportsMTLGPUFamily(Apple1)) {
@@ -2504,6 +2505,7 @@
_metalFeatures.maxPerStageTextureCount = 31;
_metalFeatures.maxTextureDimension = (8 * KIBI);
_metalFeatures.maxQueryBufferSize = (64 * KIBI);
+ _metalFeatures.nativeTextureSwizzle = true;
_metalFeatures.maxPerStageDynamicMTLBufferCount = _metalFeatures.maxPerStageBufferCount;
_metalFeatures.renderLinearTextures = true;
@@ -2727,7 +2729,6 @@
_metalFeatures.events = true;
_metalFeatures.ioSurfaces = true;
_metalFeatures.renderWithoutAttachments = true;
- _metalFeatures.nativeTextureSwizzle = true;
}
bool MVKPhysicalDevice::isTier2MetalArgumentBuffers() {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 8eda5515..392a4f98 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -1925,7 +1925,7 @@ static void signalAndUntrack(const MVKSwapchainSignaler& signaler) {
}
id<MTLTexture> texView = nil;
- if (_useSwizzle) {
+ if (_useSwizzle && getMetalFeatures().nativeTextureSwizzle) {
texView = [mtlTex newTextureViewWithPixelFormat: _mtlPixFmt
textureType: _imageView->_mtlTextureType
levels: levelRange
@@ -2103,6 +2103,55 @@ static void signalAndUntrack(const MVKSwapchainSignaler& signaler) {
}
}
+#define SWIZZLE_MATCHES(R, G, B, A) mvkVkComponentMappingsMatch(_componentSwizzle, {VK_COMPONENT_SWIZZLE_ ##R, VK_COMPONENT_SWIZZLE_ ##G, VK_COMPONENT_SWIZZLE_ ##B, VK_COMPONENT_SWIZZLE_ ##A} )
+#define VK_COMPONENT_SWIZZLE_ANY VK_COMPONENT_SWIZZLE_MAX_ENUM
+
+ if (_imageView->_image->hasPixelFormatView(_planeIndex)) {
+ switch (_mtlPixFmt) {
+ case MTLPixelFormatR8Unorm:
+ if (SWIZZLE_MATCHES(ZERO, ANY, ANY, R)) {
+ _mtlPixFmt = MTLPixelFormatA8Unorm;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatA8Unorm:
+ if (SWIZZLE_MATCHES(A, ANY, ANY, ZERO)) {
+ _mtlPixFmt = MTLPixelFormatR8Unorm;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatRGBA8Unorm:
+ if (SWIZZLE_MATCHES(B, G, R, A)) {
+ _mtlPixFmt = MTLPixelFormatBGRA8Unorm;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatRGBA8Unorm_sRGB:
+ if (SWIZZLE_MATCHES(B, G, R, A)) {
+ _mtlPixFmt = MTLPixelFormatBGRA8Unorm_sRGB;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatBGRA8Unorm:
+ if (SWIZZLE_MATCHES(B, G, R, A)) {
+ _mtlPixFmt = MTLPixelFormatRGBA8Unorm;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatBGRA8Unorm_sRGB:
+ if (SWIZZLE_MATCHES(B, G, R, A)) {
+ _mtlPixFmt = MTLPixelFormatRGBA8Unorm_sRGB;
+ return VK_SUCCESS;
+ }
+ break;
+ }
+ }
+
_useSwizzle = !mvkVkComponentMappingsMatch(_componentSwizzle, {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A});
return VK_SUCCESS;
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
index 316d7c6f..31a2c6a1 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
@@ -654,6 +654,9 @@
bool pfv = false;
+ // Swizzle emulation may need to reinterpret
+ needsReinterpretation |= !_physicalDevice->getMetalFeatures()->nativeTextureSwizzle;
+
pfv |= isColorFormat && needsReinterpretation &&
mvkIsAnyFlagEnabled(vkImageUsageFlags, (VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT |
--
2.39.5 (Apple Git-154)
+20 -8
View File
@@ -169,6 +169,11 @@ float depth32_to_depth24(float d)
return uint_to_depth24(depth_to_uint(d));
}
float4 primid_to_rgba8(float p)
{
return uint_to_rgba8(asuint(p));
}
#if defined(__ps_copy__)
OUTPUT_TYPE ps_copy(PS_INPUT input) : OUTPUT_SV
{
@@ -323,6 +328,13 @@ OUTPUT_TYPE ps_convert_depth32_depth24(PS_INPUT input) : OUTPUT_SV
}
#endif
#if defined(__ps_convert_primid_rgba8__)
OUTPUT_TYPE ps_convert_primid_rgba8(PS_INPUT input) : OUTPUT_SV
{
return primid_to_rgba8(sample_c(input.t));
}
#endif
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
uint width, height; \
Texture.GetDimensions(width, height); \
@@ -650,9 +662,9 @@ float ps_primid_image_init_0(PS_INPUT input) : SV_Target
{
float c;
if ((127.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass)
c = float(-1);
c = float(PRIMID_MIN);
else
c = float(0x7FFFFFFF);
c = float(PRIMID_MAX);
return c;
}
#endif
@@ -662,9 +674,9 @@ float ps_primid_image_init_1(PS_INPUT input) : SV_Target
{
float c;
if (sample_c(input.t).a < (127.5f / 255.0f)) // >= 0x80 pass
c = float(-1);
c = float(PRIMID_MIN);
else
c = float(0x7FFFFFFF);
c = float(PRIMID_MAX);
return c;
}
#endif
@@ -674,9 +686,9 @@ float ps_primid_image_init_2(PS_INPUT input) : SV_Target
{
float c;
if ((254.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass)
c = float(-1);
c = float(PRIMID_MIN);
else
c = float(0x7FFFFFFF);
c = float(PRIMID_MAX);
return c;
}
#endif
@@ -686,9 +698,9 @@ float ps_primid_image_init_3(PS_INPUT input) : SV_Target
{
float c;
if (sample_c(input.t).a < (254.5f / 255.0f)) // >= 0x80 pass
c = float(-1);
c = float(PRIMID_MIN);
else
c = float(0x7FFFFFFF);
c = float(PRIMID_MAX);
return c;
}
#endif
+5 -3
View File
@@ -1097,8 +1097,11 @@ void ps_fbmask(inout float4 C, float2 pos_xy)
{
if (PS_FBMASK)
{
float multi = PS_COLCLIP_HW ? 65535.0f : 255.0f;
float4 RT = trunc(RtLoad(int2(pos_xy)) * multi + 0.1f);
float multi_rgb = PS_COLCLIP_HW ? 65535.0f : 255.0f;
float multi_a = PS_RTA_CORRECTION ? 128.0f : 255.0f;
float4 RT = RtLoad(int2(pos_xy));
RT.rgb = trunc(RT.rgb * multi_rgb + 0.1f);
RT.a = round(RT.a * multi_a);
C = (float4)(((uint4)C & ~FbMask) | ((uint4)RT & FbMask));
}
}
@@ -1594,7 +1597,6 @@ if (bad)
output.c1 = o_col1;
#endif
#elif PS_RETURN_COLOR_ROV
o_col0 = (FbMask == 0xFFu) ? RtLoad(input.p.xy) : o_col0; // channel masking
if (!rov_discard_color)
RtWrite(input.p.xy, o_col0);
#endif
+17 -5
View File
@@ -139,6 +139,11 @@ float depth32_to_depth24(float d)
return uint_to_depth24(depth_to_uint(d));
}
vec4 primid_to_rgba8(float p)
{
return uint_to_rgba8(floatBitsToUint(p));
}
#ifdef ps_copy
void ps_copy()
{
@@ -212,6 +217,13 @@ void ps_convert_depth32_depth24()
}
#endif
#ifdef ps_convert_primid_rgba8
void ps_convert_primid_rgba8()
{
OUTPUT = primid_to_rgba8(sample_c());
}
#endif
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
ivec2 dims = textureSize(TextureSampler, 0); \
vec2 top_left_f = PSin_t * vec2(dims) - 0.5f; \
@@ -615,23 +627,23 @@ void ps_yuv()
void main()
{
o_col0 = vec4(0x7FFFFFFF);
o_col0 = vec4(PRIMID_MAX);
#ifdef ps_primid_image_init_0
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_1
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_2
if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_3
if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
}
#endif
+5 -5
View File
@@ -932,11 +932,11 @@ void ps_fbmask(inout vec4 C)
{
// FIXME do I need special case for 16 bits
#if PS_FBMASK
#if PS_COLCLIP_HW == 1
vec4 RT = trunc(sample_from_rt() * 65535.0f);
#else
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
#endif
float multi_rgb = PS_COLCLIP_HW != 0 ? 65535.0f : 255.0f;
float multi_a = PS_RTA_CORRECTION != 0 ? 128.0f : 255.0f;
vec4 RT = sample_from_rt();
RT.rgb = trunc(RT.rgb * multi_rgb + 0.1f);
RT.a = round(RT.a * multi_a);
C = vec4((uvec4(C) & ~FbMask) | (uvec4(RT) & FbMask));
#endif
}
+17 -5
View File
@@ -130,6 +130,11 @@ float depth32_to_depth24(float d)
return uint_to_depth24(depth_to_uint(d));
}
vec4 primid_to_rgba8(float p)
{
return uint_to_rgba8(floatBitsToUint(p));
}
#ifdef ps_copy
void ps_copy()
{
@@ -281,6 +286,13 @@ void ps_convert_depth32_depth24()
}
#endif
#ifdef ps_convert_primid_rgba8
void ps_convert_primid_rgba8()
{
OUTPUT = primid_to_rgba8(sample_c(v_tex));
}
#endif
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
ivec2 dims = textureSize(samp0, 0); \
vec2 top_left_f = v_tex * vec2(dims) - 0.5f; \
@@ -628,23 +640,23 @@ void ps_yuv()
void main()
{
o_col0 = vec4(0x7FFFFFFF);
o_col0 = vec4(PRIMID_MAX);
#ifdef ps_primid_image_init_0
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_1
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_2
if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_3
if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
}
#endif
+5 -7
View File
@@ -1448,11 +1448,11 @@ vec4 ps_color()
void ps_fbmask(inout vec4 C)
{
#if PS_FBMASK
#if PS_COLCLIP_HW == 1
vec4 RT = trunc(sample_from_rt() * 65535.0f);
#else
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
#endif
float multi_rgb = PS_COLCLIP_HW != 0 ? 65535.0f : 255.0f;
float multi_a = PS_RTA_CORRECTION != 0 ? 128.0f : 255.0f;
vec4 RT = sample_from_rt();
RT.rgb = trunc(RT.rgb * multi_rgb + 0.1f);
RT.a = round(RT.a * multi_a);
C = vec4((uvec4(C) & ~FbMask) | (uvec4(RT) & FbMask));
#endif
}
@@ -1966,8 +1966,6 @@ void main()
// Writing back color (result already written to o_col0 for non-ROV)
#if PS_RETURN_COLOR_ROV
o_col0 = mix(o_col0, sample_from_rt(), equal(FbMask, uvec4(0xFFu))); // channel masking
if (!rov_discard_color)
imageStore(RtImageRov, ivec2(gl_FragCoord.xy), o_col0);
#endif
File diff suppressed because it is too large Load Diff
+7 -4
View File
@@ -468,7 +468,7 @@ u32 cdvdGetElfCRC(const std::string& path)
return elfo.GetCRC();
}
static CDVDDiscType GetPS2ElfName(IsoReader& isor, std::string* name, std::string* version, Error* error)
static CDVDDiscType GetPS2ElfName(IsoReader& isor, std::string* name, std::string* version, std::string* vmode, Error* error)
{
CDVDDiscType retype = CDVDDiscType::Other;
name->clear();
@@ -510,6 +510,7 @@ static CDVDDiscType GetPS2ElfName(IsoReader& isor, std::string* name, std::strin
else if (key == "VMODE")
{
DevCon.WriteLn(Color_Blue, fmt::format("(SYSTEM.CNF) Disc region type = {}", value));
*vmode = value;
}
else if (key == "VER")
{
@@ -574,15 +575,15 @@ static std::string ExecutablePathToSerial(const std::string& path)
return serial;
}
void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::string* out_version, u32* out_crc,
void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::string* out_version, std::string* out_region, u32* out_crc,
CDVDDiscType* out_disc_type)
{
Error error;
IsoReader isor;
std::string elfpath, version;
std::string elfpath, version, vmode;
CDVDDiscType disc_type = CDVDDiscType::Other;
if (!isor.Open(&error) || (disc_type = GetPS2ElfName(isor, &elfpath, &version, &error)) == CDVDDiscType::Other)
if (!isor.Open(&error) || (disc_type = GetPS2ElfName(isor, &elfpath, &version, &vmode, &error)) == CDVDDiscType::Other)
Console.Error(fmt::format("Failed to get ELF name: {}", error.GetDescription()));
// Don't bother parsing it if we don't need the CRC.
@@ -616,6 +617,8 @@ void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::st
*out_version = std::move(version);
if (out_disc_type)
*out_disc_type = disc_type;
if (out_region)
*out_region = vmode;
}
void cdvdReadKey(u8, u16, u32 arg2, u8* key)
+1 -1
View File
@@ -179,7 +179,7 @@ extern void cdvdNewDiskCB();
extern u8 cdvdRead(u8 key);
extern void cdvdWrite(u8 key, u8 rt);
extern void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::string* out_version, u32* out_crc,
extern void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::string* out_version, std::string* out_region, u32* out_crc,
CDVDDiscType* out_disc_type);
extern u32 cdvdGetElfCRC(const std::string& path);
extern bool cdvdLoadElf(ElfObject* elfo, const std::string_view elfpath, bool isPSXElf, Error* error);
+1 -1
View File
@@ -1263,7 +1263,7 @@ function(setup_main_executable target)
if("${file}" MATCHES "^\\.") # Don't copy macOS garbage (mainly Finder's .DS_Store files) into application
continue()
endif()
if (NOT WIN32 AND "${path}" MATCHES "/dx11/") # Don't include unneccessary stuff
if (NOT WIN32 AND "${path}" MATCHES "/dx11/") # Don't include unnecessary stuff
continue()
endif()
if (NOT BUNDLE_EMOJI_FONT AND "${path}" MATCHES "fonts/Twemoji")
+6 -4
View File
@@ -215,7 +215,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, double framesPerSecond, u32 sca
// Dynasty Warriors 3 Xtreme Legends - fake save corruption when loading save
// Jak II - random speedups
// Shadow of Rome - FMV audio issues
const bool ntsc_hblank = gsVideoMode != GS_VideoMode::PAL && gsVideoMode != GS_VideoMode::DVD_PAL;
const bool ntsc_hblank = gsVideoMode != GS_VideoMode::PAL && gsVideoMode != GS_VideoMode::DVD_PAL && (gsVideoMode != GS_VideoMode::Uninitialized || framesPerSecond != (Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_PAL / 2));
const u64 HalfFrame = Frame / 2;
const float extra_scanlines = static_cast<float>(IsProgressiveVideoMode()) * (ntsc_hblank ? 0.5f : 1.5f);
const u64 Blank = Scanline * ((ntsc_hblank ? 22.5f : 24.5f) + extra_scanlines);
@@ -307,10 +307,12 @@ double GetVerticalFrequency()
// https://web.archive.org/web/20120629231826fw_/http://ntsc-tv.com/index.html
// https://web.archive.org/web/20200831051302/https://www.hdretrovision.com/240p/
std::string cur_region = VMManager::Internal::GetCurrentRegion();
switch (gsVideoMode)
{
case GS_VideoMode::Uninitialized: // SetGsCrt hasn't executed yet, give some temporary values.
return 60.00;
return (cur_region == "PAL") ? Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_PAL : Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_NTSC;
case GS_VideoMode::PAL:
case GS_VideoMode::DVD_PAL:
return (IsProgressiveVideoMode() == false) ? EmuConfig.GS.FrameratePAL : EmuConfig.GS.FrameratePAL - 0.24f;
@@ -352,9 +354,9 @@ void UpdateVSyncRate(bool force)
{
case GS_VideoMode::Uninitialized: // SYSCALL instruction hasn't executed yet, give some temporary values.
if (gsIsInterlaced)
total_scanlines = SCANLINES_TOTAL_NTSC_I;
total_scanlines = (vertical_frequency == Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_PAL) ? SCANLINES_TOTAL_PAL_I : SCANLINES_TOTAL_NTSC_I;
else
total_scanlines = SCANLINES_TOTAL_NTSC_NI;
total_scanlines = (vertical_frequency == Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_PAL) ? SCANLINES_TOTAL_PAL_NI : SCANLINES_TOTAL_NTSC_NI;
break;
case GS_VideoMode::PAL:
case GS_VideoMode::DVD_PAL:
+2
View File
@@ -49,6 +49,7 @@ const char* ShaderEntryPoint(ShaderConvert value)
case ShaderConvert::RGB5A1_TO_DEPTH16: return "ps_convert_rgb5a1_depth16";
case ShaderConvert::DEPTH32_TO_DEPTH24: return "ps_convert_depth32_depth24";
case ShaderConvert::DEPTH_COPY: return "ps_depth_copy";
case ShaderConvert::PRIMID_TO_RGBA8: return "ps_convert_primid_rgba8";
case ShaderConvert::DOWNSAMPLE_COPY: return "ps_downsample_copy";
case ShaderConvert::RGBA_TO_8I: return "ps_convert_rgba_8i";
case ShaderConvert::RGB5A1_TO_8I: return "ps_convert_rgb5a1_8i";
@@ -109,6 +110,7 @@ const char* ShaderConvertName(ShaderConvert shader)
ENTRY(RGBA8_TO_DEPTH16);
ENTRY(RGB5A1_TO_DEPTH16);
ENTRY(DEPTH32_TO_DEPTH24);
ENTRY(PRIMID_TO_RGBA8);
ENTRY(DOWNSAMPLE_COPY);
ENTRY(RGBA_TO_8I);
ENTRY(RGB5A1_TO_8I);
+7
View File
@@ -59,6 +59,7 @@ enum class ShaderConvert
RGBA8_TO_DEPTH16,
RGB5A1_TO_DEPTH16,
DEPTH32_TO_DEPTH24,
PRIMID_TO_RGBA8,
DOWNSAMPLE_COPY,
RGBA_TO_8I,
RGB5A1_TO_8I,
@@ -122,6 +123,7 @@ static inline constexpr bool HasColorOutput(ShaderConvert shader)
case ShaderConvert::DEPTH32_TO_RGBA8:
case ShaderConvert::DEPTH32_TO_RGB8:
case ShaderConvert::DEPTH16_TO_RGB5A1:
case ShaderConvert::PRIMID_TO_RGBA8:
case ShaderConvert::DOWNSAMPLE_COPY:
case ShaderConvert::RGBA_TO_8I:
case ShaderConvert::RGB5A1_TO_8I:
@@ -162,6 +164,7 @@ static inline constexpr bool HasFloat32Input(ShaderConvert shader)
case ShaderConvert::DEPTH32_TO_RGB8:
case ShaderConvert::DEPTH16_TO_RGB5A1:
case ShaderConvert::DEPTH32_TO_DEPTH24:
case ShaderConvert::PRIMID_TO_RGBA8:
return true;
default:
return false;
@@ -533,6 +536,10 @@ static inline ShaderConvertSelector GetConvertShader(GSTexture::Format src, GSTe
pxAssert(false);
}
break;
case GSTexture::Format::PrimID:
pxAssert(dst == GSTexture::Format::Color);
shader = ShaderConvert::PRIMID_TO_RGBA8;
break;
default:
pxAssert(false);
break;
+11
View File
@@ -63,4 +63,15 @@ enum class PS_ROV_DEPTH : uint32_t
READ_ONLY = 2,
};
#if defined(__METAL_VERSION__)
#define CONSTANT constant
#else
#define CONSTANT
#endif
static constexpr CONSTANT int PRIMID_MAX = (1 << 24) - 1;
static constexpr CONSTANT int PRIMID_MIN = -1;
#undef CONSTANT
} // namespace GSShader
+1 -1
View File
@@ -44,7 +44,7 @@ bool GSTexture::Save(const std::string& fn)
{
// Depth textures need special treatment - we have a stencil component.
// Just re-use the existing conversion shader instead.
if (m_format == Format::DepthStencil || m_format == Format::DepthColor)
if (m_format == Format::DepthStencil || m_format == Format::DepthColor || m_format == Format::PrimID)
{
GSTexture* temp = g_gs_device->CreateRenderTarget(GetWidth(), GetHeight(), Format::Color, false);
if (!temp)
+4
View File
@@ -249,6 +249,8 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
ShaderMacro sm_ps;
sm_ps.AddMacro("PIXEL_SHADER", 1);
sm_ps.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX);
sm_ps.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN);
sm_ps.AddMacro("HAS_BILN", static_cast<int>(shader.Biln()));
sm_ps.AddMacro("HAS_STENCIL_OUTPUT", static_cast<int>(shader.StencilOutput()));
sm_ps.AddMacro("HAS_INTEGER_OUTPUT", static_cast<int>(shader.IntegerOutputBpp() != 0));
@@ -582,6 +584,8 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
const std::string entry_point_macro = WrapEntryPointMacro(entry_point);
ShaderMacro sm_ps;
sm_ps.AddMacro("PIXEL_SHADER", 1);
sm_ps.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX);
sm_ps.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN);
sm_ps.AddMacro(entry_point_macro.c_str(), 1);
m_date.primid_init_ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *convert_hlsl, sm_ps.GetPtr(), entry_point.c_str());
if (!m_date.primid_init_ps[i])
+4
View File
@@ -2877,6 +2877,8 @@ bool GSDevice12::CompileConvertPipelines()
ShaderMacro sm;
sm.AddMacro("PIXEL_SHADER", 1);
sm.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX);
sm.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN);
sm.AddMacro("HAS_BILN", static_cast<int>(shader.Biln()));
sm.AddMacro("HAS_STENCIL_OUTPUT", static_cast<int>(shader.StencilOutput()));
sm.AddMacro("HAS_INTEGER_OUTPUT", static_cast<int>(shader.IntegerOutputBpp() != 0));
@@ -2930,6 +2932,8 @@ bool GSDevice12::CompileConvertPipelines()
ShaderMacro sm;
sm.AddMacro("PIXEL_SHADER", "1");
sm.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX);
sm.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN);
sm.AddMacro(entry_point_macro.c_str(), "1");
ComPtr<ID3DBlob> ps(m_shader_cache.GetPixelShader(*source, sm.GetPtr(), entry_point.c_str()));
+5 -14
View File
@@ -7689,26 +7689,17 @@ void GSRendererHW::ConfigureROV(bool color_rov, bool depth_rov)
if (color_rov)
{
// FbMask setup
if (m_conf.colormask.wrgba != 0)
if (m_conf.colormask.wrgba != 0 && m_conf.colormask.wrgba != 0xF)
{
if (!m_conf.ps.fbmask)
m_conf.cb_ps.FbMask = GSVector4i::zero();
const GSVector4i fbmask = GSVector4i(m_conf.colormask.wr ? 0 : 0xFF, m_conf.colormask.wg ? 0 : 0xFF,
m_conf.colormask.wb ? 0 : 0xFF, m_conf.colormask.wa ? 0 : 0xFF);
if (!m_conf.ps.fbmask)
{
// Don't enable FB mask emulation, just use the mask for ROV.
m_conf.cb_ps.FbMask = fbmask;
}
else
{
m_conf.cb_ps.FbMask |= fbmask;
}
m_conf.ps.fbmask = true;
m_conf.cb_ps.FbMask |= fbmask;
GL_INS("ROV: FbMask={R=%x, G=%x, B=%x, A=%x}",
m_conf.cb_ps.FbMask.r, m_conf.cb_ps.FbMask.g, m_conf.cb_ps.FbMask.b, m_conf.cb_ps.FbMask.a);
}
else
{
m_conf.ps.no_color = true;
}
// Blend setup
if (m_conf.IsBlending())
+14 -9
View File
@@ -112,22 +112,22 @@ fragment void ps_datm0(float4 p [[position]], DirectReadTextureIn<float> tex)
fragment float4 ps_primid_init_datm1(float4 p [[position]], DirectReadTextureIn<float> tex)
{
return tex.read(p).a < (127.5f / 255.f) ? -1 : FLT_MAX;
return tex.read(p).a < (127.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX;
}
fragment float4 ps_primid_init_datm0(float4 p [[position]], DirectReadTextureIn<float> tex)
{
return tex.read(p).a > (127.5f / 255.f) ? -1 : FLT_MAX;
return tex.read(p).a > (127.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX;
}
fragment float4 ps_primid_rta_init_datm1(float4 p [[position]], DirectReadTextureIn<float> tex)
{
return tex.read(p).a < (254.5f / 255.f) ? -1 : FLT_MAX;
return tex.read(p).a < (254.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX;
}
fragment float4 ps_primid_rta_init_datm0(float4 p [[position]], DirectReadTextureIn<float> tex)
{
return tex.read(p).a > (254.5f / 255.f) ? -1 : FLT_MAX;
return tex.read(p).a > (254.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX;
}
fragment float4 ps_rta_correction(ConvertShaderData data [[stage_in]], ConvertPSRes res)
@@ -175,11 +175,6 @@ fragment float4 ps_convert_depth16_rgb5a1(ConvertShaderData data [[stage_in]], C
return convert_depth16_rgba8(res.sample(data.t)) / 255.f;
}
fragment float ps_convert_float32_depth_to_color(ConvertShaderData data [[stage_in]], ConvertPSDepthRes res)
{
return res.sample(data.t);
}
fragment float4 ps_downsample_copy(ConvertShaderData data [[stage_in]],
texture2d<float> texture [[texture(GSMTLTextureIndexNonHW)]],
constant GSMTLDownsamplePSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
@@ -273,6 +268,16 @@ struct ConvertToDepthRes
}
};
static float4 primid_to_rgba8(float p)
{
return float4(as_type<uchar4>(p)) / 255.f;
}
fragment float4 ps_convert_primid_rgba8(ConvertShaderData data [[stage_in]], ConvertPSDepthOrColorRes res)
{
return primid_to_rgba8(res.sample(data.t));
}
fragment DepthOrColorOut ps_depth_copy(ConvertShaderData data [[stage_in]], ConvertPSDepthOrColorRes res)
{
return res.sample(data.t);
+7 -5
View File
@@ -1304,8 +1304,12 @@ struct PSMain
{
if (PS_FBMASK)
{
float multi = PS_COLCLIP_HW ? 65535.0 : 255.5;
C = float4((uint4(int4(C)) & (cb.fbmask ^ 0xff)) | (uint4(current_color * float4(multi, multi, multi, 255)) & cb.fbmask));
float multi_rgb = PS_COLCLIP_HW ? 65535.0 : 255.5;
float multi_a = PS_RTA_CORRECTION ? 128.0 : 255.0;
float4 RT = current_color;
RT.rgb = RT.rgb * multi_rgb;
RT.a = round(RT.a * multi_a);
C = float4((uint4(int4(C)) & (cb.fbmask ^ 0xff)) | (uint4(RT) & cb.fbmask));
}
}
@@ -1769,7 +1773,7 @@ fragment MainPSOut ps_main(
main.current_depth = ds_tex.read(coord).x;
}
if (NEEDS_RT || (PS_ROV_COLOR && any(cb.fbmask == 0xff)))
if (NEEDS_RT)
{
if (PS_ROV_COLOR)
{
@@ -1797,8 +1801,6 @@ fragment MainPSOut ps_main(
ds_rov.write(out.depth, coord);
if (PS_ROV_COLOR && !main.color_discarded)
{
if (!PS_FBMASK)
out.c0 = select(out.c0, main.current_color, cb.fbmask == 0xff);
if (ROV_NEEDS_R32)
rt_u32.write(pack_float_to_unorm4x8(out.c0), coord);
else
+7 -1
View File
@@ -432,6 +432,8 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
const char* name = shader.EntryPoint();
std::string macro;
macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX);
macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN);
macro += fmt::format("#define HAS_BILN {}\n", static_cast<int>(shader.Biln()));
macro += fmt::format("#define HAS_STENCIL_OUTPUT {}\n", static_cast<int>(shader.StencilOutput()));
macro += fmt::format("#define HAS_INTEGER_OUTPUT {}\n", static_cast<int>(shader.IntegerOutputBpp() != 0));
@@ -609,9 +611,13 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
for (size_t i = 0; i < std::size(m_date.primid_ps); i++)
{
std::string macro;
macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX);
macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN);
const std::string ps(GetShaderSource(
fmt::format("ps_primid_image_init_{}", i),
GL_FRAGMENT_SHADER, *convert_glsl));
GL_FRAGMENT_SHADER, *convert_glsl, macro));
m_shader_cache.GetProgram(&m_date.primid_ps[i], m_convert.vs, ps);
m_date.primid_ps[i].SetFormattedName("PrimID Destination Alpha Init %d", i);
}
+9 -2
View File
@@ -4200,6 +4200,8 @@ bool GSDeviceVK::CompileConvertPipelines()
gpb.SetColorWriteMask(0, shader.Mask());
std::string macro;
macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX);
macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN);
macro += fmt::format("#define HAS_BILN {}\n", static_cast<int>(shader.Biln()));
macro += fmt::format("#define HAS_STENCIL_OUTPUT {}\n", static_cast<int>(shader.StencilOutput()));
macro += fmt::format("#define HAS_INTEGER_OUTPUT {}\n", static_cast<int>(shader.IntegerOutputBpp() != 0));
@@ -4267,9 +4269,14 @@ bool GSDeviceVK::CompileConvertPipelines()
for (u32 datm = 0; datm < 4; datm++)
{
std::string macro;
macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX);
macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN);
const std::string source_with_header = macro + *source;
const std::string entry_point(StringUtil::StdStringFromFormat("ps_primid_image_init_%d", datm));
VkShaderModule ps =
GetUtilityFragmentShader(*source, entry_point.c_str());
VkShaderModule ps = GetUtilityFragmentShader(source_with_header, entry_point.c_str());
if (ps == VK_NULL_HANDLE)
return false;
+2 -2
View File
@@ -104,9 +104,9 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Usage usage, Format format, int
if (format == Format::UNorm8)
{
// for r8 textures, swizzle it across all 4 components. the shaders depend on it being in alpha.. why?
// UNorm8 wants value in alpha, not red.
static constexpr const VkComponentMapping r8_swizzle = {
VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R };
VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_R };
vci.components = r8_swizzle;
}
+1 -1
View File
@@ -267,7 +267,7 @@ bool GameList::GetIsoSerialAndCRC(const std::string& path, s32* disc_type, std::
// TODO: we could include the version in the game list?
*disc_type = DoCDVDdetectDiskType();
cdvdGetDiscInfo(serial, nullptr, nullptr, crc, nullptr);
cdvdGetDiscInfo(serial, nullptr, nullptr, nullptr, crc, nullptr);
DoCDVDclose();
return true;
}
+1 -1
View File
@@ -679,7 +679,7 @@ void eeloadHook()
{
CDVDDiscType disc_type;
std::string disc_elf;
cdvdGetDiscInfo(nullptr, &disc_elf, nullptr, nullptr, &disc_type);
cdvdGetDiscInfo(nullptr, &disc_elf, nullptr, nullptr, nullptr, &disc_type);
if (disc_type == CDVDDiscType::PS2Disc)
{
// only allow fast boot for PS2 games
+1 -1
View File
@@ -3,4 +3,4 @@
/// Version number for GS and other shaders. Increment whenever any of the contents of the
/// shaders change, to invalidate the cache.
static constexpr u32 SHADER_CACHE_VERSION = 110; // Last changed in PR 14897
static constexpr u32 SHADER_CACHE_VERSION = 113; // Last changed in PR 14743
+10 -1
View File
@@ -171,6 +171,7 @@ static std::string s_disc_version;
static std::string s_title;
static std::string s_title_en_search;
static std::string s_title_en_replace;
static std::string s_cur_region;
static u32 s_disc_crc;
static u32 s_current_crc;
static u32 s_elf_entry_point = 0xFFFFFFFFu;
@@ -1051,11 +1052,12 @@ void VMManager::UpdateDiscDetails(bool booting)
s_disc_crc = GSDumpReplayer::GetDumpCRC();
s_disc_elf = {};
s_disc_version = {};
s_cur_region = "NTSC";
serial_is_valid = !s_disc_serial.empty();
}
else if (CDVDsys_GetSourceType() != CDVD_SourceType::NoDisc)
{
cdvdGetDiscInfo(&s_disc_serial, &s_disc_elf, &s_disc_version, &s_disc_crc, nullptr);
cdvdGetDiscInfo(&s_disc_serial, &s_disc_elf, &s_disc_version, &s_cur_region, &s_disc_crc, nullptr);
serial_is_valid = !s_disc_serial.empty();
}
else if (!s_elf_override.empty())
@@ -1063,12 +1065,14 @@ void VMManager::UpdateDiscDetails(bool booting)
s_disc_serial = Path::GetFileTitle(s_elf_override);
s_disc_version = {};
s_disc_crc = 0; // set below
s_cur_region = "NTSC";
}
else
{
s_disc_serial = BiosSerial;
s_disc_version = {};
s_disc_crc = 0;
s_cur_region = (BiosZone == "Europe") ? "PAL" : "NTSC";
title = fmt::format(TRANSLATE_FS("VMManager", "PS2 BIOS ({})"), BiosZone);
}
@@ -2818,6 +2822,11 @@ bool VMManager::Internal::IsFastBootInProgress()
return s_fast_boot_requested && !HasBootedELF();
}
std::string VMManager::Internal::GetCurrentRegion()
{
return s_cur_region;
}
void VMManager::Internal::DisableFastBoot()
{
if (!s_fast_boot_requested)
+3
View File
@@ -306,6 +306,9 @@ namespace VMManager
/// Returns true if fast booting is active (requested but ELF not started).
bool IsFastBootInProgress();
// Returns the current disc/BIOS region, if set.
std::string GetCurrentRegion();
/// Disables fast boot if it was requested, and found to be incompatible.
void DisableFastBoot();