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

View File

@ -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
}
/// <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>
/// Acquires a swapchain texture.
/// 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
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<Math.Float.Matrix4x4>(textVertShader, "main", 0);
TextFragmentShaderInfo = GraphicsShaderInfo.Create<float>(textFragShader, "main", 1);
TextVertexInputState = VertexInputState.CreateSingleBinding<Font.Vertex>();

View File

@ -113,7 +113,7 @@ namespace MoonWorks.Graphics
/// </summary>
public unsafe void GetData<T>(
Span<T> data,
uint bufferOffsetInBytes
uint bufferOffsetInBytes = 0
) where T : unmanaged
{
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);
}