From 1832620a389d30fa627c32fa1138a450e3ecc11e Mon Sep 17 00:00:00 2001 From: Vasili Maslov Date: Sun, 16 Jan 2022 03:50:42 +0300 Subject: [PATCH] Supporting the BlendFactor in the D3D backend (#424) * Test on using the BlendFactor in a blend state. * #424. Supporting the BlendFactor in the D3D backend. --- src/Veldrid.Tests/RenderTests.cs | 112 ++++++++++++++++++++++++++ src/Veldrid/D3D11/D3D11CommandList.cs | 7 +- src/Veldrid/D3D11/D3D11Formats.cs | 2 +- src/Veldrid/D3D11/D3D11Pipeline.cs | 3 + 4 files changed, 121 insertions(+), 3 deletions(-) diff --git a/src/Veldrid.Tests/RenderTests.cs b/src/Veldrid.Tests/RenderTests.cs index 1d71d4bb2..6018d7fe6 100644 --- a/src/Veldrid.Tests/RenderTests.cs +++ b/src/Veldrid.Tests/RenderTests.cs @@ -1241,6 +1241,118 @@ public void WriteFragmentDepth() } GD.Unmap(readback); } + + [Fact] + public void UseBlendFactor() + { + const uint width = 512; + const uint height = 512; + using var output = RF.CreateTexture( + TextureDescription.Texture2D(width, height, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget)); + using var framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, output)); + + var yMod = GD.IsClipSpaceYInverted ? -1.0f : 1.0f; + var vertices = new[] + { + new ColoredVertex { Position = new Vector2(-1, 1 * yMod), Color = Vector4.One }, + new ColoredVertex { Position = new Vector2(1, 1 * yMod), Color = Vector4.One }, + new ColoredVertex { Position = new Vector2(-1, -1 * yMod), Color = Vector4.One }, + new ColoredVertex { Position = new Vector2(1, -1 * yMod), Color = Vector4.One } + }; + uint vertexSize = (uint)Unsafe.SizeOf(); + using var buffer = RF.CreateBuffer(new BufferDescription( + vertexSize * (uint)vertices.Length, + BufferUsage.StructuredBufferReadOnly, + vertexSize, + true)); + GD.UpdateBuffer(buffer, 0, vertices); + + using var graphicsLayout = RF.CreateResourceLayout(new ResourceLayoutDescription( + new ResourceLayoutElementDescription("InputVertices", ResourceKind.StructuredBufferReadOnly, ShaderStages.Vertex))); + using var graphicsSet = RF.CreateResourceSet(new ResourceSetDescription(graphicsLayout, buffer)); + + var blendDesc = new BlendStateDescription + { + BlendFactor = new RgbaFloat(0.25f, 0.5f, 0.75f, 1), + AttachmentStates = new[] + { + new BlendAttachmentDescription + { + BlendEnabled = true, + SourceColorFactor = BlendFactor.BlendFactor, + DestinationColorFactor = BlendFactor.Zero, + ColorFunction = BlendFunction.Add, + SourceAlphaFactor = BlendFactor.BlendFactor, + DestinationAlphaFactor = BlendFactor.Zero, + AlphaFunction = BlendFunction.Add + } + } + }; + var pipelineDesc = new GraphicsPipelineDescription( + blendDesc, + DepthStencilStateDescription.Disabled, + RasterizerStateDescription.Default, + PrimitiveTopology.TriangleStrip, + new ShaderSetDescription( + Array.Empty(), + TestShaders.LoadVertexFragment(RF, "ColoredQuadRenderer")), + graphicsLayout, + framebuffer.OutputDescription); + + using (var pipeline1 = RF.CreateGraphicsPipeline(pipelineDesc)) + using (var cl = RF.CreateCommandList()) + { + cl.Begin(); + cl.SetFramebuffer(framebuffer); + cl.ClearColorTarget(0, RgbaFloat.Clear); + cl.SetPipeline(pipeline1); + cl.SetGraphicsResourceSet(0, graphicsSet); + cl.Draw((uint)vertices.Length); + cl.End(); + GD.SubmitCommands(cl); + GD.WaitForIdle(); + } + + using (var readback = GetReadback(output)) + { + var readView = GD.Map(readback, MapMode.Read); + for (uint y = 0; y < height; y++) + for (uint x = 0; x < width; x++) + { + Assert.Equal(new RgbaFloat(0.25f, 0.5f, 0.75f, 1), readView[x, y]); + } + GD.Unmap(readback); + } + + blendDesc.BlendFactor = new RgbaFloat(0, 1, 0.5f, 0); + blendDesc.AttachmentStates[0].DestinationColorFactor = BlendFactor.InverseBlendFactor; + blendDesc.AttachmentStates[0].DestinationAlphaFactor = BlendFactor.InverseBlendFactor; + pipelineDesc.BlendState = blendDesc; + + using (var pipeline2 = RF.CreateGraphicsPipeline(pipelineDesc)) + using (var cl = RF.CreateCommandList()) + { + cl.Begin(); + cl.SetFramebuffer(framebuffer); + cl.SetPipeline(pipeline2); + cl.SetGraphicsResourceSet(0, graphicsSet); + cl.Draw((uint)vertices.Length); + cl.End(); + GD.SubmitCommands(cl); + GD.WaitForIdle(); + } + + using (var readback = GetReadback(output)) + { + var readView = GD.Map(readback, MapMode.Read); + for (uint y = 0; y < height; y++) + for (uint x = 0; x < width; x++) + { + Assert.Equal(new RgbaFloat(0.25f, 1, 0.875f, 1), readView[x, y]); + } + GD.Unmap(readback); + } + } } #if TEST_OPENGL diff --git a/src/Veldrid/D3D11/D3D11CommandList.cs b/src/Veldrid/D3D11/D3D11CommandList.cs index 5763658a6..e7f62e50e 100644 --- a/src/Veldrid/D3D11/D3D11CommandList.cs +++ b/src/Veldrid/D3D11/D3D11CommandList.cs @@ -35,6 +35,7 @@ internal class D3D11CommandList : CommandList private DeviceBuffer _ib; private uint _ibOffset; private ID3D11BlendState _blendState; + private Color4 _blendFactor; private ID3D11DepthStencilState _depthStencilState; private uint _stencilReference; private ID3D11RasterizerState _rasterizerState; @@ -237,10 +238,12 @@ private protected override void SetPipelineCore(Pipeline pipeline) Util.ClearArray(_invalidatedGraphicsResourceSets); ID3D11BlendState blendState = d3dPipeline.BlendState; - if (_blendState != blendState) + Color4 blendFactor = d3dPipeline.BlendFactor; + if (_blendState != blendState || _blendFactor != blendFactor) { _blendState = blendState; - _context.OMSetBlendState(blendState); + _blendFactor = blendFactor; + _context.OMSetBlendState(blendState, blendFactor); } ID3D11DepthStencilState depthStencilState = d3dPipeline.DepthStencilState; diff --git a/src/Veldrid/D3D11/D3D11Formats.cs b/src/Veldrid/D3D11/D3D11Formats.cs index 7f77f61c7..0428f050d 100644 --- a/src/Veldrid/D3D11/D3D11Formats.cs +++ b/src/Veldrid/D3D11/D3D11Formats.cs @@ -369,7 +369,7 @@ internal static Blend VdToD3D11Blend(BlendFactor factor) case BlendFactor.BlendFactor: return Blend.BlendFactor; case BlendFactor.InverseBlendFactor: - return Blend.BlendFactor; + return Blend.InverseBlendFactor; default: throw Illegal.Value(); } diff --git a/src/Veldrid/D3D11/D3D11Pipeline.cs b/src/Veldrid/D3D11/D3D11Pipeline.cs index bff19dd88..b22a0bac6 100644 --- a/src/Veldrid/D3D11/D3D11Pipeline.cs +++ b/src/Veldrid/D3D11/D3D11Pipeline.cs @@ -1,6 +1,7 @@ using Vortice.Direct3D11; using System.Diagnostics; using System; +using Vortice.Mathematics; namespace Veldrid.D3D11 { @@ -10,6 +11,7 @@ internal class D3D11Pipeline : Pipeline private bool _disposed; public ID3D11BlendState BlendState { get; } + public Color4 BlendFactor { get; } public ID3D11DepthStencilState DepthStencilState { get; } public uint StencilReference { get; } public ID3D11RasterizerState RasterizerState { get; } @@ -74,6 +76,7 @@ public D3D11Pipeline(D3D11ResourceCache cache, ref GraphicsPipelineDescription d out ID3D11InputLayout inputLayout); BlendState = blendState; + BlendFactor = new Color4(description.BlendState.BlendFactor.ToVector4()); DepthStencilState = depthStencilState; StencilReference = description.DepthStencilState.StencilReference; RasterizerState = rasterizerState;