mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-10-30 07:11:05 +00:00
Compare commits
2 commits
8633787306
...
4744a5e1a2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4744a5e1a2 | ||
|
|
1c3ffe0f41 |
74 changed files with 1226 additions and 159 deletions
5
.github/workflows/validate.yml
vendored
5
.github/workflows/validate.yml
vendored
|
|
@ -233,11 +233,6 @@ jobs:
|
|||
token: ${{ secrets.ASSET_REPO_TOKEN }}
|
||||
path: ./private
|
||||
|
||||
- name: Setup latest Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: latest-stable
|
||||
|
||||
- name: Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
|
|
|
|||
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/MoltenVK/MoltenVK
vendored
2
thirdparty/MoltenVK/MoltenVK
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 3a0b07a24a4a681ffe70b461b1f4333b2729e2ef
|
||||
Subproject commit 3e935eb5642813f0506518771528aee37539e601
|
||||
2
thirdparty/MoltenVK/SPIRV-Cross
vendored
2
thirdparty/MoltenVK/SPIRV-Cross
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 22b22f5685d868828be01c9ac00c31902e60afd9
|
||||
Subproject commit 7affe74d77f93a622bb5002789d5332d32e512ee
|
||||
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