XenosRecomp/ShaderRecomp/shader_common.h
Skyth (Asilkan) f936ed2212
Specialization constants, reverse Z and smol-v implementation. (#2)
* Specialization constant & DXIL library implementation.

* Fix alpha to coverage.

* Add reverse Z implementation.

* Avoid dynamic branches when loading array constants.

* Remove "has bone" specialization constant.

* Integrate smol-v.
2024-11-29 23:14:08 +03:00

217 lines
6.1 KiB
C

#ifndef SHADER_COMMON_H_INCLUDED
#define SHADER_COMMON_H_INCLUDED
#define SPEC_CONSTANT_R11G11B10_NORMAL (1 << 0)
#define SPEC_CONSTANT_BICUBIC_GI_FILTER (1 << 1)
#define SPEC_CONSTANT_ALPHA_TEST (1 << 2)
#define SPEC_CONSTANT_ALPHA_TO_COVERAGE (1 << 3)
#define SPEC_CONSTANT_REVERSE_Z (1 << 4)
#if !defined(__cplusplus) || defined(__INTELLISENSE__)
#define FLT_MIN asfloat(0xff7fffff)
#define FLT_MAX asfloat(0x7f7fffff)
#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
#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
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));
}
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;
}
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);
}
struct CubeMapData
{
float3 cubeMapDirections[2];
uint cubeMapIndex;
};
float4 tfetchCube(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord, inout CubeMapData cubeMapData)
{
return g_TextureCubeDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], cubeMapData.cubeMapDirections[texCoord.z]);
}
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
{
return asfloat(value);
}
}
float4 tfetchTexcoord(uint swappedTexcoords, float4 value, uint semanticIndex)
{
return (swappedTexcoords & (1ull << semanticIndex)) != 0 ? value.yxwz : value;
}
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);
}
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));
}
float2 getPixelCoord(uint resourceDescriptorIndex, float2 texCoord)
{
return getTexture2DDimensions(g_Texture2DDescriptorHeap[resourceDescriptorIndex]) * texCoord;
}
float computeMipLevel(float2 pixelCoord)
{
float2 dx = ddx(pixelCoord);
float2 dy = ddy(pixelCoord);
float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy));
return max(0.0, 0.5 * log2(deltaMaxSqr));
}
#endif
#endif