Compare commits
14 Commits
178a5ea3cf
...
9195e445b2
Author | SHA1 | Date |
---|---|---|
|
9195e445b2 | |
|
f30d8f0197 | |
|
bde31fbe07 | |
|
a762a80c4f | |
|
099c07aa39 | |
|
cba6ca59d3 | |
|
a004488f81 | |
|
33ed8b2364 | |
|
3c832550d0 | |
|
c84752f38c | |
|
019afa91f5 | |
|
00adec189c | |
|
0e723514df | |
|
e0f4c19dc2 |
|
@ -3,7 +3,6 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<LangVersion>11</LangVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2e346d84016fb7b26dbe7c5b6c485109571c30f4
|
Subproject commit 029f19196a94e13b8ed98d10f47a701221951f2f
|
|
@ -53,10 +53,10 @@ namespace MoonWorks
|
||||||
public Game(
|
public Game(
|
||||||
WindowCreateInfo windowCreateInfo,
|
WindowCreateInfo windowCreateInfo,
|
||||||
FrameLimiterSettings frameLimiterSettings,
|
FrameLimiterSettings frameLimiterSettings,
|
||||||
|
Span<Backend> preferredBackends,
|
||||||
int targetTimestep = 60,
|
int targetTimestep = 60,
|
||||||
bool debugMode = false
|
bool debugMode = false
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
Logger.LogInfo("Initializing frame limiter...");
|
Logger.LogInfo("Initializing frame limiter...");
|
||||||
Timestep = TimeSpan.FromTicks(TimeSpan.TicksPerSecond / targetTimestep);
|
Timestep = TimeSpan.FromTicks(TimeSpan.TicksPerSecond / targetTimestep);
|
||||||
gameTimer = Stopwatch.StartNew();
|
gameTimer = Stopwatch.StartNew();
|
||||||
|
@ -82,7 +82,7 @@ namespace MoonWorks
|
||||||
|
|
||||||
Logger.LogInfo("Initializing graphics device...");
|
Logger.LogInfo("Initializing graphics device...");
|
||||||
GraphicsDevice = new GraphicsDevice(
|
GraphicsDevice = new GraphicsDevice(
|
||||||
Backend.Vulkan,
|
preferredBackends,
|
||||||
debugMode
|
debugMode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
namespace MoonWorks.Graphics
|
using RefreshCS;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A buffer-offset pair to be used when binding vertex buffers.
|
/// A buffer-offset pair to be used when binding vertex or index buffers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct BufferBinding
|
public readonly record struct BufferBinding(
|
||||||
{
|
GpuBuffer Buffer,
|
||||||
public GpuBuffer Buffer;
|
uint Offset
|
||||||
public ulong Offset;
|
) {
|
||||||
|
public Refresh.BufferBinding ToRefresh()
|
||||||
public BufferBinding(GpuBuffer buffer, ulong offset)
|
|
||||||
{
|
{
|
||||||
Buffer = buffer;
|
return new Refresh.BufferBinding
|
||||||
Offset = offset;
|
{
|
||||||
|
gpuBuffer = Buffer.Handle,
|
||||||
|
offset = Offset
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
using RefreshCS;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Binding specification to be used when binding buffers for compute shaders.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="GpuBuffer">The GpuBuffer to bind.</param>
|
||||||
|
/// <param name="WriteOption">
|
||||||
|
/// Specifies data dependency behavior when this buffer is written to in the shader. <br/>
|
||||||
|
///
|
||||||
|
/// Cycle:
|
||||||
|
/// If this buffer has been used in commands that have not finished,
|
||||||
|
/// the implementation may choose to prevent a dependency on those commands
|
||||||
|
/// at the cost of increased memory usage.
|
||||||
|
/// You may NOT assume that any of the previous data is retained.
|
||||||
|
/// This may prevent stalls when frequently updating a resource. <br />
|
||||||
|
///
|
||||||
|
/// SafeOverwrite:
|
||||||
|
/// Overwrites the data safely using a GPU memory barrier.
|
||||||
|
/// </param>
|
||||||
|
public readonly record struct ComputeBufferBinding(
|
||||||
|
GpuBuffer GpuBuffer,
|
||||||
|
WriteOptions WriteOption
|
||||||
|
) {
|
||||||
|
public Refresh.ComputeBufferBinding ToRefresh()
|
||||||
|
{
|
||||||
|
return new Refresh.ComputeBufferBinding
|
||||||
|
{
|
||||||
|
gpuBuffer = GpuBuffer.Handle,
|
||||||
|
writeOption = (Refresh.WriteOptions) WriteOption
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
using RefreshCS;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Binding specification used for binding texture slices for compute shaders.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="TextureSlice">The TextureSlice to bind.</param>
|
||||||
|
/// <param name="WriteOption">
|
||||||
|
/// Specifies data dependency behavior when this texture is written to in the shader. <br/>
|
||||||
|
///
|
||||||
|
/// Cycle:
|
||||||
|
/// If this buffer has been used in commands that have not finished,
|
||||||
|
/// the implementation may choose to prevent a dependency on those commands
|
||||||
|
/// at the cost of increased memory usage.
|
||||||
|
/// You may NOT assume that any of the previous data is retained.
|
||||||
|
/// This may prevent stalls when frequently updating a resource. <br />
|
||||||
|
///
|
||||||
|
/// SafeOverwrite:
|
||||||
|
/// Overwrites the data safely using a GPU memory barrier.
|
||||||
|
/// </param>
|
||||||
|
public readonly record struct ComputeTextureBinding(
|
||||||
|
TextureSlice TextureSlice,
|
||||||
|
WriteOptions WriteOption
|
||||||
|
) {
|
||||||
|
public Refresh.ComputeTextureBinding ToRefresh()
|
||||||
|
{
|
||||||
|
return new Refresh.ComputeTextureBinding
|
||||||
|
{
|
||||||
|
textureSlice = TextureSlice.ToRefreshTextureSlice(),
|
||||||
|
writeOption = (Refresh.WriteOptions) WriteOption
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
namespace MoonWorks.Graphics
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A texture-level pair to be used when binding compute textures.
|
|
||||||
/// </summary>
|
|
||||||
public struct TextureLevelBinding
|
|
||||||
{
|
|
||||||
public Texture Texture;
|
|
||||||
public uint MipLevel;
|
|
||||||
|
|
||||||
public TextureLevelBinding(Texture texture, uint mipLevel = 0)
|
|
||||||
{
|
|
||||||
Texture = texture;
|
|
||||||
MipLevel = mipLevel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +1,21 @@
|
||||||
namespace MoonWorks.Graphics
|
using RefreshCS;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A texture-sampler pair to be used when binding samplers.
|
/// A texture-sampler pair to be used when binding samplers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct TextureSamplerBinding
|
public readonly record struct TextureSamplerBinding(
|
||||||
{
|
Texture Texture,
|
||||||
public Texture Texture;
|
Sampler Sampler
|
||||||
public Sampler Sampler;
|
) {
|
||||||
|
public Refresh.TextureSamplerBinding ToRefresh()
|
||||||
public TextureSamplerBinding(Texture texture, Sampler sampler)
|
|
||||||
{
|
{
|
||||||
Texture = texture;
|
return new Refresh.TextureSamplerBinding
|
||||||
Sampler = sampler;
|
{
|
||||||
|
texture = Texture.Handle,
|
||||||
|
sampler = Sampler.Handle
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -49,24 +49,12 @@ namespace MoonWorks.Graphics.Font
|
||||||
|
|
||||||
var imagePath = Path.ChangeExtension(fontPath, ".png");
|
var imagePath = Path.ChangeExtension(fontPath, ".png");
|
||||||
ImageUtils.ImageInfoFromFile(imagePath, out var width, out var height, out var sizeInBytes);
|
ImageUtils.ImageInfoFromFile(imagePath, out var width, out var height, out var sizeInBytes);
|
||||||
var texture = Texture.CreateTexture2D(graphicsDevice, width, height, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler);
|
|
||||||
|
|
||||||
var transferBuffer = new TransferBuffer(graphicsDevice, sizeInBytes);
|
var uploader = new ResourceUploader(graphicsDevice);
|
||||||
ImageUtils.DecodeIntoTransferBuffer(
|
var texture = uploader.CreateTexture2DFromCompressed(imagePath);
|
||||||
imagePath,
|
uploader.Upload();
|
||||||
transferBuffer,
|
uploader.Dispose();
|
||||||
0,
|
|
||||||
SetDataOptions.Overwrite
|
|
||||||
);
|
|
||||||
|
|
||||||
commandBuffer.BeginCopyPass();
|
|
||||||
commandBuffer.UploadToTexture(
|
|
||||||
transferBuffer,
|
|
||||||
texture
|
|
||||||
);
|
|
||||||
commandBuffer.EndCopyPass();
|
|
||||||
|
|
||||||
transferBuffer.Dispose();
|
|
||||||
NativeMemory.Free(fontFileByteBuffer);
|
NativeMemory.Free(fontFileByteBuffer);
|
||||||
NativeMemory.Free(atlasFileByteBuffer);
|
NativeMemory.Free(atlasFileByteBuffer);
|
||||||
|
|
||||||
|
|
|
@ -124,11 +124,11 @@ namespace MoonWorks.Graphics.Font
|
||||||
|
|
||||||
if (vertexDataLengthInBytes > 0 && indexDataLengthInBytes > 0)
|
if (vertexDataLengthInBytes > 0 && indexDataLengthInBytes > 0)
|
||||||
{
|
{
|
||||||
TransferBuffer.SetData(vertexSpan, SetDataOptions.Discard);
|
TransferBuffer.SetData(vertexSpan, TransferOptions.Cycle);
|
||||||
TransferBuffer.SetData(indexSpan, (uint) vertexSpan.Length, SetDataOptions.Overwrite);
|
TransferBuffer.SetData(indexSpan, (uint) vertexSpan.Length, TransferOptions.Overwrite);
|
||||||
|
|
||||||
commandBuffer.UploadToBuffer(TransferBuffer, VertexBuffer, new BufferCopy(0, 0, (uint) vertexSpan.Length));
|
commandBuffer.UploadToBuffer(TransferBuffer, VertexBuffer, new BufferCopy(0, 0, (uint) vertexSpan.Length), WriteOptions.Cycle);
|
||||||
commandBuffer.UploadToBuffer(TransferBuffer, IndexBuffer, new BufferCopy((uint) vertexSpan.Length, 0, (uint) indexSpan.Length));
|
commandBuffer.UploadToBuffer(TransferBuffer, IndexBuffer, new BufferCopy((uint) vertexSpan.Length, 0, (uint) indexSpan.Length), WriteOptions.Cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimitiveCount = vertexCount / 2;
|
PrimitiveCount = vertexCount / 2;
|
||||||
|
|
|
@ -40,11 +40,17 @@ namespace MoonWorks.Graphics
|
||||||
private FencePool FencePool;
|
private FencePool FencePool;
|
||||||
private CommandBufferPool CommandBufferPool;
|
private CommandBufferPool CommandBufferPool;
|
||||||
|
|
||||||
internal GraphicsDevice(
|
internal unsafe GraphicsDevice(
|
||||||
Backend preferredBackend,
|
Span<Backend> preferredBackends,
|
||||||
bool debugMode
|
bool debugMode
|
||||||
) {
|
) {
|
||||||
Backend = (Backend) Refresh.Refresh_SelectBackend((Refresh.Backend) preferredBackend, out windowFlags);
|
var backends = stackalloc Refresh.Backend[preferredBackends.Length];
|
||||||
|
for (var i = 0; i < preferredBackends.Length; i += 1)
|
||||||
|
{
|
||||||
|
backends[i] = (Refresh.Backend) preferredBackends[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend = (Backend) Refresh.Refresh_SelectBackend(backends, (uint) preferredBackends.Length, out windowFlags);
|
||||||
|
|
||||||
if (Backend == Backend.Invalid)
|
if (Backend == Backend.Invalid)
|
||||||
{
|
{
|
||||||
|
@ -467,6 +473,118 @@ namespace MoonWorks.Graphics
|
||||||
FencePool.Return(fence);
|
FencePool.Return(fence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ⚠️⚠️⚠️ <br/>
|
||||||
|
/// Downloads data from a Texture to a TransferBuffer.
|
||||||
|
/// This copy occurs immediately on the CPU timeline.<br/>
|
||||||
|
///
|
||||||
|
/// If you modify this texture in a command buffer and then call this function without calling
|
||||||
|
/// SubmitAndAcquireFence and WaitForFences first, the results will not be what you expect.<br/>
|
||||||
|
///
|
||||||
|
/// This method forces a sync point and is generally a bad thing to do.
|
||||||
|
/// Only use it if you have exhausted all other options.<br/>
|
||||||
|
///
|
||||||
|
/// Remember: friends don't let friends readback.<br/>
|
||||||
|
/// ⚠️⚠️⚠️
|
||||||
|
/// </summary>
|
||||||
|
public void DownloadFromTexture(
|
||||||
|
in TextureRegion textureRegion,
|
||||||
|
TransferBuffer transferBuffer,
|
||||||
|
in BufferImageCopy copyParams,
|
||||||
|
TransferOptions transferOption
|
||||||
|
) {
|
||||||
|
Refresh.Refresh_DownloadFromTexture(
|
||||||
|
Handle,
|
||||||
|
textureRegion.ToRefreshTextureRegion(),
|
||||||
|
transferBuffer.Handle,
|
||||||
|
copyParams.ToRefresh(),
|
||||||
|
(Refresh.TransferOptions) transferOption
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ⚠️⚠️⚠️ <br/>
|
||||||
|
/// Downloads all data from a 2D texture with no mips to a TransferBuffer.
|
||||||
|
/// This copy occurs immediately on the CPU timeline.<br/>
|
||||||
|
///
|
||||||
|
/// If you modify this texture in a command buffer and then call this function without calling
|
||||||
|
/// SubmitAndAcquireFence and WaitForFences first, the results will not be what you expect.<br/>
|
||||||
|
///
|
||||||
|
/// This method forces a sync point and is generally a bad thing to do.
|
||||||
|
/// Only use it if you have exhausted all other options.<br/>
|
||||||
|
///
|
||||||
|
/// Remember: friends don't let friends readback.<br/>
|
||||||
|
/// ⚠️⚠️⚠️
|
||||||
|
/// </summary>
|
||||||
|
public void DownloadFromTexture(
|
||||||
|
Texture texture,
|
||||||
|
TransferBuffer transferBuffer,
|
||||||
|
TransferOptions transferOption
|
||||||
|
) {
|
||||||
|
DownloadFromTexture(
|
||||||
|
new TextureRegion(texture),
|
||||||
|
transferBuffer,
|
||||||
|
new BufferImageCopy(0, 0, 0),
|
||||||
|
transferOption
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ⚠️⚠️⚠️ <br/>
|
||||||
|
/// Downloads data from a GpuBuffer to a TransferBuffer.
|
||||||
|
/// This copy occurs immediately on the CPU timeline.<br/>
|
||||||
|
///
|
||||||
|
/// If you modify this GpuBuffer in a command buffer and then call this function without calling
|
||||||
|
/// SubmitAndAcquireFence and WaitForFences first, the results will not be what you expect.<br/>
|
||||||
|
///
|
||||||
|
/// This method forces a sync point and is generally a bad thing to do.
|
||||||
|
/// Only use it if you have exhausted all other options.<br/>
|
||||||
|
///
|
||||||
|
/// Remember: friends don't let friends readback.<br/>
|
||||||
|
/// ⚠️⚠️⚠️
|
||||||
|
/// </summary>
|
||||||
|
public void DownloadFromBuffer(
|
||||||
|
GpuBuffer gpuBuffer,
|
||||||
|
TransferBuffer transferBuffer,
|
||||||
|
in BufferCopy copyParams,
|
||||||
|
TransferOptions transferOption
|
||||||
|
) {
|
||||||
|
Refresh.Refresh_DownloadFromBuffer(
|
||||||
|
Handle,
|
||||||
|
gpuBuffer.Handle,
|
||||||
|
transferBuffer.Handle,
|
||||||
|
copyParams.ToRefresh(),
|
||||||
|
(Refresh.TransferOptions) transferOption
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ⚠️⚠️⚠️ <br/>
|
||||||
|
/// Downloads all data in a GpuBuffer to a TransferBuffer.
|
||||||
|
/// This copy occurs immediately on the CPU timeline.<br/>
|
||||||
|
///
|
||||||
|
/// If you modify this GpuBuffer in a command buffer and then call this function without calling
|
||||||
|
/// SubmitAndAcquireFence and WaitForFences first, the results will not be what you expect.<br/>
|
||||||
|
///
|
||||||
|
/// This method forces a sync point and is generally a bad thing to do.
|
||||||
|
/// Only use it if you have exhausted all other options.<br/>
|
||||||
|
///
|
||||||
|
/// Remember: friends don't let friends readback.<br/>
|
||||||
|
/// ⚠️⚠️⚠️
|
||||||
|
/// </summary>
|
||||||
|
public void DownloadFromBuffer(
|
||||||
|
GpuBuffer gpuBuffer,
|
||||||
|
TransferBuffer transferBuffer,
|
||||||
|
TransferOptions option
|
||||||
|
) {
|
||||||
|
DownloadFromBuffer(
|
||||||
|
gpuBuffer,
|
||||||
|
transferBuffer,
|
||||||
|
new BufferCopy(0, 0, gpuBuffer.Size),
|
||||||
|
option
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private TextureFormat GetSwapchainFormat(Window window)
|
private TextureFormat GetSwapchainFormat(Window window)
|
||||||
{
|
{
|
||||||
return (TextureFormat) Refresh.Refresh_GetSwapchainFormat(Handle, window.Handle);
|
return (TextureFormat) Refresh.Refresh_GetSwapchainFormat(Handle, window.Handle);
|
||||||
|
|
|
@ -145,51 +145,6 @@ namespace MoonWorks.Graphics
|
||||||
Refresh.Refresh_Image_Free(pixels);
|
Refresh.Refresh_Image_Free(pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decodes image data into a TransferBuffer to prepare for image upload.
|
|
||||||
/// </summary>
|
|
||||||
public static unsafe uint DecodeIntoTransferBuffer(
|
|
||||||
Span<byte> data,
|
|
||||||
TransferBuffer transferBuffer,
|
|
||||||
uint bufferOffsetInBytes,
|
|
||||||
SetDataOptions option
|
|
||||||
) {
|
|
||||||
var pixelData = GetPixelDataFromBytes(data, out var w, out var h, out var sizeInBytes);
|
|
||||||
var length = transferBuffer.SetData(new Span<byte>((void*) pixelData, (int) sizeInBytes), bufferOffsetInBytes, option);
|
|
||||||
FreePixelData(pixelData);
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decodes an image stream into a TransferBuffer to prepare for image upload.
|
|
||||||
/// </summary>
|
|
||||||
public static unsafe uint DecodeIntoTransferBuffer(
|
|
||||||
Stream stream,
|
|
||||||
TransferBuffer transferBuffer,
|
|
||||||
uint bufferOffsetInBytes,
|
|
||||||
SetDataOptions option
|
|
||||||
) {
|
|
||||||
var pixelData = GetPixelDataFromStream(stream, out var w, out var h, out var sizeInBytes);
|
|
||||||
var length = transferBuffer.SetData(new Span<byte>((void*) pixelData, (int) sizeInBytes), bufferOffsetInBytes, option);
|
|
||||||
FreePixelData(pixelData);
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decodes an image file into a TransferBuffer to prepare for image upload.
|
|
||||||
/// </summary>
|
|
||||||
public static unsafe uint DecodeIntoTransferBuffer(
|
|
||||||
string path,
|
|
||||||
TransferBuffer transferBuffer,
|
|
||||||
uint bufferOffsetInBytes,
|
|
||||||
SetDataOptions option
|
|
||||||
) {
|
|
||||||
var pixelData = GetPixelDataFromFile(path, out var w, out var h, out var sizeInBytes);
|
|
||||||
var length = transferBuffer.SetData(new Span<byte>((void*) pixelData, (int) sizeInBytes), bufferOffsetInBytes, option);
|
|
||||||
FreePixelData(pixelData);
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves pixel data contained in a TransferBuffer to a PNG file.
|
/// Saves pixel data contained in a TransferBuffer to a PNG file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -297,16 +297,22 @@ namespace MoonWorks.Graphics
|
||||||
IntOpaqueWhite
|
IntOpaqueWhite
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SetDataOptions
|
public enum TransferOptions
|
||||||
{
|
{
|
||||||
Discard,
|
Cycle,
|
||||||
Overwrite
|
Overwrite
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum WriteOptions
|
||||||
|
{
|
||||||
|
Cycle,
|
||||||
|
SafeOverwrite
|
||||||
|
}
|
||||||
|
|
||||||
public enum Backend
|
public enum Backend
|
||||||
{
|
{
|
||||||
DontCare,
|
|
||||||
Vulkan,
|
Vulkan,
|
||||||
|
D3D11,
|
||||||
PS5,
|
PS5,
|
||||||
Invalid
|
Invalid
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,11 +154,7 @@ namespace MoonWorks.Graphics
|
||||||
public StencilOp PassOp;
|
public StencilOp PassOp;
|
||||||
public StencilOp DepthFailOp;
|
public StencilOp DepthFailOp;
|
||||||
public CompareOp CompareOp;
|
public CompareOp CompareOp;
|
||||||
public uint CompareMask;
|
|
||||||
public uint WriteMask;
|
|
||||||
public uint Reference;
|
|
||||||
|
|
||||||
// FIXME: can we do an explicit cast here?
|
|
||||||
public Refresh.StencilOpState ToRefresh()
|
public Refresh.StencilOpState ToRefresh()
|
||||||
{
|
{
|
||||||
return new Refresh.StencilOpState
|
return new Refresh.StencilOpState
|
||||||
|
@ -166,61 +162,97 @@ namespace MoonWorks.Graphics
|
||||||
failOp = (Refresh.StencilOp) FailOp,
|
failOp = (Refresh.StencilOp) FailOp,
|
||||||
passOp = (Refresh.StencilOp) PassOp,
|
passOp = (Refresh.StencilOp) PassOp,
|
||||||
depthFailOp = (Refresh.StencilOp) DepthFailOp,
|
depthFailOp = (Refresh.StencilOp) DepthFailOp,
|
||||||
compareOp = (Refresh.CompareOp) CompareOp,
|
compareOp = (Refresh.CompareOp) CompareOp
|
||||||
compareMask = CompareMask,
|
|
||||||
writeMask = WriteMask,
|
|
||||||
reference = Reference
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
/// <summary>
|
||||||
|
/// Determines how a color texture will be read/written in a render pass.
|
||||||
|
/// </summary>
|
||||||
public struct ColorAttachmentInfo
|
public struct ColorAttachmentInfo
|
||||||
{
|
{
|
||||||
public Texture Texture;
|
public TextureSlice TextureSlice;
|
||||||
public uint Depth;
|
|
||||||
public uint Layer;
|
/// <summary>
|
||||||
public uint Level;
|
/// If LoadOp is set to Clear, the texture slice will be cleared to this color.
|
||||||
|
/// </summary>
|
||||||
public Color ClearColor;
|
public Color ClearColor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines what is done with the texture slice memory
|
||||||
|
/// at the beginning of the render pass. <br/>
|
||||||
|
///
|
||||||
|
/// Load:
|
||||||
|
/// Loads the data currently in the texture slice. <br/>
|
||||||
|
///
|
||||||
|
/// Clear:
|
||||||
|
/// Clears the texture slice to a single color. <br/>
|
||||||
|
///
|
||||||
|
/// DontCare:
|
||||||
|
/// The driver will do whatever it wants with the texture slice data.
|
||||||
|
/// This is a good option if you know that every single pixel will be written in the render pass.
|
||||||
|
/// </summary>
|
||||||
public LoadOp LoadOp;
|
public LoadOp LoadOp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines what is done with the texture slice memory
|
||||||
|
/// at the end of the render pass. <br/>
|
||||||
|
///
|
||||||
|
/// Store:
|
||||||
|
/// Stores the results of the render pass in the texture slice memory. <br/>
|
||||||
|
///
|
||||||
|
/// DontCare:
|
||||||
|
/// The driver will do whatever it wants with the texture slice memory.
|
||||||
|
/// </summary>
|
||||||
public StoreOp StoreOp;
|
public StoreOp StoreOp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies data dependency behavior. This option is ignored if LoadOp is Load. <br/>
|
||||||
|
///
|
||||||
|
/// Cycle:
|
||||||
|
/// If this texture slice has been used in commands that have not completed,
|
||||||
|
/// the implementation may prevent a dependency on those commands
|
||||||
|
/// at the cost of increased memory usage.
|
||||||
|
/// You may NOT assume that any of the previous texture (not slice!) data is retained.
|
||||||
|
/// This may prevent stalls when frequently reusing a texture slice in rendering. <br/>
|
||||||
|
///
|
||||||
|
/// SafeOverwrite:
|
||||||
|
/// Overwrites the data safely using a GPU memory barrier.
|
||||||
|
/// </summary>
|
||||||
|
public WriteOptions WriteOption;
|
||||||
|
|
||||||
public ColorAttachmentInfo(
|
public ColorAttachmentInfo(
|
||||||
Texture texture,
|
TextureSlice textureSlice,
|
||||||
|
WriteOptions writeOption,
|
||||||
Color clearColor,
|
Color clearColor,
|
||||||
StoreOp storeOp = StoreOp.Store
|
StoreOp storeOp = StoreOp.Store
|
||||||
) {
|
) {
|
||||||
Texture = texture;
|
TextureSlice = textureSlice;
|
||||||
Depth = 0;
|
|
||||||
Layer = 0;
|
|
||||||
Level = 0;
|
|
||||||
ClearColor = clearColor;
|
ClearColor = clearColor;
|
||||||
LoadOp = LoadOp.Clear;
|
LoadOp = LoadOp.Clear;
|
||||||
StoreOp = storeOp;
|
StoreOp = storeOp;
|
||||||
|
WriteOption = writeOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColorAttachmentInfo(
|
public ColorAttachmentInfo(
|
||||||
Texture texture,
|
TextureSlice textureSlice,
|
||||||
|
WriteOptions writeOption,
|
||||||
LoadOp loadOp = LoadOp.DontCare,
|
LoadOp loadOp = LoadOp.DontCare,
|
||||||
StoreOp storeOp = StoreOp.Store
|
StoreOp storeOp = StoreOp.Store
|
||||||
) {
|
) {
|
||||||
Texture = texture;
|
TextureSlice = textureSlice;
|
||||||
Depth = 0;
|
|
||||||
Layer = 0;
|
|
||||||
Level = 0;
|
|
||||||
ClearColor = Color.White;
|
ClearColor = Color.White;
|
||||||
LoadOp = loadOp;
|
LoadOp = loadOp;
|
||||||
StoreOp = storeOp;
|
StoreOp = storeOp;
|
||||||
|
WriteOption = writeOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Refresh.ColorAttachmentInfo ToRefresh()
|
public Refresh.ColorAttachmentInfo ToRefresh()
|
||||||
{
|
{
|
||||||
return new Refresh.ColorAttachmentInfo
|
return new Refresh.ColorAttachmentInfo
|
||||||
{
|
{
|
||||||
texture = Texture.Handle,
|
textureSlice = TextureSlice.ToRefreshTextureSlice(),
|
||||||
depth = Depth,
|
|
||||||
layer = Layer,
|
|
||||||
level = Level,
|
|
||||||
clearColor = new Refresh.Vec4
|
clearColor = new Refresh.Vec4
|
||||||
{
|
{
|
||||||
x = ClearColor.R / 255f,
|
x = ClearColor.R / 255f,
|
||||||
|
@ -229,92 +261,142 @@ namespace MoonWorks.Graphics
|
||||||
w = ClearColor.A / 255f
|
w = ClearColor.A / 255f
|
||||||
},
|
},
|
||||||
loadOp = (Refresh.LoadOp) LoadOp,
|
loadOp = (Refresh.LoadOp) LoadOp,
|
||||||
storeOp = (Refresh.StoreOp) StoreOp
|
storeOp = (Refresh.StoreOp) StoreOp,
|
||||||
|
writeOption = (Refresh.WriteOptions) WriteOption
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
/// <summary>
|
||||||
|
/// Determines how a depth/stencil texture will be read/written in a render pass.
|
||||||
|
/// </summary>
|
||||||
public struct DepthStencilAttachmentInfo
|
public struct DepthStencilAttachmentInfo
|
||||||
{
|
{
|
||||||
public Texture Texture;
|
public TextureSlice TextureSlice;
|
||||||
public uint Depth;
|
|
||||||
public uint Layer;
|
/// <summary>
|
||||||
public uint Level;
|
/// If LoadOp is set to Clear, the texture slice depth will be cleared to this depth value. <br/>
|
||||||
|
/// If StencilLoadOp is set to Clear, the texture slice stencil value will be cleared to this stencil value.
|
||||||
|
/// </summary>
|
||||||
public DepthStencilValue DepthStencilClearValue;
|
public DepthStencilValue DepthStencilClearValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines what is done with the texture slice depth values
|
||||||
|
/// at the beginning of the render pass. <br/>
|
||||||
|
///
|
||||||
|
/// Load:
|
||||||
|
/// Loads the data currently in the texture slice. <br/>
|
||||||
|
///
|
||||||
|
/// Clear:
|
||||||
|
/// Clears the texture slice to a single depth value. <br/>
|
||||||
|
///
|
||||||
|
/// DontCare:
|
||||||
|
/// The driver will do whatever it wants with the texture slice data.
|
||||||
|
/// This is a good option if you know that every single pixel will be written in the render pass.
|
||||||
|
/// </summary>
|
||||||
public LoadOp LoadOp;
|
public LoadOp LoadOp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines what is done with the texture slice depth values
|
||||||
|
/// at the end of the render pass. <br/>
|
||||||
|
///
|
||||||
|
/// Store:
|
||||||
|
/// Stores the results of the render pass in the texture slice memory. <br/>
|
||||||
|
///
|
||||||
|
/// DontCare:
|
||||||
|
/// The driver will do whatever it wants with the texture slice memory.
|
||||||
|
/// This is usually a good option for depth textures that don't need to be reused.
|
||||||
|
/// </summary>
|
||||||
public StoreOp StoreOp;
|
public StoreOp StoreOp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines what is done with the texture slice stencil values
|
||||||
|
/// at the beginning of the render pass. <br/>
|
||||||
|
///
|
||||||
|
/// Load:
|
||||||
|
/// Loads the data currently in the texture slice. <br/>
|
||||||
|
///
|
||||||
|
/// Clear:
|
||||||
|
/// Clears the texture slice to a single stencil value. <br/>
|
||||||
|
///
|
||||||
|
/// DontCare:
|
||||||
|
/// The driver will do whatever it wants with the texture slice data.
|
||||||
|
/// This is a good option if you know that every single pixel will be written in the render pass.
|
||||||
|
/// </summary>
|
||||||
public LoadOp StencilLoadOp;
|
public LoadOp StencilLoadOp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines what is done with the texture slice stencil values
|
||||||
|
/// at the end of the render pass. <br/>
|
||||||
|
///
|
||||||
|
/// Store:
|
||||||
|
/// Stores the results of the render pass in the texture slice memory. <br/>
|
||||||
|
///
|
||||||
|
/// DontCare:
|
||||||
|
/// The driver will do whatever it wants with the texture slice memory.
|
||||||
|
/// This is usually a good option for stencil textures that don't need to be reused.
|
||||||
|
/// </summary>
|
||||||
public StoreOp StencilStoreOp;
|
public StoreOp StencilStoreOp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies data dependency behavior. This option is ignored if LoadOp or StencilLoadOp is Load. <br/>
|
||||||
|
///
|
||||||
|
/// Cycle:
|
||||||
|
/// If this texture slice has been used in commands that have not completed,
|
||||||
|
/// the implementation may prevent a dependency on those commands
|
||||||
|
/// at the cost of increased memory usage.
|
||||||
|
/// You may NOT assume that any of the previous texture (not slice!) data is retained.
|
||||||
|
/// This may prevent stalls when frequently reusing a texture slice in rendering. <br/>
|
||||||
|
///
|
||||||
|
/// SafeOverwrite:
|
||||||
|
/// Overwrites the data safely using a GPU memory barrier.
|
||||||
|
/// </summary>
|
||||||
|
public WriteOptions WriteOption;
|
||||||
|
|
||||||
public DepthStencilAttachmentInfo(
|
public DepthStencilAttachmentInfo(
|
||||||
Texture texture,
|
TextureSlice textureSlice,
|
||||||
|
WriteOptions writeOption,
|
||||||
DepthStencilValue clearValue,
|
DepthStencilValue clearValue,
|
||||||
StoreOp depthStoreOp = StoreOp.Store,
|
StoreOp depthStoreOp = StoreOp.DontCare,
|
||||||
StoreOp stencilStoreOp = StoreOp.Store
|
StoreOp stencilStoreOp = StoreOp.DontCare
|
||||||
)
|
){
|
||||||
{
|
TextureSlice = textureSlice;
|
||||||
Texture = texture;
|
|
||||||
Depth = 0;
|
|
||||||
Layer = 0;
|
|
||||||
Level = 0;
|
|
||||||
DepthStencilClearValue = clearValue;
|
DepthStencilClearValue = clearValue;
|
||||||
LoadOp = LoadOp.Clear;
|
LoadOp = LoadOp.Clear;
|
||||||
StoreOp = depthStoreOp;
|
StoreOp = depthStoreOp;
|
||||||
StencilLoadOp = LoadOp.Clear;
|
StencilLoadOp = LoadOp.Clear;
|
||||||
StencilStoreOp = stencilStoreOp;
|
StencilStoreOp = stencilStoreOp;
|
||||||
|
WriteOption = writeOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DepthStencilAttachmentInfo(
|
public DepthStencilAttachmentInfo(
|
||||||
Texture texture,
|
TextureSlice textureSlice,
|
||||||
|
WriteOptions writeOption,
|
||||||
LoadOp loadOp = LoadOp.DontCare,
|
LoadOp loadOp = LoadOp.DontCare,
|
||||||
StoreOp storeOp = StoreOp.Store,
|
StoreOp storeOp = StoreOp.DontCare,
|
||||||
LoadOp stencilLoadOp = LoadOp.DontCare,
|
LoadOp stencilLoadOp = LoadOp.DontCare,
|
||||||
StoreOp stencilStoreOp = StoreOp.Store
|
StoreOp stencilStoreOp = StoreOp.DontCare
|
||||||
) {
|
) {
|
||||||
Texture = texture;
|
TextureSlice = textureSlice;
|
||||||
Depth = 0;
|
|
||||||
Layer = 0;
|
|
||||||
Level = 0;
|
|
||||||
DepthStencilClearValue = new DepthStencilValue();
|
DepthStencilClearValue = new DepthStencilValue();
|
||||||
LoadOp = loadOp;
|
LoadOp = loadOp;
|
||||||
StoreOp = storeOp;
|
StoreOp = storeOp;
|
||||||
StencilLoadOp = stencilLoadOp;
|
StencilLoadOp = stencilLoadOp;
|
||||||
StencilStoreOp = stencilStoreOp;
|
StencilStoreOp = stencilStoreOp;
|
||||||
}
|
WriteOption = writeOption;
|
||||||
|
|
||||||
public DepthStencilAttachmentInfo(
|
|
||||||
Texture texture,
|
|
||||||
DepthStencilValue depthStencilValue,
|
|
||||||
LoadOp loadOp,
|
|
||||||
StoreOp storeOp,
|
|
||||||
LoadOp stencilLoadOp,
|
|
||||||
StoreOp stencilStoreOp
|
|
||||||
) {
|
|
||||||
Texture = texture;
|
|
||||||
Depth = 0;
|
|
||||||
Layer = 0;
|
|
||||||
Level = 0;
|
|
||||||
DepthStencilClearValue = depthStencilValue;
|
|
||||||
LoadOp = loadOp;
|
|
||||||
StoreOp = storeOp;
|
|
||||||
StencilLoadOp = stencilLoadOp;
|
|
||||||
StencilStoreOp = stencilStoreOp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Refresh.DepthStencilAttachmentInfo ToRefresh()
|
public Refresh.DepthStencilAttachmentInfo ToRefresh()
|
||||||
{
|
{
|
||||||
return new Refresh.DepthStencilAttachmentInfo
|
return new Refresh.DepthStencilAttachmentInfo
|
||||||
{
|
{
|
||||||
texture = Texture.Handle,
|
textureSlice = TextureSlice.ToRefreshTextureSlice(),
|
||||||
depth = Depth,
|
|
||||||
layer = Layer,
|
|
||||||
level = Level,
|
|
||||||
depthStencilClearValue = DepthStencilClearValue.ToRefresh(),
|
depthStencilClearValue = DepthStencilClearValue.ToRefresh(),
|
||||||
loadOp = (Refresh.LoadOp) LoadOp,
|
loadOp = (Refresh.LoadOp) LoadOp,
|
||||||
storeOp = (Refresh.StoreOp) StoreOp,
|
storeOp = (Refresh.StoreOp) StoreOp,
|
||||||
stencilLoadOp = (Refresh.LoadOp) StencilLoadOp,
|
stencilLoadOp = (Refresh.LoadOp) StencilLoadOp,
|
||||||
stencilStoreOp = (Refresh.StoreOp) StencilStoreOp
|
stencilStoreOp = (Refresh.StoreOp) StencilStoreOp,
|
||||||
|
writeOption = (Refresh.WriteOptions) WriteOption
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,23 +465,18 @@ namespace MoonWorks.Graphics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parameters for a copy between buffer and image.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="BufferOffset">The offset into the buffer.</param>
|
||||||
|
/// <param name="BufferStride">If 0, image data is assumed tightly packed.</param>
|
||||||
|
/// <param name="BufferImageHeight">If 0, image data is assumed tightly packed.</param>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct BufferImageCopy
|
public readonly record struct BufferImageCopy(
|
||||||
{
|
uint BufferOffset,
|
||||||
public uint BufferOffset;
|
uint BufferStride,
|
||||||
public uint BufferStride; // if 0, image assumed to be tightly packed
|
uint BufferImageHeight
|
||||||
public uint BufferImageHeight; // if 0, image assumed to be tightly packed
|
) {
|
||||||
|
|
||||||
public BufferImageCopy(
|
|
||||||
uint bufferOffset,
|
|
||||||
uint bufferStride,
|
|
||||||
uint bufferImageHeight
|
|
||||||
) {
|
|
||||||
BufferOffset = bufferOffset;
|
|
||||||
BufferStride = bufferStride;
|
|
||||||
BufferImageHeight = bufferImageHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Refresh.BufferImageCopy ToRefresh()
|
public Refresh.BufferImageCopy ToRefresh()
|
||||||
{
|
{
|
||||||
return new Refresh.BufferImageCopy
|
return new Refresh.BufferImageCopy
|
||||||
|
|
|
@ -21,8 +21,8 @@ namespace MoonWorks.Graphics
|
||||||
uint dataOffset = 0;
|
uint dataOffset = 0;
|
||||||
uint dataSize = 1024;
|
uint dataSize = 1024;
|
||||||
|
|
||||||
List<(GpuBuffer, BufferCopy)> BufferUploads = new List<(GpuBuffer, BufferCopy)>();
|
List<(GpuBuffer, BufferCopy, WriteOptions)> BufferUploads = new List<(GpuBuffer, BufferCopy, WriteOptions)>();
|
||||||
List<(TextureSlice, uint)> TextureUploads = new List<(TextureSlice, uint)>();
|
List<(TextureRegion, uint, WriteOptions)> TextureUploads = new List<(TextureRegion, uint, WriteOptions)>();
|
||||||
|
|
||||||
public ResourceUploader(GraphicsDevice device) : base(device)
|
public ResourceUploader(GraphicsDevice device) : base(device)
|
||||||
{
|
{
|
||||||
|
@ -39,7 +39,7 @@ namespace MoonWorks.Graphics
|
||||||
var lengthInBytes = (uint) (Marshal.SizeOf<T>() * data.Length);
|
var lengthInBytes = (uint) (Marshal.SizeOf<T>() * data.Length);
|
||||||
var gpuBuffer = new GpuBuffer(Device, usageFlags, lengthInBytes);
|
var gpuBuffer = new GpuBuffer(Device, usageFlags, lengthInBytes);
|
||||||
|
|
||||||
SetBufferData(gpuBuffer, 0, data);
|
SetBufferData(gpuBuffer, 0, data, WriteOptions.SafeOverwrite);
|
||||||
|
|
||||||
return gpuBuffer;
|
return gpuBuffer;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ namespace MoonWorks.Graphics
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prepares upload of data into a GpuBuffer.
|
/// Prepares upload of data into a GpuBuffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetBufferData<T>(GpuBuffer buffer, uint bufferOffsetInElements, Span<T> data) where T : unmanaged
|
public void SetBufferData<T>(GpuBuffer buffer, uint bufferOffsetInElements, Span<T> data, WriteOptions option) where T : unmanaged
|
||||||
{
|
{
|
||||||
uint elementSize = (uint) Marshal.SizeOf<T>();
|
uint elementSize = (uint) Marshal.SizeOf<T>();
|
||||||
uint offsetInBytes = elementSize * bufferOffsetInElements;
|
uint offsetInBytes = elementSize * bufferOffsetInElements;
|
||||||
|
@ -60,15 +60,15 @@ namespace MoonWorks.Graphics
|
||||||
}
|
}
|
||||||
|
|
||||||
var bufferCopyParams = new BufferCopy(resourceOffset, offsetInBytes, lengthInBytes);
|
var bufferCopyParams = new BufferCopy(resourceOffset, offsetInBytes, lengthInBytes);
|
||||||
BufferUploads.Add((buffer, bufferCopyParams));
|
BufferUploads.Add((buffer, bufferCopyParams, option));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Textures
|
// Textures
|
||||||
|
|
||||||
public Texture CreateTexture2D(Span<byte> pixelData, uint width, uint height)
|
public Texture CreateTexture2D<T>(Span<T> pixelData, uint width, uint height) where T : unmanaged
|
||||||
{
|
{
|
||||||
var texture = Texture.CreateTexture2D(Device, width, height, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler);
|
var texture = Texture.CreateTexture2D(Device, width, height, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler);
|
||||||
SetTextureData(texture, pixelData);
|
SetTextureData(texture, pixelData, WriteOptions.SafeOverwrite);
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,12 +142,14 @@ namespace MoonWorks.Graphics
|
||||||
var byteSpan = new Span<byte>(byteBuffer, levelSize);
|
var byteSpan = new Span<byte>(byteBuffer, levelSize);
|
||||||
stream.ReadExactly(byteSpan);
|
stream.ReadExactly(byteSpan);
|
||||||
|
|
||||||
var textureSlice = new TextureSlice
|
var textureRegion = new TextureRegion
|
||||||
{
|
{
|
||||||
Texture = texture,
|
TextureSlice = new TextureSlice
|
||||||
MipLevel = (uint) level,
|
{
|
||||||
BaseLayer = (uint) face,
|
Texture = texture,
|
||||||
LayerCount = 1,
|
Layer = (uint) face,
|
||||||
|
MipLevel = (uint) level
|
||||||
|
},
|
||||||
X = 0,
|
X = 0,
|
||||||
Y = 0,
|
Y = 0,
|
||||||
Z = 0,
|
Z = 0,
|
||||||
|
@ -156,7 +158,7 @@ namespace MoonWorks.Graphics
|
||||||
Depth = 1
|
Depth = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
SetTextureData(textureSlice, byteSpan);
|
SetTextureData(textureRegion, byteSpan, WriteOptions.SafeOverwrite);
|
||||||
|
|
||||||
NativeMemory.Free(byteBuffer);
|
NativeMemory.Free(byteBuffer);
|
||||||
}
|
}
|
||||||
|
@ -174,36 +176,36 @@ namespace MoonWorks.Graphics
|
||||||
return CreateTextureFromDDS(stream);
|
return CreateTextureFromDDS(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTextureDataFromCompressed(TextureSlice textureSlice, Span<byte> compressedImageData)
|
public void SetTextureDataFromCompressed(TextureRegion textureRegion, Span<byte> compressedImageData)
|
||||||
{
|
{
|
||||||
var pixelData = ImageUtils.GetPixelDataFromBytes(compressedImageData, out var _, out var _, out var sizeInBytes);
|
var pixelData = ImageUtils.GetPixelDataFromBytes(compressedImageData, out var _, out var _, out var sizeInBytes);
|
||||||
var pixelSpan = new Span<byte>((void*) pixelData, (int) sizeInBytes);
|
var pixelSpan = new Span<byte>((void*) pixelData, (int) sizeInBytes);
|
||||||
|
|
||||||
SetTextureData(textureSlice, pixelSpan);
|
SetTextureData(textureRegion, pixelSpan, WriteOptions.SafeOverwrite);
|
||||||
|
|
||||||
ImageUtils.FreePixelData(pixelData);
|
ImageUtils.FreePixelData(pixelData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTextureDataFromCompressed(TextureSlice textureSlice, Stream compressedImageStream)
|
public void SetTextureDataFromCompressed(TextureRegion textureRegion, Stream compressedImageStream)
|
||||||
{
|
{
|
||||||
var length = compressedImageStream.Length;
|
var length = compressedImageStream.Length;
|
||||||
var buffer = NativeMemory.Alloc((nuint) length);
|
var buffer = NativeMemory.Alloc((nuint) length);
|
||||||
var span = new Span<byte>(buffer, (int) length);
|
var span = new Span<byte>(buffer, (int) length);
|
||||||
compressedImageStream.ReadExactly(span);
|
compressedImageStream.ReadExactly(span);
|
||||||
SetTextureDataFromCompressed(textureSlice, span);
|
SetTextureDataFromCompressed(textureRegion, span);
|
||||||
NativeMemory.Free(buffer);
|
NativeMemory.Free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTextureDataFromCompressed(TextureSlice textureSlice, string compressedImageFilePath)
|
public void SetTextureDataFromCompressed(TextureRegion textureRegion, string compressedImageFilePath)
|
||||||
{
|
{
|
||||||
var fileStream = new FileStream(compressedImageFilePath, FileMode.Open, FileAccess.Read);
|
var fileStream = new FileStream(compressedImageFilePath, FileMode.Open, FileAccess.Read);
|
||||||
SetTextureDataFromCompressed(textureSlice, fileStream);
|
SetTextureDataFromCompressed(textureRegion, fileStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prepares upload of pixel data into a TextureSlice.
|
/// Prepares upload of pixel data into a TextureSlice.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetTextureData<T>(TextureSlice textureSlice, Span<T> data) where T : unmanaged
|
public void SetTextureData<T>(TextureRegion textureRegion, Span<T> data, WriteOptions option) where T : unmanaged
|
||||||
{
|
{
|
||||||
var elementSize = Marshal.SizeOf<T>();
|
var elementSize = Marshal.SizeOf<T>();
|
||||||
var dataLengthInBytes = (uint) (elementSize * data.Length);
|
var dataLengthInBytes = (uint) (elementSize * data.Length);
|
||||||
|
@ -211,10 +213,10 @@ namespace MoonWorks.Graphics
|
||||||
uint resourceOffset;
|
uint resourceOffset;
|
||||||
fixed (T* dataPtr = data)
|
fixed (T* dataPtr = data)
|
||||||
{
|
{
|
||||||
resourceOffset = CopyDataAligned(dataPtr, dataLengthInBytes, Texture.TexelSize(textureSlice.Texture.Format));
|
resourceOffset = CopyDataAligned(dataPtr, dataLengthInBytes, Texture.TexelSize(textureRegion.TextureSlice.Texture.Format));
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureUploads.Add((textureSlice, resourceOffset));
|
TextureUploads.Add((textureRegion, resourceOffset, option));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload
|
// Upload
|
||||||
|
@ -257,32 +259,34 @@ namespace MoonWorks.Graphics
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataSpan = new Span<byte>(data, (int) dataSize);
|
var dataSpan = new Span<byte>(data, (int) dataSize);
|
||||||
TransferBuffer.SetData(dataSpan, SetDataOptions.Discard);
|
TransferBuffer.SetData(dataSpan, TransferOptions.Cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecordUploadCommands(CommandBuffer commandBuffer)
|
private void RecordUploadCommands(CommandBuffer commandBuffer)
|
||||||
{
|
{
|
||||||
commandBuffer.BeginCopyPass();
|
commandBuffer.BeginCopyPass();
|
||||||
|
|
||||||
foreach (var (gpuBuffer, bufferCopyParams) in BufferUploads)
|
foreach (var (gpuBuffer, bufferCopyParams, option) in BufferUploads)
|
||||||
{
|
{
|
||||||
commandBuffer.UploadToBuffer(
|
commandBuffer.UploadToBuffer(
|
||||||
TransferBuffer,
|
TransferBuffer,
|
||||||
gpuBuffer,
|
gpuBuffer,
|
||||||
bufferCopyParams
|
bufferCopyParams,
|
||||||
|
option
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (textureSlice, offset) in TextureUploads)
|
foreach (var (textureRegion, offset, option) in TextureUploads)
|
||||||
{
|
{
|
||||||
commandBuffer.UploadToTexture(
|
commandBuffer.UploadToTexture(
|
||||||
TransferBuffer,
|
TransferBuffer,
|
||||||
textureSlice,
|
textureRegion,
|
||||||
new BufferImageCopy(
|
new BufferImageCopy(
|
||||||
offset,
|
offset,
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
)
|
),
|
||||||
|
option
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,11 @@ namespace MoonWorks.Graphics
|
||||||
refreshGraphicsPipelineCreateInfo.blendConstants[2] = blendConstants.B;
|
refreshGraphicsPipelineCreateInfo.blendConstants[2] = blendConstants.B;
|
||||||
refreshGraphicsPipelineCreateInfo.blendConstants[3] = blendConstants.A;
|
refreshGraphicsPipelineCreateInfo.blendConstants[3] = blendConstants.A;
|
||||||
|
|
||||||
refreshGraphicsPipelineCreateInfo.depthStencilState.stencilState = depthStencilState.StencilState.ToRefresh();
|
refreshGraphicsPipelineCreateInfo.depthStencilState.backStencilState = depthStencilState.BackStencilState.ToRefresh();
|
||||||
|
refreshGraphicsPipelineCreateInfo.depthStencilState.frontStencilState = depthStencilState.FrontStencilState.ToRefresh();
|
||||||
|
refreshGraphicsPipelineCreateInfo.depthStencilState.compareMask = depthStencilState.CompareMask;
|
||||||
|
refreshGraphicsPipelineCreateInfo.depthStencilState.writeMask = depthStencilState.WriteMask;
|
||||||
|
refreshGraphicsPipelineCreateInfo.depthStencilState.reference = depthStencilState.Reference;
|
||||||
refreshGraphicsPipelineCreateInfo.depthStencilState.compareOp = (Refresh.CompareOp) depthStencilState.CompareOp;
|
refreshGraphicsPipelineCreateInfo.depthStencilState.compareOp = (Refresh.CompareOp) depthStencilState.CompareOp;
|
||||||
refreshGraphicsPipelineCreateInfo.depthStencilState.depthBoundsTestEnable = Conversions.BoolToByte(depthStencilState.DepthBoundsTestEnable);
|
refreshGraphicsPipelineCreateInfo.depthStencilState.depthBoundsTestEnable = Conversions.BoolToByte(depthStencilState.DepthBoundsTestEnable);
|
||||||
refreshGraphicsPipelineCreateInfo.depthStencilState.depthTestEnable = Conversions.BoolToByte(depthStencilState.DepthTestEnable);
|
refreshGraphicsPipelineCreateInfo.depthStencilState.depthTestEnable = Conversions.BoolToByte(depthStencilState.DepthTestEnable);
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace MoonWorks.Graphics
|
||||||
public uint Depth { get; }
|
public uint Depth { get; }
|
||||||
public TextureFormat Format { get; internal set; }
|
public TextureFormat Format { get; internal set; }
|
||||||
public bool IsCube { get; }
|
public bool IsCube { get; }
|
||||||
|
public uint LayerCount { get; }
|
||||||
public uint LevelCount { get; }
|
public uint LevelCount { get; }
|
||||||
public SampleCount SampleCount { get; }
|
public SampleCount SampleCount { get; }
|
||||||
public TextureUsageFlags UsageFlags { get; }
|
public TextureUsageFlags UsageFlags { get; }
|
||||||
|
@ -46,6 +47,7 @@ namespace MoonWorks.Graphics
|
||||||
Height = height,
|
Height = height,
|
||||||
Depth = 1,
|
Depth = 1,
|
||||||
IsCube = false,
|
IsCube = false,
|
||||||
|
LayerCount = 1,
|
||||||
LevelCount = levelCount,
|
LevelCount = levelCount,
|
||||||
SampleCount = sampleCount,
|
SampleCount = sampleCount,
|
||||||
Format = format,
|
Format = format,
|
||||||
|
@ -56,15 +58,43 @@ namespace MoonWorks.Graphics
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a 3D texture.
|
/// Creates a 2D texture array.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="device">An initialized GraphicsDevice.</param>
|
/// <param name="device">An initialized GraphicsDevice.</param>
|
||||||
/// <param name="width">The width of the texture.</param>
|
/// <param name="width">The width of the texture.</param>
|
||||||
/// <param name="height">The height of the texture.</param>
|
/// <param name="height">The height of the texture.</param>
|
||||||
/// <param name="depth">The depth of the texture.</param>
|
/// <param name="layerCount">The layer count of the texture.</param>
|
||||||
/// <param name="format">The format of the texture.</param>
|
/// <param name="format">The format of the texture.</param>
|
||||||
/// <param name="usageFlags">Specifies how the texture will be used.</param>
|
/// <param name="usageFlags">Specifies how the texture will be used.</param>
|
||||||
/// <param name="levelCount">Specifies the number of mip levels.</param>
|
/// <param name="levelCount">Specifies the number of mip levels.</param>
|
||||||
|
public static Texture CreateTexture2DArray(
|
||||||
|
GraphicsDevice device,
|
||||||
|
uint width,
|
||||||
|
uint height,
|
||||||
|
uint layerCount,
|
||||||
|
TextureFormat format,
|
||||||
|
TextureUsageFlags usageFlags,
|
||||||
|
uint levelCount = 1
|
||||||
|
) {
|
||||||
|
var textureCreateInfo = new TextureCreateInfo
|
||||||
|
{
|
||||||
|
Width = width,
|
||||||
|
Height = height,
|
||||||
|
Depth = 1,
|
||||||
|
IsCube = false,
|
||||||
|
LayerCount = layerCount,
|
||||||
|
LevelCount = levelCount,
|
||||||
|
Format = format,
|
||||||
|
UsageFlags = usageFlags
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Texture(device, textureCreateInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a 3D texture.
|
||||||
|
/// Note that the width, height and depth all form one slice and cannot be subdivided in a texture slice.
|
||||||
|
/// </summary>
|
||||||
public static Texture CreateTexture3D(
|
public static Texture CreateTexture3D(
|
||||||
GraphicsDevice device,
|
GraphicsDevice device,
|
||||||
uint width,
|
uint width,
|
||||||
|
@ -80,6 +110,7 @@ namespace MoonWorks.Graphics
|
||||||
Height = height,
|
Height = height,
|
||||||
Depth = depth,
|
Depth = depth,
|
||||||
IsCube = false,
|
IsCube = false,
|
||||||
|
LayerCount = 1,
|
||||||
LevelCount = levelCount,
|
LevelCount = levelCount,
|
||||||
Format = format,
|
Format = format,
|
||||||
UsageFlags = usageFlags
|
UsageFlags = usageFlags
|
||||||
|
@ -109,6 +140,7 @@ namespace MoonWorks.Graphics
|
||||||
Height = size,
|
Height = size,
|
||||||
Depth = 1,
|
Depth = 1,
|
||||||
IsCube = true,
|
IsCube = true,
|
||||||
|
LayerCount = 6,
|
||||||
LevelCount = levelCount,
|
LevelCount = levelCount,
|
||||||
Format = format,
|
Format = format,
|
||||||
UsageFlags = usageFlags
|
UsageFlags = usageFlags
|
||||||
|
@ -137,16 +169,14 @@ namespace MoonWorks.Graphics
|
||||||
Height = textureCreateInfo.Height;
|
Height = textureCreateInfo.Height;
|
||||||
Depth = textureCreateInfo.Depth;
|
Depth = textureCreateInfo.Depth;
|
||||||
IsCube = textureCreateInfo.IsCube;
|
IsCube = textureCreateInfo.IsCube;
|
||||||
|
LayerCount = textureCreateInfo.LayerCount;
|
||||||
LevelCount = textureCreateInfo.LevelCount;
|
LevelCount = textureCreateInfo.LevelCount;
|
||||||
SampleCount = textureCreateInfo.SampleCount;
|
SampleCount = textureCreateInfo.SampleCount;
|
||||||
UsageFlags = textureCreateInfo.UsageFlags;
|
UsageFlags = textureCreateInfo.UsageFlags;
|
||||||
Size = Width * Height * BytesPerPixel(Format) / BlockSizeSquared(Format);
|
Size = Width * Height * BytesPerPixel(Format) / BlockSizeSquared(Format);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator TextureSlice(Texture t) => new TextureSlice(t);
|
// Used by Window. Swapchain texture handles are managed by the driver backend.
|
||||||
|
|
||||||
// Used by AcquireSwapchainTexture.
|
|
||||||
// Should not be tracked, because swapchain textures are managed by Vulkan.
|
|
||||||
internal Texture(
|
internal Texture(
|
||||||
GraphicsDevice device,
|
GraphicsDevice device,
|
||||||
TextureFormat format
|
TextureFormat format
|
||||||
|
@ -270,5 +300,8 @@ namespace MoonWorks.Graphics
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static implicit operator TextureSlice(Texture t) => new TextureSlice(t);
|
||||||
|
public static implicit operator TextureRegion(Texture t) => new TextureRegion(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace MoonWorks.Graphics
|
||||||
public unsafe uint SetData<T>(
|
public unsafe uint SetData<T>(
|
||||||
Span<T> data,
|
Span<T> data,
|
||||||
uint bufferOffsetInBytes,
|
uint bufferOffsetInBytes,
|
||||||
SetDataOptions setDataOption
|
TransferOptions setDataOption
|
||||||
) where T : unmanaged
|
) where T : unmanaged
|
||||||
{
|
{
|
||||||
var elementSize = Marshal.SizeOf<T>();
|
var elementSize = Marshal.SizeOf<T>();
|
||||||
|
@ -73,7 +73,7 @@ namespace MoonWorks.Graphics
|
||||||
|
|
||||||
fixed (T* dataPtr = data)
|
fixed (T* dataPtr = data)
|
||||||
{
|
{
|
||||||
Refresh.Refresh_SetData(
|
Refresh.Refresh_SetTransferData(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
(nint) dataPtr,
|
(nint) dataPtr,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -83,7 +83,7 @@ namespace MoonWorks.Graphics
|
||||||
dstOffset = bufferOffsetInBytes,
|
dstOffset = bufferOffsetInBytes,
|
||||||
size = dataLengthInBytes
|
size = dataLengthInBytes
|
||||||
},
|
},
|
||||||
(Refresh.SetDataOptions) setDataOption
|
(Refresh.TransferOptions) setDataOption
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ namespace MoonWorks.Graphics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe uint SetData<T>(
|
public unsafe uint SetData<T>(
|
||||||
Span<T> data,
|
Span<T> data,
|
||||||
SetDataOptions setDataOption
|
TransferOptions setDataOption
|
||||||
) where T : unmanaged
|
) where T : unmanaged
|
||||||
{
|
{
|
||||||
return SetData(data, 0, setDataOption);
|
return SetData(data, 0, setDataOption);
|
||||||
|
@ -125,7 +125,7 @@ namespace MoonWorks.Graphics
|
||||||
|
|
||||||
fixed (T* dataPtr = data)
|
fixed (T* dataPtr = data)
|
||||||
{
|
{
|
||||||
Refresh.Refresh_GetData(
|
Refresh.Refresh_GetTransferData(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
(nint) dataPtr,
|
(nint) dataPtr,
|
||||||
|
@ -144,7 +144,7 @@ namespace MoonWorks.Graphics
|
||||||
{
|
{
|
||||||
if (copyLengthInBytes > bufferLengthInBytes + offsetInBytes)
|
if (copyLengthInBytes > bufferLengthInBytes + offsetInBytes)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"SetData overflow! Transfer buffer length {bufferLengthInBytes}, offset {offsetInBytes}, copy length {copyLengthInBytes}");
|
throw new InvalidOperationException($"Data overflow! Transfer buffer length {bufferLengthInBytes}, offset {offsetInBytes}, copy length {copyLengthInBytes}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,9 +11,29 @@
|
||||||
public bool DepthTestEnable;
|
public bool DepthTestEnable;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes the stencil operation.
|
/// Describes the back-face stencil operation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public StencilOpState StencilState;
|
public StencilOpState BackStencilState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the front-face stencil operation.
|
||||||
|
/// </summary>
|
||||||
|
public StencilOpState FrontStencilState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The compare mask for stencil ops.
|
||||||
|
/// </summary>
|
||||||
|
public uint CompareMask;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The write mask for stencil ops.
|
||||||
|
/// </summary>
|
||||||
|
public uint WriteMask;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The stencil reference value.
|
||||||
|
/// </summary>
|
||||||
|
public uint Reference;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The comparison operator used in the depth test.
|
/// The comparison operator used in the depth test.
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace MoonWorks.Graphics
|
||||||
public uint Height;
|
public uint Height;
|
||||||
public uint Depth;
|
public uint Depth;
|
||||||
public bool IsCube;
|
public bool IsCube;
|
||||||
|
public uint LayerCount;
|
||||||
public uint LevelCount;
|
public uint LevelCount;
|
||||||
public SampleCount SampleCount;
|
public SampleCount SampleCount;
|
||||||
public TextureFormat Format;
|
public TextureFormat Format;
|
||||||
|
@ -24,6 +25,7 @@ namespace MoonWorks.Graphics
|
||||||
height = Height,
|
height = Height,
|
||||||
depth = Depth,
|
depth = Depth,
|
||||||
isCube = Conversions.BoolToByte(IsCube),
|
isCube = Conversions.BoolToByte(IsCube),
|
||||||
|
layerCount = LayerCount,
|
||||||
levelCount = LevelCount,
|
levelCount = LevelCount,
|
||||||
sampleCount = (Refresh.SampleCount) SampleCount,
|
sampleCount = (Refresh.SampleCount) SampleCount,
|
||||||
format = (Refresh.TextureFormat) Format,
|
format = (Refresh.TextureFormat) Format,
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,46 @@
|
||||||
|
using RefreshCS;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A texture region specifies a subregion of a texture.
|
||||||
|
/// These are used by copy commands.
|
||||||
|
/// </summary>
|
||||||
|
public struct TextureRegion
|
||||||
|
{
|
||||||
|
public TextureSlice TextureSlice;
|
||||||
|
public uint X;
|
||||||
|
public uint Y;
|
||||||
|
public uint Z;
|
||||||
|
public uint Width;
|
||||||
|
public uint Height;
|
||||||
|
public uint Depth;
|
||||||
|
|
||||||
|
public uint Size => (Width * Height * Depth * Texture.BytesPerPixel(TextureSlice.Texture.Format) / Texture.BlockSizeSquared(TextureSlice.Texture.Format)) >> (int) TextureSlice.MipLevel;
|
||||||
|
|
||||||
|
public TextureRegion(Texture texture)
|
||||||
|
{
|
||||||
|
TextureSlice = new TextureSlice(texture);
|
||||||
|
X = 0;
|
||||||
|
Y = 0;
|
||||||
|
Z = 0;
|
||||||
|
Width = texture.Width;
|
||||||
|
Height = texture.Height;
|
||||||
|
Depth = texture.Depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Refresh.TextureRegion ToRefreshTextureRegion()
|
||||||
|
{
|
||||||
|
return new Refresh.TextureRegion
|
||||||
|
{
|
||||||
|
textureSlice = TextureSlice.ToRefreshTextureSlice(),
|
||||||
|
x = X,
|
||||||
|
y = Y,
|
||||||
|
z = Z,
|
||||||
|
w = Width,
|
||||||
|
h = Height,
|
||||||
|
d = Depth
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,55 +3,31 @@
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A texture slice specifies a subregion of a texture.
|
/// A texture slice specifies a subresource of a texture.
|
||||||
/// Many operations can use texture slices in place of textures for the sake of convenience.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct TextureSlice
|
public struct TextureSlice
|
||||||
{
|
{
|
||||||
public Texture Texture;
|
public Texture Texture;
|
||||||
public uint MipLevel;
|
public uint MipLevel;
|
||||||
public uint BaseLayer;
|
public uint Layer;
|
||||||
public uint LayerCount;
|
|
||||||
public uint X;
|
|
||||||
public uint Y;
|
|
||||||
public uint Z;
|
|
||||||
public uint Width;
|
|
||||||
public uint Height;
|
|
||||||
public uint Depth;
|
|
||||||
|
|
||||||
public uint Size => (Width * Height * Depth * LayerCount * Texture.BytesPerPixel(Texture.Format) / Texture.BlockSizeSquared(Texture.Format)) >> (int) MipLevel;
|
public uint Size => (Texture.Width * Texture.Height * Texture.Depth * Texture.BytesPerPixel(Texture.Format) / Texture.BlockSizeSquared(Texture.Format)) >> (int) MipLevel;
|
||||||
|
|
||||||
public TextureSlice(Texture texture)
|
public TextureSlice(Texture texture)
|
||||||
{
|
{
|
||||||
Texture = texture;
|
Texture = texture;
|
||||||
MipLevel = 0;
|
MipLevel = 0;
|
||||||
BaseLayer = 0;
|
Layer = 0;
|
||||||
LayerCount = (uint) (texture.IsCube ? 6 : 1);
|
|
||||||
X = 0;
|
|
||||||
Y = 0;
|
|
||||||
Z = 0;
|
|
||||||
Width = texture.Width;
|
|
||||||
Height = texture.Height;
|
|
||||||
Depth = texture.Depth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Refresh.TextureSlice ToRefreshTextureSlice()
|
public Refresh.TextureSlice ToRefreshTextureSlice()
|
||||||
{
|
{
|
||||||
Refresh.TextureSlice textureSlice = new Refresh.TextureSlice
|
return new Refresh.TextureSlice
|
||||||
{
|
{
|
||||||
texture = Texture.Handle,
|
texture = Texture.Handle,
|
||||||
mipLevel = MipLevel,
|
mipLevel = MipLevel,
|
||||||
baseLayer = BaseLayer,
|
layer = Layer
|
||||||
layerCount = LayerCount,
|
|
||||||
x = X,
|
|
||||||
y = Y,
|
|
||||||
z = Z,
|
|
||||||
w = Width,
|
|
||||||
h = Height,
|
|
||||||
d = Depth
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return textureSlice;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,9 +243,9 @@ namespace MoonWorks.Video
|
||||||
TransferBuffer?.Dispose();
|
TransferBuffer?.Dispose();
|
||||||
TransferBuffer = new TransferBuffer(Device, (uint) (ySpan.Length + uSpan.Length + vSpan.Length));
|
TransferBuffer = new TransferBuffer(Device, (uint) (ySpan.Length + uSpan.Length + vSpan.Length));
|
||||||
}
|
}
|
||||||
TransferBuffer.SetData(ySpan, 0, SetDataOptions.Discard);
|
TransferBuffer.SetData(ySpan, 0, TransferOptions.Cycle);
|
||||||
TransferBuffer.SetData(uSpan, (uint) ySpan.Length, SetDataOptions.Overwrite);
|
TransferBuffer.SetData(uSpan, (uint) ySpan.Length, TransferOptions.Overwrite);
|
||||||
TransferBuffer.SetData(vSpan, (uint) (ySpan.Length + uSpan.Length), SetDataOptions.Overwrite);
|
TransferBuffer.SetData(vSpan, (uint) (ySpan.Length + uSpan.Length), TransferOptions.Overwrite);
|
||||||
|
|
||||||
commandBuffer.BeginCopyPass();
|
commandBuffer.BeginCopyPass();
|
||||||
|
|
||||||
|
@ -257,7 +257,8 @@ namespace MoonWorks.Video
|
||||||
BufferOffset = 0,
|
BufferOffset = 0,
|
||||||
BufferStride = CurrentStream.yStride,
|
BufferStride = CurrentStream.yStride,
|
||||||
BufferImageHeight = yTexture.Height
|
BufferImageHeight = yTexture.Height
|
||||||
}
|
},
|
||||||
|
WriteOptions.Cycle
|
||||||
);
|
);
|
||||||
|
|
||||||
commandBuffer.UploadToTexture(
|
commandBuffer.UploadToTexture(
|
||||||
|
@ -267,7 +268,8 @@ namespace MoonWorks.Video
|
||||||
BufferOffset = (uint) ySpan.Length,
|
BufferOffset = (uint) ySpan.Length,
|
||||||
BufferStride = CurrentStream.uvStride,
|
BufferStride = CurrentStream.uvStride,
|
||||||
BufferImageHeight = uTexture.Height
|
BufferImageHeight = uTexture.Height
|
||||||
}
|
},
|
||||||
|
WriteOptions.Cycle
|
||||||
);
|
);
|
||||||
|
|
||||||
commandBuffer.UploadToTexture(
|
commandBuffer.UploadToTexture(
|
||||||
|
@ -278,13 +280,14 @@ namespace MoonWorks.Video
|
||||||
BufferOffset = (uint) (ySpan.Length + uSpan.Length),
|
BufferOffset = (uint) (ySpan.Length + uSpan.Length),
|
||||||
BufferStride = CurrentStream.uvStride,
|
BufferStride = CurrentStream.uvStride,
|
||||||
BufferImageHeight = vTexture.Height
|
BufferImageHeight = vTexture.Height
|
||||||
}
|
},
|
||||||
|
WriteOptions.Cycle
|
||||||
);
|
);
|
||||||
|
|
||||||
commandBuffer.EndCopyPass();
|
commandBuffer.EndCopyPass();
|
||||||
|
|
||||||
commandBuffer.BeginRenderPass(
|
commandBuffer.BeginRenderPass(
|
||||||
new ColorAttachmentInfo(RenderTexture, Color.Black)
|
new ColorAttachmentInfo(RenderTexture, WriteOptions.Cycle, Color.Black)
|
||||||
);
|
);
|
||||||
|
|
||||||
commandBuffer.BindGraphicsPipeline(Device.VideoPipeline);
|
commandBuffer.BindGraphicsPipeline(Device.VideoPipeline);
|
||||||
|
|
|
@ -21,6 +21,15 @@ namespace MoonWorks
|
||||||
public bool Claimed { get; internal set; }
|
public bool Claimed { get; internal set; }
|
||||||
public MoonWorks.Graphics.TextureFormat SwapchainFormat { get; internal set; }
|
public MoonWorks.Graphics.TextureFormat SwapchainFormat { get; internal set; }
|
||||||
|
|
||||||
|
public (int, int) Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
SDL.SDL_GetWindowPosition(Handle, out var x, out var y);
|
||||||
|
return (x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsDisposed;
|
private bool IsDisposed;
|
||||||
|
|
||||||
private static Dictionary<uint, Window> idLookup = new Dictionary<uint, Window>();
|
private static Dictionary<uint, Window> idLookup = new Dictionary<uint, Window>();
|
||||||
|
@ -113,6 +122,14 @@ namespace MoonWorks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the window position.
|
||||||
|
/// </summary>
|
||||||
|
public void SetPosition(int x, int y)
|
||||||
|
{
|
||||||
|
SDL.SDL_SetWindowPosition(Handle, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
internal static Window Lookup(uint windowID)
|
internal static Window Lookup(uint windowID)
|
||||||
{
|
{
|
||||||
return idLookup.ContainsKey(windowID) ? idLookup[windowID] : null;
|
return idLookup.ContainsKey(windowID) ? idLookup[windowID] : null;
|
||||||
|
|
Loading…
Reference in New Issue