Skip to content

Commit 4af4b34

Browse files
committed
Add support for custom Slang attributes (SrgbRead, Default)
```hlsl [SrgbRead] Texture2D diffuseTexture; [Default(1.0f, 1.0f, 1.0f, 1.0f)] Texture2D ambientOcclusionTexture; ```
1 parent eaa84cf commit 4af4b34

File tree

11 files changed

+366
-68
lines changed

11 files changed

+366
-68
lines changed
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[__AttributeUsage(_AttributeTargets.Var)]
2+
struct SrgbReadAttribute {}
3+
4+
[__AttributeUsage(_AttributeTargets.Var)]
5+
struct DefaultAttribute
6+
{
7+
float valueR;
8+
float valueG;
9+
float valueB;
10+
float valueA;
11+
}

Content/core/shaders/pbr.mshdr

+21-6
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,28 @@ Fragment
108108
{
109109
#define PI 3.14159265359
110110

111-
[[vk::binding(0, 0)]] Texture2D diffuseTexture;
112-
[[vk::binding(1, 0)]] Texture2D normalTexture;
113-
[[vk::binding(2, 0)]] Texture2D ambientOcclusionTexture;
114-
[[vk::binding(3, 0)]] Texture2D metalnessTexture;
115-
[[vk::binding(4, 0)]] Texture2D roughnessTexture;
111+
[[vk::binding(0, 0)]]
112+
[SrgbRead]
113+
Texture2D diffuseTexture;
116114

117-
[[vk::binding(5, 0)]] SamplerState samplerState;
115+
[[vk::binding(1, 0)]]
116+
[Default(0.5f, 0.5f, 1.0f, 1.0f)]
117+
Texture2D normalTexture;
118+
119+
[[vk::binding(2, 0)]]
120+
[Default(1.0f, 1.0f, 1.0f, 1.0f)]
121+
Texture2D ambientOcclusionTexture;
122+
123+
[[vk::binding(3, 0)]]
124+
[Default(0.0f, 0.0f, 0.0f, 1.0f)]
125+
Texture2D metalnessTexture;
126+
127+
[[vk::binding(4, 0)]]
128+
[Default(1.0f, 1.0f, 1.0f, 1.0f)]
129+
Texture2D roughnessTexture;
130+
131+
[[vk::binding(5, 0)]]
132+
SamplerState samplerState;
118133

119134
float3 fresnelSchlick(float cosTheta, float3 F0)
120135
{

Source/Mocha.Common/Resources/ShaderInfo.cs

+48-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using Mocha.Glue;
2-
using System.Runtime.InteropServices;
1+
using System.Runtime.InteropServices;
32

43
namespace Mocha.Common;
54

@@ -12,25 +11,68 @@ public enum ShaderReflectionType
1211
Sampler
1312
}
1413

14+
public enum ShaderReflectionAttributeType
15+
{
16+
Unknown,
17+
18+
// SrgbReadAttribute
19+
SrgbRead,
20+
21+
// DefaultAttribute
22+
Default
23+
};
24+
25+
[StructLayout( LayoutKind.Sequential )]
26+
public struct DefaultAttributeData
27+
{
28+
public float ValueR { get; set; }
29+
public float ValueG { get; set; }
30+
public float ValueB { get; set; }
31+
public float ValueA { get; set; }
32+
};
33+
34+
[StructLayout( LayoutKind.Sequential )]
35+
public struct ShaderReflectionAttribute
36+
{
37+
public ShaderReflectionAttributeType Type { get; set; }
38+
public byte[] Data { get; set; }
39+
40+
public void SetData<T>( T? obj ) where T : new()
41+
{
42+
if ( obj == null )
43+
return;
44+
45+
Data = Serializer.Serialize<T>( obj );
46+
}
47+
48+
public readonly T? GetData<T>() where T : new()
49+
{
50+
return Serializer.Deserialize<T>( Data );
51+
}
52+
};
53+
1554
[StructLayout( LayoutKind.Sequential )]
1655
public struct ShaderReflectionBinding
1756
{
1857
public int Set { get; set; }
1958
public int Binding { get; set; }
2059
public ShaderReflectionType Type { get; set; }
2160
public string Name { get; set; }
22-
}
2361

24-
public struct NativeShaderReflectionInfo
25-
{
26-
public UtilArray Bindings { get; set; }
62+
public ShaderReflectionAttribute[] Attributes { get; set; }
2763
}
2864

2965
public struct ShaderReflectionInfo
3066
{
3167
public ShaderReflectionBinding[] Bindings { get; set; }
3268
}
3369

70+
public struct NativeShaderStageInfo
71+
{
72+
public int[] Data { get; set; }
73+
public ShaderReflectionInfo Reflection { get; set; }
74+
}
75+
3476
public struct ShaderStageInfo
3577
{
3678
public int[] Data { get; set; }

Source/Mocha.Engine/Render/Assets/Material.cs

+39-14
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,50 @@ public Material( string path )
3030
Log.Warning( $"Material '{path}' does not exist" );
3131
}
3232

33-
foreach ( var texturePath in textureBindings.Data )
34-
{
35-
// todo: How do we determine SRGB here? We should probably just fetch it from the texture itself right?
36-
Textures.Add( texturePath.Key, new Texture( texturePath.Value, false ) );
37-
}
38-
3933
{
4034
var shaderFileBytes = FileSystem.Mounted.ReadAllBytes( "shaders/pbr.mshdr" );
4135
var shaderFormat = Serializer.Deserialize<MochaFile<ShaderInfo>>( shaderFileBytes );
4236

43-
var boundTextures = shaderFormat.Data.Fragment.Reflection.Bindings
37+
// resolve bindings
38+
var requiredBindings = shaderFormat.Data.Fragment.Reflection.Bindings
4439
.Where( binding => binding.Type == ShaderReflectionType.Texture )
45-
.Select( binding => (
46-
binding.Name,
47-
Textures.TryGetValue( binding.Name, out var tex ) ? tex : Texture.MissingTexture,
48-
binding
49-
) )
50-
.OrderBy( x => x.binding.Binding )
51-
.Select( x => x.Item2.NativeTexture )
40+
.ToList();
41+
42+
// load textures
43+
foreach ( var binding in requiredBindings )
44+
{
45+
if ( !Textures.ContainsKey( binding.Name ) && textureBindings.Data.ContainsKey( binding.Name ) )
46+
{
47+
bool isSrgb = binding.Attributes.Any( a => a.Type == ShaderReflectionAttributeType.SrgbRead );
48+
49+
Textures.Add( binding.Name, new Texture( textureBindings.Data[binding.Name], isSrgb ) );
50+
}
51+
}
52+
53+
// create the ordered list of bound textures
54+
var boundTextures = requiredBindings
55+
.OrderBy( x => x.Binding )
56+
.Select( binding =>
57+
{
58+
if ( Textures.TryGetValue( binding.Name, out var tex ) )
59+
return tex;
60+
61+
// check for default attribute
62+
var defaultAttr = binding.Attributes.Where( a => a.Type == ShaderReflectionAttributeType.Default ).Any()
63+
? binding.Attributes.First( a => a.Type == ShaderReflectionAttributeType.Default )
64+
: default;
65+
66+
bool isSrgb = binding.Attributes.Any( a => a.Type == ShaderReflectionAttributeType.SrgbRead );
67+
68+
if ( defaultAttr.Type == ShaderReflectionAttributeType.Default )
69+
{
70+
var data = defaultAttr.GetData<DefaultAttributeData>();
71+
return new Texture( data.ValueR, data.ValueG, data.ValueB, data.ValueA, isSrgb );
72+
}
73+
74+
return Texture.MissingTexture;
75+
} )
76+
.Select( x => x.NativeTexture )
5277
.ToList();
5378

5479
NativeMaterial = new(

Source/Mocha.Engine/Render/Assets/Texture.cs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace Mocha;
1+
using static Mocha.Common.Font;
2+
3+
namespace Mocha;
24

35
[Icon( FontAwesome.Image ), Title( "Texture" )]
46
public partial class Texture : Asset
@@ -70,6 +72,15 @@ public Texture( uint width, uint height, bool isSrgb = true )
7072
NativeTexture.SetData( Width, Height, 1, new byte[Width * Height * 4].ToInterop(), (int)textureFormat );
7173
}
7274

75+
internal Texture( float r, float g, float b, float a = 1.0f, bool isSrgb = true )
76+
{
77+
var textureFormat = GetRenderTextureFormat( TextureFormat.RGBA, isSrgb );
78+
var data = new byte[] { (byte)(r * 255.0f), (byte)(g * 255.0f), (byte)(b * 255.0f), (byte)(a * 255.0f) };
79+
80+
NativeTexture = new( "pixel", 1, 1 );
81+
NativeTexture.SetData( 1, 1, 1, data.ToInterop(), (int)textureFormat );
82+
}
83+
7384
public void Copy( uint srcX, uint srcY, uint dstX, uint dstY, uint width, uint height, Texture src )
7485
{
7586
NativeTexture.Copy( srcX, srcY, dstX, dstY, width, height, src.NativeTexture );

Source/Mocha.Host/Rendering/shadercompiler.cpp

+45-4
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ bool ShaderCompiler::Compile( const ShaderType shaderType, const char* pShader,
7777

7878
std::vector<ShaderReflectionBinding> reflectionBindings = {};
7979
ShaderReflectionInfo shaderReflectionInfo = {};
80-
80+
8181
{
8282
slang::ProgramLayout* layout = program->getLayout( targetIndex );
8383
auto globalScope = layout->getGlobalParamsVarLayout();
@@ -116,12 +116,53 @@ bool ShaderCompiler::Compile( const ShaderType shaderType, const char* pShader,
116116
break;
117117
}
118118

119-
reflectionBindings.push_back( ShaderReflectionBinding{
120-
.Set = ( int )set, .Binding = ( int )binding, .Type = mochaReflectionType, .Name = name } );
119+
// get attributes
120+
auto attributeCount = param->getVariable()->getUserAttributeCount();
121+
spdlog::info( "Variable {} has {} attributes", name, attributeCount );
122+
123+
std::vector<ShaderReflectionAttribute> reflectedAttributes{};
124+
125+
for ( int attributeIndex = 0; attributeIndex < attributeCount; ++attributeIndex )
126+
{
127+
auto attribute = param->getVariable()->getUserAttributeByIndex( attributeIndex );
128+
auto attributeName = attribute->getName();
129+
130+
auto attributeArgumentCount = attribute->getArgumentCount();
131+
132+
ShaderReflectionAttribute reflectedAttribute;
133+
134+
if ( strcmp( attributeName, "Default" ) == 0 )
135+
{
136+
// Default attribute
137+
reflectedAttribute.Type = SHADER_REFLECTION_ATTRIBUTE_TYPE_DEFAULT;
138+
reflectedAttribute.Data = new DefaultAttributeData();
139+
attribute->getArgumentValueFloat( 0, &( ( DefaultAttributeData* )reflectedAttribute.Data )->ValueR );
140+
attribute->getArgumentValueFloat( 1, &( ( DefaultAttributeData* )reflectedAttribute.Data )->ValueG );
141+
attribute->getArgumentValueFloat( 2, &( ( DefaultAttributeData* )reflectedAttribute.Data )->ValueB );
142+
attribute->getArgumentValueFloat( 3, &( ( DefaultAttributeData* )reflectedAttribute.Data )->ValueA );
143+
}
144+
else if ( strcmp( attributeName, "SrgbRead" ) == 0 )
145+
{
146+
// SRGB read attribute
147+
reflectedAttribute.Type = SHADER_REFLECTION_ATTRIBUTE_TYPE_SRGB_READ;
148+
}
149+
else
150+
{
151+
spdlog::warn( "Unhandled attribute '{}'", attributeName );
152+
}
153+
154+
reflectedAttributes.emplace_back( reflectedAttribute );
155+
}
156+
157+
reflectionBindings.push_back( ShaderReflectionBinding{ .Set = ( int )set,
158+
.Binding = ( int )binding,
159+
.Type = mochaReflectionType,
160+
.Name = name,
161+
.Attributes = UtilArray::FromVector<ShaderReflectionAttribute>( reflectedAttributes ) } );
121162
}
122163
}
123164

124-
outResult.ReflectionData = ShaderReflectionInfo { .Bindings = UtilArray::FromVector( reflectionBindings ) };
165+
outResult.ReflectionData = ShaderReflectionInfo{ .Bindings = UtilArray::FromVector( reflectionBindings ) };
125166

126167
return true;
127168
}

Source/Mocha.Host/Rendering/shadercompiler.h

+34-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
#pragma once
22

3-
#include <slang.h>
3+
#include "baserendercontext.h"
4+
45
#include <slang-com-ptr.h>
6+
#include <slang.h>
57
#include <vector>
68

7-
#include "baserendercontext.h"
8-
99
using namespace slang;
1010

11-
1211
enum ShaderReflectionType
1312
{
1413
SHADER_REFLECTION_TYPE_UNKNOWN,
@@ -18,12 +17,39 @@ enum ShaderReflectionType
1817
SHADER_REFLECTION_TYPE_SAMPLER
1918
};
2019

20+
enum ShaderReflectionAttributeType
21+
{
22+
SHADER_REFLECTION_ATTRIBUTE_TYPE_UNKNOWN,
23+
24+
// SrgbReadAttribute
25+
SHADER_REFLECTION_ATTRIBUTE_TYPE_SRGB_READ,
26+
27+
// DefaultAttribute
28+
SHADER_REFLECTION_ATTRIBUTE_TYPE_DEFAULT
29+
};
30+
31+
struct DefaultAttributeData
32+
{
33+
float ValueR = 0.0f;
34+
float ValueG = 0.0f;
35+
float ValueB = 0.0f;
36+
float ValueA = 0.0f;
37+
};
38+
39+
struct ShaderReflectionAttribute
40+
{
41+
ShaderReflectionAttributeType Type = SHADER_REFLECTION_ATTRIBUTE_TYPE_UNKNOWN;
42+
void* Data = nullptr;
43+
};
44+
2145
struct ShaderReflectionBinding
2246
{
23-
int Set;
24-
int Binding;
25-
ShaderReflectionType Type;
26-
const char* Name;
47+
int Set = -1;
48+
int Binding = -1;
49+
ShaderReflectionType Type = SHADER_REFLECTION_TYPE_UNKNOWN;
50+
const char* Name = nullptr;
51+
52+
UtilArray Attributes;
2753
};
2854

2955
struct ShaderReflectionInfo

Source/Mocha.Tests/Mocha.Tests.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
<Nullable>enable</Nullable>
77

88
<IsPackable>false</IsPackable>
9+
10+
<Platforms>AnyCPU;x64</Platforms>
911
</PropertyGroup>
1012

1113
<ItemGroup>

Source/Mocha.sln

+2-2
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ Global
193193
{860C57C4-6E4B-445F-9614-9084AF4CD46B}.Release|x86.Build.0 = Release|Win32
194194
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
195195
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
196-
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x64.ActiveCfg = Debug|Any CPU
197-
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x64.Build.0 = Debug|Any CPU
196+
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x64.ActiveCfg = Debug|x64
197+
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x64.Build.0 = Debug|x64
198198
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x86.ActiveCfg = Debug|Any CPU
199199
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x86.Build.0 = Debug|Any CPU
200200
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Release|Any CPU.ActiveCfg = Release|Any CPU

0 commit comments

Comments
 (0)