RenderTargetGroup GetData, Shader uint support

This commit is contained in:
Simon Lübeß
2022-05-25 22:00:11 +02:00
parent 1418063d68
commit 28f1fad464
19 changed files with 354 additions and 44 deletions
+11 -3
View File
@@ -29,9 +29,17 @@ namespace ImGui
public static bool ColorPicker4(char* label, ref ColorRGBA col, ColorEditFlags flags = (ColorEditFlags) 0, float* ref_col = null) => ColorPicker4Impl(label, *(float[4]*)&col, flags, ref_col);
public static extern void Image(Texture2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero);
// Wouldn't be necesseary if RenderTarget2D was Texture2D
public static extern void Image(RenderTarget2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero);
public static void Image(Texture2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero)
{
Image(texture.GetViewBinding(), size, uv0, uv1, tint_col, border_col);
}
public static void Image(RenderTarget2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero)
{
Image(texture.GetViewBinding(), size, uv0, uv1, tint_col, border_col);
}
public static extern void Image(TextureViewBinding textureViewBinding, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero);
public static void TextUnformatted(StringView text) => TextUnformattedImpl(text.Ptr, text.Ptr + text.Length);
@@ -12,20 +12,14 @@ namespace ImGui
{
static List<ID3D11ShaderResourceView*> _resourceViews = new .() ~ delete _;
public static override void Image(Texture2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero)
public static override void Image(TextureViewBinding textureViewBinding, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero)
{
var view = texture._nativeResourceView..AddRef();
var view = textureViewBinding._nativeShaderResourceView..AddRef();
_resourceViews.Add(view);
ImGui.Image(view, size, uv0, uv1, tint_col, border_col);
}
public static override void Image(RenderTarget2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero)
{
var view = texture._nativeResourceView..AddRef();
_resourceViews.Add(view);
ImGui.Image(view, size, uv0, uv1, tint_col, border_col);
textureViewBinding.ReleaseRef();
}
protected internal static override void CleanupFrame()
@@ -37,6 +37,8 @@ namespace GlitchyEngine.Renderer
_type = .Float;
case .Int:
_type = .Int;
case .UInt:
_type = .UInt;
default:
Log.EngineLogger.Assert(false, scope $"Unhandled shader variable type: {shaderTypeDescription.Type}");
}
@@ -4,6 +4,7 @@ using DirectX.Common;
using DirectX.D3D11;
using GlitchyEngine.Platform.DX11;
using DirectX.DXGI.DXGI1_2;
using System;
using internal GlitchyEngine.Platform.DX11;
@@ -131,6 +132,11 @@ namespace GlitchyEngine.Renderer
{
switch(this)
{
case .R8_SInt:
return .R8_SInt;
case .R32_UInt:
return .R32_UInt;
case .R8G8B8A8_UNorm:
return .R8G8B8A8_UNorm;
case .R8G8B8A8_SNorm:
@@ -179,6 +185,7 @@ namespace GlitchyEngine.Renderer
extension RenderTargetGroup
{
protected uint32 _mipLevels;
internal ID3D11Texture2D*[] _nativeTextures;
internal ID3D11RenderTargetView*[] _renderTargetViews;
internal ID3D11ShaderResourceView*[] _nativeResourceViews;
@@ -218,6 +225,11 @@ namespace GlitchyEngine.Renderer
var result = NativeDevice.CreateTexture2D(ref desc, null, &texture);
Log.EngineLogger.Assert(result.Succeeded, "Failed to create RenderTarget2D");
// TODO: calculate the max mip level
// Read back the description to get the actual mip level count.
texture.GetDescription(let actualDesc);
_mipLevels = actualDesc.MipLevels;
return texture;
}
@@ -374,6 +386,63 @@ namespace GlitchyEngine.Renderer
return .(_nativeResourceViews[index], _colorSamplerStates[index].nativeSamplerState);
}
}
protected override Result<void> PlatformGetData(void* destination, uint32 elementSize, uint32 x, uint32 y, uint32 width, uint32 height, int renderTarget, uint32 arraySlice, uint32 mipLevel) // mapType?
{
Debug.Profiler.ProfileResourceFunction!();
ID3D11Texture2D* texture = renderTarget == -1 ? _nativeDepthTexture : _nativeTextures[renderTarget];
if (texture == null)
return .Err;
// TODO: Dynamic textures with CPU read access don't need a staging texture.
ID3D11Texture2D* stagingTexture = null;
Texture2DDescription stagingDesc = .();
stagingDesc.Width = width;
stagingDesc.Height = height;
stagingDesc.MipLevels = 1;
stagingDesc.ArraySize = 1;
stagingDesc.Format = _colorTargetDescriptions[renderTarget].Format.GetTextureFormat();
stagingDesc.SampleDesc = .(_description.Samples, 0);
stagingDesc.Usage = .Staging;
stagingDesc.BindFlags = .None;
stagingDesc.CpuAccessFlags = .Read;
stagingDesc.MiscFlags = .None;
var result = NativeDevice.CreateTexture2D(ref stagingDesc, null, &stagingTexture);
if (result != 0)
return .Err;
defer stagingTexture.Release();
uint32 srcSubResource = D3D11.CalcSubresource(mipLevel, arraySlice, _mipLevels);
Box srcBox = .(x, y, arraySlice, x + width, y + height, arraySlice + 1);
NativeContext.CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, texture, srcSubResource, &srcBox);
MappedSubresource subresource = ?;
result = NativeContext.Map(stagingTexture, 0, .Read, .None, &subresource);
defer NativeContext.Unmap(stagingTexture, 0);
if (result != 0)
return .Err;
for (int i < height)
{
uint32 destRowLength = elementSize * width;
uint32 count = Math.Min(destRowLength, subresource.RowPitch);
Internal.MemCpy((uint8*)destination + i * destRowLength, (uint8*)subresource.Data + i * subresource.RowPitch,
count);
}
return .Ok;
}
}
}
@@ -2,6 +2,7 @@
using GlitchyEngine.Math;
using GlitchyEngine.Platform.DX11;
using System;
using internal GlitchyEngine.Renderer;
using internal GlitchyEngine.Platform.DX11;
@@ -61,14 +62,31 @@ 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)
private void ClearRtv(DirectX.D3D11.ID3D11RenderTargetView* rtv, ClearColor clearColor)
{
switch(clearColor)
{
case .Color(let color):
NativeContext.ClearRenderTargetView(rtv, color);
case .UInt(let value):
/*#unwarn
NativeContext.OutputMerger.SetRenderTargets(1, &rtv, null);
BindRenderTargets();*/
default:
Runtime.NotImplemented();
}
}
public override void Clear(RenderTargetGroup renderTarget, ClearOptions options, ClearColor? 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);
ClearRtv(renderTarget._renderTargetViews[i], color ?? renderTarget._colorTargetDescriptions[i].ClearColor);
}
}
@@ -88,9 +106,24 @@ namespace GlitchyEngine.Renderer
if (flags != default)
{
NativeContext.ClearDepthStencilView(renderTarget._nativeDepthTargetView, flags,
renderTarget._depthTargetDescription.ClearColor.R,
(uint8)renderTarget._depthTargetDescription.ClearColor.G);
float clearDepth = 0.0f;
uint8 clearStencil = 0;
if (renderTarget._depthTargetDescription.ClearColor case .DepthStencil(let d, let s))
{
clearDepth = d;
clearStencil = s;
}
else
{
Log.EngineLogger.Error("Clear color of depth stencil target must be of type DepthStencil.");
Log.EngineLogger.AssertDebug(false);
}
clearDepth = depth ?? clearDepth;
clearStencil = stencil ?? clearStencil;
NativeContext.ClearDepthStencilView(renderTarget._nativeDepthTargetView, flags, clearDepth, clearStencil);
}
}
}
@@ -96,6 +96,9 @@ namespace GlitchyEngine.Renderer
case typeof(Int4):
EnsureTypeMatch(1, 4, .Int);
case typeof(uint32):
EnsureTypeMatch(1, 1, .UInt);
case typeof(Matrix4x3):
EnsureTypeMatch(4, 3, .Float);
case typeof(Matrix3x3):
@@ -102,6 +102,7 @@ namespace GlitchyEngine.Renderer
Bool,
Float,
Int,
UInt
// todo
}
}
@@ -0,0 +1,52 @@
namespace GlitchyEngine.Renderer
{
static class FullscreenQuad
{
//static GeometryBinding s_fullscreenQuadGeometry;
public static void Init()
{
/*s_fullscreenQuadGeometry = new GeometryBinding();
s_fullscreenQuadGeometry.SetPrimitiveTopology(.TriangleList);
using(var quadVertices = new VertexBuffer(typeof(Vector4), 4, .Immutable))
{
Vector4[4] vertices = .(
.(-1,-1, 0, 1),
.(-1, 1, 0, 0),
.( 1, 1, 1, 0),
.( 1,-1, 1, 1)
);
quadVertices.SetData(vertices);
s_fullscreenQuadGeometry.SetVertexBufferSlot(quadVertices, 0);
}
using(var quadIndices = new IndexBuffer(6, .Immutable))
{
uint16[6] indices = .(
0, 1, 2,
2, 3, 0
);
quadIndices.SetData(indices);
s_fullscreenQuadGeometry.SetIndexBuffer(quadIndices);
}
VertexElement[] vertexElements = new .(
VertexElement(.R32G32_Float, "POSITION"),
VertexElement(.R32G32_Float, "TEXCOORD")
);
using (var quadBatchLayout = new VertexLayout(vertexElements, true, TestFullscreenEffect.VertexShader))
{
s_fullscreenQuadGeometry.SetVertexLayout(quadBatchLayout);
}*/
}
public static void Deinit()
{
//s_fullscreenQuadGeometry.ReleaseRef();
}
}
}
+2
View File
@@ -132,6 +132,8 @@ namespace GlitchyEngine.Renderer
public void SetVariable(String name, Int3 value) => SetVariable<Int3>(name, value);
public void SetVariable(String name, Int4 value) => SetVariable<Int4>(name, value);
public void SetVariable(String name, uint32 value) => SetVariable<uint32>(name, value);
public void SetVariable(String name, Color value) => SetVariable<ColorRGBA>(name, value);
public void SetVariable(String name, ColorRGB value) => SetVariable<ColorRGB>(name, value);
public void SetVariable(String name, ColorRGBA value) => SetVariable<ColorRGBA>(name, value);
+34 -3
View File
@@ -88,6 +88,9 @@ namespace GlitchyEngine.Renderer
case None = 0;
case R8_SInt;
case R32_UInt;
case R8G8B8A8_UNorm;
case R8G8B8A8_SNorm;
@@ -104,6 +107,18 @@ namespace GlitchyEngine.Renderer
public bool IsDepth => HasFlag(DepthMarker);
}
public enum ClearColor
{
case Color(ColorRGBA ClearColor);
case UInt(uint32 ClearValue);
case DepthStencil(float Depth, uint8 Stencil);
public static implicit operator ClearColor(ColorRGBA color)
{
return .Color(color);
}
}
public struct TargetDescription
{
public RenderTargetFormat Format = .None;
@@ -113,13 +128,13 @@ namespace GlitchyEngine.Renderer
public bool IsShaderReadable = true;
/// Clear color. For DepthStencilBuffers: R is Depth, G is Stencil
public ColorRGBA ClearColor = .Black;
public ClearColor ClearColor = .Color(.Black);
public SamplerStateDescription SamplerDescription = .();
public this() { }
public this(RenderTargetFormat format, bool isSwapchainTarget = false, bool isShaderReadable = true, ColorRGBA clearColor = .Black, SamplerStateDescription samplerDescription = .())
public this(RenderTargetFormat format, bool isSwapchainTarget = false, bool isShaderReadable = true, ClearColor clearColor = .Color(.(0, 0, 0, 1)), SamplerStateDescription samplerDescription = .())
{
Format = format;
IsSwapchainTarget = isSwapchainTarget;
@@ -179,6 +194,9 @@ namespace GlitchyEngine.Renderer
{
_description = description;
Log.EngineLogger.AssertDebug(_description.Width != 0);
Log.EngineLogger.AssertDebug(_description.Height != 0);
var colorTargets = description.ColorTargetDescriptions;
if (!colorTargets.IsNull && !colorTargets.IsEmpty)
@@ -206,10 +224,12 @@ namespace GlitchyEngine.Renderer
}
_depthTargetDescription = description.DepthTargetDescription;
Log.EngineLogger.AssertDebug(_depthTargetDescription.Format.IsDepth, "Depth target must have depth format.");
if (_depthTargetDescription.Format != .None)
{
Log.EngineLogger.AssertDebug(_depthTargetDescription.Format.IsDepth, "Depth target must have depth format.");
Log.EngineLogger.AssertDebug(_depthTargetDescription.ClearColor case .DepthStencil, "Clear color for depth stencil target must be of type DepthStencil.");
_depthSamplerState = SamplerStateManager.GetSampler(_depthTargetDescription.SamplerDescription);
}
@@ -227,5 +247,16 @@ namespace GlitchyEngine.Renderer
}
protected extern TextureViewBinding PlatformGetViewBinding(int index);
protected extern Result<void> PlatformGetData(void* destination, uint32 elementSize,
uint32 x, uint32 y, uint32 width, uint32 height, int renderTarget, uint32 arraySlice, uint32 mipLevel); // mapType?
public Result<void> GetData<T>(T* data, int renderTarget, uint32 left, uint32 top, uint32 width, uint32 height, uint32 arraySlice = 0, uint32 mipSlice = 0)
{
Log.EngineLogger.AssertDebug(left + width < Width);
Log.EngineLogger.AssertDebug(top + height < Height);
return PlatformGetData(data, (.)sizeof(T), left, top, width, height, renderTarget, arraySlice, mipSlice);
}
}
}
+23 -9
View File
@@ -12,7 +12,7 @@ namespace GlitchyEngine.Renderer
public Matrix ViewProjection;
public Vector3 CameraPosition;
public RenderTarget2D CameraTarget;
public RenderTarget2D CompositionTarget;
public RenderTargetGroup CompositionTarget;
}
struct ObjectConstants
@@ -78,11 +78,12 @@ namespace GlitchyEngine.Renderer
.(RenderTargetFormat.R16G16B16A16_SNorm){SamplerDescription = desc},
.(RenderTargetFormat.R16G16B16A16_SNorm){SamplerDescription = desc},
.(RenderTargetFormat.R32G32B32A32_Float){SamplerDescription = desc},
.(RenderTargetFormat.R8G8B8A8_UNorm){SamplerDescription = desc}
.(RenderTargetFormat.R8G8B8A8_UNorm){SamplerDescription = desc},
.(RenderTargetFormat.R32_UInt){SamplerDescription = desc, ClearColor = ColorRGBA(0, 0, 0, 0)},
),
TargetDescription(.D24_UNorm_S8_UInt){
SamplerDescription = desc,
ClearColor = .(1.0f, 0, 0)
ClearColor = .DepthStencil(1.0f, 0)
});
Target = new RenderTargetGroup(targetDesc);
}
@@ -167,6 +168,7 @@ namespace GlitchyEngine.Renderer
RenderCommand.Init();
Renderer2D.Init();
FullscreenQuad.Init();
InitLineRenderer(effectLibrary);
InitDeferredRenderer(effectLibrary);
@@ -179,7 +181,8 @@ namespace GlitchyEngine.Renderer
DeinitDeferredRenderer();
DeinitLineRenderer();
FullscreenQuad.Deinit();
Renderer2D.Deinit();
_context.ReleaseRef();
@@ -303,7 +306,7 @@ namespace GlitchyEngine.Renderer
//_sceneConstants.Update();
}
public static void BeginScene(Camera camera, Matrix transform, RenderTarget2D renderTarget, RenderTarget2D finalTarget)
public static void BeginScene(Camera camera, Matrix transform, RenderTarget2D renderTarget, RenderTargetGroup finalTarget)
{
Debug.Profiler.ProfileRendererFunction!();
@@ -314,7 +317,7 @@ namespace GlitchyEngine.Renderer
_sceneConstants.CompositionTarget = finalTarget;
}
public static void BeginScene(EditorCamera camera, RenderTarget2D finalTarget)
public static void BeginScene(EditorCamera camera, RenderTargetGroup finalTarget)
{
Debug.Profiler.ProfileRendererFunction!();
@@ -390,6 +393,8 @@ namespace GlitchyEngine.Renderer
entry.Material.SetVariable("Transform", entry.Transform);
entry.Material.SetVariable("EntityId", entry.EntityId);
Matrix3x3 mat = (Matrix3x3)(entry.Transform).Invert().Transpose();
entry.Material.SetVariable("Transform_InvT", mat);
}
@@ -446,7 +451,7 @@ namespace GlitchyEngine.Renderer
RenderCommand.SetBlendState(_gBufferBlend);
RenderCommand.SetRenderTarget(_sceneConstants.CompositionTarget, 0, false);
RenderCommand.SetRenderTargetGroup(_sceneConstants.CompositionTarget, true);
RenderCommand.BindRenderTargets();
// TODO: Postprocessing effects
@@ -491,12 +496,14 @@ namespace GlitchyEngine.Renderer
public GeometryBinding Mesh;
public Material Material;
public Matrix Transform;
public uint32 EntityId;
public this(GeometryBinding mesh, Material material, Matrix transform)
public this(GeometryBinding mesh, Material material, Matrix transform, uint32 id)
{
Mesh = mesh..AddRef();
Material = material..AddRef();
Transform = transform;
EntityId = id;
}
public void Dispose()
@@ -525,7 +532,14 @@ namespace GlitchyEngine.Renderer
{
Debug.Profiler.ProfileRendererFunction!();
_queue.Add(SubmittedMesh(geometry, material, transform));
_queue.Add(SubmittedMesh(geometry, material, transform, 0));
}
public static void Submit(GeometryBinding geometry, Material material, EcsEntity entity, Matrix transform = .Identity)
{
Debug.Profiler.ProfileRendererFunction!();
_queue.Add(SubmittedMesh(geometry, material, transform, entity.[Friend]Index));
}
public static void Submit(SceneLight light, Matrix transform = .Identity)
+2 -1
View File
@@ -21,7 +21,8 @@ namespace GlitchyEngine.Renderer
public extern void Clear(DepthStencilTarget target, ClearOptions options, float depth, uint8 stencil);
public extern void Clear(RenderTargetGroup renderTarget, ClearOptions options, ColorRGBA? color = null, float? depth = null, uint8? stencil = null);
//public extern void Clear(RenderTargetGroup renderTarget, ClearOptions options, ColorRGBA? color = null, float? depth = null, uint8? stencil = null);
public extern void Clear(RenderTargetGroup renderTarget, ClearOptions options, ClearColor? color = null, float? depth = null, uint8? stencil = null);
public void Clear(RenderTarget2D renderTarget, ClearOptions options, ColorRGBA color, float depth, uint8 stencil)
{
+24 -2
View File
@@ -8,7 +8,7 @@ namespace GlitchyEngine.World
{
public class EcsWorld
{
const int MaxEntities = 1024;
const int MaxEntities = 16348;
internal typealias BitmaskEntry = (EcsEntity ID, BitArray ComponentMask);
internal List<BitmaskEntry> _entities = new .();
@@ -149,6 +149,28 @@ namespace GlitchyEngine.World
}
}
/// Returns whether the given entity is valid or not.
public bool IsValid(EcsEntity entity)
{
if(entity.Index > _entities.Count)
return false;
var listEntity = ref _entities[entity.Index];
return entity == listEntity.ID;
}
/// Returns the entity with the same ID and the current version. Or null, if no such entity exists.
public EcsEntity? GetCurrentVersion(EcsEntity entity)
{
if(entity.Index > _entities.Count)
return null;
var listEntity = ref _entities[entity.Index];
return listEntity.ID;
}
/**
* Assigns a component of type T to the specified entity and returns it.
*/
@@ -208,7 +230,7 @@ namespace GlitchyEngine.World
listEntity.ComponentMask[entry.Id] = false;
}
public void RemoveComponent<T>(EcsEntity entity) where T : struct, new, IDisposableComponent
{
if(entity.Index > _entities.Count)
+3 -3
View File
@@ -48,7 +48,7 @@ namespace GlitchyEngine.World
{
}
public void UpdateRuntime(GameTime gameTime, RenderTarget2D finalTarget)
public void UpdateRuntime(GameTime gameTime, RenderTargetGroup finalTarget)
{
Debug.Profiler.ProfileRendererFunction!();
@@ -111,7 +111,7 @@ namespace GlitchyEngine.World
}
}
public void UpdateEditor(GameTime gameTime, EditorCamera camera, RenderTarget2D viewportTarget, delegate void() DebugDraw3D, delegate void() DrawDebug2D)
public void UpdateEditor(GameTime gameTime, EditorCamera camera, RenderTargetGroup viewportTarget, delegate void() DebugDraw3D, delegate void() DrawDebug2D)
{
Debug.Profiler.ProfileRendererFunction!();
@@ -124,7 +124,7 @@ namespace GlitchyEngine.World
for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
{
Renderer.Submit(mesh.Mesh, meshRenderer.Material, transform.WorldTransform);
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
}
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())