mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
First working effects with new pipeline
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using GlitchyEngine.Renderer;
|
||||
|
||||
namespace GlitchyEngine.Content.Loaders;
|
||||
|
||||
class ShaderLoader : IProcessedAssetLoader
|
||||
{
|
||||
public Result<Asset> Load(Stream stream)
|
||||
{
|
||||
uint64 vsDataSize = Try!(stream.Read<uint64>());
|
||||
uint64 psDataSize = Try!(stream.Read<uint64>());
|
||||
|
||||
VertexShader vertexShader = null;
|
||||
PixelShader pixelShader = null;
|
||||
|
||||
Effect effect = new Effect();
|
||||
|
||||
// Properly clean up in case of an error
|
||||
defer
|
||||
{
|
||||
vertexShader?.ReleaseRef();
|
||||
pixelShader?.ReleaseRef();
|
||||
if (@return case .Err)
|
||||
{
|
||||
effect.ReleaseLastRef();
|
||||
}
|
||||
}
|
||||
|
||||
if (vsDataSize > 0)
|
||||
{
|
||||
uint8[] vsData = new:ScopedAlloc! uint8[vsDataSize];
|
||||
Try!(stream.TryRead(vsData));
|
||||
|
||||
vertexShader = (VertexShader)Try!(Shader.CreateFromBlob(vsData, .Vertex));
|
||||
}
|
||||
|
||||
if (psDataSize > 0)
|
||||
{
|
||||
uint8[] psData = new:ScopedAlloc! uint8[psDataSize];
|
||||
Try!(stream.TryRead(psData));
|
||||
|
||||
pixelShader = (PixelShader)Try!(Shader.CreateFromBlob(psData, .Pixel));
|
||||
}
|
||||
|
||||
uint16 textureCount = Try!(stream.Read<uint16>());
|
||||
|
||||
for (int i < textureCount)
|
||||
{
|
||||
TextureDimension dimension = Try!(stream.Read<TextureDimension>());
|
||||
int32 vertexShaderBindPoint = Try!(stream.Read<int32>());
|
||||
int32 pixelShaderBindPoint = Try!(stream.Read<int32>());
|
||||
|
||||
int16 textureNameLength = Try!(stream.Read<int16>());
|
||||
String textureName = new String(textureNameLength);
|
||||
stream.ReadStrSized32(textureNameLength, textureName);
|
||||
|
||||
Effect.TextureEntry entry = .(TextureViewBinding.CreateDefault(), dimension, null, null);
|
||||
|
||||
if (vertexShaderBindPoint != -1 && vertexShader != null)
|
||||
{
|
||||
vertexShader.Textures.Add(textureName, (.)vertexShaderBindPoint, entry.BoundTexture, dimension);
|
||||
entry.VsSlot = vertexShader.Textures[textureName];
|
||||
}
|
||||
|
||||
if (pixelShaderBindPoint != -1)
|
||||
{
|
||||
pixelShader?.Textures.Add(textureName, (.)pixelShaderBindPoint, entry.BoundTexture, dimension);
|
||||
entry.PsSlot = pixelShader.Textures[textureName];
|
||||
}
|
||||
|
||||
effect.Textures[textureName] = entry;
|
||||
}
|
||||
|
||||
uint16 bufferCount = Try!(stream.Read<uint16>());
|
||||
|
||||
for (int i < bufferCount)
|
||||
{
|
||||
int64 bufferSize = Try!(stream.Read<int64>());
|
||||
|
||||
int32 vertexShaderBindPoint = Try!(stream.Read<int32>());
|
||||
int32 pixelShaderBindPoint = Try!(stream.Read<int32>());
|
||||
|
||||
int16 bufferNameLength = Try!(stream.Read<int16>());
|
||||
String bufferName = scope String(bufferNameLength);
|
||||
stream.ReadStrSized32(bufferNameLength, bufferName);
|
||||
|
||||
int16 engineBufferNameLength = Try!(stream.Read<int16>());
|
||||
String engineBufferName = null;
|
||||
|
||||
if (engineBufferNameLength > 0)
|
||||
{
|
||||
scope String(engineBufferNameLength);
|
||||
stream.ReadStrSized32(engineBufferNameLength, engineBufferName);
|
||||
|
||||
// TODO: Engine buffers currently do nothing. The bind points for each engine buffer are hardcoded.
|
||||
// It only marks the buffer as engine buffer, preventing the variables from becomming accessible.
|
||||
//effect.[Friend]_engineBuffers.Add()
|
||||
}
|
||||
|
||||
uint16 variableCount = Try!(stream.Read<uint16>());
|
||||
|
||||
ConstantBuffer buffer = new ConstantBuffer(bufferName, bufferSize);
|
||||
defer buffer.ReleaseRef();
|
||||
|
||||
for (int v < variableCount)
|
||||
{
|
||||
uint64 variableOffset = Try!(stream.Read<uint64>());
|
||||
uint64 sizeInBytes = Try!(stream.Read<uint64>());
|
||||
bool isUsed = Try!(stream.Read<uint8>()) > 0;
|
||||
ShaderVariableType type = Try!(stream.Read<ShaderVariableType>());
|
||||
uint8 rows = Try!(stream.Read<uint8>());
|
||||
uint8 columns = Try!(stream.Read<uint8>());
|
||||
uint64 arraySize = Try!(stream.Read<uint64>());
|
||||
|
||||
int16 variableNameLength = Try!(stream.Read<int16>());
|
||||
String variableName = scope String(variableNameLength);
|
||||
stream.ReadStrSized32(variableNameLength, variableName);
|
||||
|
||||
if (engineBufferName == null)
|
||||
buffer.AddVariable(variableName, variableOffset, sizeInBytes, isUsed, type, rows, columns, arraySize);
|
||||
}
|
||||
|
||||
Try!(stream.TryRead(buffer.RawData));
|
||||
Try!(buffer.Update());
|
||||
|
||||
if (vertexShaderBindPoint != -1)
|
||||
vertexShader.Buffers.Add(vertexShaderBindPoint, buffer.Name, buffer);
|
||||
|
||||
if (pixelShaderBindPoint != -1)
|
||||
pixelShader.Buffers.Add(pixelShaderBindPoint, buffer.Name, buffer);
|
||||
|
||||
// TODO: Allow binding buffers to different indices? Does this theoretically work with textures?
|
||||
let tempBindPoint = (vertexShaderBindPoint != -1) ? vertexShaderBindPoint : pixelShaderBindPoint;
|
||||
effect.Buffers.Add(tempBindPoint, buffer.Name, buffer);
|
||||
|
||||
for (var variable in buffer.Variables)
|
||||
{
|
||||
effect.Variables.Add(variable);
|
||||
}
|
||||
}
|
||||
|
||||
effect.[Friend]VertexShader = vertexShader;
|
||||
effect.[Friend]PixelShader = pixelShader;
|
||||
|
||||
return effect;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,18 @@ using GlitchyEngine.Content;
|
||||
using System.Collections;
|
||||
|
||||
using internal GlitchyEngine.Renderer;
|
||||
using internal GlitchyEngine.Platform.DX11;
|
||||
|
||||
using System;
|
||||
using GlitchyEngine.Renderer;
|
||||
using DirectX.D3D11;
|
||||
using DirectX.D3DCompiler;
|
||||
using GlitchyEngine.Platform.DX11;
|
||||
using GlitchyEngine.Content;
|
||||
using DirectX.Common;
|
||||
|
||||
using internal GlitchyEngine.Renderer;
|
||||
using internal GlitchyEngine.Platform.DX11;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
@@ -115,6 +127,40 @@ namespace GlitchyEngine.Renderer
|
||||
*/
|
||||
internal ID3DBlob* nativeCode ~ _?.Release();
|
||||
|
||||
protected override Result<void> InternalCreateFromBlob(Span<uint8> blob)
|
||||
{
|
||||
HResult shaderCreationResult = HResult.S_FALSE;
|
||||
|
||||
// TODO Temporary, because we need to generate the vertex layout from it!
|
||||
D3DCompiler.D3DCreateBlob((.)blob.Length, &nativeCode);
|
||||
Internal.MemCpy(nativeCode.GetBufferPointer(), blob.Ptr, blob.Length);
|
||||
|
||||
switch (_shaderType)
|
||||
{
|
||||
case .Vertex:
|
||||
shaderCreationResult = NativeDevice.CreateVertexShader(blob.Ptr, (uint)blob.Length, null, (ID3D11VertexShader**)&nativeShader);
|
||||
case .Pixel:
|
||||
shaderCreationResult = NativeDevice.CreatePixelShader(blob.Ptr, (uint)blob.Length, null, (ID3D11PixelShader**)&nativeShader);
|
||||
default:
|
||||
Log.EngineLogger.Error($"Can't create native shader of type {_shaderType}.");
|
||||
return .Err;
|
||||
}
|
||||
|
||||
if(shaderCreationResult.Failed)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to create native shader from blob: {shaderCreationResult} ({(int)shaderCreationResult})");
|
||||
|
||||
if (nativeShader != null)
|
||||
{
|
||||
nativeShader.Release();
|
||||
}
|
||||
|
||||
return .Err;
|
||||
}
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
protected const ShaderCompileFlags DefaultCompileFlags = .EnableStrictness |
|
||||
#if DEBUG
|
||||
.Debug;
|
||||
|
||||
@@ -29,5 +29,7 @@ namespace GlitchyEngine.Renderer
|
||||
_nativeShaderResourceView?.Release();
|
||||
_nativeSamplerState?.Release();
|
||||
}
|
||||
|
||||
public static override TextureViewBinding CreateDefault() => .(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace GlitchyEngine.Renderer
|
||||
output[i] = .(input[i].SemanticName, input[i].SemanticIndex, (.)input[i].Format, input[i].InputSlot, input[i].AlignedByteOffset, (.)input[i].InputSlotClass, input[i].InstanceDataStepRate);
|
||||
}
|
||||
|
||||
/// This should happen during shader compilation!
|
||||
/// Validates or gets the validated input layout for the given vertexshader.
|
||||
internal ID3D11InputLayout* GetNativeVertexLayout(ID3DBlob* vertexShaderCode)
|
||||
{
|
||||
|
||||
@@ -38,8 +38,9 @@ namespace GlitchyEngine.Renderer
|
||||
[Inline]
|
||||
internal uint8* firstByte => _constantBuffer.rawData.CArray() + _offset;
|
||||
|
||||
public this(ConstantBuffer constantBuffer, ShaderVariableType type, uint32 columns, uint32 rows, uint32 offset, uint32 sizeInBytes, uint32 elements, bool isUsed)
|
||||
public this(StringView name, ConstantBuffer constantBuffer, ShaderVariableType type, uint32 columns, uint32 rows, uint32 offset, uint32 sizeInBytes, uint32 elements, bool isUsed)
|
||||
{
|
||||
_name = new String(name);
|
||||
_constantBuffer = constantBuffer..AddRef();
|
||||
_type = type;
|
||||
_columns = columns;
|
||||
|
||||
@@ -74,13 +74,28 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
public BufferVariableCollection Variables => _variables;
|
||||
|
||||
/// Gets a span to the rawData held on the CPU.
|
||||
public Span<uint8> RawData => rawData;
|
||||
|
||||
protected this() {}
|
||||
|
||||
public this(StringView name, int64 size)
|
||||
{
|
||||
_name = new String(name);
|
||||
rawData = new uint8[size];
|
||||
ConstructBuffer();
|
||||
}
|
||||
|
||||
protected internal void AddVariable(BufferVariable ownVariable)
|
||||
{
|
||||
_variables.Add(ownVariable);
|
||||
}
|
||||
|
||||
public void AddVariable(StringView name, uint64 offset, uint64 sizeInBytes, bool isUsed, ShaderVariableType type, uint8 rows, uint8 columns, uint64 arraySize)
|
||||
{
|
||||
_variables.Add(new BufferVariable(name, this, type, columns, rows, (uint32)offset, (uint32)sizeInBytes, (uint32)arraySize, isUsed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the buffer description.
|
||||
*/
|
||||
@@ -96,9 +111,9 @@ namespace GlitchyEngine.Renderer
|
||||
/**
|
||||
* Uploads the date to the GPU.
|
||||
*/
|
||||
public void Update()
|
||||
public Result<void> Update()
|
||||
{
|
||||
PlatformSetData(rawData.CArray(), (uint32)rawData.Count, 0, .WriteDiscard);
|
||||
return PlatformSetData(rawData.CArray(), (uint32)rawData.Count, 0, .WriteDiscard);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public class Effect : Asset
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<String, TextureEntry> _textures ~ delete _;
|
||||
Dictionary<String, TextureEntry> _textures ~ DeleteDictionaryAndKeys!(_);
|
||||
|
||||
public Dictionary<String, TextureEntry> Textures => _textures;
|
||||
|
||||
@@ -99,7 +99,8 @@ public class Effect : Asset
|
||||
|
||||
MergeResources();
|
||||
}
|
||||
|
||||
|
||||
[Obsolete("", false)]
|
||||
public this(Stream data, StringView assetIdentifier, IContentManager contentManager)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
@@ -115,6 +116,13 @@ public class Effect : Asset
|
||||
MergeResources();
|
||||
}
|
||||
|
||||
public this()
|
||||
{
|
||||
_bufferCollection = new BufferCollection();
|
||||
_variables = new BufferVariableCollection(false);
|
||||
_textures = new Dictionary<String, TextureEntry>();
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
@@ -668,7 +676,7 @@ public class Effect : Asset
|
||||
}
|
||||
|
||||
// save entry
|
||||
_textures[shaderEntry.Name] = entry;
|
||||
_textures[new String(shaderEntry.Name)] = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,7 @@ namespace GlitchyEngine.Renderer
|
||||
[AllowAppend]
|
||||
public this(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager, ShaderDefine[] macros = null)
|
||||
: base(code, fileName, entryPoint, contentManager, macros) { }
|
||||
|
||||
public this() : base() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,29 @@ namespace GlitchyEngine.Renderer
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class Shader : RefCounter
|
||||
public enum ShaderType
|
||||
{
|
||||
Unknown,
|
||||
Vertex,
|
||||
Pixel
|
||||
}
|
||||
|
||||
// TODO: We may not even need the distinction between shader types anymore (maybe just as an enum)
|
||||
public abstract class
|
||||
Shader : RefCounter
|
||||
{
|
||||
protected internal BufferCollection _buffers ~ _.ReleaseRef();//:append _;
|
||||
|
||||
protected ShaderTextureCollection _textures ~ delete _;
|
||||
|
||||
|
||||
protected ShaderType _shaderType;
|
||||
|
||||
public BufferCollection Buffers => _buffers;
|
||||
|
||||
public ShaderTextureCollection Textures => _textures;
|
||||
|
||||
public ShaderType ShaderType => _shaderType;
|
||||
|
||||
[AllowAppend]
|
||||
public this(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager, ShaderDefine[] macros = null)
|
||||
{
|
||||
@@ -43,24 +56,49 @@ namespace GlitchyEngine.Renderer
|
||||
CompileFromSource(code, fileName, entryPoint, contentManager);
|
||||
}
|
||||
|
||||
public this()
|
||||
{
|
||||
_buffers = new BufferCollection();
|
||||
_textures = new ShaderTextureCollection();
|
||||
}
|
||||
|
||||
public static Result<Shader> CreateFromBlob(Span<uint8> shaderBlob, ShaderType shaderType)
|
||||
{
|
||||
Shader shader = null;
|
||||
|
||||
defer
|
||||
{
|
||||
if (@return case .Err)
|
||||
{
|
||||
shader?.ReleaseRef();
|
||||
}
|
||||
}
|
||||
|
||||
switch (shaderType)
|
||||
{
|
||||
case .Vertex:
|
||||
shader = new VertexShader();
|
||||
case .Pixel:
|
||||
shader = new PixelShader();
|
||||
default:
|
||||
Log.EngineLogger.Error($"Can't create shader of type {shaderType}");
|
||||
return .Err;
|
||||
}
|
||||
|
||||
shader._shaderType = shaderType;
|
||||
|
||||
Try!(shader.InternalCreateFromBlob(shaderBlob));
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
}
|
||||
|
||||
/*public static mixin FromFile<T>(String fileName, String entryPoint, IContentManager contentManager, ShaderDefine[] macros = null) where T : Shader
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
String fileContent = new String();
|
||||
File.ReadAllText(fileName, fileContent, true);
|
||||
T shader = new T(fileContent, (StringView)fileName, contentManager, entryPoint, macros);
|
||||
|
||||
delete fileContent;
|
||||
|
||||
shader
|
||||
}*/
|
||||
|
||||
public abstract void CompileFromSource(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager, ShaderDefine[] macros = null);
|
||||
|
||||
protected abstract Result<void> InternalCreateFromBlob(Span<uint8> blob);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ namespace GlitchyEngine.Renderer
|
||||
}
|
||||
|
||||
// TODO: finish implementation (like BufferCollection)
|
||||
public ResourceEntry* this[int idx] => _idxToBuf[idx];
|
||||
public ResourceEntry* this[String name] => _strToBuf[name];
|
||||
|
||||
public void Add(String name, uint32 index, TextureViewBinding texture, TextureDimension dimension)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
// TODO: I hate this. It is a reference counting struct?!
|
||||
/// Represents a reference to a texture that can be used as shader input resource.
|
||||
public struct TextureViewBinding : IRefCounted, IDisposable
|
||||
{
|
||||
@@ -11,6 +12,8 @@ namespace GlitchyEngine.Renderer
|
||||
public extern void AddRef();
|
||||
public extern void Release();
|
||||
|
||||
public static extern TextureViewBinding CreateDefault();
|
||||
|
||||
public void Dispose() => Release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,7 @@ namespace GlitchyEngine.Renderer
|
||||
[AllowAppend]
|
||||
public this(StringView code, StringView? fileName, String entryPoint, IContentManager contentManager = null, ShaderDefine[] macros = null)
|
||||
: base(code, fileName, entryPoint, contentManager, macros) { }
|
||||
|
||||
public this() : base() { }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user