CopyTextureExample

refresh2
cosmonaut 2024-06-06 11:14:24 -07:00
parent 2387a03e1d
commit 8258bb07a4
4 changed files with 187 additions and 182 deletions

View File

@ -0,0 +1,184 @@
using System.Runtime.InteropServices;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests
{
class CopyTextureExample : Example
{
private Texture OriginalTexture;
private Texture TextureCopy;
private Texture TextureSmall;
public override unsafe void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("CopyTexture");
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
OriginalTexture = resourceUploader.CreateTexture2DFromCompressed(
TestUtils.GetTexturePath("ravioli.png")
);
resourceUploader.Upload();
resourceUploader.Dispose();
// Load the texture bytes so we can compare them.
var pixels = ImageUtils.GetPixelDataFromFile(
TestUtils.GetTexturePath("ravioli.png"),
out var width,
out var height,
out var byteCount
);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
var textureCreateInfo = new TextureCreateInfo
{
Width = OriginalTexture.Width,
Height = OriginalTexture.Height,
Depth = OriginalTexture.Depth,
IsCube = OriginalTexture.IsCube,
LayerCount = OriginalTexture.LayerCount,
LevelCount = OriginalTexture.LevelCount,
SampleCount = OriginalTexture.SampleCount,
Format = OriginalTexture.Format,
UsageFlags = OriginalTexture.UsageFlags
};
// Create a 1:1 copy of the texture
TextureCopy = new Texture(GraphicsDevice, textureCreateInfo);
// Create a download transfer buffer
TransferBuffer compareBuffer = new TransferBuffer(
GraphicsDevice,
TransferUsage.Texture,
TransferBufferMapFlags.Read,
byteCount
);
var copyPass = cmdbuf.BeginCopyPass();
copyPass.CopyTextureToTexture(
OriginalTexture,
TextureCopy,
false
);
cmdbuf.EndCopyPass(copyPass);
// Create a half-sized copy of this texture
textureCreateInfo.Width /= 2;
textureCreateInfo.Height /= 2;
textureCreateInfo.UsageFlags |= TextureUsageFlags.ColorTarget;
TextureSmall = new Texture(GraphicsDevice, textureCreateInfo);
// Render the half-size copy
cmdbuf.Blit(OriginalTexture, TextureSmall, Filter.Linear, false);
// Copy the texture to a transfer buffer
copyPass = cmdbuf.BeginCopyPass();
copyPass.DownloadFromTexture(
TextureCopy,
compareBuffer,
new BufferImageCopy(0, 0, 0)
);
cmdbuf.EndCopyPass(copyPass);
var fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFence(fence);
GraphicsDevice.ReleaseFence(fence);
// Compare the original bytes to the copied bytes.
var copiedBytes = NativeMemory.Alloc(byteCount);
var copiedSpan = new System.Span<byte>(copiedBytes, (int) byteCount);
compareBuffer.GetData(copiedSpan);
var originalSpan = new System.Span<byte>(pixels, (int)byteCount);
if (System.MemoryExtensions.SequenceEqual(originalSpan, copiedSpan))
{
Logger.LogInfo("SUCCESS! Original texture bytes and the downloaded bytes match!");
}
else
{
Logger.LogError("FAIL! Original texture bytes do not match downloaded bytes!");
}
RefreshCS.Refresh.Refresh_Image_Free(pixels);
NativeMemory.Free(copiedBytes);
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var clearPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(swapchainTexture, false, Color.Black)
);
cmdbuf.EndRenderPass(clearPass);
cmdbuf.Blit(
OriginalTexture,
new TextureRegion
{
TextureSlice = swapchainTexture,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
cmdbuf.Blit(
TextureCopy,
new TextureRegion
{
TextureSlice = swapchainTexture,
X = swapchainTexture.Width / 2,
Y = 0,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
cmdbuf.Blit(
TextureSmall,
new TextureRegion
{
TextureSlice = swapchainTexture,
X = swapchainTexture.Width / 4,
Y = swapchainTexture.Height / 2,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
OriginalTexture.Dispose();
TextureCopy.Dispose();
TextureSmall.Dispose();
}
}
}

View File

@ -1,181 +0,0 @@
using System.Runtime.InteropServices;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests
{
class CopyTextureGame : Game
{
private GraphicsPipeline pipeline;
private GpuBuffer vertexBuffer;
private GpuBuffer indexBuffer;
private Texture originalTexture;
private Texture textureCopy;
private Texture textureSmallCopy;
private Sampler sampler;
public unsafe CopyTextureGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), TestUtils.PreferredBackends, 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions[0].BlendState = ColorAttachmentBlendState.AlphaBlend;
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create sampler
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
vertexBuffer = resourceUploader.CreateBuffer(
[
new PositionTextureVertex(new Vector3(-1f, 0f, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3( 0f, 0f, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3( 0f, 1f, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-1f, 1f, 0), new Vector2(0, 1)),
new PositionTextureVertex(new Vector3(0f, 0f, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3(1f, 0f, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3(1f, 1f, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(0f, 1f, 0), new Vector2(0, 1)),
new PositionTextureVertex(new Vector3(-0.5f, -1f, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3( 0.5f, -1f, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3( 0.5f, 0f, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-0.5f, 0f, 0), new Vector2(0, 1))
],
BufferUsageFlags.Vertex
);
indexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2,
0, 2, 3,
],
BufferUsageFlags.Index
);
originalTexture = resourceUploader.CreateTexture2DFromCompressed(
TestUtils.GetTexturePath("ravioli.png")
);
resourceUploader.Upload();
resourceUploader.Dispose();
// Load the texture bytes so we can compare them.
var pixels = ImageUtils.GetPixelDataFromFile(
TestUtils.GetTexturePath("ravioli.png"),
out var width,
out var height,
out var byteCount
);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
var textureCreateInfo = new TextureCreateInfo
{
Width = originalTexture.Width,
Height = originalTexture.Height,
Depth = originalTexture.Depth,
IsCube = originalTexture.IsCube,
LayerCount = originalTexture.LayerCount,
LevelCount = originalTexture.LevelCount,
SampleCount = originalTexture.SampleCount,
Format = originalTexture.Format,
UsageFlags = originalTexture.UsageFlags
};
// Create a 1:1 copy of the texture
textureCopy = new Texture(GraphicsDevice, textureCreateInfo);
cmdbuf.BeginCopyPass();
cmdbuf.CopyTextureToTexture(
originalTexture,
textureCopy,
WriteOptions.Unsafe
);
cmdbuf.EndCopyPass();
// Create a half-sized copy of this texture
textureCreateInfo.Width /= 2;
textureCreateInfo.Height /= 2;
textureCreateInfo.UsageFlags |= TextureUsageFlags.ColorTarget;
textureSmallCopy = new Texture(GraphicsDevice, textureCreateInfo);
// Render the half-size copy
cmdbuf.Blit(originalTexture, textureSmallCopy, Filter.Linear, WriteOptions.Unsafe);
var fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFences(fence);
GraphicsDevice.ReleaseFence(fence);
// Copy the texture to a transfer buffer
TransferBuffer compareBuffer = new TransferBuffer(GraphicsDevice, TransferUsage.Texture, byteCount);
GraphicsDevice.DownloadFromTexture(
textureCopy,
compareBuffer,
TransferOptions.Unsafe
);
// Compare the original bytes to the copied bytes.
var copiedBytes = NativeMemory.Alloc(byteCount);
var copiedSpan = new System.Span<byte>(copiedBytes, (int) byteCount);
compareBuffer.GetData(copiedSpan);
var originalSpan = new System.Span<byte>((void*) pixels, (int)byteCount);
if (System.MemoryExtensions.SequenceEqual(originalSpan, copiedSpan))
{
Logger.LogInfo("SUCCESS! Original texture bytes and the downloaded bytes match!");
}
else
{
Logger.LogError("FAIL! Original texture bytes do not match downloaded bytes!");
}
RefreshCS.Refresh.Refresh_Image_Free(pixels);
NativeMemory.Free(copiedBytes);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, WriteOptions.Cycle, Color.Black));
cmdbuf.BindGraphicsPipeline(pipeline);
cmdbuf.BindVertexBuffers(vertexBuffer);
cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(originalTexture, sampler));
cmdbuf.DrawIndexedPrimitives(0, 0, 2);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(textureCopy, sampler));
cmdbuf.DrawIndexedPrimitives(4, 0, 2);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(textureSmallCopy, sampler));
cmdbuf.DrawIndexedPrimitives(8, 0, 2);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
CopyTextureGame game = new CopyTextureGame();
game.Run();
}
}
}

View File

@ -31,6 +31,7 @@
<Compile Include="Examples\ClearScreen_MultiWindowExample.cs" /> <Compile Include="Examples\ClearScreen_MultiWindowExample.cs" />
<Compile Include="Examples\CompressedTexturesExample.cs" /> <Compile Include="Examples\CompressedTexturesExample.cs" />
<Compile Include="Examples\ComputeUniformsExample.cs" /> <Compile Include="Examples\ComputeUniformsExample.cs" />
<Compile Include="Examples\CopyTextureExample.cs" />
</ItemGroup> </ItemGroup>
<Import Project=".\CopyMoonlibs.targets" /> <Import Project=".\CopyMoonlibs.targets" />

View File

@ -14,7 +14,8 @@ class Program : Game
new BasicTriangleExample(), new BasicTriangleExample(),
new CompressedTexturesExample(), new CompressedTexturesExample(),
new BasicComputeExample(), new BasicComputeExample(),
new ComputeUniformsExample() new ComputeUniformsExample(),
new CopyTextureExample()
]; ];
int ExampleIndex = 0; int ExampleIndex = 0;