Skip to content

Commit

Permalink
Fix tests when staging textures/buffers are not zeroed at init
Browse files Browse the repository at this point in the history
  • Loading branch information
xoofx committed Jul 13, 2024
1 parent 6a11c8f commit 7325b67
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 8 deletions.
13 changes: 11 additions & 2 deletions src/XenoAtom.Graphics.Tests/ComputeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ public void ComputeCubemapBindSingleTextureMipLevelOutput()
MipLevels,
1,
PixelFormat.R8_G8_B8_A8_UNorm,
TextureUsage.Sampled | TextureUsage.Storage | TextureUsage.Cubemap);
TextureUsage.Sampled | TextureUsage.Storage | TextureUsage.Cubemap | TextureUsage.RenderTarget);
Texture computeOutput = GD.CreateTexture(texDesc);

TextureView computeOutputMipLevel = GD.CreateTextureView(new TextureViewDescription(computeOutput, BoundMipLevel, 1, 0, 1));
Expand All @@ -318,6 +318,16 @@ public void ComputeCubemapBindSingleTextureMipLevelOutput()
computeLayout,
32, 32, 1));

CommandList cl = GD.CreateCommandList();
cl.Begin();
cl.ClearTexture(computeOutput);
cl.End();
{
var fence = GD.CreateFence(false);
GD.SubmitCommands(cl, fence);
GD.WaitForFence(fence);
}

using (var readback = GetReadback(computeOutput))
{
for (uint mip = 0; mip < MipLevels; mip++)
Expand All @@ -338,7 +348,6 @@ public void ComputeCubemapBindSingleTextureMipLevelOutput()
}
}

CommandList cl = GD.CreateCommandList();
cl.Begin();
cl.SetPipeline(computePipeline);
cl.SetComputeResourceSet(0, computeSet);
Expand Down
2 changes: 2 additions & 0 deletions src/XenoAtom.Graphics.Tests/TextureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ public void CubeMap_Copy_MultipleMip_CopySingleMipFaces()

CommandList cl = GD.CreateCommandList();
cl.Begin();
cl.ClearTexture(dst); // Clear the dest texture otherwise we will get garbage in the assert below
for (uint face = 0; face < 6; face++)
cl.CopyTexture(src, dst, CopiedMip, face);
cl.End();
Expand Down Expand Up @@ -457,6 +458,7 @@ public void CubeMap_Copy_MultipleMip_SpecificArrayLayer()

CommandList cl = GD.CreateCommandList();
cl.Begin();
cl.ClearTexture(dst); // need to clear otherwise we get garbage as we copy only a specific layer
for (uint mip = 0; mip < MipLevels; mip++)
cl.CopyTexture(src, dst, mip, CopiedArrayLayer);
cl.End();
Expand Down
9 changes: 8 additions & 1 deletion src/XenoAtom.Graphics/CommandList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,13 @@ public void ClearColorTarget(uint index, RgbaFloat clearColor)

private protected abstract void ClearColorTargetCore(uint index, RgbaFloat clearColor);

public void ClearTexture(Texture texture)
{
ClearTextureCore(texture);
}

private protected abstract void ClearTextureCore(Texture texture);

/// <summary>
/// Clears the depth-stencil target of the active <see cref="Framebuffer"/>.
/// The active <see cref="Framebuffer"/> must have a depth attachment.
Expand Down Expand Up @@ -462,7 +469,7 @@ public void SetFullViewports()
{
throw new GraphicsException($"Cannot use {nameof(SetFullViewports)}. There is no Framebuffer bound.");
}

SetViewport(0, new Viewport(0, 0, _framebuffer.Width, _framebuffer.Height, 0, 1));

for (uint index = 1; index < _framebuffer.ColorTargets.Length; index++)
Expand Down
46 changes: 41 additions & 5 deletions src/XenoAtom.Graphics/Vk/VkCommandList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public VkCommandList(VkGraphicsDevice gd, in CommandListDescription description)
vkCmdBeginDebugUtilsLabelExt = manager.vkCmdBeginDebugUtilsLabelExt;
vkCmdEndDebugUtilsLabelExt = manager.vkCmdEndDebugUtilsLabelExt;
vkCmdInsertDebugUtilsLabelExt = manager.vkCmdInsertDebugUtilsLabelExt;

var poolCInfo = new VkCommandPoolCreateInfo
{
flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
Expand Down Expand Up @@ -215,6 +215,42 @@ private protected override void ClearColorTargetCore(uint index, RgbaFloat clear
}
}

private protected override void ClearTextureCore(Texture textureArg)
{
EnsureBegin();
var texture = Util.AssertSubtype<Texture, VkTexture>(textureArg);
if ((texture.Usage & TextureUsage.Staging) != 0)
{
var buffer = texture.StagingBuffer;
var ptr = Device.MemoryManager.Map(texture.Memory);
var span = new Span<byte>((byte*)ptr, (int)texture.Memory.Size);
span.Clear();
Device.MemoryManager.Unmap(texture.Memory);
}
else
{
uint effectiveLayers = texture.ArrayLayers;
if ((texture.Usage & TextureUsage.Cubemap) != 0)
{
effectiveLayers *= 6;
}

VkImageSubresourceRange range = new()
{
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
baseMipLevel = 0,
levelCount = texture.MipLevels,
baseArrayLayer = 0,
layerCount = effectiveLayers
};
VkClearColorValue color = default;
texture.TransitionImageLayout(_cb, 0, texture.MipLevels, 0, effectiveLayers, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
vkCmdClearColorImage(_cb, texture.OptimalDeviceImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (VkClearColorValue*)&color, 1, &range);
VkImageLayout colorLayout = texture.IsSwapchainTexture ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
texture.TransitionImageLayout(_cb, 0, texture.MipLevels, 0, effectiveLayers, colorLayout);
}
}

private protected override void ClearDepthStencilCore(float depth, byte stencil)
{
EnsureBegin();
Expand Down Expand Up @@ -740,7 +776,7 @@ protected override void SetComputeResourceSetCore(uint slot, ResourceSet rs, uin
public override void SetScissorRect(uint index, uint x, uint y, uint width, uint height)
{
EnsureBegin();

if (index == 0 || Device.Features.MultipleViewports)
{
VkRect2D scissor = new VkRect2D((int)x, (int)y, width, height);
Expand All @@ -755,7 +791,7 @@ public override void SetScissorRect(uint index, uint x, uint y, uint width, uint
public override void SetViewport(uint index, ref Viewport viewport)
{
EnsureBegin();

if (index == 0 || Device.Features.MultipleViewports)
{
float vpY = Device.IsClipSpaceYInverted
Expand Down Expand Up @@ -1373,7 +1409,7 @@ internal override void Destroy()
RecycleStagingInfo(_currentStagingInfo);
_currentStagingInfo = null;
}

vkDestroyCommandPool(Device, _pool, null);

Debug.Assert(_submittedStagingInfos.Count == 0);
Expand Down Expand Up @@ -1446,7 +1482,7 @@ private void EnsureComputePipeline()
throw new InvalidOperationException($"Invalid call. Current Compute Pipeline is not set. The `{nameof(SetPipeline)}` method should have been called before.");
}
}

private class StagingResourceInfo
{
public readonly List<VkBuffer> BuffersUsed = new ();
Expand Down

0 comments on commit 7325b67

Please sign in to comment.