built-in Blit operation

what_if_no_video_threads
cosmonaut 2024-02-23 12:39:59 -08:00
parent 8229e5dd33
commit 31c79d3179
8 changed files with 105 additions and 14 deletions

View File

@ -26,8 +26,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="src\Graphics\StockShaders\Binary\video_fullscreen.vert.refresh"> <EmbeddedResource Include="src\Graphics\StockShaders\Binary\fullscreen.vert.refresh">
<LogicalName>MoonWorks.Graphics.StockShaders.VideoFullscreen.vert.refresh</LogicalName> <LogicalName>MoonWorks.Graphics.StockShaders.Fullscreen.vert.refresh</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="src\Graphics\StockShaders\Binary\video_yuv2rgba.frag.refresh"> <EmbeddedResource Include="src\Graphics\StockShaders\Binary\video_yuv2rgba.frag.refresh">
<LogicalName>MoonWorks.Graphics.StockShaders.VideoYUV2RGBA.frag.refresh</LogicalName> <LogicalName>MoonWorks.Graphics.StockShaders.VideoYUV2RGBA.frag.refresh</LogicalName>
@ -38,5 +38,8 @@
<EmbeddedResource Include="src\Graphics\StockShaders\Binary\text_msdf.frag.refresh"> <EmbeddedResource Include="src\Graphics\StockShaders\Binary\text_msdf.frag.refresh">
<LogicalName>MoonWorks.Graphics.StockShaders.TextMSDF.frag.refresh</LogicalName> <LogicalName>MoonWorks.Graphics.StockShaders.TextMSDF.frag.refresh</LogicalName>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="src\Graphics\StockShaders\Binary\blit.frag.refresh">
<LogicalName>MoonWorks.Graphics.StockShaders.Blit.frag.refresh</LogicalName>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -87,6 +87,7 @@ namespace MoonWorks.Graphics
) { ) {
#if DEBUG #if DEBUG
AssertNotSubmitted(); AssertNotSubmitted();
AssertNotInPass("Cannot begin a render pass inside another pass!");
AssertTextureNotNull(colorAttachmentInfo); AssertTextureNotNull(colorAttachmentInfo);
AssertColorTarget(colorAttachmentInfo); AssertColorTarget(colorAttachmentInfo);
#endif #endif
@ -528,6 +529,7 @@ namespace MoonWorks.Graphics
public void BeginComputePass() public void BeginComputePass()
{ {
#if DEBUG #if DEBUG
AssertNotSubmitted();
AssertNotInPass("Cannot begin compute pass while in another pass!"); AssertNotInPass("Cannot begin compute pass while in another pass!");
computePassActive = true; computePassActive = true;
#endif #endif
@ -1844,6 +1846,25 @@ namespace MoonWorks.Graphics
#endif #endif
} }
/// <summary>
/// Blits a texture to another texture with the specified filter.
///
/// This operation cannot be performed inside any pass.
/// </summary>
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();
}
/// <summary> /// <summary>
/// Acquires a swapchain texture. /// Acquires a swapchain texture.
/// This texture will be presented to the given window when the command buffer is submitted. /// This texture will be presented to the given window when the command buffer is submitted.

View File

@ -22,6 +22,9 @@ namespace MoonWorks.Graphics
// Built-in video pipeline // Built-in video pipeline
internal GraphicsPipeline VideoPipeline { get; } internal GraphicsPipeline VideoPipeline { get; }
// Built-in blit pipeline
internal GraphicsPipeline BlitPipeline { get; }
// Built-in text shader info // Built-in text shader info
public GraphicsShaderInfo TextVertexShaderInfo { get; } public GraphicsShaderInfo TextVertexShaderInfo { get; }
public GraphicsShaderInfo TextFragmentShaderInfo { get; } public GraphicsShaderInfo TextFragmentShaderInfo { get; }
@ -57,32 +60,43 @@ namespace MoonWorks.Graphics
// Check for replacement stock shaders // Check for replacement stock shaders
string basePath = System.AppContext.BaseDirectory; string basePath = System.AppContext.BaseDirectory;
string videoVertPath = Path.Combine(basePath, "video_fullscreen.vert.refresh"); string fullscreenVertPath = Path.Combine(basePath, "fullscreen.vert.refresh");
string videoFragPath = Path.Combine(basePath, "video_yuv2rgba.frag.refresh");
string textVertPath = Path.Combine(basePath, "text_transform.vert.refresh"); string textVertPath = Path.Combine(basePath, "text_transform.vert.refresh");
string textFragPath = Path.Combine(basePath, "text_msdf.frag.refresh"); string textFragPath = Path.Combine(basePath, "text_msdf.frag.refresh");
ShaderModule videoVertShader; string videoFragPath = Path.Combine(basePath, "video_yuv2rgba.frag.refresh");
ShaderModule videoFragShader; string blitFragPath = Path.Combine(basePath, "blit.frag.refresh");
ShaderModule fullscreenVertShader;
ShaderModule textVertShader; ShaderModule textVertShader;
ShaderModule textFragShader; 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); videoFragShader = new ShaderModule(this, videoFragPath);
} }
else else
{ {
// use defaults // use defaults
var assembly = typeof(GraphicsDevice).Assembly; 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"); using var fragStream = assembly.GetManifestResourceStream("MoonWorks.Graphics.StockShaders.VideoYUV2RGBA.frag.refresh");
videoVertShader = new ShaderModule(this, vertStream);
videoFragShader = new ShaderModule(this, fragStream); videoFragShader = new ShaderModule(this, fragStream);
} }
@ -103,6 +117,19 @@ namespace MoonWorks.Graphics
textFragShader = new ShaderModule(this, fragStream); 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( VideoPipeline = new GraphicsPipeline(
this, this,
new GraphicsPipelineCreateInfo new GraphicsPipelineCreateInfo
@ -115,7 +142,7 @@ namespace MoonWorks.Graphics
), ),
DepthStencilState = DepthStencilState.Disable, DepthStencilState = DepthStencilState.Disable,
VertexShaderInfo = GraphicsShaderInfo.Create( VertexShaderInfo = GraphicsShaderInfo.Create(
videoVertShader, fullscreenVertShader,
"main", "main",
0 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<Math.Float.Matrix4x4>(textVertShader, "main", 0); TextVertexShaderInfo = GraphicsShaderInfo.Create<Math.Float.Matrix4x4>(textVertShader, "main", 0);
TextFragmentShaderInfo = GraphicsShaderInfo.Create<float>(textFragShader, "main", 1); TextFragmentShaderInfo = GraphicsShaderInfo.Create<float>(textFragShader, "main", 1);
TextVertexInputState = VertexInputState.CreateSingleBinding<Font.Vertex>(); TextVertexInputState = VertexInputState.CreateSingleBinding<Font.Vertex>();

View File

@ -113,7 +113,7 @@ namespace MoonWorks.Graphics
/// </summary> /// </summary>
public unsafe void GetData<T>( public unsafe void GetData<T>(
Span<T> data, Span<T> data,
uint bufferOffsetInBytes uint bufferOffsetInBytes = 0
) where T : unmanaged ) where T : unmanaged
{ {
var elementSize = Marshal.SizeOf<T>(); var elementSize = Marshal.SizeOf<T>();

Binary file not shown.

View File

@ -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);
}