RenderTargetGroup

This commit is contained in:
Simon Lübeß
2022-05-20 18:37:59 +02:00
parent 4cd0bff91d
commit 1418063d68
15 changed files with 667 additions and 53 deletions
@@ -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();
}
}
}