mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-06 05:01:53 +00:00
RenderTargetGroup
This commit is contained in:
@@ -120,6 +120,11 @@ namespace GlitchyEngine.Renderer
|
||||
_depthStencilTarget = target?.nativeView;
|
||||
}
|
||||
|
||||
internal void SetNativeDepthStencilTarget(ID3D11DepthStencilView* depthStencilTarget)
|
||||
{
|
||||
_depthStencilTarget = depthStencilTarget;
|
||||
}
|
||||
|
||||
public override void SetRenderTarget(RenderTarget2D renderTarget, int slot, bool setDepthTarget)
|
||||
{
|
||||
_renderTargets[slot] = (renderTarget ?? _swapChain.BackBuffer)._nativeRenderTargetView;
|
||||
@@ -129,6 +134,14 @@ namespace GlitchyEngine.Renderer
|
||||
SetDepthStencilTarget((renderTarget ?? _swapChain.BackBuffer).DepthStencilTarget);
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetNativeRenderTargets(Span<ID3D11RenderTargetView*> renderTargets, int startSlot)
|
||||
{
|
||||
for (int i < renderTargets.Length)
|
||||
{
|
||||
_renderTargets[i + startSlot] = renderTargets[i];
|
||||
}
|
||||
}
|
||||
|
||||
public override void UnbindRenderTargets()
|
||||
{
|
||||
@@ -206,8 +219,8 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
for(let entry in shader.Textures)
|
||||
{
|
||||
_textures[entry.Index] = entry.Texture?._nativeResourceView;
|
||||
_samplers[entry.Index] = entry.Texture?.SamplerState?.nativeSamplerState;
|
||||
_textures[entry.Index] = entry.BoundTexture._nativeShaderResourceView;
|
||||
_samplers[entry.Index] = entry.BoundTexture._nativeSamplerState;
|
||||
|
||||
if(entry.Index >= _textureCount)
|
||||
_textureCount = entry.Index + 1;
|
||||
|
||||
@@ -118,6 +118,262 @@ namespace GlitchyEngine.Renderer
|
||||
Log.EngineLogger.Assert(result.Succeeded, "Failed to create render target view");
|
||||
}
|
||||
}
|
||||
|
||||
protected override TextureViewBinding PlatformGetViewBinding()
|
||||
{
|
||||
return .(_nativeResourceView, _samplerState.nativeSamplerState);
|
||||
}
|
||||
}
|
||||
|
||||
extension RenderTargetFormat
|
||||
{
|
||||
public DirectX.DXGI.Format GetTextureFormat()
|
||||
{
|
||||
switch(this)
|
||||
{
|
||||
case .R8G8B8A8_UNorm:
|
||||
return .R8G8B8A8_UNorm;
|
||||
case .R8G8B8A8_SNorm:
|
||||
return .R8G8B8A8_SNorm;
|
||||
|
||||
case .R16G16B16A16_SNorm:
|
||||
return .R16G16B16A16_SNorm;
|
||||
case .R16G16B16A16_Float:
|
||||
return .R16G16B16A16_Float;
|
||||
|
||||
case .R32G32B32A32_Float:
|
||||
return .R32G32B32A32_Float;
|
||||
|
||||
case .D24_UNorm_S8_UInt:
|
||||
return .R24G8_Typeless;
|
||||
|
||||
default:
|
||||
return .Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public DirectX.DXGI.Format GetShaderViewFormat()
|
||||
{
|
||||
switch(this)
|
||||
{
|
||||
case .D24_UNorm_S8_UInt:
|
||||
return .R24_UNorm_X8_Typeless;
|
||||
|
||||
default:
|
||||
return GetTextureFormat();
|
||||
}
|
||||
}
|
||||
|
||||
public DirectX.DXGI.Format GetTargetViewFormat()
|
||||
{
|
||||
switch(this)
|
||||
{
|
||||
case .D24_UNorm_S8_UInt:
|
||||
return .D24_UNorm_S8_UInt;
|
||||
|
||||
default:
|
||||
return GetTextureFormat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension RenderTargetGroup
|
||||
{
|
||||
internal ID3D11Texture2D*[] _nativeTextures;
|
||||
internal ID3D11RenderTargetView*[] _renderTargetViews;
|
||||
internal ID3D11ShaderResourceView*[] _nativeResourceViews;
|
||||
|
||||
internal ID3D11Texture2D* _nativeDepthTexture;
|
||||
internal ID3D11DepthStencilView* _nativeDepthTargetView;
|
||||
internal ID3D11ShaderResourceView* _nativeDepthResourceView;
|
||||
|
||||
~this()
|
||||
{
|
||||
ReleaseEveryThing();
|
||||
}
|
||||
|
||||
private ID3D11Texture2D* PlatformCreateTexture(TargetDescription target)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
Texture2DDescription desc = .()
|
||||
{
|
||||
Width = _description.Width,
|
||||
Height = _description.Height,
|
||||
ArraySize = _description.ArraySize,
|
||||
MipLevels = _description.MipLevels,
|
||||
Format = target.Format.GetTextureFormat(),
|
||||
// Always bindable as ShaderResource and RenderTarget
|
||||
BindFlags = .ShaderResource | (target.Format.IsDepth ? .DepthStencil : .RenderTarget),
|
||||
// TODO: CpuAccessFlags = (.)_description.CpuAccess,
|
||||
//CpuAccessFlags = (.)_description.CpuAccess,
|
||||
// 2D RenderTarget never has misc flags
|
||||
MiscFlags = .None,
|
||||
SampleDesc = .(_description.Samples, 0), // TODO: SampleQuality?
|
||||
// RenderTarget always has Default usage
|
||||
Usage = .Default
|
||||
};
|
||||
|
||||
ID3D11Texture2D* texture = null;
|
||||
var result = NativeDevice.CreateTexture2D(ref desc, null, &texture);
|
||||
Log.EngineLogger.Assert(result.Succeeded, "Failed to create RenderTarget2D");
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
private (ID3D11ShaderResourceView* ResourceView, ID3D11DeviceChild* TargetOrDepthView) CreateViews(TargetDescription target, ID3D11Texture2D* texture)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
ShaderResourceViewDescription svDesc = .();
|
||||
RenderTargetViewDescription rtDesc = .();
|
||||
DepthStencilViewDescription dsDesc = .();
|
||||
|
||||
svDesc.Format = target.Format.GetShaderViewFormat();
|
||||
rtDesc.Format = target.Format.GetTargetViewFormat();
|
||||
dsDesc.Format = target.Format.GetTargetViewFormat();
|
||||
|
||||
if (_description.ArraySize > 1)
|
||||
{
|
||||
if (_description.Samples > 1)
|
||||
{
|
||||
svDesc.ViewDimension = .Texture2DMultisampledArray;
|
||||
rtDesc.ViewDimension = .Texture2DArrayMultisample;
|
||||
dsDesc.ViewDimension = .Texture2DMultisampledArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
svDesc.ViewDimension = .Texture2DArray;
|
||||
rtDesc.ViewDimension = .Texture2DArray;
|
||||
dsDesc.ViewDimension = .Texture2DArray;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_description.Samples > 1)
|
||||
{
|
||||
svDesc.ViewDimension = .Texture2DMultisampled;
|
||||
rtDesc.ViewDimension = .Texture2DMultisample;
|
||||
dsDesc.ViewDimension = .Texture2DMultisampled;
|
||||
}
|
||||
else
|
||||
{
|
||||
svDesc.ViewDimension = .Texture2D;
|
||||
rtDesc.ViewDimension = .Texture2D;
|
||||
dsDesc.ViewDimension = .Texture2D;
|
||||
}
|
||||
}
|
||||
|
||||
svDesc.Description = .(svDesc.ViewDimension);
|
||||
rtDesc.Description = .(rtDesc.ViewDimension);
|
||||
dsDesc.Description = .(dsDesc.ViewDimension);
|
||||
|
||||
ID3D11ShaderResourceView* resourceView = null;
|
||||
ID3D11DeviceChild* targetOrDepthView = null;
|
||||
|
||||
var result = NativeDevice.CreateShaderResourceView(texture, &svDesc, &resourceView);
|
||||
Log.EngineLogger.Assert(result.Succeeded, "Failed to create resource view");
|
||||
|
||||
if (target.Format.IsDepth)
|
||||
result = NativeDevice.CreateDepthStencilView(texture, &dsDesc, (.)&targetOrDepthView);
|
||||
else
|
||||
result = NativeDevice.CreateRenderTargetView(texture, &rtDesc, (.)&targetOrDepthView);
|
||||
|
||||
Log.EngineLogger.Assert(result.Succeeded, "Failed to create render target view");
|
||||
|
||||
// TODO: UAVs
|
||||
|
||||
return (resourceView, targetOrDepthView);
|
||||
}
|
||||
|
||||
mixin DeleteContainerReleaseItemsAndNullify(var container)
|
||||
{
|
||||
if (container != null)
|
||||
{
|
||||
for (var tex in container)
|
||||
{
|
||||
tex.Release();
|
||||
}
|
||||
DeleteAndNullify!(container);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReleaseEveryThing()
|
||||
{
|
||||
DeleteContainerReleaseItemsAndNullify!(_nativeTextures);
|
||||
DeleteContainerReleaseItemsAndNullify!(_renderTargetViews);
|
||||
DeleteContainerReleaseItemsAndNullify!(_nativeResourceViews);
|
||||
|
||||
ReleaseAndNullify!(_nativeDepthTexture);
|
||||
ReleaseAndNullify!(_nativeDepthTargetView);
|
||||
ReleaseAndNullify!(_nativeDepthResourceView);
|
||||
}
|
||||
|
||||
public override void ApplyChanges()
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
ReleaseEveryThing();
|
||||
|
||||
if (_colorTargetDescriptions != null)
|
||||
{
|
||||
_nativeTextures = new .[_colorTargetDescriptions.Count];
|
||||
_renderTargetViews = new .[_colorTargetDescriptions.Count];
|
||||
_nativeResourceViews = new .[_colorTargetDescriptions.Count];
|
||||
|
||||
for (int i < _nativeTextures.Count)
|
||||
{
|
||||
TargetDescription target = _colorTargetDescriptions[i];
|
||||
|
||||
if (target.IsSwapchainTarget)
|
||||
{
|
||||
// TODO: if the engine supports multiple windows it has to support multiple swap chains.
|
||||
|
||||
// kinda dirty...
|
||||
var context = GraphicsContext.Get();
|
||||
|
||||
context.SwapChain.GetBackbuffer(out _nativeTextures[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_nativeTextures[i] = PlatformCreateTexture(target);
|
||||
}
|
||||
|
||||
(_nativeResourceViews[i], _renderTargetViews[i]) = (.)CreateViews(target, _nativeTextures[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (_depthTargetDescription.Format != .None)
|
||||
{
|
||||
_nativeDepthTexture = PlatformCreateTexture(_depthTargetDescription);
|
||||
|
||||
(_nativeDepthResourceView, _nativeDepthTargetView) = (.)CreateViews(_depthTargetDescription, _nativeDepthTexture);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Resize(uint32 width, uint32 height)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
_description.Width = width;
|
||||
_description.Height = height;
|
||||
|
||||
ApplyChanges();
|
||||
}
|
||||
|
||||
protected override TextureViewBinding PlatformGetViewBinding(int index)
|
||||
{
|
||||
if (index == -1)
|
||||
{
|
||||
return .(_nativeDepthResourceView, _depthSamplerState.nativeSamplerState);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.EngineLogger.AssertDebug(index < _nativeResourceViews.Count);
|
||||
|
||||
return .(_nativeResourceViews[index], _colorSamplerStates[index].nativeSamplerState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,13 +61,63 @@ namespace GlitchyEngine.Renderer
|
||||
NativeContext.ClearDepthStencilView(target.nativeView, flags, depth, stencil);
|
||||
}
|
||||
|
||||
public override void Clear(RenderTargetGroup renderTarget, ClearOptions options, ColorRGBA? color = null, float? depth = null, uint8? stencil = null)
|
||||
{
|
||||
if (options.HasFlag(.Color) && renderTarget._renderTargetViews != null)
|
||||
{
|
||||
for (int i < renderTarget._renderTargetViews.Count)
|
||||
{
|
||||
NativeContext.ClearRenderTargetView(renderTarget._renderTargetViews[i],
|
||||
color ?? renderTarget._colorTargetDescriptions[i].ClearColor);
|
||||
}
|
||||
}
|
||||
|
||||
if (renderTarget._nativeDepthTargetView != null)
|
||||
{
|
||||
DirectX.D3D11.ClearFlag flags = default;
|
||||
|
||||
if(options.HasFlag(.Depth))
|
||||
{
|
||||
flags |= .Depth;
|
||||
}
|
||||
|
||||
if(options.HasFlag(.Stencil))
|
||||
{
|
||||
flags |= .Stencil;
|
||||
}
|
||||
|
||||
if (flags != default)
|
||||
{
|
||||
NativeContext.ClearDepthStencilView(renderTarget._nativeDepthTargetView, flags,
|
||||
renderTarget._depthTargetDescription.ClearColor.R,
|
||||
(uint8)renderTarget._depthTargetDescription.ClearColor.G);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetRenderTarget(RenderTarget2D renderTarget, int slot, bool setDepthBuffer)
|
||||
{
|
||||
Debug.Profiler.ProfileRendererFunction!();
|
||||
|
||||
_context.SetRenderTarget(renderTarget, slot, setDepthBuffer);
|
||||
}
|
||||
|
||||
|
||||
public override void SetRenderTargetGroup(RenderTargetGroup renderTarget, bool setDepthBuffer)
|
||||
{
|
||||
if (renderTarget._renderTargetViews != null)
|
||||
{
|
||||
for (int i < renderTarget._renderTargetViews.Count)
|
||||
{
|
||||
_context.SetNativeRenderTargets(renderTarget._renderTargetViews, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (setDepthBuffer)
|
||||
{
|
||||
_context.SetNativeDepthStencilTarget(renderTarget._nativeDepthTargetView);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetDepthStencilTarget(DepthStencilTarget target)
|
||||
{
|
||||
Debug.Profiler.ProfileRendererFunction!();
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace GlitchyEngine.Renderer
|
||||
buffer.ReleaseRef();
|
||||
}
|
||||
case .Texture:
|
||||
_textures.Add(scope String(bindDesc.Name), bindDesc.BindPoint, null);
|
||||
_textures.Add(scope String(bindDesc.Name), bindDesc.BindPoint, TextureViewBinding(null, null));
|
||||
case .Sampler:
|
||||
// TODO: do we have to do something for samplers?
|
||||
default:
|
||||
|
||||
@@ -256,6 +256,11 @@ namespace GlitchyEngine.Renderer
|
||||
nativeTexture, D3D11.CalcSubresource(mipSlice, arraySlice, MipLevels), (.)&sourceBox);
|
||||
}
|
||||
}
|
||||
|
||||
protected override TextureViewBinding PlatformGetViewBinding()
|
||||
{
|
||||
return .(_nativeResourceView, _samplerState.nativeSamplerState);
|
||||
}
|
||||
}
|
||||
|
||||
extension TextureCube
|
||||
@@ -282,6 +287,11 @@ namespace GlitchyEngine.Renderer
|
||||
Log.EngineLogger.Assert(nativeDesc.MiscFlags.HasFlag(.TextureCube), scope $"The texture \"{_path}\" is not a texture cube.");
|
||||
// TODO: load fallback texture
|
||||
}
|
||||
|
||||
protected override TextureViewBinding PlatformGetViewBinding()
|
||||
{
|
||||
return .(_nativeResourceView, _samplerState.nativeSamplerState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using DirectX.D3D11;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
extension TextureViewBinding
|
||||
{
|
||||
internal ID3D11ShaderResourceView* _nativeShaderResourceView;
|
||||
internal ID3D11SamplerState* _nativeSamplerState;
|
||||
|
||||
public override bool IsEmpty => _nativeShaderResourceView != null;
|
||||
|
||||
internal this(ID3D11ShaderResourceView* shaderResourceView, ID3D11SamplerState* samplerState)
|
||||
{
|
||||
_nativeShaderResourceView = shaderResourceView;
|
||||
_nativeShaderResourceView?.AddRef();
|
||||
|
||||
_nativeSamplerState = samplerState;
|
||||
_nativeSamplerState?.AddRef();
|
||||
}
|
||||
|
||||
public override void AddRef()
|
||||
{
|
||||
_nativeShaderResourceView?.AddRef();
|
||||
_nativeSamplerState?.AddRef();
|
||||
}
|
||||
|
||||
public override void ReleaseRef()
|
||||
{
|
||||
_nativeShaderResourceView?.Release();
|
||||
_nativeSamplerState?.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user