2024-06-05 02:35:17 +00:00
|
|
|
using System.Runtime.InteropServices;
|
2024-06-05 19:34:24 +00:00
|
|
|
using RefreshCS;
|
2024-06-05 02:35:17 +00:00
|
|
|
|
|
|
|
namespace MoonWorks.Graphics;
|
|
|
|
|
|
|
|
public class CopyPass
|
|
|
|
{
|
|
|
|
public nint Handle { get; private set; }
|
|
|
|
|
|
|
|
internal void SetHandle(nint handle)
|
|
|
|
{
|
|
|
|
Handle = handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Uploads data from a TransferBuffer to a TextureSlice.
|
|
|
|
/// This copy occurs on the GPU timeline.
|
|
|
|
///
|
|
|
|
/// Overwriting the contents of the TransferBuffer before the command buffer
|
|
|
|
/// has finished execution will cause undefined behavior.
|
|
|
|
///
|
|
|
|
/// You MAY assume that the copy has finished for subsequent commands.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="cycle">If true, cycles the texture if the given slice is bound.</param>
|
|
|
|
public void UploadToTexture(
|
|
|
|
TransferBuffer transferBuffer,
|
|
|
|
in TextureRegion textureRegion,
|
|
|
|
in BufferImageCopy copyParams,
|
|
|
|
bool cycle
|
|
|
|
) {
|
|
|
|
#if DEBUG
|
|
|
|
AssertBufferBoundsCheck(transferBuffer.Size, copyParams.BufferOffset, textureRegion.Size);
|
|
|
|
#endif
|
|
|
|
|
2024-06-05 19:34:24 +00:00
|
|
|
Refresh.Refresh_UploadToTexture(
|
2024-06-05 02:35:17 +00:00
|
|
|
Handle,
|
|
|
|
transferBuffer.Handle,
|
2024-06-05 19:34:24 +00:00
|
|
|
textureRegion.ToRefresh(),
|
|
|
|
copyParams.ToRefresh(),
|
2024-06-05 02:35:17 +00:00
|
|
|
Conversions.BoolToInt(cycle)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Uploads the contents of an entire buffer to a 2D texture with no mips.
|
|
|
|
/// </summary>
|
|
|
|
public void UploadToTexture(
|
|
|
|
TransferBuffer transferBuffer,
|
|
|
|
Texture texture,
|
|
|
|
bool cycle
|
|
|
|
) {
|
|
|
|
UploadToTexture(
|
|
|
|
transferBuffer,
|
|
|
|
new TextureRegion(texture),
|
|
|
|
new BufferImageCopy(0, 0, 0),
|
|
|
|
cycle
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Uploads data from a TransferBuffer to a GpuBuffer.
|
|
|
|
/// This copy occurs on the GPU timeline.
|
|
|
|
///
|
|
|
|
/// Overwriting the contents of the TransferBuffer before the command buffer
|
|
|
|
/// has finished execution will cause undefined behavior.
|
|
|
|
///
|
|
|
|
/// You MAY assume that the copy has finished for subsequent commands.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="cycle">If true, cycles the buffer if it is bound.</param>
|
|
|
|
public void UploadToBuffer(
|
|
|
|
TransferBuffer transferBuffer,
|
|
|
|
GpuBuffer buffer,
|
|
|
|
in BufferCopy copyParams,
|
|
|
|
bool cycle
|
|
|
|
) {
|
|
|
|
#if DEBUG
|
|
|
|
AssertBufferBoundsCheck(transferBuffer.Size, copyParams.SrcOffset, copyParams.Size);
|
|
|
|
AssertBufferBoundsCheck(buffer.Size, copyParams.DstOffset, copyParams.Size);
|
|
|
|
#endif
|
|
|
|
|
2024-06-05 19:34:24 +00:00
|
|
|
Refresh.Refresh_UploadToBuffer(
|
2024-06-05 02:35:17 +00:00
|
|
|
Handle,
|
|
|
|
transferBuffer.Handle,
|
|
|
|
buffer.Handle,
|
2024-06-05 19:34:24 +00:00
|
|
|
copyParams.ToRefresh(),
|
2024-06-05 02:35:17 +00:00
|
|
|
Conversions.BoolToInt(cycle)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Copies the entire contents of a TransferBuffer to a GpuBuffer.
|
|
|
|
/// </summary>
|
|
|
|
public void UploadToBuffer(
|
|
|
|
TransferBuffer transferBuffer,
|
|
|
|
GpuBuffer buffer,
|
|
|
|
bool cycle
|
|
|
|
) {
|
|
|
|
UploadToBuffer(
|
|
|
|
transferBuffer,
|
|
|
|
buffer,
|
|
|
|
new BufferCopy(0, 0, transferBuffer.Size),
|
|
|
|
cycle
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Copies data element-wise into from a TransferBuffer to a GpuBuffer.
|
|
|
|
/// </summary>
|
|
|
|
public void UploadToBuffer<T>(
|
|
|
|
TransferBuffer transferBuffer,
|
|
|
|
GpuBuffer buffer,
|
|
|
|
uint sourceStartElement,
|
|
|
|
uint destinationStartElement,
|
|
|
|
uint numElements,
|
|
|
|
bool cycle
|
|
|
|
) where T : unmanaged
|
|
|
|
{
|
|
|
|
var elementSize = Marshal.SizeOf<T>();
|
|
|
|
var dataLengthInBytes = (uint) (elementSize * numElements);
|
|
|
|
var srcOffsetInBytes = (uint) (elementSize * sourceStartElement);
|
|
|
|
var dstOffsetInBytes = (uint) (elementSize * destinationStartElement);
|
|
|
|
|
|
|
|
UploadToBuffer(
|
|
|
|
transferBuffer,
|
|
|
|
buffer,
|
|
|
|
new BufferCopy(srcOffsetInBytes, dstOffsetInBytes, dataLengthInBytes),
|
|
|
|
cycle
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Copies the contents of a TextureRegion to another TextureRegion.
|
|
|
|
/// The regions must have the same dimensions.
|
|
|
|
/// This copy occurs on the GPU timeline.
|
|
|
|
///
|
|
|
|
/// You MAY assume that the copy has finished in subsequent commands.
|
|
|
|
/// </summary>
|
|
|
|
public void CopyTextureToTexture(
|
|
|
|
in TextureRegion source,
|
|
|
|
in TextureRegion destination,
|
|
|
|
bool cycle
|
|
|
|
) {
|
|
|
|
#if DEBUG
|
|
|
|
AssertTextureBoundsCheck(destination.Size, source.Size);
|
|
|
|
|
|
|
|
if (source.Width != destination.Width || source.Height != destination.Height || source.Depth != destination.Depth)
|
|
|
|
{
|
|
|
|
throw new System.InvalidOperationException("Texture copy must have the same dimensions!");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-06-05 19:34:24 +00:00
|
|
|
Refresh.Refresh_CopyTextureToTexture(
|
2024-06-05 02:35:17 +00:00
|
|
|
Handle,
|
2024-06-05 19:34:24 +00:00
|
|
|
source.ToRefresh(),
|
|
|
|
destination.ToRefresh(),
|
2024-06-05 02:35:17 +00:00
|
|
|
Conversions.BoolToInt(cycle)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Copies data from a GpuBuffer to another GpuBuffer.
|
|
|
|
/// This copy occurs on the GPU timeline.
|
|
|
|
///
|
|
|
|
/// You MAY assume that the copy has finished in subsequent commands.
|
|
|
|
/// </summary>
|
|
|
|
public void CopyBufferToBuffer(
|
|
|
|
GpuBuffer source,
|
|
|
|
GpuBuffer destination,
|
|
|
|
in BufferCopy copyParams,
|
|
|
|
bool cycle
|
|
|
|
) {
|
|
|
|
#if DEBUG
|
|
|
|
AssertBufferBoundsCheck(source.Size, copyParams.SrcOffset, copyParams.Size);
|
|
|
|
AssertBufferBoundsCheck(destination.Size, copyParams.DstOffset, copyParams.Size);
|
|
|
|
#endif
|
|
|
|
|
2024-06-05 19:34:24 +00:00
|
|
|
Refresh.Refresh_CopyBufferToBuffer(
|
2024-06-05 02:35:17 +00:00
|
|
|
Handle,
|
|
|
|
source.Handle,
|
|
|
|
destination.Handle,
|
2024-06-05 19:34:24 +00:00
|
|
|
copyParams.ToRefresh(),
|
2024-06-05 02:35:17 +00:00
|
|
|
Conversions.BoolToInt(cycle)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-06-05 21:19:17 +00:00
|
|
|
public void DownloadFromBuffer(
|
|
|
|
GpuBuffer buffer,
|
|
|
|
TransferBuffer transferBuffer,
|
|
|
|
in BufferCopy copyParams
|
|
|
|
) {
|
|
|
|
#if DEBUG
|
|
|
|
AssertBufferBoundsCheck(buffer.Size, copyParams.SrcOffset, copyParams.Size);
|
|
|
|
AssertBufferBoundsCheck(transferBuffer.Size, copyParams.DstOffset, copyParams.Size);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Refresh.Refresh_DownloadFromBuffer(
|
|
|
|
Handle,
|
|
|
|
buffer.Handle,
|
|
|
|
transferBuffer.Handle,
|
|
|
|
copyParams.ToRefresh()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void DownloadFromTexture(
|
|
|
|
in TextureRegion textureRegion,
|
|
|
|
TransferBuffer transferBuffer,
|
|
|
|
in BufferImageCopy copyParams
|
|
|
|
) {
|
|
|
|
#if DEBUG
|
|
|
|
AssertBufferBoundsCheck(transferBuffer.Size, copyParams.BufferOffset, textureRegion.Size);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Refresh.Refresh_DownloadFromTexture(
|
|
|
|
Handle,
|
|
|
|
textureRegion.ToRefresh(),
|
|
|
|
transferBuffer.Handle,
|
|
|
|
copyParams.ToRefresh()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-06-05 02:35:17 +00:00
|
|
|
#if DEBUG
|
|
|
|
private void AssertBufferBoundsCheck(uint bufferLengthInBytes, uint offsetInBytes, uint copyLengthInBytes)
|
|
|
|
{
|
|
|
|
if (copyLengthInBytes > bufferLengthInBytes + offsetInBytes)
|
|
|
|
{
|
|
|
|
throw new System.InvalidOperationException($"SetBufferData overflow! buffer length {bufferLengthInBytes}, offset {offsetInBytes}, copy length {copyLengthInBytes}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void AssertTextureBoundsCheck(uint textureSizeInBytes, uint dataLengthInBytes)
|
|
|
|
{
|
|
|
|
if (dataLengthInBytes > textureSizeInBytes)
|
|
|
|
{
|
|
|
|
throw new System.InvalidOperationException($"SetTextureData overflow! texture size {textureSizeInBytes}, data size {dataLengthInBytes}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|