mirror of
				https://github.com/hedge-dev/UnleashedRecomp.git
				synced 2025-10-30 07:11:05 +00:00 
			
		
		
		
	Compare commits
	
		
			2 commits
		
	
	
		
			4744a5e1a2
			...
			8633787306
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
							 | 
						8633787306 | ||
| 
							 | 
						d62e55ad22 | 
					 71 changed files with 1224 additions and 152 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
	url = https://github.com/redorav/ddspp.git
 | 
			
		||||
[submodule "tools/XenosRecomp"]
 | 
			
		||||
	path = tools/XenosRecomp
 | 
			
		||||
	url = https://github.com/hedge-dev/XenosRecomp.git
 | 
			
		||||
	url = https://github.com/squidbus/XenosRecomp.git
 | 
			
		||||
[submodule "UnleashedRecompResources"]
 | 
			
		||||
	path = UnleashedRecompResources
 | 
			
		||||
	url = https://github.com/hedge-dev/UnleashedRecompResources.git
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,11 @@ if (UNLEASHED_RECOMP_ARCHITECTURE STREQUAL "x86_64" OR UNLEASHED_RECOMP_ARCHITEC
 | 
			
		|||
    )
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
 | 
			
		||||
    # Normally only defined by Visual Studio, added for consistency
 | 
			
		||||
    add_compile_definitions(_DEBUG)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
add_subdirectory(${UNLEASHED_RECOMP_THIRDPARTY_ROOT})
 | 
			
		||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,10 @@ if (WIN32)
 | 
			
		|||
    option(UNLEASHED_RECOMP_D3D12 "Add D3D12 support for rendering" ON)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if (APPLE)
 | 
			
		||||
    option(UNLEASHED_RECOMP_METAL "Add Metal support for rendering" ON)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
 | 
			
		||||
    option(UNLEASHED_RECOMP_FLATPAK "Configure the build for Flatpak compatibility." OFF)
 | 
			
		||||
endif()
 | 
			
		||||
| 
						 | 
				
			
			@ -255,6 +259,10 @@ if (NOT ${CMAKE_BUILD_TYPE} MATCHES "Release")
 | 
			
		|||
    set(SHOW_GIT_INFO_AND_BUILD_TYPE 1)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if (UNLEASHED_RECOMP_METAL)
 | 
			
		||||
    set(XCRUN_TOOL "/usr/bin/xcrun")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
GenerateVersionSources(
 | 
			
		||||
    OUTPUT_DIR ${PROJECT_SOURCE_DIR}
 | 
			
		||||
    VERSION_TXT ${VERSION_TXT}
 | 
			
		||||
| 
						 | 
				
			
			@ -375,6 +383,10 @@ if (UNLEASHED_RECOMP_D3D12)
 | 
			
		|||
    )
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if (UNLEASHED_RECOMP_METAL)
 | 
			
		||||
    target_compile_definitions(UnleashedRecomp PRIVATE UNLEASHED_RECOMP_METAL)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if (WIN32)
 | 
			
		||||
    target_link_libraries(UnleashedRecomp PRIVATE
 | 
			
		||||
        comctl32
 | 
			
		||||
| 
						 | 
				
			
			@ -418,22 +430,37 @@ endif()
 | 
			
		|||
target_precompile_headers(UnleashedRecomp PUBLIC ${UNLEASHED_RECOMP_PRECOMPILED_HEADERS})
 | 
			
		||||
 | 
			
		||||
function(compile_shader FILE_PATH TARGET_NAME)
 | 
			
		||||
    set(FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gpu/shader/${FILE_PATH}.hlsl)
 | 
			
		||||
    cmake_path(GET FILE_PATH STEM VARIABLE_NAME)
 | 
			
		||||
    set(HLSL_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gpu/shader/hlsl/${FILE_PATH}.hlsl)
 | 
			
		||||
    set(MSL_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gpu/shader/msl/${FILE_PATH}.metal)
 | 
			
		||||
    cmake_path(GET HLSL_FILE_PATH STEM HLSL_NAME)
 | 
			
		||||
    cmake_path(GET MSL_FILE_PATH STEM MSL_NAME)
 | 
			
		||||
    if (UNLEASHED_RECOMP_METAL)
 | 
			
		||||
        add_custom_command(
 | 
			
		||||
                OUTPUT ${MSL_FILE_PATH}.ir
 | 
			
		||||
                COMMAND ${XCRUN_TOOL} -sdk macosx metal -o ${MSL_FILE_PATH}.ir -c ${MSL_FILE_PATH} -D__air__ -frecord-sources -gline-tables-only
 | 
			
		||||
                DEPENDS ${MSL_FILE_PATH}
 | 
			
		||||
        )
 | 
			
		||||
        add_custom_command(
 | 
			
		||||
                OUTPUT ${MSL_FILE_PATH}.metallib
 | 
			
		||||
                COMMAND ${XCRUN_TOOL} -sdk macosx metallib -o ${MSL_FILE_PATH}.metallib ${MSL_FILE_PATH}.ir
 | 
			
		||||
                DEPENDS ${MSL_FILE_PATH}.ir
 | 
			
		||||
        )
 | 
			
		||||
        BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${MSL_FILE_PATH}.metallib" DEST_FILE "${MSL_FILE_PATH}.metallib" ARRAY_NAME "g_${MSL_NAME}_air")
 | 
			
		||||
    endif()
 | 
			
		||||
    if (UNLEASHED_RECOMP_D3D12)
 | 
			
		||||
        add_custom_command(
 | 
			
		||||
            OUTPUT ${FILE_PATH}.dxil.h
 | 
			
		||||
            COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -Wno-ignored-attributes -Fh ${FILE_PATH}.dxil.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_dxil
 | 
			
		||||
            DEPENDS ${FILE_PATH}
 | 
			
		||||
            OUTPUT ${HLSL_FILE_PATH}.dxil.h
 | 
			
		||||
            COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -Wno-ignored-attributes -E shaderMain -Fh ${HLSL_FILE_PATH}.dxil.h ${HLSL_FILE_PATH} -Vn g_${HLSL_NAME}_dxil
 | 
			
		||||
            DEPENDS ${HLSL_FILE_PATH}
 | 
			
		||||
        )
 | 
			
		||||
        target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.dxil.h)
 | 
			
		||||
        target_sources(UnleashedRecomp PRIVATE ${HLSL_FILE_PATH}.dxil.h)
 | 
			
		||||
    endif()
 | 
			
		||||
    add_custom_command(
 | 
			
		||||
        OUTPUT ${FILE_PATH}.spirv.h
 | 
			
		||||
        COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -spirv -fvk-use-dx-layout ${ARGN} -Fh ${FILE_PATH}.spirv.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_spirv
 | 
			
		||||
        DEPENDS ${FILE_PATH}
 | 
			
		||||
        OUTPUT ${HLSL_FILE_PATH}.spirv.h
 | 
			
		||||
        COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -spirv -fvk-use-dx-layout ${ARGN} -E shaderMain -Fh ${HLSL_FILE_PATH}.spirv.h ${HLSL_FILE_PATH} -Vn g_${HLSL_NAME}_spirv
 | 
			
		||||
        DEPENDS ${HLSL_FILE_PATH}
 | 
			
		||||
    )
 | 
			
		||||
    target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.spirv.h)
 | 
			
		||||
    target_sources(UnleashedRecomp PRIVATE ${HLSL_FILE_PATH}.spirv.h)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
function(compile_vertex_shader FILE_PATH)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@
 | 
			
		|||
#define IMGUI_SHADER_MODIFIER_RECTANGLE_BEVEL          10
 | 
			
		||||
#define IMGUI_SHADER_MODIFIER_LOW_QUALITY_TEXT         11
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
#if defined(__cplusplus) && !defined(__air__)
 | 
			
		||||
 | 
			
		||||
enum class ImGuiCallback : int32_t
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __spirv__
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ cbuffer SharedConstants : register(b2, space4)
 | 
			
		|||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
float4 main(
 | 
			
		||||
float4 shaderMain(
 | 
			
		||||
    in float4 iPos : SV_Position,
 | 
			
		||||
    in float4 iTexCoord0 : TEXCOORD0) : SV_Target0
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 | 
			
		||||
Texture2D<float4> g_Texture2DDescriptorHeap[] : register(t0, space0);
 | 
			
		||||
 | 
			
		||||
float4 main(in float4 position : SV_Position) : SV_Target
 | 
			
		||||
float4 shaderMain(in float4 position : SV_Position) : SV_Target
 | 
			
		||||
{
 | 
			
		||||
    return g_Texture2DDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].Load(int3(position.xy, 0));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 | 
			
		||||
Texture2D<float> g_Texture2DDescriptorHeap[] : register(t0, space0);
 | 
			
		||||
 | 
			
		||||
float main(in float4 position : SV_Position) : SV_Depth
 | 
			
		||||
float shaderMain(in float4 position : SV_Position) : SV_Depth
 | 
			
		||||
{
 | 
			
		||||
    return g_Texture2DDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].Load(int3(position.xy, 0));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
void main(in uint vertexId : SV_VertexID, out float4 position : SV_Position, out float2 texCoord : TEXCOORD)
 | 
			
		||||
void shaderMain(in uint vertexId : SV_VertexID, out float4 position : SV_Position, out float2 texCoord : TEXCOORD)
 | 
			
		||||
{
 | 
			
		||||
    texCoord = float2((vertexId << 1) & 2, vertexId & 2);
 | 
			
		||||
    position = float4(texCoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __spirv__
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ cbuffer SharedConstants : register(b2, space4)
 | 
			
		|||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
float4 main(
 | 
			
		||||
float4 shaderMain(
 | 
			
		||||
	in float4 iPosition : SV_Position,
 | 
			
		||||
	in float4 iTexCoord0 : TEXCOORD0,
 | 
			
		||||
	in float4 iTexCoord1 : TEXCOORD1) : SV_Target
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __spirv__
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ cbuffer SharedConstants : register(b2, space4)
 | 
			
		|||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void main(
 | 
			
		||||
void shaderMain(
 | 
			
		||||
	[[vk::location(0)]] in float4 iPosition0 : POSITION0,
 | 
			
		||||
	[[vk::location(8)]] in float4 iColor0 : COLOR0,
 | 
			
		||||
	out float4 oPos : SV_Position,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __spirv__
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ cbuffer SharedConstants : register(b2, space4)
 | 
			
		|||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void main(
 | 
			
		||||
void shaderMain(
 | 
			
		||||
	[[vk::location(0)]] in float4 iPosition0 : POSITION0,
 | 
			
		||||
	[[vk::location(8)]] in float4 iColor0 : COLOR0,
 | 
			
		||||
	[[vk::location(4)]] in float4 iTexCoord0 : TEXCOORD0,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __spirv__
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ cbuffer SharedConstants : register(b2, space4)
 | 
			
		|||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
float4 main(in float4 position : SV_Position, in float4 texCoord : TEXCOORD0) : SV_Target
 | 
			
		||||
float4 shaderMain(in float4 position : SV_Position, in float4 texCoord : TEXCOORD0) : SV_Target
 | 
			
		||||
{
 | 
			
		||||
    Texture2D<float4> sampColor = g_Texture2DDescriptorHeap[sampColor_Texture2DDescriptorIndex];
 | 
			
		||||
    Texture2D<float4> sampVelocityMap = g_Texture2DDescriptorHeap[sampVelocityMap_Texture2DDescriptorIndex];
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __spirv__
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ cbuffer SharedConstants : register(b2, space4)
 | 
			
		|||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
float4 main(in float4 position : SV_Position) : SV_Target
 | 
			
		||||
float4 shaderMain(in float4 position : SV_Position) : SV_Target
 | 
			
		||||
{
 | 
			
		||||
    Texture2D<float4> texture = g_Texture2DDescriptorHeap[g_TextureDescriptorIndex];
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __spirv__
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ float ComputeWeight(float x)
 | 
			
		|||
    return exp(-(x * x) / (2.0 * std * std)) / (std * sqrt(2.0 * PI));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float4 main(in float4 iPosition : SV_Position, in float4 iTexCoord0 : TEXCOORD0) : SV_Target
 | 
			
		||||
float4 shaderMain(in float4 iPosition : SV_Position, in float4 iTexCoord0 : TEXCOORD0) : SV_Target
 | 
			
		||||
{
 | 
			
		||||
    Texture2D<float4> texture = g_Texture2DDescriptorHeap[s0_Texture2DDescriptorIndex];
 | 
			
		||||
    SamplerState samplerState = g_SamplerDescriptorHeap[s0_SamplerDescriptorIndex];
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "../imgui/imgui_common.h"
 | 
			
		||||
#include "../../imgui/imgui_common.h"
 | 
			
		||||
 | 
			
		||||
struct PushConstants
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +123,7 @@ float4 SampleSdfFont(float4 color, Texture2D<float4> texture, float2 uv, float2
 | 
			
		|||
    return color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float4 main(in Interpolators interpolators) : SV_Target
 | 
			
		||||
float4 shaderMain(in Interpolators interpolators) : SV_Target
 | 
			
		||||
{
 | 
			
		||||
    float4 color = interpolators.Color;
 | 
			
		||||
    color *= PixelAntialiasing(interpolators.Position.xy - g_PushConstants.ProceduralOrigin);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
#include "imgui_common.hlsli"
 | 
			
		||||
 | 
			
		||||
void main(in float2 position : POSITION, in float2 uv : TEXCOORD, in float4 color : COLOR, out Interpolators interpolators)
 | 
			
		||||
void shaderMain(in float2 position : POSITION, in float2 uv : TEXCOORD, in float4 color : COLOR, out Interpolators interpolators)
 | 
			
		||||
{    
 | 
			
		||||
    if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TEXT_SKEW)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __spirv__
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
#include "movie_common.hlsli"
 | 
			
		||||
 | 
			
		||||
PixelShaderOutput main(in Interpolators In)
 | 
			
		||||
PixelShaderOutput shaderMain(in Interpolators In)
 | 
			
		||||
{
 | 
			
		||||
    Texture2D<float4> Tex0 = g_Texture2DDescriptorHeap[Tex0_ResourceDescriptorIndex];
 | 
			
		||||
    Texture2D<float4> Tex1 = g_Texture2DDescriptorHeap[Tex1_ResourceDescriptorIndex];
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
#include "movie_common.hlsli"
 | 
			
		||||
 | 
			
		||||
Interpolators main(in VertexShaderInput In)
 | 
			
		||||
Interpolators shaderMain(in VertexShaderInput In)
 | 
			
		||||
{
 | 
			
		||||
    Interpolators Out;
 | 
			
		||||
    Out.ProjPos = In.ObjPos;
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
 | 
			
		||||
Texture2DMS<float4, SAMPLE_COUNT> g_Texture2DMSDescriptorHeap[] : register(t0, space0);
 | 
			
		||||
 | 
			
		||||
float4 main(in float4 position : SV_Position) : SV_Target
 | 
			
		||||
float4 shaderMain(in float4 position : SV_Position) : SV_Target
 | 
			
		||||
{
 | 
			
		||||
    float4 result = g_Texture2DMSDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].Load(int2(position.xy), 0);
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
 | 
			
		||||
Texture2DMS<float, SAMPLE_COUNT> g_Texture2DMSDescriptorHeap[] : register(t0, space0);
 | 
			
		||||
 | 
			
		||||
float main(in float4 position : SV_Position) : SV_Depth
 | 
			
		||||
float shaderMain(in float4 position : SV_Position) : SV_Depth
 | 
			
		||||
{
 | 
			
		||||
    float result = g_Texture2DMSDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].Load(int2(position.xy), 0);
 | 
			
		||||
    
 | 
			
		||||
							
								
								
									
										4
									
								
								UnleashedRecomp/gpu/shader/msl/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								UnleashedRecomp/gpu/shader/msl/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
*.ir
 | 
			
		||||
*.metallib
 | 
			
		||||
*.metal.*.c
 | 
			
		||||
*.metal.*.h
 | 
			
		||||
							
								
								
									
										31
									
								
								UnleashedRecomp/gpu/shader/msl/blend_color_alpha_ps.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								UnleashedRecomp/gpu/shader/msl/blend_color_alpha_ps.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#define g_SrcAlpha_DestAlpha (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 2400)))
 | 
			
		||||
#define s0_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
 | 
			
		||||
#define s0_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 192)))
 | 
			
		||||
 | 
			
		||||
struct Interpolators
 | 
			
		||||
{
 | 
			
		||||
    float4 iTexCoord0 [[user(TEXCOORD0)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
float4 shaderMain(float4 iPos [[position]],
 | 
			
		||||
                  Interpolators input [[stage_in]],
 | 
			
		||||
                  constant Texture2DDescriptorHeap* g_Texture2DDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                  constant SamplerDescriptorHeap* g_SamplerDescriptorHeap [[buffer(3)]],
 | 
			
		||||
                  constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    texture2d<float> texture = g_Texture2DDescriptorHeap[s0_Texture2DDescriptorIndex].tex;
 | 
			
		||||
    sampler samplerState = g_SamplerDescriptorHeap[s0_SamplerDescriptorIndex].samp;
 | 
			
		||||
    
 | 
			
		||||
    float4 color = texture.sample(samplerState, input.iTexCoord0.xy);
 | 
			
		||||
    
 | 
			
		||||
    if (any(input.iTexCoord0.xy < 0.0 || input.iTexCoord0.xy > 1.0))
 | 
			
		||||
        color = float4(0.0, 0.0, 0.0, 1.0);
 | 
			
		||||
    
 | 
			
		||||
    color.rgb *= color.a * g_SrcAlpha_DestAlpha.x;
 | 
			
		||||
    color.a = g_SrcAlpha_DestAlpha.y + (1.0 - color.a) * g_SrcAlpha_DestAlpha.x;
 | 
			
		||||
    
 | 
			
		||||
    return color;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								UnleashedRecomp/gpu/shader/msl/copy_color_ps.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								UnleashedRecomp/gpu/shader/msl/copy_color_ps.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
#include "copy_common.metali"
 | 
			
		||||
 | 
			
		||||
struct Texture2DDescriptorHeap
 | 
			
		||||
{
 | 
			
		||||
    texture2d<float> tex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
float4 shaderMain(float4 position [[position]],
 | 
			
		||||
                  constant Texture2DDescriptorHeap* g_Texture2DDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                  constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    return g_Texture2DDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].tex.read(uint2(position.xy), 0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								UnleashedRecomp/gpu/shader/msl/copy_common.metali
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								UnleashedRecomp/gpu/shader/msl/copy_common.metali
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
#include <metal_stdlib>
 | 
			
		||||
 | 
			
		||||
using namespace metal;
 | 
			
		||||
 | 
			
		||||
struct PushConstants
 | 
			
		||||
{
 | 
			
		||||
    uint ResourceDescriptorIndex;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										23
									
								
								UnleashedRecomp/gpu/shader/msl/copy_depth_ps.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								UnleashedRecomp/gpu/shader/msl/copy_depth_ps.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
#include "copy_common.metali"
 | 
			
		||||
 | 
			
		||||
struct Texture2DDescriptorHeap
 | 
			
		||||
{
 | 
			
		||||
    texture2d<float> tex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct PixelShaderOutput
 | 
			
		||||
{
 | 
			
		||||
    float oDepth [[depth(any)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
PixelShaderOutput shaderMain(float4 position [[position]],
 | 
			
		||||
                             constant Texture2DDescriptorHeap* g_Texture2DDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                             constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    PixelShaderOutput output = PixelShaderOutput{};
 | 
			
		||||
 | 
			
		||||
    output.oDepth = g_Texture2DDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].tex.read(uint2(position.xy), 0).x;
 | 
			
		||||
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								UnleashedRecomp/gpu/shader/msl/copy_vs.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								UnleashedRecomp/gpu/shader/msl/copy_vs.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
struct Interpolators
 | 
			
		||||
{
 | 
			
		||||
    float4 position [[position]];
 | 
			
		||||
    float2 texCoord [[user(TEXCOORD)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[vertex]]
 | 
			
		||||
Interpolators shaderMain(uint vertexId [[vertex_id]])
 | 
			
		||||
{
 | 
			
		||||
    Interpolators interpolators;
 | 
			
		||||
 | 
			
		||||
    interpolators.texCoord = float2((vertexId << 1) & 2, vertexId & 2);
 | 
			
		||||
    interpolators.position = float4(interpolators.texCoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
 | 
			
		||||
 | 
			
		||||
    return interpolators;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								UnleashedRecomp/gpu/shader/msl/csd_filter_ps.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								UnleashedRecomp/gpu/shader/msl/csd_filter_ps.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#define s0_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
 | 
			
		||||
#define s0_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 192)))
 | 
			
		||||
 | 
			
		||||
struct Interpolators
 | 
			
		||||
{
 | 
			
		||||
    float4 iPosition [[position]];
 | 
			
		||||
    float4 iTexCoord0 [[user(TEXCOORD0)]];
 | 
			
		||||
    float4 iTexCoord1 [[user(TEXCOORD1)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
float4 shaderMain(Interpolators input [[stage_in]],
 | 
			
		||||
                  constant Texture2DDescriptorHeap* g_Texture2DDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                  constant SamplerDescriptorHeap* g_SamplerDescriptorHeap [[buffer(3)]],
 | 
			
		||||
                  constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    texture2d<float> texture = g_Texture2DDescriptorHeap[s0_Texture2DDescriptorIndex].tex;
 | 
			
		||||
    sampler samplerState = g_SamplerDescriptorHeap[s0_SamplerDescriptorIndex].samp;
 | 
			
		||||
 | 
			
		||||
    uint2 dimensions = getTexture2DDimensions(texture);
 | 
			
		||||
 | 
			
		||||
    // https://www.shadertoy.com/view/csX3RH
 | 
			
		||||
    float2 uvTexspace = input.iTexCoord1.xy * float2(dimensions);
 | 
			
		||||
    float2 seam = floor(uvTexspace + 0.5);
 | 
			
		||||
    uvTexspace = (uvTexspace - seam) / fwidth(uvTexspace) + seam;
 | 
			
		||||
    uvTexspace = clamp(uvTexspace, seam - 0.5, seam + 0.5);
 | 
			
		||||
    float2 texCoord = uvTexspace / float2(dimensions);
 | 
			
		||||
    
 | 
			
		||||
    float4 color = texture.sample(samplerState, texCoord);
 | 
			
		||||
    color *= input.iTexCoord0;
 | 
			
		||||
    
 | 
			
		||||
    // The game enables alpha test for CSD, but the alpha threshold doesn't seem to be assigned anywhere? Weird.
 | 
			
		||||
    clip(color.a - g_AlphaThreshold);
 | 
			
		||||
    
 | 
			
		||||
    return color;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								UnleashedRecomp/gpu/shader/msl/csd_no_tex_vs.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								UnleashedRecomp/gpu/shader/msl/csd_no_tex_vs.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#define g_ViewportSize (*(reinterpret_cast<device float4*>(g_PushConstants.VertexShaderConstants + 2880)))
 | 
			
		||||
#define g_Z (*(reinterpret_cast<device float4*>(g_PushConstants.VertexShaderConstants + 3936)))
 | 
			
		||||
 | 
			
		||||
struct VertexShaderInput
 | 
			
		||||
{
 | 
			
		||||
    float4 iPosition0 [[attribute(0)]];
 | 
			
		||||
    float4 iColor0 [[attribute(8)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Interpolators
 | 
			
		||||
{
 | 
			
		||||
    float4 oPos [[position]];
 | 
			
		||||
    float4 oTexCoord0 [[user(TEXCOORD0)]];
 | 
			
		||||
    float4 oTexCoord1 [[user(TEXCOORD1)]];
 | 
			
		||||
    float4 oTexCoord2 [[user(TEXCOORD2)]];
 | 
			
		||||
    float4 oTexCoord3 [[user(TEXCOORD3)]];
 | 
			
		||||
    float4 oTexCoord4 [[user(TEXCOORD4)]];
 | 
			
		||||
    float4 oTexCoord5 [[user(TEXCOORD5)]];
 | 
			
		||||
    float4 oTexCoord6 [[user(TEXCOORD6)]];
 | 
			
		||||
    float4 oTexCoord7 [[user(TEXCOORD7)]];
 | 
			
		||||
    float4 oTexCoord8 [[user(TEXCOORD8)]];
 | 
			
		||||
    float4 oTexCoord9 [[user(TEXCOORD9)]];
 | 
			
		||||
    float4 oTexCoord10 [[user(TEXCOORD10)]];
 | 
			
		||||
    float4 oTexCoord11 [[user(TEXCOORD11)]];
 | 
			
		||||
    float4 oTexCoord12 [[user(TEXCOORD12)]];
 | 
			
		||||
    float4 oTexCoord13 [[user(TEXCOORD13)]];
 | 
			
		||||
    float4 oTexCoord14 [[user(TEXCOORD14)]];
 | 
			
		||||
    float4 oTexCoord15 [[user(TEXCOORD15)]];
 | 
			
		||||
    float4 oColor0 [[user(COLOR0)]];
 | 
			
		||||
    float4 oColor1 [[user(COLOR1)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[vertex]]
 | 
			
		||||
Interpolators shaderMain(VertexShaderInput input [[stage_in]],
 | 
			
		||||
                         constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    Interpolators output;
 | 
			
		||||
 | 
			
		||||
    output.oPos.xy = input.iPosition0.xy * g_ViewportSize.zw * float2(2.0, -2.0) + float2(-1.0, 1.0);
 | 
			
		||||
    output.oPos.z = g_Z.x;
 | 
			
		||||
    output.oPos.w = 1.0;
 | 
			
		||||
    output.oTexCoord0 = input.iColor0.wxyz;
 | 
			
		||||
    output.oTexCoord1 = 0.0;
 | 
			
		||||
    output.oTexCoord2 = 0.0;
 | 
			
		||||
    output.oTexCoord3 = 0.0;
 | 
			
		||||
    output.oTexCoord4 = 0.0;
 | 
			
		||||
    output.oTexCoord5 = 0.0;
 | 
			
		||||
    output.oTexCoord6 = 0.0;
 | 
			
		||||
    output.oTexCoord7 = 0.0;
 | 
			
		||||
    output.oTexCoord8 = 0.0;
 | 
			
		||||
    output.oTexCoord9 = 0.0;
 | 
			
		||||
    output.oTexCoord10 = 0.0;
 | 
			
		||||
    output.oTexCoord11 = 0.0;
 | 
			
		||||
    output.oTexCoord12 = 0.0;
 | 
			
		||||
    output.oTexCoord13 = 0.0;
 | 
			
		||||
    output.oTexCoord14 = 0.0;
 | 
			
		||||
    output.oTexCoord15 = 0.0;
 | 
			
		||||
    output.oColor0 = 0.0;
 | 
			
		||||
    output.oColor1 = 0.0;
 | 
			
		||||
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								UnleashedRecomp/gpu/shader/msl/csd_vs.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								UnleashedRecomp/gpu/shader/msl/csd_vs.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,66 @@
 | 
			
		|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#define g_ViewportSize (*(reinterpret_cast<device float4*>(g_PushConstants.VertexShaderConstants + 2880)))
 | 
			
		||||
#define g_Z (*(reinterpret_cast<device float4*>(g_PushConstants.VertexShaderConstants + 3936)))
 | 
			
		||||
 | 
			
		||||
struct VertexShaderInput
 | 
			
		||||
{
 | 
			
		||||
    float4 iPosition0 [[attribute(0)]];
 | 
			
		||||
    float4 iColor0 [[attribute(8)]];
 | 
			
		||||
    float4 iTexCoord0 [[attribute(4)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Interpolators
 | 
			
		||||
{
 | 
			
		||||
    float4 oPos [[position]];
 | 
			
		||||
    float4 oTexCoord0 [[user(TEXCOORD0)]];
 | 
			
		||||
    float4 oTexCoord1 [[user(TEXCOORD1)]];
 | 
			
		||||
    float4 oTexCoord2 [[user(TEXCOORD2)]];
 | 
			
		||||
    float4 oTexCoord3 [[user(TEXCOORD3)]];
 | 
			
		||||
    float4 oTexCoord4 [[user(TEXCOORD4)]];
 | 
			
		||||
    float4 oTexCoord5 [[user(TEXCOORD5)]];
 | 
			
		||||
    float4 oTexCoord6 [[user(TEXCOORD6)]];
 | 
			
		||||
    float4 oTexCoord7 [[user(TEXCOORD7)]];
 | 
			
		||||
    float4 oTexCoord8 [[user(TEXCOORD8)]];
 | 
			
		||||
    float4 oTexCoord9 [[user(TEXCOORD9)]];
 | 
			
		||||
    float4 oTexCoord10 [[user(TEXCOORD10)]];
 | 
			
		||||
    float4 oTexCoord11 [[user(TEXCOORD11)]];
 | 
			
		||||
    float4 oTexCoord12 [[user(TEXCOORD12)]];
 | 
			
		||||
    float4 oTexCoord13 [[user(TEXCOORD13)]];
 | 
			
		||||
    float4 oTexCoord14 [[user(TEXCOORD14)]];
 | 
			
		||||
    float4 oTexCoord15 [[user(TEXCOORD15)]];
 | 
			
		||||
    float4 oColor0 [[user(COLOR0)]];
 | 
			
		||||
    float4 oColor1 [[user(COLOR1)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[vertex]]
 | 
			
		||||
Interpolators shaderMain(VertexShaderInput input [[stage_in]],
 | 
			
		||||
                         constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    Interpolators output;
 | 
			
		||||
 | 
			
		||||
    output.oPos.xy = input.iPosition0.xy * g_ViewportSize.zw * float2(2.0, -2.0) + float2(-1.0, 1.0);
 | 
			
		||||
    output.oPos.z = g_Z.x;
 | 
			
		||||
    output.oPos.w = 1.0;
 | 
			
		||||
    output.oTexCoord0 = input.iColor0.wxyz;
 | 
			
		||||
    output.oTexCoord1.xy = input.iTexCoord0.xy;
 | 
			
		||||
    output.oTexCoord1.zw = 0.0;
 | 
			
		||||
    output.oTexCoord2 = 0.0;
 | 
			
		||||
    output.oTexCoord3 = 0.0;
 | 
			
		||||
    output.oTexCoord4 = 0.0;
 | 
			
		||||
    output.oTexCoord5 = 0.0;
 | 
			
		||||
    output.oTexCoord6 = 0.0;
 | 
			
		||||
    output.oTexCoord7 = 0.0;
 | 
			
		||||
    output.oTexCoord8 = 0.0;
 | 
			
		||||
    output.oTexCoord9 = 0.0;
 | 
			
		||||
    output.oTexCoord10 = 0.0;
 | 
			
		||||
    output.oTexCoord11 = 0.0;
 | 
			
		||||
    output.oTexCoord12 = 0.0;
 | 
			
		||||
    output.oTexCoord13 = 0.0;
 | 
			
		||||
    output.oTexCoord14 = 0.0;
 | 
			
		||||
    output.oTexCoord15 = 0.0;
 | 
			
		||||
    output.oColor0 = 0.0;
 | 
			
		||||
    output.oColor1 = 0.0;
 | 
			
		||||
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								UnleashedRecomp/gpu/shader/msl/enhanced_motion_blur_ps.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								UnleashedRecomp/gpu/shader/msl/enhanced_motion_blur_ps.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#define g_BlurRate (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 2400)))
 | 
			
		||||
#define g_ViewportSize (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 384)))
 | 
			
		||||
 | 
			
		||||
#define sampColor_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
 | 
			
		||||
#define sampColor_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 192)))
 | 
			
		||||
 | 
			
		||||
#define sampVelocityMap_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 4)))
 | 
			
		||||
#define sampVelocityMap_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 196)))
 | 
			
		||||
 | 
			
		||||
#define sampZBuffer_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 8)))
 | 
			
		||||
#define sampZBuffer_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 200)))
 | 
			
		||||
 | 
			
		||||
struct Interpolators
 | 
			
		||||
{
 | 
			
		||||
    float4 texCoord [[user(TEXCOORD0)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
float4 shaderMain(float4 position [[position]],
 | 
			
		||||
                  Interpolators input [[stage_in]],
 | 
			
		||||
                  constant Texture2DDescriptorHeap* g_Texture2DDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                  constant SamplerDescriptorHeap* g_SamplerDescriptorHeap [[buffer(3)]],
 | 
			
		||||
                  constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    texture2d<float> sampColor = g_Texture2DDescriptorHeap[sampColor_Texture2DDescriptorIndex].tex;
 | 
			
		||||
    texture2d<float> sampVelocityMap = g_Texture2DDescriptorHeap[sampVelocityMap_Texture2DDescriptorIndex].tex;
 | 
			
		||||
    texture2d<float> sampZBuffer = g_Texture2DDescriptorHeap[sampZBuffer_Texture2DDescriptorIndex].tex;
 | 
			
		||||
    
 | 
			
		||||
    sampler sampColor_s = g_SamplerDescriptorHeap[sampColor_SamplerDescriptorIndex].samp;
 | 
			
		||||
    sampler sampVelocityMap_s = g_SamplerDescriptorHeap[sampVelocityMap_SamplerDescriptorIndex].samp;
 | 
			
		||||
    sampler sampZBuffer_s = g_SamplerDescriptorHeap[sampZBuffer_SamplerDescriptorIndex].samp;
 | 
			
		||||
    
 | 
			
		||||
    float depth = sampZBuffer.sample(sampZBuffer_s, input.texCoord.xy, level(0)).x;
 | 
			
		||||
    float4 velocityMap = sampVelocityMap.sample(sampVelocityMap_s, input.texCoord.xy, level(0));
 | 
			
		||||
    float2 velocity = (velocityMap.xz + velocityMap.yw / 255.0) * 2.0 - 1.0;
 | 
			
		||||
 | 
			
		||||
    int sampleCount = min(64, int(round(length(velocity * g_ViewportSize.xy))));
 | 
			
		||||
    float2 sampleOffset = velocity / (float) sampleCount;
 | 
			
		||||
 | 
			
		||||
    float3 color = sampColor.sample(sampColor_s, input.texCoord.xy, level(0)).rgb;
 | 
			
		||||
    int count = 1;
 | 
			
		||||
 | 
			
		||||
    for (int i = 1; i <= sampleCount; i++)
 | 
			
		||||
    {
 | 
			
		||||
        float2 sampleCoord = input.texCoord.xy + sampleOffset * i;
 | 
			
		||||
        float3 sampleColor = sampColor.sample(sampColor_s, sampleCoord, level(0)).rgb;
 | 
			
		||||
        float sampleDepth = sampZBuffer.sample(sampZBuffer_s, sampleCoord, 0).x;
 | 
			
		||||
 | 
			
		||||
        if (sampleDepth - depth < 0.01)
 | 
			
		||||
        {
 | 
			
		||||
            color += sampleColor;
 | 
			
		||||
            count += 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return float4(color / count, g_BlurRate.x * saturate(dot(abs(velocity), g_ViewportSize.xy) / 8.0) * saturate(float(count - 1)));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								UnleashedRecomp/gpu/shader/msl/gamma_correction_ps.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								UnleashedRecomp/gpu/shader/msl/gamma_correction_ps.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#define g_Gamma (*(reinterpret_cast<device float3*>(g_PushConstants.SharedConstants + 0)))
 | 
			
		||||
#define g_TextureDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 12)))
 | 
			
		||||
 | 
			
		||||
#define g_ViewportOffset (*(reinterpret_cast<device int2*>(g_PushConstants.SharedConstants + 16)))
 | 
			
		||||
#define g_ViewportSize (*(reinterpret_cast<device int2*>(g_PushConstants.SharedConstants + 24)))
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
float4 shaderMain(float4 position [[position]],
 | 
			
		||||
                  constant Texture2DDescriptorHeap* g_Texture2DDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                  constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    texture2d<float> texture = g_Texture2DDescriptorHeap[g_TextureDescriptorIndex].tex;
 | 
			
		||||
    
 | 
			
		||||
    int2 movedPosition = int2(position.xy) - g_ViewportOffset;
 | 
			
		||||
    bool boxed = any(movedPosition < 0) || any(movedPosition >= g_ViewportSize);
 | 
			
		||||
    if (boxed) movedPosition = 0;
 | 
			
		||||
    
 | 
			
		||||
    float4 color = boxed ? 0.0 : texture.read(uint2(movedPosition), 0);
 | 
			
		||||
    color.rgb = pow(color.rgb, g_Gamma);
 | 
			
		||||
    return color;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur.metali
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur.metali
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#define g_ViewportSize (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 384)))
 | 
			
		||||
#define g_offsets(INDEX) selectWrapper((INDEX) < 74,(*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + (150 + min(INDEX, 73)) * 16))), 0.0)
 | 
			
		||||
#define g_weights (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 2656)))
 | 
			
		||||
 | 
			
		||||
#define s0_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
 | 
			
		||||
#define s0_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 192)))
 | 
			
		||||
 | 
			
		||||
#ifdef __INTELLISENSE__
 | 
			
		||||
#define KERNEL_SIZE 5
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define PI 3.14159265358979323846
 | 
			
		||||
 | 
			
		||||
float ComputeWeight(float x)
 | 
			
		||||
{
 | 
			
		||||
    float std = 0.952;
 | 
			
		||||
    return exp(-(x * x) / (2.0 * std * std)) / (std * sqrt(2.0 * PI));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Interpolators
 | 
			
		||||
{
 | 
			
		||||
    float4 iTexCoord0 [[user(TEXCOORD0)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
float4 shaderMain(float4 iPosition [[position]],
 | 
			
		||||
                  Interpolators input [[stage_in]],
 | 
			
		||||
                  constant Texture2DDescriptorHeap* g_Texture2DDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                  constant SamplerDescriptorHeap* g_SamplerDescriptorHeap [[buffer(3)]],
 | 
			
		||||
                  constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    texture2d<float> texture = g_Texture2DDescriptorHeap[s0_Texture2DDescriptorIndex].tex;
 | 
			
		||||
    sampler samplerState = g_SamplerDescriptorHeap[s0_SamplerDescriptorIndex].samp;
 | 
			
		||||
    
 | 
			
		||||
    float scale;
 | 
			
		||||
    if ((g_ViewportSize.x * g_ViewportSize.w) >= (16.0 / 9.0))
 | 
			
		||||
        scale = g_ViewportSize.y / 360.0;
 | 
			
		||||
    else
 | 
			
		||||
        scale = g_ViewportSize.x / 640.0;
 | 
			
		||||
    
 | 
			
		||||
    float2 offsets[3];
 | 
			
		||||
    offsets[0] = g_offsets(0).xy * scale;
 | 
			
		||||
    offsets[1] = g_offsets(0).zw * scale;
 | 
			
		||||
    offsets[2] = g_offsets(1).xy * scale;
 | 
			
		||||
    
 | 
			
		||||
    float4 color = 0.0;
 | 
			
		||||
    float weightSum = 0.0;
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < KERNEL_SIZE; i++)
 | 
			
		||||
    {
 | 
			
		||||
        float step = i / float(KERNEL_SIZE - 1);
 | 
			
		||||
        float scaled = step * 2;
 | 
			
		||||
        float2 offset = mix(offsets[int(scaled)], offsets[min(int(scaled) + 1, 2)], frac(scaled));
 | 
			
		||||
        float offsetScale = 1.0 / 0.75;
 | 
			
		||||
        float weight = ComputeWeight(mix(-offsetScale, offsetScale, step));
 | 
			
		||||
        color += texture.sample(samplerState, input.iTexCoord0.xy + offset, level(0)) * weight;
 | 
			
		||||
        weightSum += weight;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return color / weightSum;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur_3x3.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur_3x3.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define KERNEL_SIZE 3
 | 
			
		||||
#include "gaussian_blur.metali"
 | 
			
		||||
							
								
								
									
										2
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur_5x5.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur_5x5.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define KERNEL_SIZE 5
 | 
			
		||||
#include "gaussian_blur.metali"
 | 
			
		||||
							
								
								
									
										2
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur_7x7.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur_7x7.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define KERNEL_SIZE 7
 | 
			
		||||
#include "gaussian_blur.metali"
 | 
			
		||||
							
								
								
									
										2
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur_9x9.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								UnleashedRecomp/gpu/shader/msl/gaussian_blur_9x9.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define KERNEL_SIZE 9
 | 
			
		||||
#include "gaussian_blur.metali"
 | 
			
		||||
							
								
								
									
										41
									
								
								UnleashedRecomp/gpu/shader/msl/imgui_common.metali
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								UnleashedRecomp/gpu/shader/msl/imgui_common.metali
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
#include <metal_stdlib>
 | 
			
		||||
 | 
			
		||||
using namespace metal;
 | 
			
		||||
 | 
			
		||||
#include "../../imgui/imgui_common.h"
 | 
			
		||||
 | 
			
		||||
struct PushConstants
 | 
			
		||||
{
 | 
			
		||||
    float2 BoundsMin;
 | 
			
		||||
    float2 BoundsMax;
 | 
			
		||||
    uint GradientTopLeft;
 | 
			
		||||
    uint GradientTopRight;
 | 
			
		||||
    uint GradientBottomRight;
 | 
			
		||||
    uint GradientBottomLeft;
 | 
			
		||||
    uint ShaderModifier;
 | 
			
		||||
    uint Texture2DDescriptorIndex;
 | 
			
		||||
    float2 DisplaySize;
 | 
			
		||||
    float2 InverseDisplaySize;
 | 
			
		||||
    float2 Origin;
 | 
			
		||||
    float2 Scale;
 | 
			
		||||
    float2 ProceduralOrigin;
 | 
			
		||||
    float Outline;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Interpolators
 | 
			
		||||
{
 | 
			
		||||
    float4 Position [[position]];
 | 
			
		||||
    float2 UV;
 | 
			
		||||
    float4 Color;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Texture2DDescriptorHeap
 | 
			
		||||
{
 | 
			
		||||
    texture2d<float> tex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SamplerDescriptorHeap
 | 
			
		||||
{
 | 
			
		||||
    sampler samp;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										235
									
								
								UnleashedRecomp/gpu/shader/msl/imgui_ps.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								UnleashedRecomp/gpu/shader/msl/imgui_ps.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,235 @@
 | 
			
		|||
#include "imgui_common.metali"
 | 
			
		||||
 | 
			
		||||
float4 DecodeColor(uint color)
 | 
			
		||||
{
 | 
			
		||||
    return float4(color & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF, (color >> 24) & 0xFF) / 255.0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float4 SamplePoint(int2 position, constant PushConstants& g_PushConstants)
 | 
			
		||||
{
 | 
			
		||||
    switch (g_PushConstants.ShaderModifier)
 | 
			
		||||
    {
 | 
			
		||||
        case IMGUI_SHADER_MODIFIER_SCANLINE:
 | 
			
		||||
            {
 | 
			
		||||
                if (int(position.y) % 2 == 0)
 | 
			
		||||
                    return float4(1.0, 1.0, 1.0, 0.0);
 | 
			
		||||
            
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        case IMGUI_SHADER_MODIFIER_CHECKERBOARD:
 | 
			
		||||
            {
 | 
			
		||||
                int remnantX = int(position.x) % 9;
 | 
			
		||||
                int remnantY = int(position.y) % 9;
 | 
			
		||||
            
 | 
			
		||||
                float4 color = 1.0;
 | 
			
		||||
            
 | 
			
		||||
                if (remnantX == 0 || remnantY == 0)
 | 
			
		||||
                    color.a = 0.0;
 | 
			
		||||
            
 | 
			
		||||
                if ((remnantY % 2) == 0)
 | 
			
		||||
                    color.rgb = 0.5;
 | 
			
		||||
            
 | 
			
		||||
                return color;
 | 
			
		||||
            }
 | 
			
		||||
        case IMGUI_SHADER_MODIFIER_SCANLINE_BUTTON:
 | 
			
		||||
            {
 | 
			
		||||
                if (int(position.y) % 2 == 0)
 | 
			
		||||
                    return float4(1.0, 1.0, 1.0, 0.5);
 | 
			
		||||
            
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return 1.0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float4 SampleLinear(float2 uvTexspace, constant PushConstants& g_PushConstants)
 | 
			
		||||
{    
 | 
			
		||||
    int2 integerPart = int2(floor(uvTexspace));
 | 
			
		||||
    float2 fracPart = fract(uvTexspace);
 | 
			
		||||
    
 | 
			
		||||
    float4 topLeft = SamplePoint(integerPart + int2(0, 0), g_PushConstants);
 | 
			
		||||
    float4 topRight = SamplePoint(integerPart + int2(1, 0), g_PushConstants);
 | 
			
		||||
    float4 bottomLeft = SamplePoint(integerPart + int2(0, 1), g_PushConstants);
 | 
			
		||||
    float4 bottomRight = SamplePoint(integerPart + int2(1, 1), g_PushConstants);
 | 
			
		||||
    
 | 
			
		||||
    float4 top = mix(topLeft, topRight, fracPart.x);
 | 
			
		||||
    float4 bottom = mix(bottomLeft, bottomRight, fracPart.x);
 | 
			
		||||
 | 
			
		||||
    return mix(top, bottom, fracPart.y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float4 PixelAntialiasing(float2 uvTexspace, constant PushConstants& g_PushConstants)
 | 
			
		||||
{    
 | 
			
		||||
    if ((g_PushConstants.DisplaySize.x * g_PushConstants.InverseDisplaySize.y) >= (4.0 / 3.0))
 | 
			
		||||
        uvTexspace *= g_PushConstants.InverseDisplaySize.y * 720.0;
 | 
			
		||||
    else
 | 
			
		||||
        uvTexspace *= g_PushConstants.InverseDisplaySize.x * 960.0;
 | 
			
		||||
 | 
			
		||||
    float2 seam = floor(uvTexspace + 0.5);
 | 
			
		||||
    uvTexspace = (uvTexspace - seam) / fwidth(uvTexspace) + seam;
 | 
			
		||||
    uvTexspace = clamp(uvTexspace, seam - 0.5, seam + 0.5);
 | 
			
		||||
    
 | 
			
		||||
    return SampleLinear(uvTexspace - 0.5, g_PushConstants);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float median(float r, float g, float b)
 | 
			
		||||
{
 | 
			
		||||
    return max(min(r, g), min(max(r, g), b));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float4 SampleSdfFont(float4 color, texture2d<float> texture, float2 uv, float2 screenTexSize,
 | 
			
		||||
                     constant SamplerDescriptorHeap* g_SamplerDescriptorHeap,
 | 
			
		||||
                     constant PushConstants& g_PushConstants)
 | 
			
		||||
{
 | 
			
		||||
    float4 textureColor = texture.sample(g_SamplerDescriptorHeap[0].samp, uv);
 | 
			
		||||
    
 | 
			
		||||
    uint width = texture.get_width();
 | 
			
		||||
    uint height = texture.get_height();
 | 
			
		||||
            
 | 
			
		||||
    float pxRange = 8.0;
 | 
			
		||||
    float2 unitRange = pxRange / float2(width, height);
 | 
			
		||||
    float screenPxRange = max(0.5 * dot(unitRange, screenTexSize), 1.0);
 | 
			
		||||
            
 | 
			
		||||
    float sd = median(textureColor.r, textureColor.g, textureColor.b) - 0.5;
 | 
			
		||||
    float screenPxDistance = screenPxRange * (sd + g_PushConstants.Outline / (pxRange * 1.5));
 | 
			
		||||
            
 | 
			
		||||
    if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TITLE_BEVEL)
 | 
			
		||||
    {
 | 
			
		||||
        float2 normal = normalize(float3(dfdx(sd), dfdy(sd), 0.01)).xy;
 | 
			
		||||
        float3 rimColor = float3(1, 0.8, 0.29);
 | 
			
		||||
        float3 shadowColor = float3(0.84, 0.57, 0);
 | 
			
		||||
 | 
			
		||||
        float cosTheta = dot(normal, normalize(float2(1, 1)));
 | 
			
		||||
        float3 gradient = mix(color.rgb, cosTheta >= 0.0 ? rimColor : shadowColor, abs(cosTheta));
 | 
			
		||||
        color.rgb = mix(gradient, color.rgb, pow(saturate(sd + 0.77), 32.0));
 | 
			
		||||
    }
 | 
			
		||||
    else if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_CATEGORY_BEVEL)
 | 
			
		||||
    {
 | 
			
		||||
        float2 normal = normalize(float3(dfdx(sd), dfdy(sd), 0.25)).xy;
 | 
			
		||||
        float cosTheta = dot(normal, normalize(float2(1, 1)));
 | 
			
		||||
        float gradient = 1.0 + cosTheta * 0.5;
 | 
			
		||||
        color.rgb = saturate(color.rgb * gradient);
 | 
			
		||||
    }
 | 
			
		||||
    else if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TEXT_SKEW)
 | 
			
		||||
    {
 | 
			
		||||
        float2 normal = normalize(float3(dfdx(sd), dfdy(sd), 0.5)).xy;
 | 
			
		||||
        float cosTheta = dot(normal, normalize(float2(1, 1)));
 | 
			
		||||
        float gradient = saturate(1.0 + cosTheta);
 | 
			
		||||
        color.rgb = mix(color.rgb * gradient, color.rgb, pow(saturate(sd + 0.77), 32.0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    color.a *= saturate(screenPxDistance + 0.5);
 | 
			
		||||
    color.a *= textureColor.a;
 | 
			
		||||
    
 | 
			
		||||
    return color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
float4 shaderMain(Interpolators interpolators [[stage_in]],
 | 
			
		||||
                  constant Texture2DDescriptorHeap* g_Texture2DDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                  constant SamplerDescriptorHeap* g_SamplerDescriptorHeap [[buffer(1)]],
 | 
			
		||||
                  constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    float4 color = interpolators.Color;
 | 
			
		||||
    color *= PixelAntialiasing(interpolators.Position.xy - g_PushConstants.ProceduralOrigin, g_PushConstants);
 | 
			
		||||
    
 | 
			
		||||
    if (g_PushConstants.Texture2DDescriptorIndex != 0)
 | 
			
		||||
    {
 | 
			
		||||
        texture2d<float> texture = g_Texture2DDescriptorHeap[g_PushConstants.Texture2DDescriptorIndex & 0x7FFFFFFF].tex;
 | 
			
		||||
        
 | 
			
		||||
        if ((g_PushConstants.Texture2DDescriptorIndex & 0x80000000) != 0)
 | 
			
		||||
        {
 | 
			
		||||
            if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_LOW_QUALITY_TEXT)
 | 
			
		||||
            {
 | 
			
		||||
                float scale;
 | 
			
		||||
                float invScale;
 | 
			
		||||
                
 | 
			
		||||
                if ((g_PushConstants.DisplaySize.x * g_PushConstants.InverseDisplaySize.y) >= (4.0 / 3.0))
 | 
			
		||||
                {
 | 
			
		||||
                    scale = g_PushConstants.InverseDisplaySize.y * 720.0;
 | 
			
		||||
                    invScale = g_PushConstants.DisplaySize.y / 720.0;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    scale = g_PushConstants.InverseDisplaySize.x * 960.0;
 | 
			
		||||
                    invScale = g_PushConstants.DisplaySize.x / 960.0;
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                float2 lowQualityPosition = (interpolators.Position.xy - 0.5) * scale;                
 | 
			
		||||
                float2 fracPart = fract(lowQualityPosition);
 | 
			
		||||
                
 | 
			
		||||
                float2 uvStep = fwidth(interpolators.UV) * invScale;
 | 
			
		||||
                float2 lowQualityUV = interpolators.UV - fracPart * uvStep;
 | 
			
		||||
                float2 screenTexSize = 1.0 / uvStep;
 | 
			
		||||
                
 | 
			
		||||
                float4 topLeft = SampleSdfFont(color, texture, lowQualityUV + float2(0, 0), screenTexSize, g_SamplerDescriptorHeap, g_PushConstants);
 | 
			
		||||
                float4 topRight = SampleSdfFont(color, texture, lowQualityUV + float2(uvStep.x, 0), screenTexSize, g_SamplerDescriptorHeap, g_PushConstants);
 | 
			
		||||
                float4 bottomLeft = SampleSdfFont(color, texture, lowQualityUV + float2(0, uvStep.y), screenTexSize, g_SamplerDescriptorHeap, g_PushConstants);
 | 
			
		||||
                float4 bottomRight = SampleSdfFont(color, texture, lowQualityUV + uvStep.xy, screenTexSize, g_SamplerDescriptorHeap, g_PushConstants);
 | 
			
		||||
                
 | 
			
		||||
                float4 top = mix(topLeft, topRight, fracPart.x);
 | 
			
		||||
                float4 bottom = mix(bottomLeft, bottomRight, fracPart.x);
 | 
			
		||||
                
 | 
			
		||||
                color = mix(top, bottom, fracPart.y);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                color = SampleSdfFont(color, texture, interpolators.UV, 1.0 / fwidth(interpolators.UV), g_SamplerDescriptorHeap, g_PushConstants);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            color *= texture.sample(g_SamplerDescriptorHeap[0].samp, interpolators.UV);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_HORIZONTAL_MARQUEE_FADE)
 | 
			
		||||
    {
 | 
			
		||||
        float minAlpha = saturate((interpolators.Position.x - g_PushConstants.BoundsMin.x) / g_PushConstants.Scale.x);
 | 
			
		||||
        float maxAlpha = saturate((g_PushConstants.BoundsMax.x - interpolators.Position.x) / g_PushConstants.Scale.y);
 | 
			
		||||
        
 | 
			
		||||
        color.a *= minAlpha;
 | 
			
		||||
        color.a *= maxAlpha;
 | 
			
		||||
    }
 | 
			
		||||
    else if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_VERTICAL_MARQUEE_FADE)
 | 
			
		||||
    {
 | 
			
		||||
        float minAlpha = saturate((interpolators.Position.y - g_PushConstants.BoundsMin.y) / g_PushConstants.Scale.x);
 | 
			
		||||
        float maxAlpha = saturate((g_PushConstants.BoundsMax.y - interpolators.Position.y) / g_PushConstants.Scale.y);
 | 
			
		||||
        
 | 
			
		||||
        color.a *= minAlpha;
 | 
			
		||||
        color.a *= maxAlpha;
 | 
			
		||||
    }
 | 
			
		||||
    else if (any(g_PushConstants.BoundsMin != g_PushConstants.BoundsMax))
 | 
			
		||||
    {
 | 
			
		||||
        float2 factor = saturate((interpolators.Position.xy - g_PushConstants.BoundsMin) / (g_PushConstants.BoundsMax - g_PushConstants.BoundsMin));
 | 
			
		||||
        
 | 
			
		||||
        if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_RECTANGLE_BEVEL)
 | 
			
		||||
        {
 | 
			
		||||
            float bevelSize = 0.9;
 | 
			
		||||
 | 
			
		||||
            float shadow = saturate((factor.x - bevelSize) / (1.0 - bevelSize));
 | 
			
		||||
            shadow = max(shadow, saturate((factor.y - bevelSize) / (1.0 - bevelSize)));
 | 
			
		||||
 | 
			
		||||
            float rim = saturate((1.0 - factor.x - bevelSize) / (1.0 - bevelSize));
 | 
			
		||||
            rim = max(rim, saturate((1.0 - factor.y - bevelSize) / (1.0 - bevelSize)));
 | 
			
		||||
 | 
			
		||||
            float3 rimColor = float3(1, 0.8, 0.29);
 | 
			
		||||
            float3 shadowColor = float3(0.84, 0.57, 0);
 | 
			
		||||
 | 
			
		||||
            color.rgb = mix(color.rgb, rimColor, smoothstep(0.0, 1.0, rim));
 | 
			
		||||
            color.rgb = mix(color.rgb, shadowColor, smoothstep(0.0, 1.0, shadow));
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            float4 top = mix(DecodeColor(g_PushConstants.GradientTopLeft), DecodeColor(g_PushConstants.GradientTopRight), smoothstep(0.0, 1.0, factor.x));
 | 
			
		||||
            float4 bottom = mix(DecodeColor(g_PushConstants.GradientBottomLeft), DecodeColor(g_PushConstants.GradientBottomRight), smoothstep(0.0, 1.0, factor.x));
 | 
			
		||||
            color *= mix(top, bottom, smoothstep(0.0, 1.0, factor.y));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
        
 | 
			
		||||
    if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_GRAYSCALE)
 | 
			
		||||
        color.rgb = dot(color.rgb, float3(0.2126, 0.7152, 0.0722));
 | 
			
		||||
    
 | 
			
		||||
    return color;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								UnleashedRecomp/gpu/shader/msl/imgui_vs.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								UnleashedRecomp/gpu/shader/msl/imgui_vs.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
#include "imgui_common.metali"
 | 
			
		||||
 | 
			
		||||
struct VertexStageIn
 | 
			
		||||
{
 | 
			
		||||
    float2 position [[attribute(0)]];
 | 
			
		||||
    float2 uv [[attribute(1)]];
 | 
			
		||||
    float4 color [[attribute(2)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[vertex]]
 | 
			
		||||
Interpolators shaderMain(VertexStageIn input [[stage_in]],
 | 
			
		||||
                         constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    Interpolators interpolators = Interpolators{};
 | 
			
		||||
 | 
			
		||||
    if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TEXT_SKEW)
 | 
			
		||||
    {
 | 
			
		||||
        if (input.position.y < g_PushConstants.Origin.y)
 | 
			
		||||
            input.position.x += g_PushConstants.Scale.x;
 | 
			
		||||
    }
 | 
			
		||||
    else if (g_PushConstants.ShaderModifier != IMGUI_SHADER_MODIFIER_HORIZONTAL_MARQUEE_FADE && 
 | 
			
		||||
        g_PushConstants.ShaderModifier != IMGUI_SHADER_MODIFIER_VERTICAL_MARQUEE_FADE)
 | 
			
		||||
    {
 | 
			
		||||
        input.position.xy = g_PushConstants.Origin + (input.position.xy - g_PushConstants.Origin) * g_PushConstants.Scale;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    interpolators.Position = float4(input.position.xy * g_PushConstants.InverseDisplaySize * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
 | 
			
		||||
    interpolators.UV = input.uv;
 | 
			
		||||
    interpolators.Color = input.color;
 | 
			
		||||
 | 
			
		||||
    return interpolators;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								UnleashedRecomp/gpu/shader/msl/movie_common.metali
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								UnleashedRecomp/gpu/shader/msl/movie_common.metali
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#define fZmin (*(reinterpret_cast<device float*>(g_PushConstants.PixelShaderConstants + 0)))
 | 
			
		||||
#define fZmax (*(reinterpret_cast<device float*>(g_PushConstants.PixelShaderConstants + 16)))
 | 
			
		||||
 | 
			
		||||
#define Tex0_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
 | 
			
		||||
#define Tex1_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 4)))
 | 
			
		||||
#define Tex2_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 8)))
 | 
			
		||||
#define Tex3_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 12)))
 | 
			
		||||
#define Tex4_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 16)))
 | 
			
		||||
 | 
			
		||||
#define Tex0_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 64)))
 | 
			
		||||
#define Tex1_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 68)))
 | 
			
		||||
#define Tex2_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 72)))
 | 
			
		||||
#define Tex3_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 76)))
 | 
			
		||||
#define Tex4_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 80)))
 | 
			
		||||
 | 
			
		||||
#define bCsc (g_Booleans & (1 << (16 + 0)))
 | 
			
		||||
#define bAmv (g_Booleans & (1 << (16 + 1)))
 | 
			
		||||
#define bZmv (g_Booleans & (1 << (16 + 2)))
 | 
			
		||||
 
 | 
			
		||||
struct VertexShaderInput
 | 
			
		||||
{
 | 
			
		||||
    float4 ObjPos [[attribute(0)]];
 | 
			
		||||
    float2 UV [[attribute(4)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Interpolators
 | 
			
		||||
{
 | 
			
		||||
    float4 ProjPos [[position]];
 | 
			
		||||
    float2 UV;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct PixelShaderOutput
 | 
			
		||||
{
 | 
			
		||||
    float4 Color [[color(0)]];
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										104
									
								
								UnleashedRecomp/gpu/shader/msl/movie_ps.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								UnleashedRecomp/gpu/shader/msl/movie_ps.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,104 @@
 | 
			
		|||
#include "movie_common.metali"
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
PixelShaderOutput shaderMain(Interpolators In [[stage_in]],
 | 
			
		||||
                             constant Texture2DDescriptorHeap* g_Texture2DDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                             constant SamplerDescriptorHeap* g_SamplerDescriptorHeap [[buffer(3)]],
 | 
			
		||||
                             constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    texture2d<float> Tex0 = g_Texture2DDescriptorHeap[Tex0_ResourceDescriptorIndex].tex;
 | 
			
		||||
    texture2d<float> Tex1 = g_Texture2DDescriptorHeap[Tex1_ResourceDescriptorIndex].tex;
 | 
			
		||||
    texture2d<float> Tex2 = g_Texture2DDescriptorHeap[Tex2_ResourceDescriptorIndex].tex;
 | 
			
		||||
    texture2d<float> Tex3 = g_Texture2DDescriptorHeap[Tex3_ResourceDescriptorIndex].tex;
 | 
			
		||||
    texture2d<float> Tex4 = g_Texture2DDescriptorHeap[Tex4_ResourceDescriptorIndex].tex;
 | 
			
		||||
    
 | 
			
		||||
    sampler Tex0_s = g_SamplerDescriptorHeap[Tex0_SamplerDescriptorIndex].samp;
 | 
			
		||||
    sampler Tex1_s = g_SamplerDescriptorHeap[Tex1_SamplerDescriptorIndex].samp;
 | 
			
		||||
    sampler Tex2_s = g_SamplerDescriptorHeap[Tex2_SamplerDescriptorIndex].samp;
 | 
			
		||||
    sampler Tex3_s = g_SamplerDescriptorHeap[Tex3_SamplerDescriptorIndex].samp;
 | 
			
		||||
    sampler Tex4_s = g_SamplerDescriptorHeap[Tex4_SamplerDescriptorIndex].samp;
 | 
			
		||||
    
 | 
			
		||||
    PixelShaderOutput Out;
 | 
			
		||||
    float ValY = Tex0.sample(Tex0_s, In.UV).r;
 | 
			
		||||
    float ValU = Tex1.sample(Tex1_s, In.UV).r - 0.5;
 | 
			
		||||
    float ValV = Tex2.sample(Tex2_s, In.UV).r - 0.5;
 | 
			
		||||
    float ValA = 1.0;
 | 
			
		||||
    float ValD = 0.0;
 | 
			
		||||
    if (bAmv)
 | 
			
		||||
        ValA = (Tex3.sample(Tex3_s, In.UV).r - 0.0625) * 1.164;
 | 
			
		||||
    if (bZmv)
 | 
			
		||||
    {
 | 
			
		||||
        ValD = (Tex4.sample(Tex4_s, In.UV).r - 0.0625) * 1.164;
 | 
			
		||||
        if (ValD < 9.0 / 255.0)
 | 
			
		||||
        {
 | 
			
		||||
            ValD = 0.0;
 | 
			
		||||
        }
 | 
			
		||||
        else if (ValD < 17.0 / 255.0)
 | 
			
		||||
        {
 | 
			
		||||
            ValD = fZmin;
 | 
			
		||||
        }
 | 
			
		||||
        else if (ValD < 224.0 / 255.0)
 | 
			
		||||
        {
 | 
			
		||||
            ValD = (ValD - 17.0 / 255.0) / (223.0 / 255.0 - 17.0 / 255.0) * (fZmax - fZmin) + fZmin;
 | 
			
		||||
        }
 | 
			
		||||
        else if (ValD < 240.0 / 255.0)
 | 
			
		||||
        {
 | 
			
		||||
            ValD = fZmax;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            ValD = 1.0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (bCsc)
 | 
			
		||||
    {
 | 
			
		||||
        if (ValY < 16.0 / 255.0)
 | 
			
		||||
        {
 | 
			
		||||
            ValY = ValY * 3.0 / 2.0;
 | 
			
		||||
        }
 | 
			
		||||
        else if (ValY < 176.0 / 255.0)
 | 
			
		||||
        {
 | 
			
		||||
            ValY = 24.0 / 255.0 + (ValY - 16.0 / 255.0) / 2.0;
 | 
			
		||||
        }
 | 
			
		||||
        else if (ValY < 192.0 / 255.0)
 | 
			
		||||
        {
 | 
			
		||||
            ValY = 104.0 / 255.0 + (ValY - 176.0 / 255.0) / 1.0;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            ValY = 120.0 / 255.0 + (ValY - 192.0 / 255.0) * 2.0;
 | 
			
		||||
        }
 | 
			
		||||
        if (abs(ValU) < 24.0 / 255.0)
 | 
			
		||||
        {
 | 
			
		||||
            ValU /= 3.0;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            ValU = (8.0 / 255.0 + (abs(ValU) - 24.0 / 255.0) * (120.0 / 104.0)) * sign(ValU);
 | 
			
		||||
        }
 | 
			
		||||
        if (abs(ValV) < 24.0 / 255.0)
 | 
			
		||||
        {
 | 
			
		||||
            ValV /= 3.0;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            ValV = (8.0 / 255.0 + (abs(ValV) - 24.0 / 255.0) * (120.0 / 104.0)) * sign(ValV);
 | 
			
		||||
        }
 | 
			
		||||
        Out.Color.r = ValY + ValV * 1.402;
 | 
			
		||||
        Out.Color.g = ValY - ValU * 0.344 - ValV * 0.714;
 | 
			
		||||
        Out.Color.b = ValY + ValU * 1.772;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ValY = (ValY - 0.0625) * 1.164;
 | 
			
		||||
        Out.Color.r = ValY + ValV * 1.596;
 | 
			
		||||
        Out.Color.g = ValY - ValU * 0.392 - ValV * 0.813;
 | 
			
		||||
        Out.Color.b = ValY + ValU * 2.017;
 | 
			
		||||
    }
 | 
			
		||||
    Out.Color.a = ValA;
 | 
			
		||||
    
 | 
			
		||||
    if (any(In.UV < 0.0) || any(In.UV > 1.0))
 | 
			
		||||
        Out.Color.rgb = 0.0;
 | 
			
		||||
 | 
			
		||||
    return Out;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								UnleashedRecomp/gpu/shader/msl/movie_vs.metal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								UnleashedRecomp/gpu/shader/msl/movie_vs.metal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
#include "movie_common.metali"
 | 
			
		||||
 | 
			
		||||
[[vertex]]
 | 
			
		||||
Interpolators shaderMain(VertexShaderInput In [[stage_in]],
 | 
			
		||||
                         constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    Interpolators Out;
 | 
			
		||||
    Out.ProjPos = In.ObjPos;
 | 
			
		||||
    Out.ProjPos.xy += g_HalfPixelOffset * Out.ProjPos.w;
 | 
			
		||||
    Out.UV = In.UV;
 | 
			
		||||
    return Out;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								UnleashedRecomp/gpu/shader/msl/resolve_msaa_color.metali
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								UnleashedRecomp/gpu/shader/msl/resolve_msaa_color.metali
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "copy_common.metali"
 | 
			
		||||
 | 
			
		||||
struct Texture2DMSDescriptorHeap
 | 
			
		||||
{
 | 
			
		||||
    texture2d_ms<float> tex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
float4 shaderMain(float4 position [[position]],
 | 
			
		||||
                  constant Texture2DMSDescriptorHeap* g_Texture2DMSDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                  constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    float4 result = g_Texture2DMSDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].tex.read(uint2(position.xy), 0);
 | 
			
		||||
    
 | 
			
		||||
    for (int i = 1; i < SAMPLE_COUNT; i++)
 | 
			
		||||
        result += g_Texture2DMSDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].tex.read(uint2(position.xy), i);
 | 
			
		||||
 | 
			
		||||
    return result / SAMPLE_COUNT;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define SAMPLE_COUNT 2
 | 
			
		||||
#include "resolve_msaa_color.metali"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define SAMPLE_COUNT 4
 | 
			
		||||
#include "resolve_msaa_color.metali"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define SAMPLE_COUNT 8
 | 
			
		||||
#include "resolve_msaa_color.metali"
 | 
			
		||||
							
								
								
									
										30
									
								
								UnleashedRecomp/gpu/shader/msl/resolve_msaa_depth.metali
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								UnleashedRecomp/gpu/shader/msl/resolve_msaa_depth.metali
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "copy_common.metali"
 | 
			
		||||
 | 
			
		||||
struct Texture2DMSDescriptorHeap
 | 
			
		||||
{
 | 
			
		||||
    texture2d_ms<float> tex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct PixelShaderOutput
 | 
			
		||||
{
 | 
			
		||||
    float oDepth [[depth(any)]];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
[[fragment]]
 | 
			
		||||
PixelShaderOutput shaderMain(float4 position [[position]],
 | 
			
		||||
                       constant Texture2DMSDescriptorHeap* g_Texture2DMSDescriptorHeap [[buffer(0)]],
 | 
			
		||||
                       constant PushConstants& g_PushConstants [[buffer(8)]])
 | 
			
		||||
{
 | 
			
		||||
    PixelShaderOutput output = PixelShaderOutput{};
 | 
			
		||||
 | 
			
		||||
    float result = g_Texture2DMSDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].tex.read(uint2(position.xy), 0).x;
 | 
			
		||||
    
 | 
			
		||||
    for (int i = 1; i < SAMPLE_COUNT; i++)
 | 
			
		||||
        result = min(result, g_Texture2DMSDescriptorHeap[g_PushConstants.ResourceDescriptorIndex].tex.read(uint2(position.xy), i).x);
 | 
			
		||||
 | 
			
		||||
    output.oDepth = result;
 | 
			
		||||
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define SAMPLE_COUNT 2
 | 
			
		||||
#include "resolve_msaa_depth.metali"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define SAMPLE_COUNT 4
 | 
			
		||||
#include "resolve_msaa_depth.metali"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
#define SAMPLE_COUNT 8
 | 
			
		||||
#include "resolve_msaa_depth.metali"
 | 
			
		||||
| 
						 | 
				
			
			@ -41,54 +41,80 @@
 | 
			
		|||
#include "../../tools/XenosRecomp/XenosRecomp/shader_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_D3D12
 | 
			
		||||
#include "shader/blend_color_alpha_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/copy_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/copy_color_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/copy_depth_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/csd_filter_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/csd_no_tex_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/csd_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/enhanced_motion_blur_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/gamma_correction_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/gaussian_blur_3x3.hlsl.dxil.h"
 | 
			
		||||
#include "shader/gaussian_blur_5x5.hlsl.dxil.h"
 | 
			
		||||
#include "shader/gaussian_blur_7x7.hlsl.dxil.h"
 | 
			
		||||
#include "shader/gaussian_blur_9x9.hlsl.dxil.h"
 | 
			
		||||
#include "shader/imgui_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/imgui_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/movie_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/movie_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/resolve_msaa_color_2x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/resolve_msaa_color_4x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/resolve_msaa_color_8x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/resolve_msaa_depth_2x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/resolve_msaa_depth_4x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/resolve_msaa_depth_8x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/blend_color_alpha_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/copy_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/copy_color_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/copy_depth_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/csd_filter_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/csd_no_tex_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/csd_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/enhanced_motion_blur_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/gamma_correction_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/gaussian_blur_3x3.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/gaussian_blur_5x5.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/gaussian_blur_7x7.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/gaussian_blur_9x9.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/imgui_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/imgui_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/movie_ps.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/movie_vs.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_color_2x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_color_4x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_color_8x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_depth_2x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_depth_4x.hlsl.dxil.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_depth_8x.hlsl.dxil.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "shader/blend_color_alpha_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/copy_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/copy_color_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/copy_depth_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/csd_filter_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/csd_no_tex_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/csd_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/enhanced_motion_blur_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/gamma_correction_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/gaussian_blur_3x3.hlsl.spirv.h"
 | 
			
		||||
#include "shader/gaussian_blur_5x5.hlsl.spirv.h"
 | 
			
		||||
#include "shader/gaussian_blur_7x7.hlsl.spirv.h"
 | 
			
		||||
#include "shader/gaussian_blur_9x9.hlsl.spirv.h"
 | 
			
		||||
#include "shader/imgui_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/imgui_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/movie_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/movie_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/resolve_msaa_color_2x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/resolve_msaa_color_4x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/resolve_msaa_color_8x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/resolve_msaa_depth_2x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/resolve_msaa_depth_4x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/resolve_msaa_depth_8x.hlsl.spirv.h"
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_METAL
 | 
			
		||||
#include "shader/msl/blend_color_alpha_ps.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/copy_vs.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/copy_color_ps.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/copy_depth_ps.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/csd_filter_ps.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/csd_no_tex_vs.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/csd_vs.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/enhanced_motion_blur_ps.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/gamma_correction_ps.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/gaussian_blur_3x3.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/gaussian_blur_5x5.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/gaussian_blur_7x7.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/gaussian_blur_9x9.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/imgui_ps.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/imgui_vs.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/movie_ps.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/movie_vs.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/resolve_msaa_color_2x.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/resolve_msaa_color_4x.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/resolve_msaa_color_8x.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/resolve_msaa_depth_2x.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/resolve_msaa_depth_4x.metal.metallib.h"
 | 
			
		||||
#include "shader/msl/resolve_msaa_depth_8x.metal.metallib.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "shader/hlsl/blend_color_alpha_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/copy_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/copy_color_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/copy_depth_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/csd_filter_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/csd_no_tex_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/csd_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/enhanced_motion_blur_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/gamma_correction_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/gaussian_blur_3x3.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/gaussian_blur_5x5.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/gaussian_blur_7x7.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/gaussian_blur_9x9.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/imgui_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/imgui_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/movie_ps.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/movie_vs.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_color_2x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_color_4x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_color_8x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_depth_2x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_depth_4x.hlsl.spirv.h"
 | 
			
		||||
#include "shader/hlsl/resolve_msaa_depth_8x.hlsl.spirv.h"
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
extern "C"
 | 
			
		||||
| 
						 | 
				
			
			@ -103,6 +129,9 @@ namespace plume
 | 
			
		|||
#ifdef UNLEASHED_RECOMP_D3D12
 | 
			
		||||
    extern std::unique_ptr<RenderInterface> CreateD3D12Interface();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_METAL
 | 
			
		||||
    extern std::unique_ptr<RenderInterface> CreateMetalInterface();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SDL_VULKAN_ENABLED
 | 
			
		||||
    extern std::unique_ptr<RenderInterface> CreateVulkanInterface(RenderWindow sdlWindow);
 | 
			
		||||
#else
 | 
			
		||||
| 
						 | 
				
			
			@ -283,17 +312,14 @@ static Profiler g_swapChainAcquireProfiler;
 | 
			
		|||
static bool g_profilerVisible;
 | 
			
		||||
static bool g_profilerWasToggled;
 | 
			
		||||
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_D3D12
 | 
			
		||||
static bool g_vulkan = false;
 | 
			
		||||
#if !defined(UNLEASHED_RECOMP_D3D12) && !defined(UNLEASHED_RECOMP_METAL)
 | 
			
		||||
static constexpr Backend g_backend = Backend::VULKAN;
 | 
			
		||||
#else
 | 
			
		||||
static constexpr bool g_vulkan = true;
 | 
			
		||||
static Backend g_backend;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static bool g_triangleStripWorkaround = false;
 | 
			
		||||
 | 
			
		||||
static bool g_hardwareResolve = true;
 | 
			
		||||
static bool g_hardwareDepthResolve = true;
 | 
			
		||||
 | 
			
		||||
static std::unique_ptr<RenderInterface> g_interface;
 | 
			
		||||
static std::unique_ptr<RenderDevice> g_device;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -486,7 +512,7 @@ struct UploadAllocator
 | 
			
		|||
        auto& buffer = buffers[index];
 | 
			
		||||
        if (buffer.buffer == nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            buffer.buffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(UploadBuffer::SIZE, RenderBufferFlag::CONSTANT | RenderBufferFlag::VERTEX | RenderBufferFlag::INDEX));
 | 
			
		||||
            buffer.buffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(UploadBuffer::SIZE, RenderBufferFlag::CONSTANT | RenderBufferFlag::VERTEX | RenderBufferFlag::INDEX | RenderBufferFlag::DEVICE_ADDRESSABLE));
 | 
			
		||||
            buffer.memory = reinterpret_cast<uint8_t*>(buffer.buffer->map());
 | 
			
		||||
            buffer.deviceAddress = buffer.buffer->getDeviceAddress();
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -780,18 +806,26 @@ static std::unique_ptr<uint8_t[]> g_buttonBcDiff;
 | 
			
		|||
 | 
			
		||||
static void LoadEmbeddedResources()
 | 
			
		||||
{
 | 
			
		||||
    if (g_vulkan)
 | 
			
		||||
    switch (g_backend)
 | 
			
		||||
    {
 | 
			
		||||
    case Backend::VULKAN:
 | 
			
		||||
        g_shaderCache = std::make_unique<uint8_t[]>(g_spirvCacheDecompressedSize);
 | 
			
		||||
        ZSTD_decompress(g_shaderCache.get(), g_spirvCacheDecompressedSize, g_compressedSpirvCache, g_spirvCacheCompressedSize);
 | 
			
		||||
    }
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_D3D12
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        break;
 | 
			
		||||
#if defined(UNLEASHED_RECOMP_D3D12)
 | 
			
		||||
    case Backend::D3D12:
 | 
			
		||||
        g_shaderCache = std::make_unique<uint8_t[]>(g_dxilCacheDecompressedSize);
 | 
			
		||||
        ZSTD_decompress(g_shaderCache.get(), g_dxilCacheDecompressedSize, g_compressedDxilCache, g_dxilCacheCompressedSize);
 | 
			
		||||
    }
 | 
			
		||||
        break;
 | 
			
		||||
#elif defined(UNLEASHED_RECOMP_METAL)
 | 
			
		||||
    case Backend::METAL:
 | 
			
		||||
        g_shaderCache = std::make_unique<uint8_t[]>(g_airCacheDecompressedSize);
 | 
			
		||||
        ZSTD_decompress(g_shaderCache.get(), g_airCacheDecompressedSize, g_compressedAirCache, g_airCacheCompressedSize);
 | 
			
		||||
        break;
 | 
			
		||||
#endif
 | 
			
		||||
    default:
 | 
			
		||||
        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_buttonBcDiff = decompressZstd(g_button_bc_diff, g_button_bc_diff_uncompressed_size);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1187,7 +1221,7 @@ static void ProcSetRenderState(const RenderCommand& cmd)
 | 
			
		|||
    }
 | 
			
		||||
    case D3DRS_ALPHAREF:
 | 
			
		||||
    {
 | 
			
		||||
        SetDirtyValue(g_dirtyStates.pipelineState, g_sharedConstants.alphaThreshold, float(value) / 256.0f);
 | 
			
		||||
        SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.alphaThreshold, float(value) / 256.0f);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case D3DRS_ALPHABLENDENABLE:
 | 
			
		||||
| 
						 | 
				
			
			@ -1294,19 +1328,28 @@ static GuestShader* g_csdShader;
 | 
			
		|||
 | 
			
		||||
static std::unique_ptr<GuestShader> g_enhancedMotionBlurShader;
 | 
			
		||||
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_D3D12
 | 
			
		||||
#if defined(UNLEASHED_RECOMP_D3D12)
 | 
			
		||||
 | 
			
		||||
#define CREATE_SHADER(NAME) \
 | 
			
		||||
    g_device->createShader( \
 | 
			
		||||
        g_vulkan ? g_##NAME##_spirv : g_##NAME##_dxil, \
 | 
			
		||||
        g_vulkan ? sizeof(g_##NAME##_spirv) : sizeof(g_##NAME##_dxil), \
 | 
			
		||||
        "main", \
 | 
			
		||||
        g_vulkan ? RenderShaderFormat::SPIRV : RenderShaderFormat::DXIL)
 | 
			
		||||
        (g_backend == Backend::VULKAN) ? g_##NAME##_spirv : g_##NAME##_dxil, \
 | 
			
		||||
        (g_backend == Backend::VULKAN) ? sizeof(g_##NAME##_spirv) : sizeof(g_##NAME##_dxil), \
 | 
			
		||||
        "shaderMain", \
 | 
			
		||||
        (g_backend == Backend::VULKAN) ? RenderShaderFormat::SPIRV : RenderShaderFormat::DXIL)
 | 
			
		||||
 | 
			
		||||
#elif defined(UNLEASHED_RECOMP_METAL)
 | 
			
		||||
 | 
			
		||||
#define CREATE_SHADER(NAME) \
 | 
			
		||||
    g_device->createShader( \
 | 
			
		||||
        (g_backend == Backend::VULKAN) ? g_##NAME##_spirv : g_##NAME##_air, \
 | 
			
		||||
        (g_backend == Backend::VULKAN) ? sizeof(g_##NAME##_spirv) : sizeof(g_##NAME##_air), \
 | 
			
		||||
        "shaderMain", \
 | 
			
		||||
        (g_backend == Backend::VULKAN) ? RenderShaderFormat::SPIRV : RenderShaderFormat::METAL)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define CREATE_SHADER(NAME) \
 | 
			
		||||
    g_device->createShader(g_##NAME##_spirv, sizeof(g_##NAME##_spirv), "main", RenderShaderFormat::SPIRV)
 | 
			
		||||
    g_device->createShader(g_##NAME##_spirv, sizeof(g_##NAME##_spirv), "shaderMain", RenderShaderFormat::SPIRV)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1671,8 +1714,10 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
 | 
			
		|||
 | 
			
		||||
    GameWindow::Init(sdlVideoDriver);
 | 
			
		||||
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_D3D12
 | 
			
		||||
    g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan;
 | 
			
		||||
#if defined(UNLEASHED_RECOMP_D3D12)
 | 
			
		||||
    g_backend = (DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan) ? Backend::VULKAN : Backend::D3D12;
 | 
			
		||||
#elif defined(UNLEASHED_RECOMP_METAL)
 | 
			
		||||
    g_backend = Config::GraphicsAPI == EGraphicsAPI::Vulkan ? Backend::VULKAN : Backend::METAL;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // Attempt to create the possible backends using a vector of function pointers. Whichever succeeds first will be the chosen API.
 | 
			
		||||
| 
						 | 
				
			
			@ -1685,15 +1730,18 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
 | 
			
		|||
    if (graphicsApiRetry)
 | 
			
		||||
    {
 | 
			
		||||
        // If we are attempting to create again after a reboot due to a crash, swap the order.
 | 
			
		||||
        g_vulkan = !g_vulkan;
 | 
			
		||||
        g_backend = (g_backend == Backend::VULKAN) ? Backend::D3D12 : Backend::VULKAN;
 | 
			
		||||
 | 
			
		||||
        // Don't allow redirection to Vulkan if we are retrying after a crash, 
 | 
			
		||||
        // so the user can at least boot the game with D3D12 if Vulkan fails to work.
 | 
			
		||||
        allowVulkanRedirection = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    interfaceFunctions.push_back(g_vulkan ? CreateVulkanInterfaceWrapper : CreateD3D12Interface);
 | 
			
		||||
    interfaceFunctions.push_back(g_vulkan ? CreateD3D12Interface : CreateVulkanInterfaceWrapper);
 | 
			
		||||
    interfaceFunctions.push_back((g_backend == Backend::VULKAN) ? CreateVulkanInterfaceWrapper : CreateD3D12Interface);
 | 
			
		||||
    interfaceFunctions.push_back((g_backend == Backend::VULKAN) ? CreateD3D12Interface : CreateVulkanInterfaceWrapper);
 | 
			
		||||
#elif defined(UNLEASHED_RECOMP_METAL)
 | 
			
		||||
    interfaceFunctions.push_back((g_backend == Backend::VULKAN) ? CreateVulkanInterfaceWrapper : CreateMetalInterface);
 | 
			
		||||
    interfaceFunctions.push_back((g_backend == Backend::VULKAN) ? CreateMetalInterface : CreateVulkanInterfaceWrapper);
 | 
			
		||||
#else
 | 
			
		||||
    interfaceFunctions.push_back(CreateVulkanInterfaceWrapper);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1718,7 +1766,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
 | 
			
		|||
            {
 | 
			
		||||
                const RenderDeviceDescription &deviceDescription = g_device->getDescription();
 | 
			
		||||
                
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_D3D12
 | 
			
		||||
#if defined(UNLEASHED_RECOMP_D3D12)
 | 
			
		||||
                if (interfaceFunction == CreateD3D12Interface)
 | 
			
		||||
                {
 | 
			
		||||
                    if (allowVulkanRedirection)
 | 
			
		||||
| 
						 | 
				
			
			@ -1749,7 +1797,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
 | 
			
		|||
 | 
			
		||||
                            // In case Vulkan fails to initialize, we will try D3D12 again afterwards, 
 | 
			
		||||
                            // just to get the game to boot. This only really happens in very old Intel GPU drivers.
 | 
			
		||||
                            if (!g_vulkan)
 | 
			
		||||
                            if (g_backend != Backend::VULKAN)
 | 
			
		||||
                            {
 | 
			
		||||
                                interfaceFunctions.push_back(CreateD3D12Interface);
 | 
			
		||||
                                allowVulkanRedirection = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1758,13 +1806,11 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
 | 
			
		|||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Hardware resolve seems to be completely bugged on Intel D3D12 drivers.
 | 
			
		||||
                    g_hardwareResolve = (deviceDescription.vendor != RenderDeviceVendor::INTEL);
 | 
			
		||||
                    g_hardwareDepthResolve = (deviceDescription.vendor != RenderDeviceVendor::INTEL);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                g_vulkan = (interfaceFunction == CreateVulkanInterfaceWrapper);
 | 
			
		||||
                g_backend = (interfaceFunction == CreateVulkanInterfaceWrapper) ? Backend::VULKAN : Backend::D3D12;
 | 
			
		||||
#elif defined(UNLEASHED_RECOMP_METAL)
 | 
			
		||||
                g_backend = (interfaceFunction == CreateVulkanInterfaceWrapper) ? Backend::VULKAN : Backend::METAL;
 | 
			
		||||
#endif
 | 
			
		||||
                // Enable triangle strip workaround if we are on AMD, as there is a bug where
 | 
			
		||||
                // restart indices cause triangles to be culled incorrectly. Converting them to degenerate triangles fixes it.
 | 
			
		||||
| 
						 | 
				
			
			@ -1800,7 +1846,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
 | 
			
		|||
    if (graphicsApiRetry)
 | 
			
		||||
    {
 | 
			
		||||
        // If we managed to create a device after retrying it in a reboot, remember the one we picked.
 | 
			
		||||
        Config::GraphicsAPI = g_vulkan ? EGraphicsAPI::Vulkan : EGraphicsAPI::D3D12;
 | 
			
		||||
        Config::GraphicsAPI = g_backend == Backend::VULKAN ? EGraphicsAPI::Vulkan : EGraphicsAPI::D3D12;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1855,15 +1901,18 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
 | 
			
		|||
    switch (Config::TripleBuffering)
 | 
			
		||||
    {
 | 
			
		||||
    case ETripleBuffering::Auto:
 | 
			
		||||
        if (g_vulkan)
 | 
			
		||||
        {
 | 
			
		||||
        switch (g_backend) {
 | 
			
		||||
        case Backend::VULKAN:
 | 
			
		||||
            // Defaulting to 3 is fine if presentWait as supported, as the maximum frame latency allowed is only 1.
 | 
			
		||||
            bufferCount = g_device->getCapabilities().presentWait ? 3 : 2;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            break;
 | 
			
		||||
        case Backend::D3D12:
 | 
			
		||||
            // Defaulting to 3 is fine on D3D12 thanks to flip discard model.
 | 
			
		||||
            bufferCount = 3;
 | 
			
		||||
            break;
 | 
			
		||||
        case Backend::METAL:
 | 
			
		||||
            bufferCount = 2;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1960,7 +2009,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
 | 
			
		|||
 | 
			
		||||
    pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);
 | 
			
		||||
 | 
			
		||||
    if (g_vulkan)
 | 
			
		||||
    if (g_backend != Backend::D3D12)
 | 
			
		||||
    {
 | 
			
		||||
        pipelineLayoutBuilder.addPushConstant(0, 4, 24, RenderShaderStageFlag::VERTEX | RenderShaderStageFlag::PIXEL);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2459,12 +2508,27 @@ static void DrawProfiler()
 | 
			
		|||
        ImGui::Text("Present Wait: %s", g_capabilities.presentWait ? "Supported" : "Unsupported");
 | 
			
		||||
        ImGui::Text("Triangle Fan: %s", g_capabilities.triangleFan ? "Supported" : "Unsupported");
 | 
			
		||||
        ImGui::Text("Dynamic Depth Bias: %s", g_capabilities.dynamicDepthBias ? "Supported" : "Unsupported");
 | 
			
		||||
        ImGui::Text("Hardware Resolve Modes: %s", g_capabilities.resolveModes ? "Supported" : "Unsupported");
 | 
			
		||||
        ImGui::Text("Triangle Strip Workaround: %s", g_triangleStripWorkaround ? "Enabled" : "Disabled");
 | 
			
		||||
        ImGui::Text("Hardware Resolve: %s", g_hardwareResolve ? "Enabled" : "Disabled");
 | 
			
		||||
        ImGui::Text("Hardware Depth Resolve: %s", g_hardwareDepthResolve ? "Enabled" : "Disabled");
 | 
			
		||||
        ImGui::NewLine();
 | 
			
		||||
 | 
			
		||||
        ImGui::Text("API: %s", g_vulkan ? "Vulkan" : "D3D12");
 | 
			
		||||
        std::string backend;
 | 
			
		||||
 | 
			
		||||
        switch (g_backend) {
 | 
			
		||||
        case Backend::VULKAN:
 | 
			
		||||
            backend = "Vulkan";
 | 
			
		||||
            break;
 | 
			
		||||
        case Backend::D3D12:
 | 
			
		||||
            backend = "D3D12";
 | 
			
		||||
            break;
 | 
			
		||||
        case Backend::METAL:
 | 
			
		||||
            backend = "Metal";
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            assert(false && "Unknown graphics backend");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ImGui::Text("API: %s", backend.c_str());
 | 
			
		||||
        ImGui::Text("Device: %s", g_device->getDescription().name.c_str());
 | 
			
		||||
        ImGui::Text("Device Type: %s", DeviceTypeName(g_device->getDescription().type));
 | 
			
		||||
        ImGui::Text("VRAM: %.2f MiB", (double)(g_device->getDescription().dedicatedVideoMemory) / (1024.0 * 1024.0));
 | 
			
		||||
| 
						 | 
				
			
			@ -2888,7 +2952,7 @@ static void SetRootDescriptor(const UploadAllocation& allocation, size_t index)
 | 
			
		|||
{
 | 
			
		||||
    auto& commandList = g_commandLists[g_frame];
 | 
			
		||||
 | 
			
		||||
    if (g_vulkan)
 | 
			
		||||
    if (g_backend != Backend::D3D12)
 | 
			
		||||
        commandList->setGraphicsPushConstants(0, &allocation.deviceAddress, 8 * index, 8);
 | 
			
		||||
    else
 | 
			
		||||
        commandList->setGraphicsRootDescriptor(allocation.buffer->at(allocation.offset), index);
 | 
			
		||||
| 
						 | 
				
			
			@ -3375,12 +3439,9 @@ static bool PopulateBarriersForStretchRect(GuestSurface* renderTarget, GuestSurf
 | 
			
		|||
            RenderTextureLayout dstLayout;
 | 
			
		||||
            bool shaderResolve = true;
 | 
			
		||||
 | 
			
		||||
            if (multiSampling && g_hardwareResolve)
 | 
			
		||||
            if (multiSampling)
 | 
			
		||||
            {
 | 
			
		||||
                // Hardware depth resolve is only supported on D3D12 when programmable sample positions are available.
 | 
			
		||||
                bool hardwareDepthResolveAvailable = g_hardwareDepthResolve && !g_vulkan && g_capabilities.sampleLocations;
 | 
			
		||||
 | 
			
		||||
                if (surface->format != RenderFormat::D32_FLOAT || hardwareDepthResolveAvailable)
 | 
			
		||||
                if (surface->format != RenderFormat::D32_FLOAT || g_capabilities.resolveModes)
 | 
			
		||||
                {
 | 
			
		||||
                    srcLayout = RenderTextureLayout::RESOLVE_SOURCE;
 | 
			
		||||
                    dstLayout = RenderTextureLayout::RESOLVE_DEST;
 | 
			
		||||
| 
						 | 
				
			
			@ -3420,11 +3481,9 @@ static void ExecutePendingStretchRectCommands(GuestSurface* renderTarget, GuestS
 | 
			
		|||
            {
 | 
			
		||||
                bool shaderResolve = true;
 | 
			
		||||
 | 
			
		||||
                if (multiSampling && g_hardwareResolve)
 | 
			
		||||
                if (multiSampling)
 | 
			
		||||
                {
 | 
			
		||||
                    bool hardwareDepthResolveAvailable = g_hardwareDepthResolve && !g_vulkan && g_capabilities.sampleLocations;
 | 
			
		||||
 | 
			
		||||
                    if (surface->format != RenderFormat::D32_FLOAT || hardwareDepthResolveAvailable)
 | 
			
		||||
                    if (surface->format != RenderFormat::D32_FLOAT || g_capabilities.resolveModes)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (surface->format == RenderFormat::D32_FLOAT)
 | 
			
		||||
                            commandList->resolveTextureRegion(texture->texture, 0, 0, surface->texture, nullptr, RenderResolveMode::MIN);
 | 
			
		||||
| 
						 | 
				
			
			@ -3540,7 +3599,7 @@ static void ExecutePendingStretchRectCommands(GuestSurface* renderTarget, GuestS
 | 
			
		|||
                    g_dirtyStates.pipelineState = true;
 | 
			
		||||
                    g_dirtyStates.scissorRect = true;
 | 
			
		||||
 | 
			
		||||
                    if (g_vulkan)
 | 
			
		||||
                    if (g_backend != Backend::D3D12)
 | 
			
		||||
                    {
 | 
			
		||||
                        g_dirtyStates.vertexShaderConstants = true; // The push constant call invalidates vertex shader constants.
 | 
			
		||||
                        g_dirtyStates.depthBias = true; // Static depth bias in copy pipeline invalidates dynamic depth bias.
 | 
			
		||||
| 
						 | 
				
			
			@ -3853,7 +3912,7 @@ static void ProcSetScissorRect(const RenderCommand& cmd)
 | 
			
		|||
 | 
			
		||||
static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specConstants)
 | 
			
		||||
{
 | 
			
		||||
    if (g_vulkan ||
 | 
			
		||||
    if (g_backend != Backend::D3D12 ||
 | 
			
		||||
        guestShader->shaderCacheEntry == nullptr || 
 | 
			
		||||
        guestShader->shaderCacheEntry->specConstantsMask == 0)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -3863,7 +3922,8 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
 | 
			
		|||
        {
 | 
			
		||||
            assert(guestShader->shaderCacheEntry != nullptr);
 | 
			
		||||
 | 
			
		||||
            if (g_vulkan)
 | 
			
		||||
            switch (g_backend) {
 | 
			
		||||
            case Backend::VULKAN:
 | 
			
		||||
            {
 | 
			
		||||
                auto compressedSpirvData = g_shaderCache.get() + guestShader->shaderCacheEntry->spirvOffset;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3871,13 +3931,26 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
 | 
			
		|||
                bool result = smolv::Decode(compressedSpirvData, guestShader->shaderCacheEntry->spirvSize, decoded.data(), decoded.size());
 | 
			
		||||
                assert(result);
 | 
			
		||||
 | 
			
		||||
                guestShader->shader = g_device->createShader(decoded.data(), decoded.size(), "main", RenderShaderFormat::SPIRV);
 | 
			
		||||
                guestShader->shader = g_device->createShader(decoded.data(), decoded.size(), "shaderMain", RenderShaderFormat::SPIRV);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            case Backend::D3D12:
 | 
			
		||||
            {
 | 
			
		||||
                guestShader->shader = g_device->createShader(g_shaderCache.get() + guestShader->shaderCacheEntry->dxilOffset, 
 | 
			
		||||
                    guestShader->shaderCacheEntry->dxilSize, "main", RenderShaderFormat::DXIL);
 | 
			
		||||
                guestShader->shader = g_device->createShader(g_shaderCache.get() + guestShader->shaderCacheEntry->dxilOffset,
 | 
			
		||||
                    guestShader->shaderCacheEntry->dxilSize, "shaderMain", RenderShaderFormat::DXIL);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case Backend::METAL:
 | 
			
		||||
            {
 | 
			
		||||
                guestShader->shader = g_device->createShader(g_shaderCache.get() + guestShader->shaderCacheEntry->airOffset,
 | 
			
		||||
                    guestShader->shaderCacheEntry->airSize, "shaderMain", RenderShaderFormat::METAL);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
#ifdef _DEBUG
 | 
			
		||||
            guestShader->shader->setName(fmt::format("{}:{:x}", guestShader->shaderCacheEntry->filename, guestShader->shaderCacheEntry->hash));
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return guestShader->shader.get();
 | 
			
		||||
| 
						 | 
				
			
			@ -3981,7 +4054,7 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
 | 
			
		|||
        const wchar_t* libraryNames[] = { specConstantsLibName, shaderLibName };
 | 
			
		||||
 | 
			
		||||
        ComPtr<IDxcOperationResult> result;
 | 
			
		||||
        HRESULT hr = s_dxcLinker->Link(L"main", guestShader->type == ResourceType::VertexShader ? L"vs_6_0" : L"ps_6_0",
 | 
			
		||||
        HRESULT hr = s_dxcLinker->Link(L"shaderMain", guestShader->type == ResourceType::VertexShader ? L"vs_6_0" : L"ps_6_0",
 | 
			
		||||
            libraryNames, std::size(libraryNames), nullptr, 0, result.GetAddressOf());
 | 
			
		||||
 | 
			
		||||
        assert(SUCCEEDED(hr) && result != nullptr);
 | 
			
		||||
| 
						 | 
				
			
			@ -3996,11 +4069,15 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
 | 
			
		|||
            auto& linkedShader = guestShader->linkedShaders[specConstants];
 | 
			
		||||
            if (linkedShader == nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                linkedShader = g_device->createShader(blob->GetBufferPointer(), blob->GetBufferSize(), "main", RenderShaderFormat::DXIL);
 | 
			
		||||
                linkedShader = g_device->createShader(blob->GetBufferPointer(), blob->GetBufferSize(), "shaderMain", RenderShaderFormat::DXIL);
 | 
			
		||||
                guestShader->shaderBlobs.push_back(std::move(blob));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            shader = linkedShader.get();
 | 
			
		||||
 | 
			
		||||
#ifdef _DEBUG
 | 
			
		||||
            shader->setName(fmt::format("{}:{:x}", guestShader->shaderCacheEntry->filename, guestShader->shaderCacheEntry->hash));
 | 
			
		||||
#endif
 | 
			
		||||
        }        
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -4494,7 +4571,7 @@ static void FlushRenderStateForRenderThread()
 | 
			
		|||
 | 
			
		||||
    // D3D12 resets depth bias values to the pipeline values, even if they are dynamic.
 | 
			
		||||
    // We can reduce unnecessary calls by making common depth bias values part of the pipeline.
 | 
			
		||||
    if (g_capabilities.dynamicDepthBias && !g_vulkan)
 | 
			
		||||
    if (g_capabilities.dynamicDepthBias && g_backend == Backend::D3D12)
 | 
			
		||||
    {
 | 
			
		||||
        bool useDepthBias = (g_depthBias != 0) || (g_slopeScaledDepthBias != 0.0f);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4510,7 +4587,7 @@ static void FlushRenderStateForRenderThread()
 | 
			
		|||
        commandList->setPipeline(CreateGraphicsPipelineInRenderThread(g_pipelineState));
 | 
			
		||||
 | 
			
		||||
        // D3D12 resets the depth bias values. Check if they need to be set again.
 | 
			
		||||
        if (g_capabilities.dynamicDepthBias && !g_vulkan)
 | 
			
		||||
        if (g_capabilities.dynamicDepthBias && g_backend == Backend::D3D12)
 | 
			
		||||
            g_dirtyStates.depthBias = (g_depthBias != g_pipelineState.depthBias) || (g_slopeScaledDepthBias != g_pipelineState.slopeScaledDepthBias);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4544,7 +4621,7 @@ static void FlushRenderStateForRenderThread()
 | 
			
		|||
            g_inputSlots + g_dirtyStates.vertexStreamFirst);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_dirtyStates.indices && (!g_vulkan || g_indexBufferView.buffer.ref != nullptr))
 | 
			
		||||
    if (g_dirtyStates.indices && (g_backend == Backend::D3D12 || g_indexBufferView.buffer.ref != nullptr))
 | 
			
		||||
        commandList->setIndexBuffer(&g_indexBufferView);
 | 
			
		||||
 | 
			
		||||
    g_dirtyStates = DirtyStates(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -6479,7 +6556,7 @@ static void CompileMeshPipeline(const Mesh& mesh, CompilationArgs& args)
 | 
			
		|||
        if (g_capabilities.dynamicDepthBias)
 | 
			
		||||
        {
 | 
			
		||||
            // Put common depth bias values for reducing unnecessary calls.
 | 
			
		||||
            if (!g_vulkan)
 | 
			
		||||
            if (g_backend == Backend::D3D12)
 | 
			
		||||
            {
 | 
			
		||||
                pipelineState.depthBias = COMMON_DEPTH_BIAS_VALUE;
 | 
			
		||||
                pipelineState.slopeScaledDepthBias = COMMON_SLOPE_SCALED_DEPTH_BIAS_VALUE;
 | 
			
		||||
| 
						 | 
				
			
			@ -7240,8 +7317,8 @@ static void PipelineTaskConsumerThread()
 | 
			
		|||
                    if (!g_capabilities.triangleFan && pipelineState.primitiveTopology == RenderPrimitiveTopology::TRIANGLE_FAN)
 | 
			
		||||
                        pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_LIST;
 | 
			
		||||
 | 
			
		||||
                    // Zero out depth bias for Vulkan, we only store common values for D3D12.
 | 
			
		||||
                    if (g_capabilities.dynamicDepthBias && g_vulkan)
 | 
			
		||||
                    // Zero out depth bias for Vulkan/Metal, we only store common values for D3D12.
 | 
			
		||||
                    if (g_capabilities.dynamicDepthBias && g_backend != Backend::D3D12)
 | 
			
		||||
                    {
 | 
			
		||||
                        pipelineState.depthBias = 0;
 | 
			
		||||
                        pipelineState.slopeScaledDepthBias = 0.0f;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,12 @@ struct Video
 | 
			
		|||
    static void ComputeViewportDimensions();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class Backend {
 | 
			
		||||
    VULKAN,
 | 
			
		||||
    D3D12,
 | 
			
		||||
    METAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct GuestSamplerState
 | 
			
		||||
{
 | 
			
		||||
    be<uint32_t> data[6];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -305,6 +305,9 @@ CONFIG_DEFINE_ENUM_TEMPLATE(EGraphicsAPI)
 | 
			
		|||
    { "Auto", EGraphicsAPI::Auto },
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_D3D12
 | 
			
		||||
    { "D3D12",  EGraphicsAPI::D3D12 },
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_METAL
 | 
			
		||||
    { "Metal",  EGraphicsAPI::Metal },
 | 
			
		||||
#endif
 | 
			
		||||
    { "Vulkan", EGraphicsAPI::Vulkan }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,6 +70,9 @@ enum class EGraphicsAPI : uint32_t
 | 
			
		|||
    Auto,
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_D3D12
 | 
			
		||||
    D3D12,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef UNLEASHED_RECOMP_METAL
 | 
			
		||||
    Metal,
 | 
			
		||||
#endif
 | 
			
		||||
    Vulkan
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,10 @@ struct ShaderCacheEntry
 | 
			
		|||
    const uint32_t dxilSize;
 | 
			
		||||
    const uint32_t spirvOffset;
 | 
			
		||||
    const uint32_t spirvSize;
 | 
			
		||||
    const uint32_t airOffset;
 | 
			
		||||
    const uint32_t airSize;
 | 
			
		||||
    const uint32_t specConstantsMask;
 | 
			
		||||
    char filename[256];
 | 
			
		||||
    struct GuestShader* guestShader;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +21,10 @@ extern const uint8_t g_compressedDxilCache[];
 | 
			
		|||
extern const size_t g_dxilCacheCompressedSize;
 | 
			
		||||
extern const size_t g_dxilCacheDecompressedSize;
 | 
			
		||||
 | 
			
		||||
extern const uint8_t g_compressedAirCache[];
 | 
			
		||||
extern const size_t g_airCacheCompressedSize;
 | 
			
		||||
extern const size_t g_airCacheDecompressedSize;
 | 
			
		||||
 | 
			
		||||
extern const uint8_t g_compressedSpirvCache[];
 | 
			
		||||
extern const size_t g_spirvCacheCompressedSize;
 | 
			
		||||
extern const size_t g_spirvCacheDecompressedSize;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								thirdparty/plume
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								thirdparty/plume
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
Subproject commit 11926860e878e68626ea99ec88562ce2b8badc4f
 | 
			
		||||
Subproject commit 61e19e19dcf4f44fbe7f7445f21904b0e27fbb3d
 | 
			
		||||
| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
Subproject commit 990d03b28a27b50277ee5d8d942e1c5f873869d1
 | 
			
		||||
Subproject commit 490699203914fe240b86ccf2401fe1f7d37b1bef
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue