Skip to content

Commit

Permalink
Add support for custom Slang attributes (SrgbRead, Default)
Browse files Browse the repository at this point in the history
```hlsl
[SrgbRead]
Texture2D diffuseTexture;

[Default(1.0f, 1.0f, 1.0f, 1.0f)]
Texture2D ambientOcclusionTexture;
```
  • Loading branch information
xezno committed Dec 23, 2024
1 parent eaa84cf commit 4af4b34
Show file tree
Hide file tree
Showing 11 changed files with 366 additions and 68 deletions.
11 changes: 11 additions & 0 deletions Content/core/shaders/attributes.mshdri
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[__AttributeUsage(_AttributeTargets.Var)]
struct SrgbReadAttribute {}

[__AttributeUsage(_AttributeTargets.Var)]
struct DefaultAttribute
{
float valueR;
float valueG;
float valueB;
float valueA;
}
27 changes: 21 additions & 6 deletions Content/core/shaders/pbr.mshdr
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,28 @@ Fragment
{
#define PI 3.14159265359

[[vk::binding(0, 0)]] Texture2D diffuseTexture;
[[vk::binding(1, 0)]] Texture2D normalTexture;
[[vk::binding(2, 0)]] Texture2D ambientOcclusionTexture;
[[vk::binding(3, 0)]] Texture2D metalnessTexture;
[[vk::binding(4, 0)]] Texture2D roughnessTexture;
[[vk::binding(0, 0)]]
[SrgbRead]
Texture2D diffuseTexture;

[[vk::binding(5, 0)]] SamplerState samplerState;
[[vk::binding(1, 0)]]
[Default(0.5f, 0.5f, 1.0f, 1.0f)]
Texture2D normalTexture;

[[vk::binding(2, 0)]]
[Default(1.0f, 1.0f, 1.0f, 1.0f)]
Texture2D ambientOcclusionTexture;

[[vk::binding(3, 0)]]
[Default(0.0f, 0.0f, 0.0f, 1.0f)]
Texture2D metalnessTexture;

[[vk::binding(4, 0)]]
[Default(1.0f, 1.0f, 1.0f, 1.0f)]
Texture2D roughnessTexture;

[[vk::binding(5, 0)]]
SamplerState samplerState;

float3 fresnelSchlick(float cosTheta, float3 F0)
{
Expand Down
54 changes: 48 additions & 6 deletions Source/Mocha.Common/Resources/ShaderInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Mocha.Glue;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;

namespace Mocha.Common;

Expand All @@ -12,25 +11,68 @@ public enum ShaderReflectionType
Sampler
}

public enum ShaderReflectionAttributeType
{
Unknown,

// SrgbReadAttribute
SrgbRead,

// DefaultAttribute
Default
};

[StructLayout( LayoutKind.Sequential )]
public struct DefaultAttributeData
{
public float ValueR { get; set; }
public float ValueG { get; set; }
public float ValueB { get; set; }
public float ValueA { get; set; }
};

[StructLayout( LayoutKind.Sequential )]
public struct ShaderReflectionAttribute
{
public ShaderReflectionAttributeType Type { get; set; }
public byte[] Data { get; set; }

public void SetData<T>( T? obj ) where T : new()
{
if ( obj == null )
return;

Data = Serializer.Serialize<T>( obj );
}

public readonly T? GetData<T>() where T : new()
{
return Serializer.Deserialize<T>( Data );
}
};

[StructLayout( LayoutKind.Sequential )]
public struct ShaderReflectionBinding
{
public int Set { get; set; }
public int Binding { get; set; }
public ShaderReflectionType Type { get; set; }
public string Name { get; set; }
}

public struct NativeShaderReflectionInfo
{
public UtilArray Bindings { get; set; }
public ShaderReflectionAttribute[] Attributes { get; set; }
}

public struct ShaderReflectionInfo
{
public ShaderReflectionBinding[] Bindings { get; set; }
}

public struct NativeShaderStageInfo
{
public int[] Data { get; set; }
public ShaderReflectionInfo Reflection { get; set; }
}

public struct ShaderStageInfo
{
public int[] Data { get; set; }
Expand Down
53 changes: 39 additions & 14 deletions Source/Mocha.Engine/Render/Assets/Material.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,50 @@ public Material( string path )
Log.Warning( $"Material '{path}' does not exist" );
}

foreach ( var texturePath in textureBindings.Data )
{
// todo: How do we determine SRGB here? We should probably just fetch it from the texture itself right?
Textures.Add( texturePath.Key, new Texture( texturePath.Value, false ) );
}

{
var shaderFileBytes = FileSystem.Mounted.ReadAllBytes( "shaders/pbr.mshdr" );
var shaderFormat = Serializer.Deserialize<MochaFile<ShaderInfo>>( shaderFileBytes );

var boundTextures = shaderFormat.Data.Fragment.Reflection.Bindings
// resolve bindings
var requiredBindings = shaderFormat.Data.Fragment.Reflection.Bindings
.Where( binding => binding.Type == ShaderReflectionType.Texture )
.Select( binding => (
binding.Name,
Textures.TryGetValue( binding.Name, out var tex ) ? tex : Texture.MissingTexture,
binding
) )
.OrderBy( x => x.binding.Binding )
.Select( x => x.Item2.NativeTexture )
.ToList();

// load textures
foreach ( var binding in requiredBindings )
{
if ( !Textures.ContainsKey( binding.Name ) && textureBindings.Data.ContainsKey( binding.Name ) )
{
bool isSrgb = binding.Attributes.Any( a => a.Type == ShaderReflectionAttributeType.SrgbRead );

Textures.Add( binding.Name, new Texture( textureBindings.Data[binding.Name], isSrgb ) );
}
}

// create the ordered list of bound textures
var boundTextures = requiredBindings
.OrderBy( x => x.Binding )
.Select( binding =>
{
if ( Textures.TryGetValue( binding.Name, out var tex ) )
return tex;

// check for default attribute
var defaultAttr = binding.Attributes.Where( a => a.Type == ShaderReflectionAttributeType.Default ).Any()
? binding.Attributes.First( a => a.Type == ShaderReflectionAttributeType.Default )
: default;

bool isSrgb = binding.Attributes.Any( a => a.Type == ShaderReflectionAttributeType.SrgbRead );

if ( defaultAttr.Type == ShaderReflectionAttributeType.Default )
{
var data = defaultAttr.GetData<DefaultAttributeData>();
return new Texture( data.ValueR, data.ValueG, data.ValueB, data.ValueA, isSrgb );
}

return Texture.MissingTexture;
} )
.Select( x => x.NativeTexture )
.ToList();

NativeMaterial = new(
Expand Down
13 changes: 12 additions & 1 deletion Source/Mocha.Engine/Render/Assets/Texture.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Mocha;
using static Mocha.Common.Font;

namespace Mocha;

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

internal Texture( float r, float g, float b, float a = 1.0f, bool isSrgb = true )
{
var textureFormat = GetRenderTextureFormat( TextureFormat.RGBA, isSrgb );
var data = new byte[] { (byte)(r * 255.0f), (byte)(g * 255.0f), (byte)(b * 255.0f), (byte)(a * 255.0f) };

NativeTexture = new( "pixel", 1, 1 );
NativeTexture.SetData( 1, 1, 1, data.ToInterop(), (int)textureFormat );
}

public void Copy( uint srcX, uint srcY, uint dstX, uint dstY, uint width, uint height, Texture src )
{
NativeTexture.Copy( srcX, srcY, dstX, dstY, width, height, src.NativeTexture );
Expand Down
49 changes: 45 additions & 4 deletions Source/Mocha.Host/Rendering/shadercompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ bool ShaderCompiler::Compile( const ShaderType shaderType, const char* pShader,

std::vector<ShaderReflectionBinding> reflectionBindings = {};
ShaderReflectionInfo shaderReflectionInfo = {};

{
slang::ProgramLayout* layout = program->getLayout( targetIndex );
auto globalScope = layout->getGlobalParamsVarLayout();
Expand Down Expand Up @@ -116,12 +116,53 @@ bool ShaderCompiler::Compile( const ShaderType shaderType, const char* pShader,
break;
}

reflectionBindings.push_back( ShaderReflectionBinding{
.Set = ( int )set, .Binding = ( int )binding, .Type = mochaReflectionType, .Name = name } );
// get attributes
auto attributeCount = param->getVariable()->getUserAttributeCount();
spdlog::info( "Variable {} has {} attributes", name, attributeCount );

std::vector<ShaderReflectionAttribute> reflectedAttributes{};

for ( int attributeIndex = 0; attributeIndex < attributeCount; ++attributeIndex )
{
auto attribute = param->getVariable()->getUserAttributeByIndex( attributeIndex );
auto attributeName = attribute->getName();

auto attributeArgumentCount = attribute->getArgumentCount();

ShaderReflectionAttribute reflectedAttribute;

if ( strcmp( attributeName, "Default" ) == 0 )
{
// Default attribute
reflectedAttribute.Type = SHADER_REFLECTION_ATTRIBUTE_TYPE_DEFAULT;
reflectedAttribute.Data = new DefaultAttributeData();
attribute->getArgumentValueFloat( 0, &( ( DefaultAttributeData* )reflectedAttribute.Data )->ValueR );
attribute->getArgumentValueFloat( 1, &( ( DefaultAttributeData* )reflectedAttribute.Data )->ValueG );
attribute->getArgumentValueFloat( 2, &( ( DefaultAttributeData* )reflectedAttribute.Data )->ValueB );
attribute->getArgumentValueFloat( 3, &( ( DefaultAttributeData* )reflectedAttribute.Data )->ValueA );
}
else if ( strcmp( attributeName, "SrgbRead" ) == 0 )
{
// SRGB read attribute
reflectedAttribute.Type = SHADER_REFLECTION_ATTRIBUTE_TYPE_SRGB_READ;
}
else
{
spdlog::warn( "Unhandled attribute '{}'", attributeName );
}

reflectedAttributes.emplace_back( reflectedAttribute );
}

reflectionBindings.push_back( ShaderReflectionBinding{ .Set = ( int )set,
.Binding = ( int )binding,
.Type = mochaReflectionType,
.Name = name,
.Attributes = UtilArray::FromVector<ShaderReflectionAttribute>( reflectedAttributes ) } );
}
}

outResult.ReflectionData = ShaderReflectionInfo { .Bindings = UtilArray::FromVector( reflectionBindings ) };
outResult.ReflectionData = ShaderReflectionInfo{ .Bindings = UtilArray::FromVector( reflectionBindings ) };

return true;
}
42 changes: 34 additions & 8 deletions Source/Mocha.Host/Rendering/shadercompiler.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
#pragma once

#include <slang.h>
#include "baserendercontext.h"

#include <slang-com-ptr.h>
#include <slang.h>
#include <vector>

#include "baserendercontext.h"

using namespace slang;


enum ShaderReflectionType
{
SHADER_REFLECTION_TYPE_UNKNOWN,
Expand All @@ -18,12 +17,39 @@ enum ShaderReflectionType
SHADER_REFLECTION_TYPE_SAMPLER
};

enum ShaderReflectionAttributeType
{
SHADER_REFLECTION_ATTRIBUTE_TYPE_UNKNOWN,

// SrgbReadAttribute
SHADER_REFLECTION_ATTRIBUTE_TYPE_SRGB_READ,

// DefaultAttribute
SHADER_REFLECTION_ATTRIBUTE_TYPE_DEFAULT
};

struct DefaultAttributeData
{
float ValueR = 0.0f;
float ValueG = 0.0f;
float ValueB = 0.0f;
float ValueA = 0.0f;
};

struct ShaderReflectionAttribute
{
ShaderReflectionAttributeType Type = SHADER_REFLECTION_ATTRIBUTE_TYPE_UNKNOWN;
void* Data = nullptr;
};

struct ShaderReflectionBinding
{
int Set;
int Binding;
ShaderReflectionType Type;
const char* Name;
int Set = -1;
int Binding = -1;
ShaderReflectionType Type = SHADER_REFLECTION_TYPE_UNKNOWN;
const char* Name = nullptr;

UtilArray Attributes;
};

struct ShaderReflectionInfo
Expand Down
2 changes: 2 additions & 0 deletions Source/Mocha.Tests/Mocha.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>

<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions Source/Mocha.sln
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ Global
{860C57C4-6E4B-445F-9614-9084AF4CD46B}.Release|x86.Build.0 = Release|Win32
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x64.ActiveCfg = Debug|Any CPU
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x64.Build.0 = Debug|Any CPU
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x64.ActiveCfg = Debug|x64
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x64.Build.0 = Debug|x64
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x86.ActiveCfg = Debug|Any CPU
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Debug|x86.Build.0 = Debug|Any CPU
{267A391D-CD51-4A29-A41B-11D57E9F9AAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down
Loading

0 comments on commit 4af4b34

Please sign in to comment.