diff --git a/MoonWorks.csproj b/MoonWorks.csproj index 2e0eb18..a1e1f4e 100644 --- a/MoonWorks.csproj +++ b/MoonWorks.csproj @@ -26,8 +26,8 @@ - - MoonWorks.Graphics.StockShaders.VideoFullscreen.vert.refresh + + MoonWorks.Graphics.StockShaders.Fullscreen.vert.refresh MoonWorks.Graphics.StockShaders.VideoYUV2RGBA.frag.refresh @@ -38,5 +38,8 @@ MoonWorks.Graphics.StockShaders.TextMSDF.frag.refresh + + MoonWorks.Graphics.StockShaders.Blit.frag.refresh + diff --git a/src/Graphics/CommandBuffer.cs b/src/Graphics/CommandBuffer.cs index c53d5d0..e44d53b 100644 --- a/src/Graphics/CommandBuffer.cs +++ b/src/Graphics/CommandBuffer.cs @@ -87,6 +87,7 @@ namespace MoonWorks.Graphics ) { #if DEBUG AssertNotSubmitted(); + AssertNotInPass("Cannot begin a render pass inside another pass!"); AssertTextureNotNull(colorAttachmentInfo); AssertColorTarget(colorAttachmentInfo); #endif @@ -528,6 +529,7 @@ namespace MoonWorks.Graphics public void BeginComputePass() { #if DEBUG + AssertNotSubmitted(); AssertNotInPass("Cannot begin compute pass while in another pass!"); computePassActive = true; #endif @@ -1844,6 +1846,25 @@ namespace MoonWorks.Graphics #endif } + /// + /// Blits a texture to another texture with the specified filter. + /// + /// This operation cannot be performed inside any pass. + /// + public void Blit( + Texture source, + Texture destination, + Filter filter + ) { + var sampler = filter == Filter.Linear ? Device.LinearSampler : Device.PointSampler; + + BeginRenderPass(new ColorAttachmentInfo(destination)); + BindGraphicsPipeline(Device.BlitPipeline); + BindFragmentSamplers(new TextureSamplerBinding(source, sampler)); + DrawPrimitives(0, 2); + EndRenderPass(); + } + /// /// Acquires a swapchain texture. /// This texture will be presented to the given window when the command buffer is submitted. diff --git a/src/Graphics/GraphicsDevice.cs b/src/Graphics/GraphicsDevice.cs index 7293f02..ce7c865 100644 --- a/src/Graphics/GraphicsDevice.cs +++ b/src/Graphics/GraphicsDevice.cs @@ -22,6 +22,9 @@ namespace MoonWorks.Graphics // Built-in video pipeline internal GraphicsPipeline VideoPipeline { get; } + // Built-in blit pipeline + internal GraphicsPipeline BlitPipeline { get; } + // Built-in text shader info public GraphicsShaderInfo TextVertexShaderInfo { get; } public GraphicsShaderInfo TextFragmentShaderInfo { get; } @@ -57,32 +60,43 @@ namespace MoonWorks.Graphics // Check for replacement stock shaders string basePath = System.AppContext.BaseDirectory; - string videoVertPath = Path.Combine(basePath, "video_fullscreen.vert.refresh"); - string videoFragPath = Path.Combine(basePath, "video_yuv2rgba.frag.refresh"); + string fullscreenVertPath = Path.Combine(basePath, "fullscreen.vert.refresh"); string textVertPath = Path.Combine(basePath, "text_transform.vert.refresh"); string textFragPath = Path.Combine(basePath, "text_msdf.frag.refresh"); - ShaderModule videoVertShader; - ShaderModule videoFragShader; + string videoFragPath = Path.Combine(basePath, "video_yuv2rgba.frag.refresh"); + string blitFragPath = Path.Combine(basePath, "blit.frag.refresh"); + + ShaderModule fullscreenVertShader; ShaderModule textVertShader; ShaderModule textFragShader; - if (File.Exists(videoVertPath) && File.Exists(videoFragPath)) + ShaderModule videoFragShader; + ShaderModule blitFragShader; + + if (File.Exists(fullscreenVertPath)) + { + fullscreenVertShader = new ShaderModule(this, fullscreenVertPath); + } + else + { + // use defaults + var assembly = typeof(GraphicsDevice).Assembly; + using var vertStream = assembly.GetManifestResourceStream("MoonWorks.Graphics.StockShaders.Fullscreen.vert.refresh"); + fullscreenVertShader = new ShaderModule(this, vertStream); + } + + if (File.Exists(videoFragPath)) { - videoVertShader = new ShaderModule(this, videoVertPath); videoFragShader = new ShaderModule(this, videoFragPath); } else { // use defaults var assembly = typeof(GraphicsDevice).Assembly; - - using var vertStream = assembly.GetManifestResourceStream("MoonWorks.Graphics.StockShaders.VideoFullscreen.vert.refresh"); using var fragStream = assembly.GetManifestResourceStream("MoonWorks.Graphics.StockShaders.VideoYUV2RGBA.frag.refresh"); - - videoVertShader = new ShaderModule(this, vertStream); videoFragShader = new ShaderModule(this, fragStream); } @@ -103,6 +117,19 @@ namespace MoonWorks.Graphics textFragShader = new ShaderModule(this, fragStream); } + if (File.Exists(blitFragPath)) + { + blitFragShader = new ShaderModule(this, blitFragPath); + } + else + { + // use defaults + var assembly = typeof(GraphicsDevice).Assembly; + + using var fragStream = assembly.GetManifestResourceStream("MoonWorks.Graphics.StockShaders.Blit.frag.refresh"); + blitFragShader = new ShaderModule(this, fragStream); + } + VideoPipeline = new GraphicsPipeline( this, new GraphicsPipelineCreateInfo @@ -115,7 +142,7 @@ namespace MoonWorks.Graphics ), DepthStencilState = DepthStencilState.Disable, VertexShaderInfo = GraphicsShaderInfo.Create( - videoVertShader, + fullscreenVertShader, "main", 0 ), @@ -131,6 +158,34 @@ namespace MoonWorks.Graphics } ); + BlitPipeline = new GraphicsPipeline( + this, + new GraphicsPipelineCreateInfo + { + AttachmentInfo = new GraphicsPipelineAttachmentInfo( + new ColorAttachmentDescription( + TextureFormat.R8G8B8A8, + ColorAttachmentBlendState.None + ) + ), + DepthStencilState = DepthStencilState.Disable, + VertexShaderInfo = GraphicsShaderInfo.Create( + fullscreenVertShader, + "main", + 0 + ), + FragmentShaderInfo = GraphicsShaderInfo.Create( + blitFragShader, + "main", + 1 + ), + VertexInputState = VertexInputState.Empty, + RasterizerState = RasterizerState.CCW_CullNone, + PrimitiveType = PrimitiveType.TriangleList, + MultisampleState = MultisampleState.None + } + ); + TextVertexShaderInfo = GraphicsShaderInfo.Create(textVertShader, "main", 0); TextFragmentShaderInfo = GraphicsShaderInfo.Create(textFragShader, "main", 1); TextVertexInputState = VertexInputState.CreateSingleBinding(); diff --git a/src/Graphics/Resources/TransferBuffer.cs b/src/Graphics/Resources/TransferBuffer.cs index b93200d..bb94aa2 100644 --- a/src/Graphics/Resources/TransferBuffer.cs +++ b/src/Graphics/Resources/TransferBuffer.cs @@ -113,7 +113,7 @@ namespace MoonWorks.Graphics /// public unsafe void GetData( Span data, - uint bufferOffsetInBytes + uint bufferOffsetInBytes = 0 ) where T : unmanaged { var elementSize = Marshal.SizeOf(); diff --git a/src/Graphics/StockShaders/Binary/blit.frag.refresh b/src/Graphics/StockShaders/Binary/blit.frag.refresh new file mode 100644 index 0000000..ac3850a Binary files /dev/null and b/src/Graphics/StockShaders/Binary/blit.frag.refresh differ diff --git a/src/Graphics/StockShaders/Binary/video_fullscreen.vert.refresh b/src/Graphics/StockShaders/Binary/fullscreen.vert.refresh similarity index 100% rename from src/Graphics/StockShaders/Binary/video_fullscreen.vert.refresh rename to src/Graphics/StockShaders/Binary/fullscreen.vert.refresh diff --git a/src/Graphics/StockShaders/Source/blit.frag b/src/Graphics/StockShaders/Source/blit.frag new file mode 100644 index 0000000..de32fd1 --- /dev/null +++ b/src/Graphics/StockShaders/Source/blit.frag @@ -0,0 +1,12 @@ +#version 450 + +layout (location = 0) in vec2 TexCoord; + +layout (location = 0) out vec4 FragColor; + +layout (binding = 0, set = 1) uniform sampler2D TexSampler; + +void main() +{ + FragColor = texture(TexSampler, TexCoord); +} diff --git a/src/Graphics/StockShaders/Source/video_fullscreen.vert b/src/Graphics/StockShaders/Source/fullscreen.vert similarity index 100% rename from src/Graphics/StockShaders/Source/video_fullscreen.vert rename to src/Graphics/StockShaders/Source/fullscreen.vert