diff --git a/Dependencies/OpenGL/Gl46.cs b/Dependencies/OpenGL/Gl46.cs
index 007c53568..04ac264b3 100644
--- a/Dependencies/OpenGL/Gl46.cs
+++ b/Dependencies/OpenGL/Gl46.cs
@@ -14444,6 +14444,14 @@ public static void glSpecializeShader(GLuint shader, string pEntryPoint, GLuint
#endif
+ public const GLenum GL_COMPLETION_STATUS_KHR = 0x91B1;
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate void PFNGLMAXSHADERCOMPILERTHREADSKHRPROC(GLuint count);
+ private static PFNGLMAXSHADERCOMPILERTHREADSKHRPROC _glMaxShaderCompilerThreadsKHR;
+ public static bool glMaxShaderCompilerThreadsKHRLoaded => _glMaxShaderCompilerThreadsKHR != null;
+ public static void glMaxShaderCompilerThreadsKHR(GLuint count) => _glMaxShaderCompilerThreadsKHR(count);
+
///
/// Loads OpenGL functions using the specified loader delegate.
///
@@ -15144,6 +15152,10 @@ public unsafe static void Import(GetProcAddressHandler loader)
_glMultiDrawElementsIndirectCount = Marshal.GetDelegateForFunctionPointer(loader.Invoke("glMultiDrawElementsIndirectCount"));
_glPolygonOffsetClamp = Marshal.GetDelegateForFunctionPointer(loader.Invoke("glPolygonOffsetClamp"));
#endif
+ IntPtr maxShaderCompilerThreads = loader.Invoke("glMaxShaderCompilerThreadsKHR");
+ if (maxShaderCompilerThreads == IntPtr.Zero)
+ maxShaderCompilerThreads = loader.Invoke("glMaxShaderCompilerThreadsARB");
+ _glMaxShaderCompilerThreadsKHR = maxShaderCompilerThreads != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer(maxShaderCompilerThreads) : null!;
}
#endif
}
diff --git a/Game.Assets/sdn/shaders/bloomadd_gl460.fs b/Game.Assets/sdn/shaders/bloomadd_gl460.fs
index f90ea2ef0..e3745b9eb 100644
--- a/Game.Assets/sdn/shaders/bloomadd_gl460.fs
+++ b/Game.Assets/sdn/shaders/bloomadd_gl460.fs
@@ -1,6 +1,6 @@
#version 460
-in vec2 vs_BaseTexCoord;
+layout(location = 0) in vec2 vs_BaseTexCoord;
layout(std140, binding = 3) uniform source_pixel_sharedUBO {
bool isAlphaTesting;
diff --git a/Game.Assets/sdn/shaders/blurfilter_gl460.fs b/Game.Assets/sdn/shaders/blurfilter_gl460.fs
index 00b0d6fca..ab81a084d 100644
--- a/Game.Assets/sdn/shaders/blurfilter_gl460.fs
+++ b/Game.Assets/sdn/shaders/blurfilter_gl460.fs
@@ -1,12 +1,12 @@
#version 460
-in vec2 vs_CoordTap0;
-in vec2 vs_CoordTap1;
-in vec2 vs_CoordTap2;
-in vec2 vs_CoordTap3;
-in vec2 vs_CoordTap1Neg;
-in vec2 vs_CoordTap2Neg;
-in vec2 vs_CoordTap3Neg;
+layout(location = 0) in vec2 vs_CoordTap0;
+layout(location = 1) in vec2 vs_CoordTap1;
+layout(location = 2) in vec2 vs_CoordTap2;
+layout(location = 3) in vec2 vs_CoordTap3;
+layout(location = 4) in vec2 vs_CoordTap1Neg;
+layout(location = 5) in vec2 vs_CoordTap2Neg;
+layout(location = 6) in vec2 vs_CoordTap3Neg;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/blurfilter_gl460.vs b/Game.Assets/sdn/shaders/blurfilter_gl460.vs
index cd39e0a6a..fdd6a0136 100644
--- a/Game.Assets/sdn/shaders/blurfilter_gl460.vs
+++ b/Game.Assets/sdn/shaders/blurfilter_gl460.vs
@@ -11,13 +11,13 @@ layout(std140, binding = 5) uniform source_vs_constants {
#define vsTapOffs1 vs_const[49].xy
#define vsTapOffs2 vs_const[50].xy
-out vec2 vs_CoordTap0;
-out vec2 vs_CoordTap1;
-out vec2 vs_CoordTap2;
-out vec2 vs_CoordTap3;
-out vec2 vs_CoordTap1Neg;
-out vec2 vs_CoordTap2Neg;
-out vec2 vs_CoordTap3Neg;
+layout(location = 0) out vec2 vs_CoordTap0;
+layout(location = 1) out vec2 vs_CoordTap1;
+layout(location = 2) out vec2 vs_CoordTap2;
+layout(location = 3) out vec2 vs_CoordTap3;
+layout(location = 4) out vec2 vs_CoordTap1Neg;
+layout(location = 5) out vec2 vs_CoordTap2Neg;
+layout(location = 6) out vec2 vs_CoordTap3Neg;
vec2 FlipV(vec2 uv)
{
diff --git a/Game.Assets/sdn/shaders/common_clipplanes_gl460.vs b/Game.Assets/sdn/shaders/common_clipplanes_gl460.vs
index b0a367a24..bf4611b7a 100644
--- a/Game.Assets/sdn/shaders/common_clipplanes_gl460.vs
+++ b/Game.Assets/sdn/shaders/common_clipplanes_gl460.vs
@@ -1,6 +1,11 @@
#ifndef COMMON_CLIPPLANES_GL460_VS
#define COMMON_CLIPPLANES_GL460_VS
+out gl_PerVertex {
+ vec4 gl_Position;
+ float gl_ClipDistance[2];
+};
+
layout(std140, binding = 7) uniform source_clip_planes {
vec4 clipPlanes[2];
};
diff --git a/Game.Assets/sdn/shaders/downsample_gl460.vs b/Game.Assets/sdn/shaders/downsample_gl460.vs
index 43b5f1873..48ad038e2 100644
--- a/Game.Assets/sdn/shaders/downsample_gl460.vs
+++ b/Game.Assets/sdn/shaders/downsample_gl460.vs
@@ -12,10 +12,10 @@ layout(std140, binding = 5) uniform source_vs_constants {
#define vsTapOffs2 vs_const[50].xy
#define vsTapOffs3 vs_const[51].xy
-out vec2 vs_CoordTap0;
-out vec2 vs_CoordTap1;
-out vec2 vs_CoordTap2;
-out vec2 vs_CoordTap3;
+layout(location = 0) out vec2 vs_CoordTap0;
+layout(location = 1) out vec2 vs_CoordTap1;
+layout(location = 2) out vec2 vs_CoordTap2;
+layout(location = 3) out vec2 vs_CoordTap3;
vec2 FlipV(vec2 uv)
{
diff --git a/Game.Assets/sdn/shaders/downsample_nohdr_gl460.fs b/Game.Assets/sdn/shaders/downsample_nohdr_gl460.fs
index 18e4d3bb3..eec65a2aa 100644
--- a/Game.Assets/sdn/shaders/downsample_nohdr_gl460.fs
+++ b/Game.Assets/sdn/shaders/downsample_nohdr_gl460.fs
@@ -1,10 +1,10 @@
#version 460
// STATIC: "CSTRIKE" "0..1"
-in vec2 vs_CoordTap0;
-in vec2 vs_CoordTap1;
-in vec2 vs_CoordTap2;
-in vec2 vs_CoordTap3;
+layout(location = 0) in vec2 vs_CoordTap0;
+layout(location = 1) in vec2 vs_CoordTap1;
+layout(location = 2) in vec2 vs_CoordTap2;
+layout(location = 3) in vec2 vs_CoordTap3;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/eyeglint_gl460.fs b/Game.Assets/sdn/shaders/eyeglint_gl460.fs
index c309f80c3..5c4b325e5 100644
--- a/Game.Assets/sdn/shaders/eyeglint_gl460.fs
+++ b/Game.Assets/sdn/shaders/eyeglint_gl460.fs
@@ -1,8 +1,8 @@
#version 460
-in vec2 vs_TexCoord;
-in vec2 vs_GlintCenter;
-in vec3 vs_GlintColor;
+layout(location = 0) in vec2 vs_TexCoord;
+layout(location = 1) in vec2 vs_GlintCenter;
+layout(location = 2) in vec3 vs_GlintColor;
out vec4 fragColor;
diff --git a/Game.Assets/sdn/shaders/eyeglint_gl460.vs b/Game.Assets/sdn/shaders/eyeglint_gl460.vs
index a469a3265..16db7d4fd 100644
--- a/Game.Assets/sdn/shaders/eyeglint_gl460.vs
+++ b/Game.Assets/sdn/shaders/eyeglint_gl460.vs
@@ -5,9 +5,9 @@ layout(location = 10) in vec2 v_TexCoord0;
layout(location = 11) in vec2 v_TexCoord1;
layout(location = 12) in vec3 v_TexCoord2;
-out vec2 vs_TexCoord;
-out vec2 vs_GlintCenter;
-out vec3 vs_GlintColor;
+layout(location = 0) out vec2 vs_TexCoord;
+layout(location = 1) out vec2 vs_GlintCenter;
+layout(location = 2) out vec3 vs_GlintColor;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/eyes_gl460.fs b/Game.Assets/sdn/shaders/eyes_gl460.fs
index 4d9636c5f..bd03e869d 100644
--- a/Game.Assets/sdn/shaders/eyes_gl460.fs
+++ b/Game.Assets/sdn/shaders/eyes_gl460.fs
@@ -2,11 +2,11 @@
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1"
// DYNAMIC: "PIXELFOGTYPE" "0..2"
-in vec2 vs_BaseTexCoord;
-in vec2 vs_IrisTexCoord;
-in vec2 vs_GlintTexCoord;
-in vec3 vs_Color;
-in vec4 vs_WorldPos_ProjPosZ;
+layout(location = 0) in vec2 vs_BaseTexCoord;
+layout(location = 1) in vec2 vs_IrisTexCoord;
+layout(location = 2) in vec2 vs_GlintTexCoord;
+layout(location = 3) in vec3 vs_Color;
+layout(location = 4) in vec4 vs_WorldPos_ProjPosZ;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/eyes_gl460.vs b/Game.Assets/sdn/shaders/eyes_gl460.vs
index db4a29985..7b4a47f2d 100644
--- a/Game.Assets/sdn/shaders/eyes_gl460.vs
+++ b/Game.Assets/sdn/shaders/eyes_gl460.vs
@@ -53,11 +53,11 @@ const bool g_bHalfLambert = HALFLAMBERT != 0;
#define modelOrigin const4.xyz
#endif
-out vec2 vs_BaseTexCoord;
-out vec2 vs_IrisTexCoord;
-out vec2 vs_GlintTexCoord;
-out vec3 vs_Color;
-out vec4 vs_WorldPos_ProjPosZ;
+layout(location = 0) out vec2 vs_BaseTexCoord;
+layout(location = 1) out vec2 vs_IrisTexCoord;
+layout(location = 2) out vec2 vs_GlintTexCoord;
+layout(location = 3) out vec3 vs_Color;
+layout(location = 4) out vec4 vs_WorldPos_ProjPosZ;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/introscreenspaceeffect_gl460.fs b/Game.Assets/sdn/shaders/introscreenspaceeffect_gl460.fs
index 1281bbc21..32f3ebb95 100644
--- a/Game.Assets/sdn/shaders/introscreenspaceeffect_gl460.fs
+++ b/Game.Assets/sdn/shaders/introscreenspaceeffect_gl460.fs
@@ -1,7 +1,7 @@
#version 460
// DYNAMIC: "MODE" "0..9"
-in vec2 vs_BaseTexCoord;
+layout(location = 0) in vec2 vs_BaseTexCoord;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/lightmappedgeneric_gl460.fs b/Game.Assets/sdn/shaders/lightmappedgeneric_gl460.fs
index 8aa32bea7..80b5c40c1 100644
--- a/Game.Assets/sdn/shaders/lightmappedgeneric_gl460.fs
+++ b/Game.Assets/sdn/shaders/lightmappedgeneric_gl460.fs
@@ -30,21 +30,21 @@
// DYNAMIC: "LIGHTING_PREVIEW" "0..1"
#if SEAMLESS
-in vec3 vs_SeamlessTexCoord; // zy xz
-in vec4 vs_DetailOrBumpAndEnvmapMaskTexCoord; // envmap mask
+layout(location = 0) in vec3 vs_SeamlessTexCoord; // zy xz
+layout(location = 1) in vec4 vs_DetailOrBumpAndEnvmapMaskTexCoord; // envmap mask
#else
-in vec2 vs_BaseTexCoord;
+layout(location = 2) in vec2 vs_BaseTexCoord;
// detail textures and bumpmaps are mutually exclusive so that we have enough texcoords.
-in vec4 vs_DetailOrBumpAndEnvmapMaskTexCoord;
+layout(location = 1) in vec4 vs_DetailOrBumpAndEnvmapMaskTexCoord;
#endif
-centroid in vec4 vs_LightmapTexCoord1And2;
-centroid in vec4 vs_LightmapTexCoord3;
-in vec4 vs_WorldPos_ProjPosZ;
+layout(location = 3) centroid in vec4 vs_LightmapTexCoord1And2;
+layout(location = 4) centroid in vec4 vs_LightmapTexCoord3;
+layout(location = 5) in vec4 vs_WorldPos_ProjPosZ;
#if CUBEMAP || (LIGHTING_PREVIEW)
-in mat3 vs_TangentSpaceTranspose;
+layout(location = 6) in mat3 vs_TangentSpaceTranspose;
#endif
-in vec4 vs_Color;
-in float vs_VertexBlendX;
+layout(location = 9) in vec4 vs_Color;
+layout(location = 10) in float vs_VertexBlendX;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/lightmappedgeneric_gl460.vs b/Game.Assets/sdn/shaders/lightmappedgeneric_gl460.vs
index 5fd1ea750..37e24ca6e 100644
--- a/Game.Assets/sdn/shaders/lightmappedgeneric_gl460.vs
+++ b/Game.Assets/sdn/shaders/lightmappedgeneric_gl460.vs
@@ -63,23 +63,23 @@ const bool g_bVertexAlphaTexBlendFactor = VERTEXALPHATEXBLENDFACTOR != 0;
const bool g_BumpMask = BUMPMASK != 0;
#if SEAMLESS
-out vec3 vs_SeamlessTexCoord; // x y z
-out vec4 vs_DetailOrBumpAndEnvmapMaskTexCoord; // envmap mask
+layout(location = 0) out vec3 vs_SeamlessTexCoord; // x y z
+layout(location = 1) out vec4 vs_DetailOrBumpAndEnvmapMaskTexCoord; // envmap mask
#else
-out vec2 vs_BaseTexCoord;
+layout(location = 2) out vec2 vs_BaseTexCoord;
// detail textures and bumpmaps are mutually exclusive so that we have enough texcoords.
-out vec4 vs_DetailOrBumpAndEnvmapMaskTexCoord;
+layout(location = 1) out vec4 vs_DetailOrBumpAndEnvmapMaskTexCoord;
#endif
-centroid out vec4 vs_LightmapTexCoord1And2;
-centroid out vec4 vs_LightmapTexCoord3; // and basetexcoord*mask_scale
-out vec4 vs_WorldPos_ProjPosZ;
+layout(location = 3) centroid out vec4 vs_LightmapTexCoord1And2;
+layout(location = 4) centroid out vec4 vs_LightmapTexCoord3; // and basetexcoord*mask_scale
+layout(location = 5) out vec4 vs_WorldPos_ProjPosZ;
#if TANGENTSPACE || (LIGHTING_PREVIEW)
-out mat3 vs_TangentSpaceTranspose;
+layout(location = 6) out mat3 vs_TangentSpaceTranspose;
#endif
-out vec4 vs_Color; // in seamless, r g b = blend weights
-out float vs_VertexBlendX;
+layout(location = 9) out vec4 vs_Color; // in seamless, r g b = blend weights
+layout(location = 10) out float vs_VertexBlendX;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/luminance_compare_gl460.fs b/Game.Assets/sdn/shaders/luminance_compare_gl460.fs
index b41febbdc..6145c3b35 100644
--- a/Game.Assets/sdn/shaders/luminance_compare_gl460.fs
+++ b/Game.Assets/sdn/shaders/luminance_compare_gl460.fs
@@ -1,6 +1,6 @@
#version 460
-in vec2 vs_BaseTexCoord;
+layout(location = 0) in vec2 vs_BaseTexCoord;
layout(std140, binding = 3) uniform source_pixel_sharedUBO {
bool isAlphaTesting;
diff --git a/Game.Assets/sdn/shaders/screenspaceeffect_gl460.vs b/Game.Assets/sdn/shaders/screenspaceeffect_gl460.vs
index f11f978a7..a117fb4a6 100644
--- a/Game.Assets/sdn/shaders/screenspaceeffect_gl460.vs
+++ b/Game.Assets/sdn/shaders/screenspaceeffect_gl460.vs
@@ -12,11 +12,11 @@ layout(std140, binding = 0) uniform source_matrices {
mat4 modelMatrix;
};
-out vec2 vs_BaseTexCoord;
-out vec4 vs_TexCoord0;
-out vec4 vs_TexCoord1;
-out vec4 vs_TexCoord2;
-out vec4 vs_Color0;
+layout(location = 0) out vec2 vs_BaseTexCoord;
+layout(location = 1) out vec4 vs_TexCoord0;
+layout(location = 2) out vec4 vs_TexCoord1;
+layout(location = 3) out vec4 vs_TexCoord2;
+layout(location = 4) out vec4 vs_Color0;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/shadow_gl460.fs b/Game.Assets/sdn/shaders/shadow_gl460.fs
index 88a289cfc..525fc5dff 100644
--- a/Game.Assets/sdn/shaders/shadow_gl460.fs
+++ b/Game.Assets/sdn/shaders/shadow_gl460.fs
@@ -1,11 +1,11 @@
#version 460
-centroid in vec2 vs_TexCoord0;
-centroid in vec2 vs_TexCoord1;
-centroid in vec2 vs_TexCoord2;
-centroid in vec2 vs_TexCoord3;
-centroid in vec2 vs_TexCoord4;
-in vec4 vs_ShadowColor;
+layout(location = 0) centroid in vec2 vs_TexCoord0;
+layout(location = 1) centroid in vec2 vs_TexCoord1;
+layout(location = 2) centroid in vec2 vs_TexCoord2;
+layout(location = 3) centroid in vec2 vs_TexCoord3;
+layout(location = 4) centroid in vec2 vs_TexCoord4;
+layout(location = 5) in vec4 vs_ShadowColor;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/shadow_gl460.vs b/Game.Assets/sdn/shaders/shadow_gl460.vs
index a9a81d5d0..1971a8f78 100644
--- a/Game.Assets/sdn/shaders/shadow_gl460.vs
+++ b/Game.Assets/sdn/shaders/shadow_gl460.vs
@@ -19,12 +19,12 @@ layout(std140, binding = 5) uniform source_vs_constants {
#define cTextureJitter0 vs_const[50]
#define cTextureJitter1 vs_const[51]
-centroid out vec2 vs_TexCoord0;
-centroid out vec2 vs_TexCoord1;
-centroid out vec2 vs_TexCoord2;
-centroid out vec2 vs_TexCoord3;
-centroid out vec2 vs_TexCoord4;
-out vec4 vs_ShadowColor;
+layout(location = 0) centroid out vec2 vs_TexCoord0;
+layout(location = 1) centroid out vec2 vs_TexCoord1;
+layout(location = 2) centroid out vec2 vs_TexCoord2;
+layout(location = 3) centroid out vec2 vs_TexCoord3;
+layout(location = 4) centroid out vec2 vs_TexCoord4;
+layout(location = 5) out vec4 vs_ShadowColor;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/shadowmodel_gl460.fs b/Game.Assets/sdn/shaders/shadowmodel_gl460.fs
index 8a8c51367..47ec56b02 100644
--- a/Game.Assets/sdn/shaders/shadowmodel_gl460.fs
+++ b/Game.Assets/sdn/shaders/shadowmodel_gl460.fs
@@ -1,10 +1,10 @@
#version 460
-in vec3 vs_T0;
-in vec3 vs_T1;
-in vec3 vs_T2;
-in float vs_T3;
-in vec4 vs_Color;
+layout(location = 0) in vec3 vs_T0;
+layout(location = 1) in vec3 vs_T1;
+layout(location = 2) in vec3 vs_T2;
+layout(location = 3) in float vs_T3;
+layout(location = 4) in vec4 vs_Color;
layout(binding = 0) uniform sampler2D basetexture;
diff --git a/Game.Assets/sdn/shaders/shadowmodel_gl460.vs b/Game.Assets/sdn/shaders/shadowmodel_gl460.vs
index 187ac37ec..568fdb4f2 100644
--- a/Game.Assets/sdn/shaders/shadowmodel_gl460.vs
+++ b/Game.Assets/sdn/shaders/shadowmodel_gl460.vs
@@ -25,11 +25,11 @@ layout(std140, binding = 5) uniform source_vs_constants {
#define flOneOverShadowDist cShadowConstants.y
#define flShadowScale cShadowConstants.z
-out vec3 vs_T0;
-out vec3 vs_T1;
-out vec3 vs_T2;
-out float vs_T3;
-out vec4 vs_Color;
+layout(location = 0) out vec3 vs_T0;
+layout(location = 1) out vec3 vs_T1;
+layout(location = 2) out vec3 vs_T2;
+layout(location = 3) out float vs_T3;
+layout(location = 4) out vec4 vs_Color;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/skin_gl460.fs b/Game.Assets/sdn/shaders/skin_gl460.fs
index 55403a0cc..c595f63e5 100644
--- a/Game.Assets/sdn/shaders/skin_gl460.fs
+++ b/Game.Assets/sdn/shaders/skin_gl460.fs
@@ -19,12 +19,12 @@
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1"
// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1"
-in vec4 vs_BaseTexCoord; // xy=base zw=detail
-in vec3 vs_LightAtten; // Scalar light attenuation factors for FOUR lights
-in vec3 vs_WorldVertToEyeVector;
-in mat3 vs_TangentSpaceTranspose;
-in vec4 vs_WorldPos_Atten3;
-in vec4 vs_ProjPos_WrinkleWeight;
+layout(location = 0) in vec4 vs_BaseTexCoord; // xy=base zw=detail
+layout(location = 1) in vec3 vs_LightAtten; // Scalar light attenuation factors for FOUR lights
+layout(location = 2) in vec3 vs_WorldVertToEyeVector;
+layout(location = 3) in mat3 vs_TangentSpaceTranspose;
+layout(location = 6) in vec4 vs_WorldPos_Atten3;
+layout(location = 7) in vec4 vs_ProjPos_WrinkleWeight;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/skin_gl460.vs b/Game.Assets/sdn/shaders/skin_gl460.vs
index 006c3995f..7da2acbd4 100644
--- a/Game.Assets/sdn/shaders/skin_gl460.vs
+++ b/Game.Assets/sdn/shaders/skin_gl460.vs
@@ -39,12 +39,12 @@ const int SHADER_SPECIFIC_CONST_4 = 52;
const bool g_bSkinning = SKINNING != 0;
-out vec4 vs_BaseTexCoord; // includes detail tex coord
-out vec3 vs_LightAtten;
-out vec3 vs_WorldVertToEyeVector;
-out mat3 vs_TangentSpaceTranspose;
-out vec4 vs_WorldPos_Atten3;
-out vec4 vs_ProjPos_WrinkleWeight;
+layout(location = 0) out vec4 vs_BaseTexCoord; // includes detail tex coord
+layout(location = 1) out vec3 vs_LightAtten;
+layout(location = 2) out vec3 vs_WorldVertToEyeVector;
+layout(location = 3) out mat3 vs_TangentSpaceTranspose;
+layout(location = 6) out vec4 vs_WorldPos_Atten3;
+layout(location = 7) out vec4 vs_ProjPos_WrinkleWeight;
//-----------------------------------------------------------------------------
// Main shader entry point
diff --git a/Game.Assets/sdn/shaders/sky_gl460.fs b/Game.Assets/sdn/shaders/sky_gl460.fs
index 29a1cda31..d76fa0d03 100644
--- a/Game.Assets/sdn/shaders/sky_gl460.fs
+++ b/Game.Assets/sdn/shaders/sky_gl460.fs
@@ -1,7 +1,7 @@
#version 460
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1"
-in vec2 vs_BaseTexCoord00;
+layout(location = 0) in vec2 vs_BaseTexCoord00;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/sky_gl460.vs b/Game.Assets/sdn/shaders/sky_gl460.vs
index edc41bef7..d522d04f0 100644
--- a/Game.Assets/sdn/shaders/sky_gl460.vs
+++ b/Game.Assets/sdn/shaders/sky_gl460.vs
@@ -22,11 +22,11 @@ layout(std140, binding = 5) uniform source_vs_constants {
#define U_TO_PIXEL_COORD_SCALE (g_vTextureSizeInfo.z)
#define V_TO_PIXEL_COORD_SCALE (g_vTextureSizeInfo.w)
-out vec2 vs_BaseTexCoord00;
-out vec2 vs_BaseTexCoord01;
-out vec2 vs_BaseTexCoord10;
-out vec2 vs_BaseTexCoord11;
-out vec2 vs_BaseTexCoord_In_Pixels;
+layout(location = 0) out vec2 vs_BaseTexCoord00;
+layout(location = 1) out vec2 vs_BaseTexCoord01;
+layout(location = 2) out vec2 vs_BaseTexCoord10;
+layout(location = 3) out vec2 vs_BaseTexCoord11;
+layout(location = 4) out vec2 vs_BaseTexCoord_In_Pixels;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/sky_hdr_compressed_gl460.fs b/Game.Assets/sdn/shaders/sky_hdr_compressed_gl460.fs
index 45452511f..854b910bc 100644
--- a/Game.Assets/sdn/shaders/sky_hdr_compressed_gl460.fs
+++ b/Game.Assets/sdn/shaders/sky_hdr_compressed_gl460.fs
@@ -1,7 +1,7 @@
#version 460
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1"
-in vec2 vs_BaseTexCoord00;
+layout(location = 0) in vec2 vs_BaseTexCoord00;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/sky_hdr_compressed_rgbs_gl460.fs b/Game.Assets/sdn/shaders/sky_hdr_compressed_rgbs_gl460.fs
index 3b2a6f938..480b7e6d4 100644
--- a/Game.Assets/sdn/shaders/sky_hdr_compressed_rgbs_gl460.fs
+++ b/Game.Assets/sdn/shaders/sky_hdr_compressed_rgbs_gl460.fs
@@ -1,11 +1,11 @@
#version 460
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1"
-in vec2 vs_BaseTexCoord00;
-in vec2 vs_BaseTexCoord01;
-in vec2 vs_BaseTexCoord10;
-in vec2 vs_BaseTexCoord11;
-in vec2 vs_BaseTexCoord_In_Pixels;
+layout(location = 0) in vec2 vs_BaseTexCoord00;
+layout(location = 1) in vec2 vs_BaseTexCoord01;
+layout(location = 2) in vec2 vs_BaseTexCoord10;
+layout(location = 3) in vec2 vs_BaseTexCoord11;
+layout(location = 4) in vec2 vs_BaseTexCoord_In_Pixels;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/teeth_bump_gl460.fs b/Game.Assets/sdn/shaders/teeth_bump_gl460.fs
index 0e6411593..9338bced1 100644
--- a/Game.Assets/sdn/shaders/teeth_bump_gl460.fs
+++ b/Game.Assets/sdn/shaders/teeth_bump_gl460.fs
@@ -4,12 +4,12 @@
// DYNAMIC: "AMBIENT_LIGHT" "0..1"
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1"
-in vec2 vs_BaseTexCoord;
-in vec4 vs_WorldVertToEyeVector_Darkening;
-in mat3 vs_TangentSpace;
-in vec4 vs_WorldPos_ProjPosZ;
-in vec2 vs_LightAtten01;
-in vec2 vs_LightAtten23;
+layout(location = 0) in vec2 vs_BaseTexCoord;
+layout(location = 1) in vec4 vs_WorldVertToEyeVector_Darkening;
+layout(location = 2) in mat3 vs_TangentSpace;
+layout(location = 5) in vec4 vs_WorldPos_ProjPosZ;
+layout(location = 6) in vec2 vs_LightAtten01;
+layout(location = 7) in vec2 vs_LightAtten23;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/teeth_bump_gl460.vs b/Game.Assets/sdn/shaders/teeth_bump_gl460.vs
index e164626f3..aaf23f13a 100644
--- a/Game.Assets/sdn/shaders/teeth_bump_gl460.vs
+++ b/Game.Assets/sdn/shaders/teeth_bump_gl460.vs
@@ -42,12 +42,12 @@ const bool g_bSkinning = SKINNING != 0;
#define modelOrigin const4.xyz
#endif
-out vec2 vs_BaseTexCoord;
-out vec4 vs_WorldVertToEyeVector_Darkening;
-out mat3 vs_TangentSpace;
-out vec4 vs_WorldPos_ProjPosZ;
-out vec2 vs_LightAtten01;
-out vec2 vs_LightAtten23;
+layout(location = 0) out vec2 vs_BaseTexCoord;
+layout(location = 1) out vec4 vs_WorldVertToEyeVector_Darkening;
+layout(location = 2) out mat3 vs_TangentSpace;
+layout(location = 5) out vec4 vs_WorldPos_ProjPosZ;
+layout(location = 6) out vec2 vs_LightAtten01;
+layout(location = 7) out vec2 vs_LightAtten23;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/teeth_gl460.fs b/Game.Assets/sdn/shaders/teeth_gl460.fs
index 068da978a..df5b25e52 100644
--- a/Game.Assets/sdn/shaders/teeth_gl460.fs
+++ b/Game.Assets/sdn/shaders/teeth_gl460.fs
@@ -2,9 +2,9 @@
// DYNAMIC: "PIXELFOGTYPE" "0..2"
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1"
-in vec2 vs_BaseTexCoord;
-in vec3 vs_VertAtten;
-in vec4 vs_WorldPos_ProjPosZ;
+layout(location = 0) in vec2 vs_BaseTexCoord;
+layout(location = 1) in vec3 vs_VertAtten;
+layout(location = 2) in vec4 vs_WorldPos_ProjPosZ;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/teeth_gl460.vs b/Game.Assets/sdn/shaders/teeth_gl460.vs
index 569dd4b16..b5baf9979 100644
--- a/Game.Assets/sdn/shaders/teeth_gl460.vs
+++ b/Game.Assets/sdn/shaders/teeth_gl460.vs
@@ -43,9 +43,9 @@ const bool g_bSkinning = SKINNING != 0;
#define modelOrigin const4.xyz
#endif
-out vec2 vs_BaseTexCoord;
-out vec3 vs_VertAtten;
-out vec4 vs_WorldPos_ProjPosZ;
+layout(location = 0) out vec2 vs_BaseTexCoord;
+layout(location = 1) out vec3 vs_VertAtten;
+layout(location = 2) out vec4 vs_WorldPos_ProjPosZ;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/unlitgeneric_gl460.fs b/Game.Assets/sdn/shaders/unlitgeneric_gl460.fs
index b030de42c..89ae88206 100644
--- a/Game.Assets/sdn/shaders/unlitgeneric_gl460.fs
+++ b/Game.Assets/sdn/shaders/unlitgeneric_gl460.fs
@@ -1,8 +1,8 @@
#version 460
// STATIC: "BASETEXTURE" "0..1"
-in vec2 vs_TexCoord;
-in vec4 vs_Color;
+layout(location = 0) in vec2 vs_TexCoord;
+layout(location = 1) in vec4 vs_Color;
layout(std140, binding = 3) uniform source_pixel_sharedUBO {
bool isAlphaTesting;
diff --git a/Game.Assets/sdn/shaders/unlitgeneric_gl460.vs b/Game.Assets/sdn/shaders/unlitgeneric_gl460.vs
index 872ef14d8..e87532ecb 100644
--- a/Game.Assets/sdn/shaders/unlitgeneric_gl460.vs
+++ b/Game.Assets/sdn/shaders/unlitgeneric_gl460.vs
@@ -19,8 +19,8 @@ const int VertexAlpha = 32;
uniform int flags;
-out vec2 vs_TexCoord;
-out vec4 vs_Color;
+layout(location = 0) out vec2 vs_TexCoord;
+layout(location = 1) out vec4 vs_Color;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/unlittwotexture_gl460.fs b/Game.Assets/sdn/shaders/unlittwotexture_gl460.fs
index 19872c6c1..374a48a37 100644
--- a/Game.Assets/sdn/shaders/unlittwotexture_gl460.fs
+++ b/Game.Assets/sdn/shaders/unlittwotexture_gl460.fs
@@ -2,9 +2,9 @@
// DYNAMIC: "PIXELFOGTYPE" "0..1"
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1"
-in vec2 vs_BaseTexCoord;
-in vec2 vs_BaseTexCoord2;
-in vec4 vs_WorldPos_ProjPosZ;
+layout(location = 0) in vec2 vs_BaseTexCoord;
+layout(location = 1) in vec2 vs_BaseTexCoord2;
+layout(location = 2) in vec4 vs_WorldPos_ProjPosZ;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/unlittwotexture_gl460.vs b/Game.Assets/sdn/shaders/unlittwotexture_gl460.vs
index e60b17c3e..60bda0b1b 100644
--- a/Game.Assets/sdn/shaders/unlittwotexture_gl460.vs
+++ b/Game.Assets/sdn/shaders/unlittwotexture_gl460.vs
@@ -30,9 +30,9 @@ const bool g_bSkinning = SKINNING != 0;
#define cBaseTexCoordTransform2_0 vs_const[SHADER_SPECIFIC_CONST_2 + 0]
#define cBaseTexCoordTransform2_1 vs_const[SHADER_SPECIFIC_CONST_2 + 1]
-out vec2 vs_BaseTexCoord;
-out vec2 vs_BaseTexCoord2;
-out vec4 vs_WorldPos_ProjPosZ;
+layout(location = 0) out vec2 vs_BaseTexCoord;
+layout(location = 1) out vec2 vs_BaseTexCoord2;
+layout(location = 2) out vec4 vs_WorldPos_ProjPosZ;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/vertexlitgeneric_bump_gl460.fs b/Game.Assets/sdn/shaders/vertexlitgeneric_bump_gl460.fs
index 0b13ca07c..e2b26bd25 100644
--- a/Game.Assets/sdn/shaders/vertexlitgeneric_bump_gl460.fs
+++ b/Game.Assets/sdn/shaders/vertexlitgeneric_bump_gl460.fs
@@ -18,14 +18,14 @@
// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1"
// DYNAMIC: "PIXELFOGTYPE" "0..2"
-in vec4 vs_BaseTexCoord2_TangentSpaceVertToEyeVectorXY;
-in vec3 vs_LightAtten;
-in vec4 vs_WorldVertToEyeVectorXYZ_TangentSpaceVertToEyeVectorZ;
-in vec3 vs_WorldNormal; // World-space normal
-in vec4 vs_WorldTangent;
-in vec4 vs_ProjPos;
-in vec4 vs_WorldPos_ProjPosZ;
-in vec3 vs_DetailTexCoord_Atten3;
+layout(location = 0) in vec4 vs_BaseTexCoord2_TangentSpaceVertToEyeVectorXY;
+layout(location = 1) in vec3 vs_LightAtten;
+layout(location = 2) in vec4 vs_WorldVertToEyeVectorXYZ_TangentSpaceVertToEyeVectorZ;
+layout(location = 3) in vec3 vs_WorldNormal; // World-space normal
+layout(location = 4) in vec4 vs_WorldTangent;
+layout(location = 5) in vec4 vs_ProjPos;
+layout(location = 6) in vec4 vs_WorldPos_ProjPosZ;
+layout(location = 7) in vec3 vs_DetailTexCoord_Atten3;
layout(std140, binding = 6) uniform source_ps_constants {
vec4 ps_const[256];
diff --git a/Game.Assets/sdn/shaders/vertexlitgeneric_bump_gl460.vs b/Game.Assets/sdn/shaders/vertexlitgeneric_bump_gl460.vs
index c3a06f430..b88c51fc0 100644
--- a/Game.Assets/sdn/shaders/vertexlitgeneric_bump_gl460.vs
+++ b/Game.Assets/sdn/shaders/vertexlitgeneric_bump_gl460.vs
@@ -42,17 +42,17 @@ const bool g_bSkinning = SKINNING != 0;
//-----------------------------------------------------------------------------
// Output vertex format
//-----------------------------------------------------------------------------
-out vec4 vs_BaseTexCoord2_TangentSpaceVertToEyeVectorXY;
-out vec3 vs_LightAtten;
-out vec4 vs_WorldVertToEyeVectorXYZ_TangentSpaceVertToEyeVectorZ;
-out vec3 vs_WorldNormal; // World-space normal
-out vec4 vs_WorldTangent;
+layout(location = 0) out vec4 vs_BaseTexCoord2_TangentSpaceVertToEyeVectorXY;
+layout(location = 1) out vec3 vs_LightAtten;
+layout(location = 2) out vec4 vs_WorldVertToEyeVectorXYZ_TangentSpaceVertToEyeVectorZ;
+layout(location = 3) out vec3 vs_WorldNormal; // World-space normal
+layout(location = 4) out vec4 vs_WorldTangent;
#if USE_WITH_2B
-out vec4 vs_ProjPos;
+layout(location = 5) out vec4 vs_ProjPos;
#else
#endif
-out vec4 vs_WorldPos_ProjPosZ;
-out vec3 vs_DetailTexCoord_Atten3;
+layout(location = 6) out vec4 vs_WorldPos_ProjPosZ;
+layout(location = 7) out vec3 vs_DetailTexCoord_Atten3;
//-----------------------------------------------------------------------------
// Main shader entry point
diff --git a/Game.Assets/sdn/shaders/vertexlitgeneric_gl460.fs b/Game.Assets/sdn/shaders/vertexlitgeneric_gl460.fs
index 74164bb11..ab0b15859 100644
--- a/Game.Assets/sdn/shaders/vertexlitgeneric_gl460.fs
+++ b/Game.Assets/sdn/shaders/vertexlitgeneric_gl460.fs
@@ -27,28 +27,28 @@
// DYNAMIC: "PIXELFOGTYPE" "0..2"
#if SEAMLESS_BASE
-in vec3 vs_SeamlessTexCoord;
+layout(location = 0) in vec3 vs_SeamlessTexCoord;
#define i_baseTexCoord vs_SeamlessTexCoord
#else
-in vec2 vs_BaseTexCoord;
+layout(location = 1) in vec2 vs_BaseTexCoord;
#define i_baseTexCoord vs_BaseTexCoord
#endif
#if SEAMLESS_DETAIL
-in vec3 vs_SeamlessDetailTexCoord;
+layout(location = 2) in vec3 vs_SeamlessDetailTexCoord;
#define i_detailTexCoord vs_SeamlessDetailTexCoord
#else
-in vec2 vs_DetailTexCoord;
+layout(location = 3) in vec2 vs_DetailTexCoord;
#define i_detailTexCoord vs_DetailTexCoord
#endif
-in vec4 vs_Color;
+layout(location = 4) in vec4 vs_Color;
#if CUBEMAP
-in vec3 vs_WorldVertToEyeVector;
+layout(location = 5) in vec3 vs_WorldVertToEyeVector;
#endif
-in vec3 vs_WorldSpaceNormal;
-in vec4 vs_ProjPos;
-in vec4 vs_WorldPos_ProjPosZ;
+layout(location = 6) in vec3 vs_WorldSpaceNormal;
+layout(location = 7) in vec4 vs_ProjPos;
+layout(location = 8) in vec4 vs_WorldPos_ProjPosZ;
#if SEAMLESS_DETAIL || SEAMLESS_BASE
-in vec3 vs_SeamlessWeights;
+layout(location = 9) in vec3 vs_SeamlessWeights;
#endif
layout(std140, binding = 6) uniform source_ps_constants {
diff --git a/Game.Assets/sdn/shaders/vertexlitgeneric_gl460.vs b/Game.Assets/sdn/shaders/vertexlitgeneric_gl460.vs
index 662ebf713..05de97b49 100644
--- a/Game.Assets/sdn/shaders/vertexlitgeneric_gl460.vs
+++ b/Game.Assets/sdn/shaders/vertexlitgeneric_gl460.vs
@@ -56,27 +56,27 @@ const bool g_bVertexColor = VERTEXCOLOR != 0;
const bool g_bHalfLambert = HALFLAMBERT != 0;
#if SEAMLESS_BASE
-out vec3 vs_SeamlessTexCoord; // Base texture x/y/z (indexed by swizzle)
+layout(location = 0) out vec3 vs_SeamlessTexCoord; // Base texture x/y/z (indexed by swizzle)
#else
-out vec2 vs_BaseTexCoord; // Base texture coordinate
+layout(location = 1) out vec2 vs_BaseTexCoord; // Base texture coordinate
#endif
#if SEAMLESS_DETAIL
-out vec3 vs_SeamlessDetailTexCoord; // Detail texture coordinate
+layout(location = 2) out vec3 vs_SeamlessDetailTexCoord; // Detail texture coordinate
#else
-out vec2 vs_DetailTexCoord; // Detail texture coordinate
+layout(location = 3) out vec2 vs_DetailTexCoord; // Detail texture coordinate
#endif
-out vec4 vs_Color; // Vertex color (from lighting or unlit)
+layout(location = 4) out vec4 vs_Color; // Vertex color (from lighting or unlit)
#if CUBEMAP
-out vec3 vs_WorldVertToEyeVector; // Necessary for cubemaps
+layout(location = 5) out vec3 vs_WorldVertToEyeVector; // Necessary for cubemaps
#endif
-out vec3 vs_WorldSpaceNormal; // Necessary for cubemaps and flashlight
+layout(location = 6) out vec3 vs_WorldSpaceNormal; // Necessary for cubemaps and flashlight
-out vec4 vs_ProjPos;
-out vec4 vs_WorldPos_ProjPosZ;
+layout(location = 7) out vec4 vs_ProjPos;
+layout(location = 8) out vec4 vs_WorldPos_ProjPosZ;
#if SEAMLESS_DETAIL || SEAMLESS_BASE
-out vec3 vs_SeamlessWeights; // x y z projection weights
+layout(location = 9) out vec3 vs_SeamlessWeights; // x y z projection weights
#endif
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/water_gl460.fs b/Game.Assets/sdn/shaders/water_gl460.fs
index f3524fa54..d4cc29470 100644
--- a/Game.Assets/sdn/shaders/water_gl460.fs
+++ b/Game.Assets/sdn/shaders/water_gl460.fs
@@ -9,17 +9,17 @@
// DYNAMIC: "PIXELFOGTYPE" "0..1"
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1"
-in vec2 vs_BumpTexCoord;
-in vec3 vs_TangentEyeVect;
-in vec4 vs_ReflectXY_RefractYX;
-in float vs_W;
-in vec4 vs_ProjPos;
+layout(location = 0) in vec2 vs_BumpTexCoord;
+layout(location = 1) in vec3 vs_TangentEyeVect;
+layout(location = 2) in vec4 vs_ReflectXY_RefractYX;
+layout(location = 3) in float vs_W;
+layout(location = 4) in vec4 vs_ProjPos;
#if MULTITEXTURE
-in vec4 vs_ExtraBumpTexCoord;
+layout(location = 5) in vec4 vs_ExtraBumpTexCoord;
#endif
#if BASETEXTURE
-centroid in vec4 vs_LightmapTexCoord1And2;
-centroid in vec4 vs_LightmapTexCoord3;
+layout(location = 6) centroid in vec4 vs_LightmapTexCoord1And2;
+layout(location = 7) centroid in vec4 vs_LightmapTexCoord3;
#endif
layout(std140, binding = 6) uniform source_ps_constants {
diff --git a/Game.Assets/sdn/shaders/water_gl460.vs b/Game.Assets/sdn/shaders/water_gl460.vs
index 92be927a9..2ee0cb323 100644
--- a/Game.Assets/sdn/shaders/water_gl460.vs
+++ b/Game.Assets/sdn/shaders/water_gl460.vs
@@ -29,17 +29,17 @@ const int SHADER_SPECIFIC_CONST_3 = 51;
#define cBumpTexCoordTransform1 vs_const[SHADER_SPECIFIC_CONST_1 + 1]
#define TexOffsets vs_const[SHADER_SPECIFIC_CONST_3]
-out vec2 vs_BumpTexCoord;
-out vec3 vs_TangentEyeVect;
-out vec4 vs_ReflectXY_RefractYX;
-out float vs_W;
-out vec4 vs_ProjPos;
+layout(location = 0) out vec2 vs_BumpTexCoord;
+layout(location = 1) out vec3 vs_TangentEyeVect;
+layout(location = 2) out vec4 vs_ReflectXY_RefractYX;
+layout(location = 3) out float vs_W;
+layout(location = 4) out vec4 vs_ProjPos;
#if MULTITEXTURE
-out vec4 vs_ExtraBumpTexCoord;
+layout(location = 5) out vec4 vs_ExtraBumpTexCoord;
#endif
#if BASETEXTURE
-centroid out vec4 vs_LightmapTexCoord1And2;
-centroid out vec4 vs_LightmapTexCoord3;
+layout(location = 6) centroid out vec4 vs_LightmapTexCoord1And2;
+layout(location = 7) centroid out vec4 vs_LightmapTexCoord3;
#endif
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/watercheap_gl460.fs b/Game.Assets/sdn/shaders/watercheap_gl460.fs
index 78e6aead5..6e1640b9e 100644
--- a/Game.Assets/sdn/shaders/watercheap_gl460.fs
+++ b/Game.Assets/sdn/shaders/watercheap_gl460.fs
@@ -8,12 +8,12 @@
// DYNAMIC: "HDRENABLED" "0..1"
// DYNAMIC: "PIXELFOGTYPE" "0..1"
-in vec2 vs_NormalMapTexCoord;
-in vec3 vs_WorldVertToEyeVector;
-in mat3 vs_TangentSpaceTranspose;
-in vec4 vs_Refract_W_ProjZ;
+layout(location = 0) in vec2 vs_NormalMapTexCoord;
+layout(location = 1) in vec3 vs_WorldVertToEyeVector;
+layout(location = 2) in mat3 vs_TangentSpaceTranspose;
+layout(location = 5) in vec4 vs_Refract_W_ProjZ;
#if MULTITEXTURE
-in vec4 vs_ExtraBumpTexCoord;
+layout(location = 6) in vec4 vs_ExtraBumpTexCoord;
#endif
layout(std140, binding = 6) uniform source_ps_constants {
diff --git a/Game.Assets/sdn/shaders/watercheap_gl460.vs b/Game.Assets/sdn/shaders/watercheap_gl460.vs
index dba0acdf7..12a6c6ac9 100644
--- a/Game.Assets/sdn/shaders/watercheap_gl460.vs
+++ b/Game.Assets/sdn/shaders/watercheap_gl460.vs
@@ -24,11 +24,11 @@ const int SHADER_SPECIFIC_CONST_3 = 51;
#define VSHADER_VECT_SCALE 1.0
#define TexOffsets vs_const[SHADER_SPECIFIC_CONST_3]
-out vec2 vs_NormalMapTexCoord;
-out vec3 vs_WorldVertToEyeVector;
-out mat3 vs_TangentSpaceTranspose;
-out vec4 vs_Refract_W_ProjZ;
-out vec4 vs_ExtraBumpTexCoord;
+layout(location = 0) out vec2 vs_NormalMapTexCoord;
+layout(location = 1) out vec3 vs_WorldVertToEyeVector;
+layout(location = 2) out mat3 vs_TangentSpaceTranspose;
+layout(location = 5) out vec4 vs_Refract_W_ProjZ;
+layout(location = 6) out vec4 vs_ExtraBumpTexCoord;
#include "common_clipplanes_gl460.vs"
diff --git a/Game.Assets/sdn/shaders/worldvertextransition_gl460.fs b/Game.Assets/sdn/shaders/worldvertextransition_gl460.fs
index d0b72d861..20a0326b0 100644
--- a/Game.Assets/sdn/shaders/worldvertextransition_gl460.fs
+++ b/Game.Assets/sdn/shaders/worldvertextransition_gl460.fs
@@ -1,7 +1,7 @@
#version 460
-in vec2 vs_TexCoord0;
-centroid in vec2 vs_TexCoord1;
-in vec4 vs_Color;
+layout(location = 0) in vec2 vs_TexCoord0;
+layout(location = 1) centroid in vec2 vs_TexCoord1;
+layout(location = 2) in vec4 vs_Color;
layout(std140, binding = 3) uniform source_pixel_sharedUBO {
bool isAlphaTesting;
diff --git a/Game.Assets/sdn/shaders/worldvertextransition_gl460.vs b/Game.Assets/sdn/shaders/worldvertextransition_gl460.vs
index 250e1827a..d009c5ca2 100644
--- a/Game.Assets/sdn/shaders/worldvertextransition_gl460.vs
+++ b/Game.Assets/sdn/shaders/worldvertextransition_gl460.vs
@@ -11,9 +11,9 @@ layout(std140, binding = 0) uniform source_matrices {
mat4 modelMatrix;
};
-out vec2 vs_TexCoord0;
-centroid out vec2 vs_TexCoord1;
-out vec4 vs_Color;
+layout(location = 0) out vec2 vs_TexCoord0;
+layout(location = 1) centroid out vec2 vs_TexCoord1;
+layout(location = 2) out vec4 vs_Color;
#include "common_clipplanes_gl460.vs"
diff --git a/Source.Common/MaterialSystem/IShader.cs b/Source.Common/MaterialSystem/IShader.cs
index f9890eed3..667ecff5c 100644
--- a/Source.Common/MaterialSystem/IShader.cs
+++ b/Source.Common/MaterialSystem/IShader.cs
@@ -16,11 +16,17 @@ public struct ShaderParamInfo
public ShaderParamFlags Flags;
}
+[Flags]
+public enum ShaderFlags
+{
+ None = 0,
+ NotEditable = 0x1
+}
public interface IShader
{
string? GetName();
- int GetFlags();
+ ShaderFlags GetFlags();
int GetNumParams();
ReadOnlySpan GetParamName(int paramIndex);
ReadOnlySpan GetParamHelp(int paramIndex);
diff --git a/Source.Common/MaterialSystem/IShaderSystem.cs b/Source.Common/MaterialSystem/IShaderSystem.cs
index f77ca68e9..00fd8d836 100644
--- a/Source.Common/MaterialSystem/IShaderSystem.cs
+++ b/Source.Common/MaterialSystem/IShaderSystem.cs
@@ -13,10 +13,17 @@ public enum ShaderUsingFlags
Editor = 0x10,
}
+public enum ShaderCompileState
+{
+ Pending,
+ Ready,
+ Failed
+}
+
public interface IShaderSystem
{
public static bool IsTranslucent(IShaderShadow renderState) {
- return (renderState.GetFlags() & ShaderFlags.OpacityTranslucent) != 0;
+ return (renderState.GetFlags() & ShaderRenderStateFlags.OpacityTranslucent) != 0;
}
void BindTexture(Sampler sampler, ITexture texture, int frame = 0);
@@ -33,6 +40,9 @@ public static bool IsTranslucent(IShaderShadow renderState) {
void ResetShaderState();
// void CleanupRenderState(ref ShaderRenderState renderState);
void DrawElements(IShader shader, IMaterialVar[] parms, IShaderShadow renderState, VertexCompressionType vertexCompression, uint materialVarTimeStamp);
+ void BeginFrame();
+ void QueueAllShaderCombos();
+ void WaitForPendingCompiles(Action? progress);
IEnumerable GetShaders();
ReadOnlySpan ShaderStateString(int i);
int GetShaderAPITextureBindHandle(ITexture? texture, int v, int textureChannel);
diff --git a/Source.Common/ShaderAPI/IShaderShadow.cs b/Source.Common/ShaderAPI/IShaderShadow.cs
index f90ccb8ab..217d3857e 100644
--- a/Source.Common/ShaderAPI/IShaderShadow.cs
+++ b/Source.Common/ShaderAPI/IShaderShadow.cs
@@ -227,7 +227,7 @@ public enum StandardTextureId
Max = 32
}
-public enum ShaderFlags
+public enum ShaderRenderStateFlags
{
OpacityAlphaTest = 0x0010,
OpacityOpaque = 0x0020,
@@ -328,8 +328,8 @@ public interface IShaderShadow
VertexFormat GetVertexFormat();
void Activate();
- ShaderFlags GetFlags();
- void SetFlags(ShaderFlags flags);
+ ShaderRenderStateFlags GetFlags();
+ void SetFlags(ShaderRenderStateFlags flags);
void EnableSRGBRead(Sampler sampler, bool state);
void EnableSRGBWrite(bool state);
}
diff --git a/Source.Engine/CL.cs b/Source.Engine/CL.cs
index 208db0eb5..45c9bc594 100644
--- a/Source.Engine/CL.cs
+++ b/Source.Engine/CL.cs
@@ -9,6 +9,7 @@
using Source.Common.Commands;
using Source.Common.Engine;
using Source.Common.Launcher;
+using Source.Common.MaterialSystem;
using Source.Common.Networking;
using Source.Engine.Client;
using Source.Engine.Server;
@@ -224,6 +225,19 @@ public void FullyConnected() {
// Level init post entity
clientDLL.LevelInitPostEntity();
+#if !SWDS
+ IShaderSystem shaderSystem = Singleton();
+ shaderSystem.QueueAllShaderCombos();
+ int lastShaderPercent = -1;
+ shaderSystem.WaitForPendingCompiles((done, total) => {
+ int percent = done * 100 / total;
+ if (percent == lastShaderPercent)
+ return;
+ lastShaderPercent = percent;
+ EngineVGui?.UpdateCustomProgressBar((float)done / total, "#LoadingProgress_LoadResources");
+ });
+#endif
+
// Start notifying dependencies
uint ip = cl.NetChannel!.GetRemoteAddress()!.GetIPHostByteOrder();
short port = cl.NetChannel.GetRemoteAddress()!.GetPort();
diff --git a/Source.Engine/Scr.cs b/Source.Engine/Scr.cs
index 5b9d02772..564a28d59 100644
--- a/Source.Engine/Scr.cs
+++ b/Source.Engine/Scr.cs
@@ -72,6 +72,7 @@ public void BeginLoadingPlaque() {
CenterStringOff();
clientDll?.HudText(null);
+ EngineVGui!.EnabledProgressBarForNextLoad();
EngineVGui!.OnLevelLoadingStarted();
clientGlobalVariables.FrameTime = 0;
diff --git a/Source.MaterialSystem/Material.cs b/Source.MaterialSystem/Material.cs
index 2a3407b9c..0b2a3e67b 100644
--- a/Source.MaterialSystem/Material.cs
+++ b/Source.MaterialSystem/Material.cs
@@ -1361,7 +1361,7 @@ public bool IsTwoSided() {
public bool IsAlphaTested() {
Precache();
if (Shader != null && IsValidRenderState())
- return (ShaderRenderState.GetFlags() & ShaderFlags.OpacityAlphaTest) != 0 || GetMaterialVarFlag(MaterialVarFlags.AlphaTest);
+ return (ShaderRenderState.GetFlags() & ShaderRenderStateFlags.OpacityAlphaTest) != 0 || GetMaterialVarFlag(MaterialVarFlags.AlphaTest);
return false;
}
diff --git a/Source.SDLManager/SDL3_LauncherManager.cs b/Source.SDLManager/SDL3_LauncherManager.cs
index b50fe2c13..01653669b 100644
--- a/Source.SDLManager/SDL3_LauncherManager.cs
+++ b/Source.SDLManager/SDL3_LauncherManager.cs
@@ -72,7 +72,8 @@ public unsafe class SDL3_OpenGL46_Context(nint window, nint ctx) : IGraphicsCont
public nint HardwareHandle => ctx;
public void MakeCurrent() {
- SDL3.SDL_GL_MakeCurrent((SDL_Window*)window, (SDL_GLContextState*)ctx);
+ if (!SDL3.SDL_GL_MakeCurrent((SDL_Window*)window, (SDL_GLContextState*)ctx))
+ Warning($"Could not make GL context current: {SDL3.SDL_GetError()}\n");
}
public void SetSwapInterval(float swapInterval) {
diff --git a/Source.ShaderAPI.Gl46/ShaderAPIGl46.cs b/Source.ShaderAPI.Gl46/ShaderAPIGl46.cs
index ba723304e..95c726cb5 100644
--- a/Source.ShaderAPI.Gl46/ShaderAPIGl46.cs
+++ b/Source.ShaderAPI.Gl46/ShaderAPIGl46.cs
@@ -998,16 +998,15 @@ public bool InFlashlightMode() {
MeshGl46? RenderMesh;
IMaterialInternal? Material;
uint CombobulateShadersIfChanged() {
- uint program;
if (pipelineChanged) {
- program = ShaderCombobulator();
+ uint program = ShaderCombobulator();
if (lastShader != program) {
lastShader = program;
- glUseProgram(program);
+ glBindProgramPipeline(program);
}
+ pipelineChanged = program == 0;
}
- pipelineChanged = false;
return lastShader;
}
@@ -1015,7 +1014,8 @@ public void RenderPass() {
if (IsDeactivated())
return;
- CombobulateShadersIfChanged();
+ if (CombobulateShadersIfChanged() == 0)
+ return;
if (RenderMesh != null)
RenderMesh.RenderPass();
@@ -1023,35 +1023,10 @@ public void RenderPass() {
MeshMgr.RenderPassWithVertexAndIndexBuffers();
}
- Dictionary shaderCombinations = [];
- private unsafe uint ShaderCombobulator() {
+ private uint ShaderCombobulator() {
// Determines the shader program used given the current shader handles.
// If one does not exist, it is created.
- Span hashedData = [activeVertexShader.Handle, activePixelShader.Handle];
- ulong hash;
- fixed (nint* data = hashedData)
- hash = XXH64.DigestOf(data, hashedData.Length * sizeof(nint), 0);
-
- if (shaderCombinations.TryGetValue(hash, out var program))
- return program; // We have already linked a program for this shader combination
-
- // We need to create a program then
- program = glCreateProgram();
- glAttachShader(program, (uint)activeVertexShader.Handle);
- glAttachShader(program, (uint)activePixelShader.Handle);
- glLinkProgram(program);
- // Even invalid program states should be hashed... for now.
- // Maybe a time based thing for invalid programs, to try allowing for the shader developer to recover, etc...
- shaderCombinations[hash] = program;
-
- if (!ShaderSystem.IsValidProgram(program, out string? error)) {
- Warning("WARNING: Shader combobulation linker error.\n");
- Warning(error);
- Warning("\n");
- return 0;
- }
-
- return program;
+ return ((ShaderSystem)ShaderManager).GetProgram(activeVertexShader, activePixelShader);
}
private bool IsDeactivated() {
@@ -1541,6 +1516,8 @@ public void GetBackBufferDimensions(out int width, out int height) {
nint TextureMemoryUsedLastFrame;
public void BeginFrame() {
+ ShaderManager.BeginFrame();
+
if (ResetRenderStateNeeded) {
ResetRenderState(false);
ResetRenderStateNeeded = false;
@@ -1824,7 +1801,32 @@ public unsafe int LocateShaderUniform(ReadOnlySpan name) {
name = name[1..];
// Combobulate
- uint shader = CombobulateShadersIfChanged();
+ if (CombobulateShadersIfChanged() == 0)
+ return -1;
+
+ ShaderSystem shaders = (ShaderSystem)ShaderManager;
+ uint pixelProgram = shaders.GetShaderProgram(activePixelShader);
+ uint vertexProgram = shaders.GetShaderProgram(activeVertexShader);
+ StageUniform stage = new(pixelProgram, LocateStageUniform(pixelProgram, name), vertexProgram, LocateStageUniform(vertexProgram, name));
+ if (stage.PixelLocation == -1 && stage.VertexLocation == -1)
+ return -1;
+
+ if (!stageUniformHandles.TryGetValue(stage, out int handle)) {
+ handle = stageUniforms.Count;
+ stageUniforms.Add(stage);
+ stageUniformHandles[stage] = handle;
+ }
+
+ return handle;
+ }
+
+ readonly record struct StageUniform(uint PixelProgram, int PixelLocation, uint VertexProgram, int VertexLocation);
+ readonly List stageUniforms = [];
+ readonly Dictionary stageUniformHandles = [];
+
+ private unsafe int LocateStageUniform(uint shader, ReadOnlySpan name) {
+ if (shader == 0)
+ return -1;
// Then get shader ID -> shader uniform lookup table
if (!locs.TryGetValue(shader, out var lookup))
@@ -1845,11 +1847,21 @@ public unsafe int LocateShaderUniform(ReadOnlySpan name) {
}
public nint GetCurrentProgram() => (nint)CombobulateShadersIfChanged();
- uint GetCurrentProgramInternal() => CombobulateShadersIfChanged();
readonly Dictionary> uniformValues = [];
- bool UniformChanged(int uniform, ReadOnlySpan values, out uint program) {
- program = GetCurrentProgramInternal();
+ bool GetStageUniform(int uniform, out StageUniform stage) {
+ if ((uint)uniform >= (uint)stageUniforms.Count) {
+ stage = default;
+ return false;
+ }
+
+ stage = stageUniforms[uniform];
+ return true;
+ }
+
+ bool UniformChanged(uint program, int uniform, ReadOnlySpan values) {
+ if (program == 0 || uniform < 0)
+ return false;
if (!uniformValues.TryGetValue(program, out var cache))
cache = uniformValues[program] = [];
@@ -1865,12 +1877,17 @@ bool UniformChanged(int uniform, ReadOnlySpan values, out uint program) {
}
public void SetShaderUniform(int uniform, int integer) {
- if (!UniformChanged(uniform, [BitConverter.Int32BitsToSingle(integer)], out uint program))
+ if (!GetStageUniform(uniform, out StageUniform stage))
return;
+
+ ReadOnlySpan values = [BitConverter.Int32BitsToSingle(integer)];
#if GL_DEBUG
int i = glGetError();
#endif
- glProgramUniform1i(program, uniform, integer);
+ if (UniformChanged(stage.PixelProgram, stage.PixelLocation, values))
+ glProgramUniform1i(stage.PixelProgram, stage.PixelLocation, integer);
+ if (UniformChanged(stage.VertexProgram, stage.VertexLocation, values))
+ glProgramUniform1i(stage.VertexProgram, stage.VertexLocation, integer);
#if GL_DEBUG
if ((i = glGetError()) != 0)
AssertMsg(false, $"GL error {i}");
@@ -1878,24 +1895,35 @@ public void SetShaderUniform(int uniform, int integer) {
}
public void SetShaderUniform(int uniform, uint integer) {
- if (!UniformChanged(uniform, [BitConverter.UInt32BitsToSingle(integer)], out uint program))
+ if (!GetStageUniform(uniform, out StageUniform stage))
return;
- glProgramUniform1ui(program, uniform, integer);
+ ReadOnlySpan values = [BitConverter.UInt32BitsToSingle(integer)];
+ if (UniformChanged(stage.PixelProgram, stage.PixelLocation, values))
+ glProgramUniform1ui(stage.PixelProgram, stage.PixelLocation, integer);
+ if (UniformChanged(stage.VertexProgram, stage.VertexLocation, values))
+ glProgramUniform1ui(stage.VertexProgram, stage.VertexLocation, integer);
}
public void SetShaderUniform(int uniform, float fl) {
- if (!UniformChanged(uniform, [fl], out uint program))
+ if (!GetStageUniform(uniform, out StageUniform stage))
return;
- glProgramUniform1f(program, uniform, fl);
+ ReadOnlySpan values = [fl];
+ if (UniformChanged(stage.PixelProgram, stage.PixelLocation, values))
+ glProgramUniform1f(stage.PixelProgram, stage.PixelLocation, fl);
+ if (UniformChanged(stage.VertexProgram, stage.VertexLocation, values))
+ glProgramUniform1f(stage.VertexProgram, stage.VertexLocation, fl);
}
public void SetShaderUniform(int uniform, ReadOnlySpan flConsts) {
- if (!UniformChanged(uniform, flConsts, out uint program))
+ if (!GetStageUniform(uniform, out StageUniform stage))
return;
- glProgramUniform1fv(program, uniform, flConsts);
+ if (UniformChanged(stage.PixelProgram, stage.PixelLocation, flConsts))
+ glProgramUniform1fv(stage.PixelProgram, stage.PixelLocation, flConsts);
+ if (UniformChanged(stage.VertexProgram, stage.VertexLocation, flConsts))
+ glProgramUniform1fv(stage.VertexProgram, stage.VertexLocation, flConsts);
}
const int GL_TEXTURE_SRGB_DECODE_EXT = 0x8A48;
diff --git a/Source.ShaderAPI.Gl46/ShaderShadow.cs b/Source.ShaderAPI.Gl46/ShaderShadow.cs
index f86a536e5..c52df59ae 100644
--- a/Source.ShaderAPI.Gl46/ShaderShadow.cs
+++ b/Source.ShaderAPI.Gl46/ShaderShadow.cs
@@ -56,8 +56,8 @@ public class ShadowStateGl46 : IShaderShadow
public SourceVertexSharedShadowState Vertex;
public SourcePixelSharedShadowState Pixel;
- public VertexShaderHandle VertexShader;
- public PixelShaderHandle PixelShader;
+ public VertexShaderHandle VertexShader = VertexShaderHandle.INVALID;
+ public PixelShaderHandle PixelShader = PixelShaderHandle.INVALID;
public BasePerMaterialContextData? ContextData;
public ShaderUsingFlags ModulationFlags;
@@ -123,9 +123,9 @@ public unsafe void Dispose() {
glDeleteBuffers(BASE_UBO, VERTEX_UBO, PIXEL_UBO);
}
- ShaderFlags Flags;
- public ShaderFlags GetFlags() => Flags;
- public void SetFlags(ShaderFlags flags) => Flags = flags;
+ ShaderRenderStateFlags Flags;
+ public ShaderRenderStateFlags GetFlags() => Flags;
+ public void SetFlags(ShaderRenderStateFlags flags) => Flags = flags;
public unsafe void Activate() {
CreateShaderObjects(); // Recreate UBO's, if we were lazy-loaded
@@ -440,6 +440,15 @@ internal sealed class ShaderComboState(IShaderSystemInternal shaders, ShaderType
readonly StringBuilder defines = new(256);
public nint SetShader(string fileName, int staticIndex) {
+ Configure(fileName, staticIndex);
+ ((ShaderSystem)shaders).RegisterStaticCombo(type, fileName, staticIndex);
+
+ variants.Clear();
+
+ return GetVariant(0);
+ }
+
+ public void Configure(string fileName, int staticIndex) {
file = fileName;
staticComboIndex = staticIndex;
@@ -450,12 +459,10 @@ public nint SetShader(string fileName, int staticIndex) {
staticComboScales = ComputeComboScales(staticCombos, out _);
dynamicComboScales = ComputeComboScales(dynamicCombos, out numDynamicCombos);
-
- variants.Clear();
-
- return GetVariant(0);
}
+ public int DynamicComboCount => numDynamicCombos;
+
private static int[] ComputeComboScales(ShaderCombo[] combos, out int total) {
int[] scales = new int[combos.Length];
total = 1;
@@ -498,22 +505,22 @@ private static void AppendComboDefines(StringBuilder defines, ShaderCombo[] comb
}
}
- private nint Compile(int variant) {
- int staticIndex = variant / numDynamicCombos;
- int dynamicIndex = variant % numDynamicCombos;
-
+ public string GetVariantDefines(int dynamicIndex) {
defines.Clear();
- AppendComboDefines(defines, staticCombos, staticComboScales, staticIndex);
+ AppendComboDefines(defines, staticCombos, staticComboScales, staticComboIndex);
AppendComboDefines(defines, dynamicCombos, dynamicComboScales, dynamicIndex);
+ return defines.ToString();
+ }
- string source = defines.ToString();
+ private nint Compile(int dynamicIndex) {
+ string source = GetVariantDefines(dynamicIndex);
return type == ShaderType.Vertex ? (nint)shaders.LoadVertexShader(file!, source) : shaders.LoadPixelShader(file!, source);
}
public nint GetVariant(int dynamicIndex) {
int variant = staticComboIndex * numDynamicCombos + dynamicIndex;
if (!variants.TryGetValue(variant, out nint handle)) {
- handle = Compile(variant);
+ handle = Compile(dynamicIndex);
variants.Add(variant, handle);
}
return handle;
diff --git a/Source.ShaderAPI.Gl46/ShaderSystem.cs b/Source.ShaderAPI.Gl46/ShaderSystem.cs
index ff5a61004..6e2239b3d 100644
--- a/Source.ShaderAPI.Gl46/ShaderSystem.cs
+++ b/Source.ShaderAPI.Gl46/ShaderSystem.cs
@@ -6,9 +6,11 @@
using Source.Common.ShaderLib;
using Source.MaterialSystem;
+using System.Buffers.Binary;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Numerics;
+using System.Runtime.InteropServices;
using System.Text;
namespace Source.ShaderAPI.Gl46;
@@ -17,6 +19,45 @@ public interface IShaderSystemInternal : IShaderInit, IShaderSystem;
public readonly record struct ShaderCombo(string Name, int Min, int Range);
+internal sealed class ShaderObject(int glType, string name, string defines, string typeName)
+{
+ public readonly int GLType = glType;
+ public readonly string Name = name;
+ public readonly string Defines = defines;
+ public readonly string TypeName = typeName;
+ public uint Handle;
+ public ShaderCompileState State;
+ public ShaderCompileJob? Job;
+}
+
+internal sealed class ShaderProgram
+{
+ public uint Handle;
+ public ShaderCompileState State;
+}
+
+internal sealed class ShaderCompileJob
+{
+ public required ShaderObject Shader;
+ public uint ShaderHandle;
+ public uint Handle;
+ public string? Error;
+ public List? SourceFiles;
+ public string? CachePath;
+ public bool FromCache;
+ public bool LinkFailed;
+ public bool Taken;
+ public bool HighPriority;
+}
+
+internal sealed class ShaderSource(byte[] text, int versionLength, List sourceFiles)
+{
+ public readonly byte[] Text = text;
+ public readonly int VersionLength = versionLength;
+ public readonly List SourceFiles = sourceFiles;
+ public readonly ulong Hash = text.AsSpan().Hash();
+}
+
public class ShaderSystem : IShaderSystemInternal
{
List ShaderDLLs = [];
@@ -293,12 +334,12 @@ public bool InitRenderState(IShader shader, IMaterialVar[] shaderParams, ref ISh
private void ComputeRenderStateFlagsFromSnapshot(IShaderShadow renderState) {
if (ShaderAPI.IsTranslucent(renderState))
- renderState.SetFlags(renderState.GetFlags() | ShaderFlags.OpacityTranslucent);
+ renderState.SetFlags(renderState.GetFlags() | ShaderRenderStateFlags.OpacityTranslucent);
else {
if (ShaderAPI.IsAlphaTested(renderState))
- renderState.SetFlags(renderState.GetFlags() | ShaderFlags.OpacityAlphaTest);
+ renderState.SetFlags(renderState.GetFlags() | ShaderRenderStateFlags.OpacityAlphaTest);
else
- renderState.SetFlags(renderState.GetFlags() | ShaderFlags.OpacityOpaque);
+ renderState.SetFlags(renderState.GetFlags() | ShaderRenderStateFlags.OpacityOpaque);
}
}
@@ -398,50 +439,61 @@ internal static unsafe bool IsValidProgram(uint program, [NotNullWhen(false)] ou
return true;
}
- private byte[]? BuildShaderSource(ReadOnlySpan source, ReadOnlySpan defines, string mainName, List sourceFiles) {
+ private ShaderSource? BuildShaderSource(ReadOnlySpan source, string mainName) {
string src = Encoding.ASCII.GetString(source);
int versionEnd = src.IndexOf('\n');
if (versionEnd < 0)
return null;
- sourceFiles.Add(mainName);
+ List sourceFiles = [mainName];
StringBuilder sb = new();
sb.Append(src.AsSpan(0, versionEnd + 1));
+ sb.Append("#line 2 0\n");
- ReadOnlySpan rest = defines;
- while (!rest.IsEmpty) {
- int sep = rest.IndexOf(';');
- ReadOnlySpan define = (sep < 0 ? rest : rest[..sep]).Trim();
- rest = sep < 0 ? default : rest[(sep + 1)..];
- if (define.IsEmpty)
- continue;
- sb.Append("#define ");
- sb.Append(define);
- sb.Append('\n');
- }
+ ProcessSource(sb, src.AsSpan(versionEnd + 1), 0, 2, sourceFiles, 0);
- sb.Append("#line 2 0\n");
+ return new(Encoding.ASCII.GetBytes(sb.ToString()), versionEnd + 1, sourceFiles);
+ }
- ProcessSource(sb, src[(versionEnd + 1)..], 0, 2, sourceFiles, 0);
+ private static byte[] BuildDefines(ReadOnlySpan defines) {
+ int length = 0;
+ foreach (Range range in MemoryExtensions.Split(defines, ';')) {
+ ReadOnlySpan define = defines[range].Trim();
+ if (!define.IsEmpty)
+ length += "#define "u8.Length + define.Length + 1;
+ }
- return Encoding.ASCII.GetBytes(sb.ToString());
+ byte[] bytes = new byte[length];
+ Span dest = bytes;
+ foreach (Range range in MemoryExtensions.Split(defines, ';')) {
+ ReadOnlySpan define = defines[range].Trim();
+ if (define.IsEmpty)
+ continue;
+ "#define "u8.CopyTo(dest);
+ dest = dest["#define "u8.Length..];
+ dest = dest[Encoding.ASCII.GetBytes(define, dest)..];
+ dest[0] = (byte)'\n';
+ dest = dest[1..];
+ }
+ return bytes;
}
- private void ProcessSource(StringBuilder sb, string source, int fileIndex, int startLine, List sourceFiles, int depth) {
+ private void ProcessSource(StringBuilder sb, ReadOnlySpan source, int fileIndex, int startLine, List sourceFiles, int depth) {
if (depth > 32) {
sb.Append(source);
return;
}
int lineNo = startLine;
- foreach (string line in source.Split('\n')) {
- ReadOnlySpan trimmed = line.AsSpan().TrimStart();
+ foreach (Range range in MemoryExtensions.Split(source, '\n')) {
+ ReadOnlySpan line = source[range];
+ ReadOnlySpan trimmed = line.TrimStart();
if (trimmed.StartsWith("#include")) {
int q1 = line.IndexOf('"');
- int q2 = q1 >= 0 ? line.IndexOf('"', q1 + 1) : -1;
- if (q1 >= 0 && q2 > q1) {
- string includeName = line[(q1 + 1)..q2];
+ int q2 = q1 >= 0 ? line[(q1 + 1)..].IndexOf('"') : -1;
+ if (q2 >= 0) {
+ string includeName = new(line.Slice(q1 + 1, q2));
using IFileHandle? includeHandle = FileSystem.Open($"shaders/{includeName}", FileOpenOptions.Read, "game");
if (includeHandle != null) {
byte[] bytes = new byte[includeHandle.Stream.Length];
@@ -486,50 +538,380 @@ private void ProcessSource(StringBuilder sb, string source, int fileIndex, int s
return Encoding.ASCII.GetBytes(source);
}
- private unsafe uint CompileShader(int glType, ReadOnlySpan name, ReadOnlySpan defines, string typeName) {
+ private ShaderSource? LoadShaderSource(string name) {
using IFileHandle? handle = FileSystem.Open($"shaders/{name}", FileOpenOptions.Read, "game");
- List sourceFiles = [];
- byte[]? built;
if (handle == null) {
- if ((built = LoadVcs(name)) == null)
- return 0;
- sourceFiles.Add(new(name));
+ byte[]? vcs = LoadVcs(name);
+ return vcs == null ? null : new(vcs, 0, [name]);
}
- else {
- Span source = stackalloc byte[(int)handle.Stream.Length];
- handle.Stream.Read(source);
- built = BuildShaderSource(source, defines, new string(name), sourceFiles);
- if (built == null)
- return 0;
+ byte[] source = new byte[handle.Stream.Length];
+ handle.Stream.ReadExactly(source);
+ return BuildShaderSource(source, name);
+ }
+
+ private ShaderSource? GetShaderSource(string name) {
+ if (!ShaderSources.TryGetValue(name, out ShaderSource? source)) {
+ source = LoadShaderSource(name);
+ ShaderSources[name] = source;
+ }
+ return source;
+ }
+
+ private string? GetCachePath(ShaderObject shader) {
+ if (ProgramCacheDir == null)
+ return null;
+
+ ShaderSource? source = GetShaderSource(shader.Name);
+ if (source == null)
+ return null;
+
+ ulong key = $"{source.Hash:x16};{shader.Defines}".AsSpan().Hash(false);
+ return $"{ProgramCacheDir}/{shader.Name}_{key:x16}.bin";
+ }
+
+ private unsafe bool LoadCachedProgram(ShaderCompileJob job) {
+ using IFileHandle? handle = FileSystem.Open(job.CachePath, FileOpenOptions.Read | FileOpenOptions.Binary, "DEFAULT_WRITE_PATH");
+ if (handle == null || handle.Stream.Length <= sizeof(int))
+ return false;
+
+ byte[] data = new byte[handle.Stream.Length];
+ handle.Stream.ReadExactly(data);
+
+ job.Handle = glCreateProgram();
+ glProgramParameteri(job.Handle, GL_PROGRAM_SEPARABLE, GL_TRUE);
+ fixed (byte* pData = data)
+ glProgramBinary(job.Handle, BinaryPrimitives.ReadInt32LittleEndian(data), pData + sizeof(int), data.Length - sizeof(int));
+ job.FromCache = true;
+ return true;
+ }
+
+ private unsafe void SaveCachedProgram(ShaderCompileJob job) {
+ int length = 0;
+ glGetProgramiv(job.Handle, GL_PROGRAM_BINARY_LENGTH, &length);
+ if (length <= 0)
+ return;
+
+ byte[] data = new byte[sizeof(int) + length];
+ int format = 0;
+ fixed (byte* pData = data)
+ glGetProgramBinary(job.Handle, length, &length, &format, pData + sizeof(int));
+ BinaryPrimitives.WriteInt32LittleEndian(data, format);
+ FileSystem.WriteFile(job.CachePath, "DEFAULT_WRITE_PATH", data.AsSpan(0, sizeof(int) + length));
+ }
+
+ private unsafe void CompileProgram(ShaderCompileJob job) {
+ ShaderObject shader = job.Shader;
+ ShaderSource? source = GetShaderSource(shader.Name);
+ if (source == null)
+ return;
+
+ job.SourceFiles = source.SourceFiles;
+ byte[] defines = source.VersionLength > 0 ? BuildDefines(shader.Defines) : [];
+
+ job.ShaderHandle = glCreateShader(shader.GLType);
+ fixed (byte* pText = source.Text)
+ fixed (byte* pDefines = defines) {
+ if (defines.Length == 0) {
+ int length = source.Text.Length;
+ glShaderSource(job.ShaderHandle, 1, &pText, &length);
+ }
+ else {
+ byte** strings = stackalloc byte*[3];
+ int* lengths = stackalloc int[3];
+ strings[0] = pText;
+ lengths[0] = source.VersionLength;
+ strings[1] = pDefines;
+ lengths[1] = defines.Length;
+ strings[2] = pText + source.VersionLength;
+ lengths[2] = source.Text.Length - source.VersionLength;
+ glShaderSource(job.ShaderHandle, 3, strings, lengths);
+ }
+ }
+ glCompileShader(job.ShaderHandle);
+
+ job.Handle = glCreateProgram();
+ glProgramParameteri(job.Handle, GL_PROGRAM_SEPARABLE, GL_TRUE);
+ if (job.CachePath != null)
+ glProgramParameteri(job.Handle, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
+ glAttachShader(job.Handle, job.ShaderHandle);
+ glLinkProgram(job.Handle);
+ }
+
+ private void SubmitCompileJob(ShaderCompileJob job) {
+ job.CachePath = GetCachePath(job.Shader);
+ if (job.CachePath != null && LoadCachedProgram(job))
+ return;
+
+ CompileProgram(job);
+ }
+
+ private unsafe void FinishCompileJob(ShaderCompileJob job) {
+ if (job.Handle == 0)
+ return;
+
+ if (job.FromCache) {
+ int status = 0;
+ glGetProgramiv(job.Handle, GL_LINK_STATUS, &status);
+ if (status == GL_TRUE)
+ return;
+
+ glDeleteProgram(job.Handle);
+ job.Handle = 0;
+ job.FromCache = false;
+ CompileProgram(job);
+ if (job.Handle == 0)
+ return;
}
- uint pShader = glCreateShader(glType);
- int len = built.Length;
- fixed (byte* pSrc = built)
- glShaderSource(pShader, 1, &pSrc, &len);
- glCompileShader(pShader);
+ if (!IsValidShader(job.ShaderHandle, out job.Error)) {
+ glDeleteProgram(job.Handle);
+ job.Handle = 0;
+ return;
+ }
+
+ glDetachShader(job.Handle, job.ShaderHandle);
+ glDeleteShader(job.ShaderHandle);
+
+ if (!IsValidProgram(job.Handle, out job.Error)) {
+ job.LinkFailed = true;
+ job.Handle = 0;
+ return;
+ }
+
+ if (job.CachePath != null)
+ SaveCachedProgram(job);
+ }
+
+ private static void ApplyCompileJob(ShaderCompileJob job) {
+ ShaderObject shader = job.Shader;
+ shader.Handle = job.Handle;
+ shader.State = job.Handle != 0 ? ShaderCompileState.Ready : ShaderCompileState.Failed;
+ shader.Job = null;
- if (!IsValidShader(pShader, out string? error)) {
- Warning($"WARNING: {typeName} shader compilation error in {name}.\n");
- Warning(error);
+ if (job.LinkFailed) {
+ Warning("WARNING: Shader combobulation linker error.\n");
+ Warning(job.Error!);
Warning("\n");
- for (int i = 0; i < sourceFiles.Count; i++)
- Warning($" [source string {i}] = {sourceFiles[i]}\n");
+ }
+ else if (job.Error != null) {
+ Warning($"WARNING: {shader.TypeName} shader compilation error in {shader.Name}.\n");
+ Warning(job.Error);
+ Warning("\n");
+ for (int i = 0; i < job.SourceFiles!.Count; i++)
+ Warning($" [source string {i}] = {job.SourceFiles[i]}\n");
Warning("\n");
- return 0;
}
- else {
- ReadOnlySpan combos = defines.SliceNullTerminatedString();
+ else if (job.Handle == 0) {
+ if (job.SourceFiles == null)
+ Warning($"WARNING: {shader.TypeName} shader source not found: {shader.Name}.\n");
+ else
+ Warning($"WARNING: {shader.TypeName} shader program could not be created for {shader.Name}.\n");
+ }
+ else if (!job.FromCache) {
+ ReadOnlySpan combos = shader.Defines.AsSpan().SliceNullTerminatedString();
if (combos.IsEmpty)
- Msg($"Compiled shader: {name} ({typeName})\n");
+ Msg($"Compiled shader: {shader.Name} ({shader.TypeName})\n");
+ else
+ Msg($"Compiled shader: {shader.Name} ({shader.TypeName}) [{combos}]\n");
+ }
+ }
+
+ const int MaxParallelSubmitsPerFrame = 32;
+ const int MaxBlockingSubmitsPerFrame = 4;
+ const int MaxSubmitsPerWait = 64;
+
+ readonly List ShaderObjects = [];
+ readonly Dictionary ShaderPrograms = [];
+ readonly Dictionary ShaderSources = [];
+ readonly HashSet<(ShaderType Type, string File, int StaticIndex)> StaticCombos = [];
+ readonly List<(ShaderType Type, string File, int StaticIndex)> NewStaticCombos = [];
+ string? ProgramCacheDir;
+ readonly Queue PendingCompileJobs = [];
+ readonly Queue HighPriorityCompileJobs = [];
+ readonly List InFlightCompileJobs = [];
+ bool CompileInitialized;
+ int OutstandingCompileJobs;
+ bool ParallelShaderCompile;
+
+ private static unsafe bool HasGLExtension(ReadOnlySpan extension) {
+ int count;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &count);
+ for (uint i = 0; i < count; i++) {
+ if (MemoryMarshal.CreateReadOnlySpanFromNullTerminated(glGetStringi(GL_EXTENSIONS, i)).SequenceEqual(extension))
+ return true;
+ }
+ return false;
+ }
+
+ private static unsafe string GetGLString(int name) => Encoding.ASCII.GetString(MemoryMarshal.CreateReadOnlySpanFromNullTerminated(glGetString(name)));
+
+ private unsafe void InitShaderCompile() {
+ CompileInitialized = true;
+
+ int binaryFormats = 0;
+ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &binaryFormats);
+ if (binaryFormats > 0) {
+ string driver = $"{GetGLString(GL_VENDOR)};{GetGLString(GL_RENDERER)};{GetGLString(GL_VERSION)}";
+ ProgramCacheDir = $"cache/shaders/{driver.AsSpan().Hash(false):x16}";
+ FileSystem.CreateDirHierarchy(ProgramCacheDir, "DEFAULT_WRITE_PATH");
+ }
+ else
+ Warning("Program binaries unsupported, shader cache disabled\n");
+
+ ParallelShaderCompile = glMaxShaderCompilerThreadsKHRLoaded && (HasGLExtension("GL_KHR_parallel_shader_compile"u8) || HasGLExtension("GL_ARB_parallel_shader_compile"u8));
+ if (ParallelShaderCompile)
+ glMaxShaderCompilerThreadsKHR(2);
+ else
+ Warning("Parallel shader compile unsupported, shaders compile blocking\n");
+ }
+
+ private ShaderCompileJob? TakeCompileJob() {
+ while (HighPriorityCompileJobs.Count > 0 || PendingCompileJobs.Count > 0) {
+ ShaderCompileJob job = HighPriorityCompileJobs.Count > 0 ? HighPriorityCompileJobs.Dequeue() : PendingCompileJobs.Dequeue();
+ if (job.Taken)
+ continue;
+ job.Taken = true;
+ return job;
+ }
+ return null;
+ }
+
+ private void QueueCompileJob(ShaderCompileJob job, bool highPriority) {
+ if (!CompileInitialized)
+ InitShaderCompile();
+
+ ++OutstandingCompileJobs;
+ job.HighPriority = highPriority;
+ (highPriority ? HighPriorityCompileJobs : PendingCompileJobs).Enqueue(job);
+ }
+
+ internal void PrioritizeShader(nint handle) {
+ if (handle < 0 || handle >= ShaderObjects.Count)
+ return;
+
+ ShaderObject shader = ShaderObjects[(int)handle];
+ ShaderCompileJob? job = shader.Job;
+ if (shader.State != ShaderCompileState.Pending || job == null || job.HighPriority || job.Taken)
+ return;
+
+ job.HighPriority = true;
+ HighPriorityCompileJobs.Enqueue(job);
+ }
+
+ public void BeginFrame() => ProcessCompileJobs(ParallelShaderCompile ? MaxParallelSubmitsPerFrame : MaxBlockingSubmitsPerFrame);
+
+ public void WaitForPendingCompiles(Action? progress) {
+ int total = OutstandingCompileJobs;
+ while (OutstandingCompileJobs > 0) {
+ ProcessCompileJobs(MaxSubmitsPerWait);
+ progress?.Invoke(total - OutstandingCompileJobs, total);
+ if (OutstandingCompileJobs > 0)
+ Thread.Sleep(1);
+ }
+ }
+
+ private void CompleteCompileJob(ShaderCompileJob job) {
+ FinishCompileJob(job);
+ ApplyCompileJob(job);
+ --OutstandingCompileJobs;
+ }
+
+ private unsafe void ProcessCompileJobs(int maxSubmits) {
+ for (int i = 0; i < maxSubmits; i++) {
+ ShaderCompileJob? job = TakeCompileJob();
+ if (job == null)
+ break;
+
+ SubmitCompileJob(job);
+ if (ParallelShaderCompile && job.Handle != 0)
+ InFlightCompileJobs.Add(job);
else
- Msg($"Compiled shader: {name} ({typeName}) [{combos}]\n");
+ CompleteCompileJob(job);
+ }
+
+ for (int i = 0; i < InFlightCompileJobs.Count; i++) {
+ ShaderCompileJob job = InFlightCompileJobs[i];
+ int complete = GL_TRUE;
+ glGetProgramiv(job.Handle, GL_COMPLETION_STATUS_KHR, &complete);
+ if (complete != GL_TRUE)
+ continue;
+
+ CompleteCompileJob(job);
+ InFlightCompileJobs.RemoveAt(i--);
+ }
+ }
+
+ private nint QueueShader(int glType, ReadOnlySpan name, ReadOnlySpan defines, string typeName) {
+ ShaderObject shader = new(glType, new(name), new(defines), typeName);
+ int index = ShaderObjects.Count;
+ ShaderObjects.Add(shader);
+ shader.Job = new() { Shader = shader };
+ QueueCompileJob(shader.Job, false);
+ return index;
+ }
+
+ internal uint GetShaderProgram(nint handle) {
+ if (handle < 0 || handle >= ShaderObjects.Count)
+ return 0;
+ return ShaderObjects[(int)handle].Handle;
+ }
+
+ internal unsafe uint GetProgram(VertexShaderHandle vertexShader, PixelShaderHandle pixelShader) {
+ if (!vertexShader.IsValid() || !pixelShader.IsValid())
+ return 0;
+
+ ulong key = ((ulong)(uint)vertexShader.Handle << 32) | (uint)pixelShader.Handle;
+ if (!ShaderPrograms.TryGetValue(key, out ShaderProgram? program)) {
+ // Even invalid program states should be hashed... for now.
+ // Maybe a time based thing for invalid programs, to try allowing for the shader developer to recover, etc...
+ program = new();
+ ShaderPrograms[key] = program;
+ }
+
+ if (program.State == ShaderCompileState.Pending) {
+ ShaderObject vertex = ShaderObjects[(int)vertexShader.Handle];
+ ShaderObject pixel = ShaderObjects[(int)pixelShader.Handle];
+ if (vertex.State == ShaderCompileState.Failed || pixel.State == ShaderCompileState.Failed)
+ program.State = ShaderCompileState.Failed;
+ else if (vertex.State == ShaderCompileState.Ready && pixel.State == ShaderCompileState.Ready) {
+ uint pipeline;
+ glCreateProgramPipelines(1, &pipeline);
+ glUseProgramStages(pipeline, (uint)GL_VERTEX_SHADER_BIT, vertex.Handle);
+ glUseProgramStages(pipeline, (uint)GL_FRAGMENT_SHADER_BIT, pixel.Handle);
+ program.Handle = pipeline;
+ program.State = ShaderCompileState.Ready;
+ }
+ else {
+ PrioritizeShader(vertexShader.Handle);
+ PrioritizeShader(pixelShader.Handle);
+ }
}
- return pShader;
+ return program.Handle;
}
+ internal void RegisterStaticCombo(ShaderType type, string file, int staticIndex) {
+ if (StaticCombos.Add((type, file, staticIndex)))
+ NewStaticCombos.Add((type, file, staticIndex));
+ }
+
+ public void QueueAllShaderCombos() {
+ foreach (var (type, file, staticIndex) in NewStaticCombos) {
+ ShaderComboState combos = new(this, type);
+ combos.Configure(file, staticIndex);
+ bool vertex = type == ShaderType.Vertex;
+ for (int i = 0; i < combos.DynamicComboCount; i++) {
+ string defines = combos.GetVariantDefines(i);
+ if (vertex)
+ LoadVertexShader(file, defines);
+ else
+ LoadPixelShader(file, defines);
+ }
+ }
+
+ NewStaticCombos.Clear();
+ }
Dictionary Static, List Dynamic)> comboCache = [];
internal (List Static, List Dynamic) GetShaderCombos(ReadOnlySpan name) {
@@ -546,12 +928,12 @@ private unsafe uint CompileShader(int glType, ReadOnlySpan name, ReadOnlyS
handle.Stream.ReadExactly(bytes);
string source = Encoding.ASCII.GetString(bytes);
- foreach (string rawLine in source.Split('\n')) {
- string line = rawLine.Trim();
+ foreach (Range lineRange in MemoryExtensions.Split(source, '\n')) {
+ ReadOnlySpan line = source.AsSpan(lineRange).Trim();
if (!line.StartsWith("//"))
continue;
- ReadOnlySpan body = line.AsSpan(2).TrimStart();
+ ReadOnlySpan body = line[2..].TrimStart();
List? list = null;
if (body.StartsWith("STATIC:"))
@@ -564,20 +946,25 @@ private unsafe uint CompileShader(int glType, ReadOnlySpan name, ReadOnlyS
int q1 = line.IndexOf('"');
if (q1 < 0)
continue;
- int q2 = line.IndexOf('"', q1 + 1);
+ ReadOnlySpan rest = line[(q1 + 1)..];
+ int q2 = rest.IndexOf('"');
if (q2 < 0)
continue;
- string comboName = line[(q1 + 1)..q2];
+ string comboName = new(rest[..q2]);
+ rest = rest[(q2 + 1)..];
int min = 0, max = 1;
- int q3 = line.IndexOf('"', q2 + 1);
- int q4 = q3 < 0 ? -1 : line.IndexOf('"', q3 + 1);
- if (q4 >= 0) {
- ReadOnlySpan range = line[(q3 + 1)..q4];
- int dots = range.IndexOf("..");
- if (dots >= 0) {
- min = int.Parse(range[..dots]);
- max = int.Parse(range[(dots + 2)..]);
+ int q3 = rest.IndexOf('"');
+ if (q3 >= 0) {
+ rest = rest[(q3 + 1)..];
+ int q4 = rest.IndexOf('"');
+ if (q4 >= 0) {
+ ReadOnlySpan range = rest[..q4];
+ int dots = range.IndexOf("..");
+ if (dots >= 0) {
+ min = int.Parse(range[..dots]);
+ max = int.Parse(range[(dots + 2)..]);
+ }
}
}
@@ -602,11 +989,7 @@ public VertexShaderHandle LoadVertexShader(ReadOnlySpan name, ReadOnlySpan
if (vshs.TryGetValue(symbol, out VertexShaderHandle value))
return value;
- uint pShader = CompileShader(GL_VERTEX_SHADER, name, defines, "Vertex");
- if (pShader == 0)
- return VertexShaderHandle.INVALID;
-
- VertexShaderHandle vsh = new((nint)pShader);
+ VertexShaderHandle vsh = new(QueueShader(GL_VERTEX_SHADER, name, defines, "Vertex"));
vshs[symbol] = vsh;
return vsh;
}
@@ -616,11 +999,7 @@ public PixelShaderHandle LoadPixelShader(ReadOnlySpan name, ReadOnlySpan GetType().Name;
- public virtual int GetFlags() => 0;
+ public virtual ShaderFlags GetFlags() => ShaderFlags.None;
public int CurrentMaterialVarFlags() {
return Params![(int)ShaderMaterialVars.Flags].GetIntValue();
diff --git a/Source.StdShader.Gl46/BlurFilterX.cs b/Source.StdShader.Gl46/BlurFilterX.cs
index dca61cc78..3deb37ac2 100644
--- a/Source.StdShader.Gl46/BlurFilterX.cs
+++ b/Source.StdShader.Gl46/BlurFilterX.cs
@@ -7,10 +7,10 @@ namespace Source.StdShader.Gl46;
public class BlurFilterX : BaseVSShader
{
public static string HelpString = "Help for BlurFilterX";
- public static int Flags = (int)ShaderParamFlags.NotEditable;
+ public static ShaderFlags Flags = ShaderFlags.NotEditable;
public override string? GetFallbackShader(IMaterialVar[] vars) => null;
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
protected override void OnInitShaderInstance(IMaterialVar[] vars, ReadOnlySpan materialName) {
if (vars[(int)ShaderMaterialVars.BaseTexture].IsDefined())
diff --git a/Source.StdShader.Gl46/BlurFilterY.cs b/Source.StdShader.Gl46/BlurFilterY.cs
index f17a9cf98..df8243305 100644
--- a/Source.StdShader.Gl46/BlurFilterY.cs
+++ b/Source.StdShader.Gl46/BlurFilterY.cs
@@ -7,19 +7,19 @@ namespace Source.StdShader.Gl46;
public class BlurFilterY : BaseVSShader
{
public static string HelpString = "Help for BlurFilterY";
- public static int Flags = (int)ShaderParamFlags.NotEditable;
+ public static ShaderFlags Flags = ShaderFlags.NotEditable;
public static List ShaderParams = [];
public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -27,7 +27,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -35,7 +35,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public static readonly ShaderParam FRAMETEXTURE = new($"${nameof(FRAMETEXTURE)}", ShaderParamType.Texture, "_rt_SmallHDR0", "");
public override string? GetFallbackShader(IMaterialVar[] vars) => null;
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/Downsample_nohdr.cs b/Source.StdShader.Gl46/Downsample_nohdr.cs
index 897663264..23f617419 100644
--- a/Source.StdShader.Gl46/Downsample_nohdr.cs
+++ b/Source.StdShader.Gl46/Downsample_nohdr.cs
@@ -8,19 +8,19 @@ namespace Source.StdShader.Gl46;
public class Downsample_nohdr : BaseVSShader
{
public static string HelpString = "Help for Downsample_nohdr";
- public static int Flags = (int)ShaderParamFlags.NotEditable;
+ public static ShaderFlags Flags = ShaderFlags.NotEditable;
public static List ShaderParams = [];
public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -28,7 +28,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -41,7 +41,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
static readonly ConVar r_bloomtintexponent = new("r_bloomtintexponent", "2.2");
public override string? GetFallbackShader(IMaterialVar[] vars) => null;
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/EyeGlint.cs b/Source.StdShader.Gl46/EyeGlint.cs
index c559dd7ce..b3b42a251 100644
--- a/Source.StdShader.Gl46/EyeGlint.cs
+++ b/Source.StdShader.Gl46/EyeGlint.cs
@@ -7,7 +7,7 @@ namespace Source.StdShader.Gl46;
public class EyeGlint : BaseVSShader
{
public static string HelpString = "Help for EyeGlint";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public override string? GetFallbackShader(IMaterialVar[] vars) => null;
diff --git a/Source.StdShader.Gl46/Eyes.cs b/Source.StdShader.Gl46/Eyes.cs
index 3fd723177..bc9a1719a 100644
--- a/Source.StdShader.Gl46/Eyes.cs
+++ b/Source.StdShader.Gl46/Eyes.cs
@@ -8,7 +8,7 @@ namespace Source.StdShader.Gl46;
public class Eyes : BaseVSShader
{
public static string HelpString = "Help for Eyes";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -16,12 +16,12 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
if (ShaderParamOverrides[(int)var] == null) {
@@ -33,12 +33,12 @@ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -46,7 +46,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -89,7 +89,7 @@ protected override void OnInitShaderParams(IMaterialVar[] parms, ReadOnlySpan null;
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/IntroScreenSpaceEffect.cs b/Source.StdShader.Gl46/IntroScreenSpaceEffect.cs
index 76d0109aa..9222cdfdb 100644
--- a/Source.StdShader.Gl46/IntroScreenSpaceEffect.cs
+++ b/Source.StdShader.Gl46/IntroScreenSpaceEffect.cs
@@ -8,7 +8,7 @@ namespace Source.StdShader.Gl46;
public class IntroScreenSpaceEffect : BaseVSShader
{
public static string HelpString = "Help for IntroScreenSpaceEffect";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -16,12 +16,12 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
if (ShaderParamOverrides[(int)var] == null) {
@@ -33,12 +33,12 @@ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -46,7 +46,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -61,7 +61,7 @@ protected override void OnInitShaderParams(IMaterialVar[] parms, ReadOnlySpan null;
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/LightmappedGeneric.cs b/Source.StdShader.Gl46/LightmappedGeneric.cs
index 79ac64fd1..1dd413c4a 100644
--- a/Source.StdShader.Gl46/LightmappedGeneric.cs
+++ b/Source.StdShader.Gl46/LightmappedGeneric.cs
@@ -10,7 +10,7 @@ public class LightmappedGeneric : BaseVSShader
{
public static string HelpString = "Help for LightmappedGeneric";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -18,22 +18,22 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
AssertMsg(ShaderParamOverrides[(int)var] == null, "Shader parameter override duplicately defined!");
ShaderParamOverrides[(int)var] = this;
Index = (int)var;
}
- public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -41,7 +41,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -95,7 +95,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public static readonly ShaderParam OUTLINEEND1 = new($"${nameof(OUTLINEEND1)}", ShaderParamType.Float, "0.0", "outer end value for outline");
public override string? GetFallbackShader(IMaterialVar[] vars) => null;
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/Occlusion.cs b/Source.StdShader.Gl46/Occlusion.cs
index 5951ed3fa..dbedaf504 100644
--- a/Source.StdShader.Gl46/Occlusion.cs
+++ b/Source.StdShader.Gl46/Occlusion.cs
@@ -7,7 +7,7 @@ public class Occlusion : BaseVSShader
{
public static string HelpString = "Help for Occlusion";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -15,12 +15,12 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
if (ShaderParamOverrides[(int)var] == null) {
@@ -32,12 +32,12 @@ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -45,10 +45,10 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/Screenspace_General.cs b/Source.StdShader.Gl46/Screenspace_General.cs
index 794a440e3..d89e85e01 100644
--- a/Source.StdShader.Gl46/Screenspace_General.cs
+++ b/Source.StdShader.Gl46/Screenspace_General.cs
@@ -5,7 +5,7 @@ namespace Source.StdShader.Gl46;
public class Screenspace_General : BaseVSShader
{
public static string HelpString = "Help for screenspace_general";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public override string? GetFallbackShader(IMaterialVar[] vars) => "screenspace_general_dx9";
}
diff --git a/Source.StdShader.Gl46/Shadow.cs b/Source.StdShader.Gl46/Shadow.cs
index b3505c091..9840c9a7c 100644
--- a/Source.StdShader.Gl46/Shadow.cs
+++ b/Source.StdShader.Gl46/Shadow.cs
@@ -9,7 +9,7 @@ public class Shadow : BaseVSShader
{
public static string HelpString = "Help for Shadow";
- public static int Flags = (int)ShaderParamFlags.NotEditable;
+ public static ShaderFlags Flags = ShaderFlags.NotEditable;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -17,12 +17,12 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
if (ShaderParamOverrides[(int)var] == null) {
@@ -34,12 +34,12 @@ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -47,7 +47,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -58,7 +58,7 @@ protected override void OnInitShaderParams(IMaterialVar[] vars, ReadOnlySpan Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/ShadowModel.cs b/Source.StdShader.Gl46/ShadowModel.cs
index c20689a99..731558545 100644
--- a/Source.StdShader.Gl46/ShadowModel.cs
+++ b/Source.StdShader.Gl46/ShadowModel.cs
@@ -8,7 +8,7 @@ namespace Source.StdShader.Gl46;
public class ShadowModel : BaseVSShader
{
public static string HelpString = "Help for ShadowModel";
- public static int Flags = (int)ShaderParamFlags.NotEditable;
+ public static ShaderFlags Flags = ShaderFlags.NotEditable;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -16,12 +16,12 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
if (ShaderParamOverrides[(int)var] == null) {
@@ -33,12 +33,12 @@ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -46,7 +46,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -71,7 +71,7 @@ protected override void OnInitShaderParams(IMaterialVar[] vars, ReadOnlySpan Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/Sky.cs b/Source.StdShader.Gl46/Sky.cs
index dfdca8589..100b7d330 100644
--- a/Source.StdShader.Gl46/Sky.cs
+++ b/Source.StdShader.Gl46/Sky.cs
@@ -5,7 +5,7 @@ namespace Source.StdShader.Gl46;
public class Sky : BaseVSShader
{
public static string HelpString = "Help for Sky";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public override string? GetFallbackShader(IMaterialVar[] vars) => "Sky_HDR_DX9";
}
diff --git a/Source.StdShader.Gl46/Sky_DX9.cs b/Source.StdShader.Gl46/Sky_DX9.cs
index ae7831124..f35166907 100644
--- a/Source.StdShader.Gl46/Sky_DX9.cs
+++ b/Source.StdShader.Gl46/Sky_DX9.cs
@@ -9,7 +9,7 @@ namespace Source.StdShader.Gl46;
public class Sky_DX9 : BaseVSShader
{
public static string HelpString = "Help for Sky_DX9 shader";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public override string? GetFallbackShader(IMaterialVar[] vars) => null;
diff --git a/Source.StdShader.Gl46/Sky_HDR_DX9.cs b/Source.StdShader.Gl46/Sky_HDR_DX9.cs
index 402245b17..243708123 100644
--- a/Source.StdShader.Gl46/Sky_HDR_DX9.cs
+++ b/Source.StdShader.Gl46/Sky_HDR_DX9.cs
@@ -10,19 +10,19 @@ namespace Source.StdShader.Gl46;
public class Sky_HDR_DX9 : BaseVSShader
{
public static string HelpString = "Help for Sky_HDR_DX9 shader";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public static List ShaderParams = [];
public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -30,7 +30,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -47,7 +47,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
return "Sky_DX9";
return null;
}
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/Teeth.cs b/Source.StdShader.Gl46/Teeth.cs
index 7937c6d14..22c1f2204 100644
--- a/Source.StdShader.Gl46/Teeth.cs
+++ b/Source.StdShader.Gl46/Teeth.cs
@@ -8,7 +8,7 @@ namespace Source.StdShader.Gl46;
public class Teeth : BaseVSShader
{
public static string HelpString = "Help for Teeth_DX9";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -16,12 +16,12 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
if (ShaderParamOverrides[(int)var] == null) {
@@ -33,12 +33,12 @@ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -46,7 +46,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -71,7 +71,7 @@ protected override void OnInitShaderParams(IMaterialVar[] parms, ReadOnlySpan null;
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/UnlitGeneric.cs b/Source.StdShader.Gl46/UnlitGeneric.cs
index b61a4fe4f..079491879 100644
--- a/Source.StdShader.Gl46/UnlitGeneric.cs
+++ b/Source.StdShader.Gl46/UnlitGeneric.cs
@@ -7,7 +7,7 @@ public class UnlitGeneric : BaseVSShader
{
public static string HelpString = "Help for UnlitGeneric";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -15,12 +15,12 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
if (ShaderParamOverrides[(int)var] == null) {
@@ -32,12 +32,12 @@ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -45,7 +45,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -76,7 +76,7 @@ protected override void OnInitShaderParams(IMaterialVar[] vars, ReadOnlySpan Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/UnlitTwoTexture.cs b/Source.StdShader.Gl46/UnlitTwoTexture.cs
index 41d6dbafe..529510f8d 100644
--- a/Source.StdShader.Gl46/UnlitTwoTexture.cs
+++ b/Source.StdShader.Gl46/UnlitTwoTexture.cs
@@ -8,7 +8,7 @@ namespace Source.StdShader.Gl46;
public class UnlitTwoTexture : BaseVSShader
{
public static string HelpString = "Help for UnlitTwoTexture";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -16,12 +16,12 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
if (ShaderParamOverrides[(int)var] == null) {
@@ -33,12 +33,12 @@ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags = 0) {
Info.Name = name;
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
Index = (int)ShaderMaterialVars.Count + ShaderParams.Count;
ShaderParams.Add(this);
}
@@ -46,7 +46,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public ReadOnlySpan GetName() => Info.Name;
public ShaderParamType GetType() => Info.Type;
public ReadOnlySpan GetDefaultValue() => Info.DefaultValue;
- public int GetFlags() => (int)Info.Flags;
+ public ShaderParamFlags GetFlags() => Info.Flags;
public ReadOnlySpan GetHelp() => Info.Help;
}
@@ -60,7 +60,7 @@ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan default
public static readonly ShaderParam REFRACTAMOUNT = new($"${nameof(REFRACTAMOUNT)}", ShaderParamType.Float, "2", "");
public override string? GetFallbackShader(IMaterialVar[] vars) => null;
- public override int GetFlags() => Flags;
+ public override ShaderFlags GetFlags() => Flags;
public override int GetNumParams() => base.GetNumParams() + ShaderParams.Count;
public override ReadOnlySpan GetParamName(int paramIndex) {
int baseClassParamCount = base.GetNumParams();
diff --git a/Source.StdShader.Gl46/VertexLitGeneric.cs b/Source.StdShader.Gl46/VertexLitGeneric.cs
index a4479e3e7..d3f1a7b97 100644
--- a/Source.StdShader.Gl46/VertexLitGeneric.cs
+++ b/Source.StdShader.Gl46/VertexLitGeneric.cs
@@ -10,7 +10,7 @@ public class VertexLitGeneric : BaseVSShader
{
public static string HelpString = "Help for VertexLitGeneric";
- public static int Flags = 0;
+ public static ShaderFlags Flags = ShaderFlags.None;
public static List ShaderParams = [];
public static ShaderParam[] ShaderParamOverrides = new ShaderParam[(int)ShaderMaterialVars.Count];
@@ -18,22 +18,22 @@ public class ShaderParam
{
public readonly ShaderParamInfo Info;
public readonly int Index;
- public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags) {
+ public ShaderParam(ShaderMaterialVars var, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, ShaderParamFlags flags) {
Info.Name = "override";
Info.Type = type;
Info.DefaultValue = new(defaultParam);
Info.Help = new(help);
- Info.Flags = (ShaderParamFlags)flags;
+ Info.Flags = flags;
AssertMsg(ShaderParamOverrides[(int)var] == null, "Shader parameter override duplicately defined!");
ShaderParamOverrides[(int)var] = this;
Index = (int)var;
}
- public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan help, int flags = 0) {
+ public ShaderParam(string name, ShaderParamType type, ReadOnlySpan defaultParam, ReadOnlySpan