mirror of
				https://github.com/hedge-dev/XenosRecomp.git
				synced 2025-10-30 07:12:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			438 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			438 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef SHADER_COMMON_H_INCLUDED
 | |
| #define SHADER_COMMON_H_INCLUDED
 | |
| 
 | |
| #define SPEC_CONSTANT_R11G11B10_NORMAL  (1 << 0)
 | |
| #define SPEC_CONSTANT_ALPHA_TEST        (1 << 1)
 | |
| 
 | |
| #ifdef UNLEASHED_RECOMP
 | |
|     #define SPEC_CONSTANT_BICUBIC_GI_FILTER (1 << 2)
 | |
|     #define SPEC_CONSTANT_ALPHA_TO_COVERAGE (1 << 3)
 | |
|     #define SPEC_CONSTANT_REVERSE_Z         (1 << 4)
 | |
| #endif
 | |
| 
 | |
| #if defined(__air__) || !defined(__cplusplus) || defined(__INTELLISENSE__)
 | |
| 
 | |
| #ifndef __air__
 | |
| #define FLT_MIN asfloat(0xff7fffff)
 | |
| #define FLT_MAX asfloat(0x7f7fffff)
 | |
| #endif
 | |
| 
 | |
| #ifdef __spirv__
 | |
| 
 | |
| struct PushConstants
 | |
| {
 | |
|     uint64_t VertexShaderConstants;
 | |
|     uint64_t PixelShaderConstants;
 | |
|     uint64_t SharedConstants;
 | |
| };
 | |
| 
 | |
| [[vk::push_constant]] ConstantBuffer<PushConstants> g_PushConstants;
 | |
| 
 | |
| #define g_Booleans                 vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 256)
 | |
| #define g_SwappedTexcoords         vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 260)
 | |
| #define g_AlphaThreshold           vk::RawBufferLoad<float>(g_PushConstants.SharedConstants + 264)
 | |
| 
 | |
| [[vk::constant_id(0)]] const uint g_SpecConstants = 0;
 | |
| 
 | |
| #define g_SpecConstants() g_SpecConstants
 | |
| 
 | |
| #elif __air__
 | |
| 
 | |
| #include <metal_stdlib>
 | |
| 
 | |
| using namespace metal;
 | |
| 
 | |
| constant uint G_SPEC_CONSTANT [[function_constant(0)]];
 | |
| 
 | |
| uint g_SpecConstants()
 | |
| {
 | |
|     return G_SPEC_CONSTANT;
 | |
| }
 | |
| 
 | |
| struct PushConstants
 | |
| {
 | |
|     ulong VertexShaderConstants;
 | |
|     ulong PixelShaderConstants;
 | |
|     ulong SharedConstants;
 | |
| };
 | |
| 
 | |
| #define g_Booleans (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 256)))
 | |
| #define g_SwappedTexcoords (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 260)))
 | |
| #define g_AlphaThreshold (*(reinterpret_cast<device float*>(g_PushConstants.SharedConstants + 264)))
 | |
| 
 | |
| #else
 | |
| 
 | |
| #define DEFINE_SHARED_CONSTANTS() \
 | |
|     uint g_Booleans : packoffset(c16.x); \
 | |
|     uint g_SwappedTexcoords : packoffset(c16.y); \
 | |
|     float g_AlphaThreshold : packoffset(c16.z) \
 | |
| 
 | |
| uint g_SpecConstants();
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #ifdef __air__
 | |
| 
 | |
| struct Texture2DDescriptorHeap
 | |
| {
 | |
|     array<texture2d<float>, 1> g [[id(0)]];
 | |
| };
 | |
| 
 | |
| struct Texture3DDescriptorHeap
 | |
| {
 | |
|     array<texture3d<float>, 1> g [[id(0)]];
 | |
| };
 | |
| 
 | |
| struct TextureCubeDescriptorHeap
 | |
| {
 | |
|     array<texturecube<float>, 1> g [[id(0)]];
 | |
| };
 | |
| 
 | |
| struct SamplerDescriptorHeap
 | |
| {
 | |
|     array<sampler, 1> g [[id(0)]];
 | |
| };
 | |
| 
 | |
| uint2 getTexture2DDimensions(texture2d<float> texture)
 | |
| {
 | |
|     return uint2(texture.get_width(), texture.get_height());
 | |
| }
 | |
| 
 | |
| float4 tfetch2D(constant Texture2DDescriptorHeap& textureHeap,
 | |
|                 constant SamplerDescriptorHeap& samplerHeap,
 | |
|                 uint resourceDescriptorIndex,
 | |
|                 uint samplerDescriptorIndex,
 | |
|                 float2 texCoord, float2 offset)
 | |
| {
 | |
|     texture2d<float> texture = textureHeap.g[resourceDescriptorIndex];
 | |
|     sampler sampler = samplerHeap.g[samplerDescriptorIndex];
 | |
|     return texture.sample(sampler, texCoord + offset / (float2)getTexture2DDimensions(texture));
 | |
| }
 | |
| 
 | |
| float2 getWeights2D(constant Texture2DDescriptorHeap& textureHeap,
 | |
|                     constant SamplerDescriptorHeap& samplerHeap,
 | |
|                     uint resourceDescriptorIndex,
 | |
|                     uint samplerDescriptorIndex,
 | |
|                     float2 texCoord, float2 offset)
 | |
| {
 | |
|     texture2d<float> texture = textureHeap.g[resourceDescriptorIndex];
 | |
|     return select(fract(texCoord * (float2)getTexture2DDimensions(texture) + offset - 0.5), 0.0, isnan(texCoord));
 | |
| }
 | |
| 
 | |
| #else
 | |
| 
 | |
| Texture2D<float4> g_Texture2DDescriptorHeap[] : register(t0, space0);
 | |
| Texture3D<float4> g_Texture3DDescriptorHeap[] : register(t0, space1);
 | |
| TextureCube<float4> g_TextureCubeDescriptorHeap[] : register(t0, space2);
 | |
| SamplerState g_SamplerDescriptorHeap[] : register(s0, space3);
 | |
| 
 | |
| uint2 getTexture2DDimensions(Texture2D<float4> texture)
 | |
| {
 | |
|     uint2 dimensions;
 | |
|     texture.GetDimensions(dimensions.x, dimensions.y);
 | |
|     return dimensions;
 | |
| }
 | |
| 
 | |
| float4 tfetch2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset)
 | |
| {
 | |
|     Texture2D<float4> texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex];
 | |
|     return texture.Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord + offset / getTexture2DDimensions(texture));
 | |
| }
 | |
| 
 | |
| float2 getWeights2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset)
 | |
| {
 | |
|     Texture2D<float4> texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex];
 | |
|     return select(isnan(texCoord), 0.0, frac(texCoord * getTexture2DDimensions(texture) + offset - 0.5));
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #ifdef __air__
 | |
| #define selectWrapper(a, b, c) select(c, b, a)
 | |
| #else
 | |
| #define selectWrapper(a, b, c) select(a, b, c)
 | |
| #endif
 | |
| 
 | |
| #ifdef __air__
 | |
| #define frac(X) fract(X)
 | |
| 
 | |
| template<typename T>
 | |
| void clip(T a)
 | |
| {
 | |
|     if (a < 0.0) {
 | |
|         discard_fragment();
 | |
|     }
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| float rcp(T a)
 | |
| {
 | |
|     return 1.0 / a;
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| float4x4 mul(T a, T b)
 | |
| {
 | |
|     return a * b;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef __air__
 | |
| #define UNROLL
 | |
| #define BRANCH
 | |
| #else
 | |
| #define UNROLL [unroll]
 | |
| #define BRANCH [branch]
 | |
| #endif
 | |
| 
 | |
| float w0(float a)
 | |
| {
 | |
|     return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f);
 | |
| }
 | |
| 
 | |
| float w1(float a)
 | |
| {
 | |
|     return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f);
 | |
| }
 | |
| 
 | |
| float w2(float a)
 | |
| {
 | |
|     return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f);
 | |
| }
 | |
| 
 | |
| float w3(float a)
 | |
| {
 | |
|     return (1.0f / 6.0f) * (a * a * a);
 | |
| }
 | |
| 
 | |
| float g0(float a)
 | |
| {
 | |
|     return w0(a) + w1(a);
 | |
| }
 | |
| 
 | |
| float g1(float a)
 | |
| {
 | |
|     return w2(a) + w3(a);
 | |
| }
 | |
| 
 | |
| float h0(float a)
 | |
| {
 | |
|     return -1.0f + w1(a) / (w0(a) + w1(a)) + 0.5f;
 | |
| }
 | |
| 
 | |
| float h1(float a)
 | |
| {
 | |
|     return 1.0f + w3(a) / (w2(a) + w3(a)) + 0.5f;
 | |
| }
 | |
| 
 | |
| struct CubeMapData
 | |
| {
 | |
|     float3 cubeMapDirections[2];
 | |
|     uint cubeMapIndex;
 | |
| };
 | |
| 
 | |
| #ifdef __air__
 | |
| 
 | |
| float4 tfetch2DBicubic(constant Texture2DDescriptorHeap& textureHeap,
 | |
|                        constant SamplerDescriptorHeap& samplerHeap,
 | |
|                        uint resourceDescriptorIndex,
 | |
|                        uint samplerDescriptorIndex,
 | |
|                        float2 texCoord, float2 offset)
 | |
| {
 | |
|     texture2d<float> texture = textureHeap.g[resourceDescriptorIndex];
 | |
|     sampler sampler = samplerHeap.g[samplerDescriptorIndex];
 | |
|     uint2 dimensions = getTexture2DDimensions(texture);
 | |
| 
 | |
|     float x = texCoord.x * dimensions.x + offset.x;
 | |
|     float y = texCoord.y * dimensions.y + offset.y;
 | |
| 
 | |
|     x -= 0.5f;
 | |
|     y -= 0.5f;
 | |
|     float px = floor(x);
 | |
|     float py = floor(y);
 | |
|     float fx = x - px;
 | |
|     float fy = y - py;
 | |
| 
 | |
|     float g0x = g0(fx);
 | |
|     float g1x = g1(fx);
 | |
|     float h0x = h0(fx);
 | |
|     float h1x = h1(fx);
 | |
|     float h0y = h0(fy);
 | |
|     float h1y = h1(fy);
 | |
| 
 | |
|     float4 r =
 | |
|         g0(fy) * (g0x * texture.sample(sampler, float2(px + h0x, py + h0y) / float2(dimensions)) +
 | |
|               g1x * texture.sample(sampler, float2(px + h1x, py + h0y) / float2(dimensions))) +
 | |
|         g1(fy) * (g0x * texture.sample(sampler, float2(px + h0x, py + h1y) / float2(dimensions)) +
 | |
|               g1x * texture.sample(sampler, float2(px + h1x, py + h1y) / float2(dimensions)));
 | |
| 
 | |
|     return r;
 | |
| }
 | |
| 
 | |
| float4 tfetch3D(constant Texture3DDescriptorHeap& textureHeap,
 | |
|                 constant SamplerDescriptorHeap& samplerHeap,
 | |
|                 uint resourceDescriptorIndex,
 | |
|                 uint samplerDescriptorIndex,
 | |
|                 float3 texCoord)
 | |
| {
 | |
|     texture3d<float> texture = textureHeap.g[resourceDescriptorIndex];
 | |
|     sampler sampler = samplerHeap.g[samplerDescriptorIndex];
 | |
|     return texture.sample(sampler, texCoord);
 | |
| }
 | |
| 
 | |
| float4 tfetchCube(constant TextureCubeDescriptorHeap& textureHeap,
 | |
|                   constant SamplerDescriptorHeap& samplerHeap,
 | |
|                   uint resourceDescriptorIndex,
 | |
|                   uint samplerDescriptorIndex,
 | |
|                   float3 texCoord, thread CubeMapData* cubeMapData)
 | |
| {
 | |
|     texturecube<float> texture = textureHeap.g[resourceDescriptorIndex];
 | |
|     sampler sampler = samplerHeap.g[samplerDescriptorIndex];
 | |
|     return texture.sample(sampler, cubeMapData->cubeMapDirections[(uint)texCoord.z]);
 | |
| }
 | |
| 
 | |
| #else
 | |
| 
 | |
| float4 tfetch2DBicubic(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset)
 | |
| {
 | |
|     Texture2D<float4> texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex];
 | |
|     SamplerState samplerState = g_SamplerDescriptorHeap[samplerDescriptorIndex];
 | |
|     uint2 dimensions = getTexture2DDimensions(texture);
 | |
|     
 | |
|     float x = texCoord.x * dimensions.x + offset.x;
 | |
|     float y = texCoord.y * dimensions.y + offset.y;
 | |
| 
 | |
|     x -= 0.5f;
 | |
|     y -= 0.5f;
 | |
|     float px = floor(x);
 | |
|     float py = floor(y);
 | |
|     float fx = x - px;
 | |
|     float fy = y - py;
 | |
| 
 | |
|     float g0x = g0(fx);
 | |
|     float g1x = g1(fx);
 | |
|     float h0x = h0(fx);
 | |
|     float h1x = h1(fx);
 | |
|     float h0y = h0(fy);
 | |
|     float h1y = h1(fy);
 | |
| 
 | |
|     float4 r =
 | |
|         g0(fy) * (g0x * texture.Sample(samplerState, float2(px + h0x, py + h0y) / float2(dimensions)) +
 | |
|             g1x * texture.Sample(samplerState, float2(px + h1x, py + h0y) / float2(dimensions))) +
 | |
|         g1(fy) * (g0x * texture.Sample(samplerState, float2(px + h0x, py + h1y) / float2(dimensions)) +
 | |
|             g1x * texture.Sample(samplerState, float2(px + h1x, py + h1y) / float2(dimensions)));
 | |
| 
 | |
|     return r;
 | |
| }
 | |
| 
 | |
| float4 tfetch3D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord)
 | |
| {
 | |
|     return g_Texture3DDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord);
 | |
| }
 | |
| 
 | |
| float4 tfetchCube(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord, inout CubeMapData cubeMapData)
 | |
| {
 | |
|     return g_TextureCubeDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], cubeMapData.cubeMapDirections[texCoord.z]);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| float4 tfetchR11G11B10(uint4 value)
 | |
| {
 | |
|     if (g_SpecConstants() & SPEC_CONSTANT_R11G11B10_NORMAL)
 | |
|     {
 | |
|         return float4(
 | |
|             (value.x & 0x00000400 ? -1.0 : 0.0) + ((value.x & 0x3FF) / 1024.0),
 | |
|             (value.x & 0x00200000 ? -1.0 : 0.0) + (((value.x >> 11) & 0x3FF) / 1024.0),
 | |
|             (value.x & 0x80000000 ? -1.0 : 0.0) + (((value.x >> 22) & 0x1FF) / 512.0),
 | |
|             0.0);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| #ifdef __air__
 | |
|         return as_type<float4>(value);
 | |
| #else
 | |
|         return asfloat(value);
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| float4 tfetchTexcoord(uint swappedTexcoords, float4 value, uint semanticIndex)
 | |
| {
 | |
|     return (swappedTexcoords & (1ull << semanticIndex)) != 0 ? value.yxwz : value;
 | |
| }
 | |
| 
 | |
| #ifdef __air__
 | |
| 
 | |
| float4 cube(float4 value, thread CubeMapData* cubeMapData)
 | |
| {
 | |
|     uint index = cubeMapData->cubeMapIndex;
 | |
|     cubeMapData->cubeMapDirections[index] = value.xyz;
 | |
|     ++cubeMapData->cubeMapIndex;
 | |
| 
 | |
|     return float4(0.0, 0.0, 0.0, index);
 | |
| }
 | |
| 
 | |
| #else
 | |
| 
 | |
| float4 cube(float4 value, inout CubeMapData cubeMapData)
 | |
| {
 | |
|     uint index = cubeMapData.cubeMapIndex;
 | |
|     cubeMapData.cubeMapDirections[index] = value.xyz;
 | |
|     ++cubeMapData.cubeMapIndex;
 | |
|     
 | |
|     return float4(0.0, 0.0, 0.0, index);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| float4 dst(float4 src0, float4 src1)
 | |
| {
 | |
|     float4 dest;
 | |
|     dest.x = 1.0;
 | |
|     dest.y = src0.y * src1.y;
 | |
|     dest.z = src0.z;
 | |
|     dest.w = src1.w;
 | |
|     return dest;
 | |
| }
 | |
| 
 | |
| float4 max4(float4 src0)
 | |
| {
 | |
|     return max(max(src0.x, src0.y), max(src0.z, src0.w));
 | |
| }
 | |
| 
 | |
| #ifdef __air__
 | |
| 
 | |
| float2 getPixelCoord(constant Texture2DDescriptorHeap& textureHeap,
 | |
|                      uint resourceDescriptorIndex,
 | |
|                      float2 texCoord)
 | |
| {
 | |
|     texture2d<float> texture = textureHeap.g[resourceDescriptorIndex];
 | |
|     return (float2)getTexture2DDimensions(texture) * texCoord;
 | |
| }
 | |
| 
 | |
| #else
 | |
| 
 | |
| float2 getPixelCoord(uint resourceDescriptorIndex, float2 texCoord)
 | |
| {
 | |
|     return getTexture2DDimensions(g_Texture2DDescriptorHeap[resourceDescriptorIndex]) * texCoord;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| float computeMipLevel(float2 pixelCoord)
 | |
| {
 | |
| #ifdef __air__
 | |
|     float2 dx = dfdx(pixelCoord);
 | |
|     float2 dy = dfdy(pixelCoord);
 | |
| #else
 | |
|     float2 dx = ddx(pixelCoord);
 | |
|     float2 dy = ddy(pixelCoord);
 | |
| #endif
 | |
|     float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy));
 | |
|     return max(0.0, 0.5 * log2(deltaMaxSqr));
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #endif
 | 
