add graphics state validation in debug mode
parent
5c080a4c42
commit
d5a7daa524
|
@ -10,7 +10,12 @@ namespace MoonWorks.Graphics
|
||||||
public struct CommandBuffer
|
public struct CommandBuffer
|
||||||
{
|
{
|
||||||
public GraphicsDevice Device { get; }
|
public GraphicsDevice Device { get; }
|
||||||
public IntPtr Handle { get; internal set; }
|
public IntPtr Handle { get; }
|
||||||
|
|
||||||
|
// some state for debug validation
|
||||||
|
GraphicsPipeline currentGraphicsPipeline = null;
|
||||||
|
ComputePipeline currentComputePipeline = null;
|
||||||
|
bool renderPassActive = false;
|
||||||
|
|
||||||
// called from RefreshDevice
|
// called from RefreshDevice
|
||||||
internal CommandBuffer(GraphicsDevice device, IntPtr handle)
|
internal CommandBuffer(GraphicsDevice device, IntPtr handle)
|
||||||
|
@ -61,6 +66,8 @@ namespace MoonWorks.Graphics
|
||||||
IntPtr.Zero
|
IntPtr.Zero
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPassActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -102,6 +109,8 @@ namespace MoonWorks.Graphics
|
||||||
&refreshDepthStencilAttachmentInfo
|
&refreshDepthStencilAttachmentInfo
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPassActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -146,6 +155,8 @@ namespace MoonWorks.Graphics
|
||||||
IntPtr.Zero
|
IntPtr.Zero
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPassActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -189,6 +200,8 @@ namespace MoonWorks.Graphics
|
||||||
&refreshDepthStencilAttachmentInfo
|
&refreshDepthStencilAttachmentInfo
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPassActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -204,6 +217,8 @@ namespace MoonWorks.Graphics
|
||||||
Handle,
|
Handle,
|
||||||
computePipeline.Handle
|
computePipeline.Handle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
currentComputePipeline = computePipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -214,6 +229,20 @@ namespace MoonWorks.Graphics
|
||||||
params Buffer[] buffers
|
params Buffer[] buffers
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
|
||||||
|
if (currentComputePipeline.ComputeShaderInfo.BufferBindingCount == 0)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("The current compute shader does not take any buffers!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentComputePipeline.ComputeShaderInfo.BufferBindingCount < buffers.Length)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("Buffer count exceeds the amount used by the current compute shader!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
var bufferPtrs = stackalloc IntPtr[buffers.Length];
|
var bufferPtrs = stackalloc IntPtr[buffers.Length];
|
||||||
|
|
||||||
for (var i = 0; i < buffers.Length; i += 1)
|
for (var i = 0; i < buffers.Length; i += 1)
|
||||||
|
@ -236,6 +265,20 @@ namespace MoonWorks.Graphics
|
||||||
params Texture[] textures
|
params Texture[] textures
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
|
||||||
|
if (currentComputePipeline.ComputeShaderInfo.ImageBindingCount == 0)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("The current compute shader does not take any textures!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentComputePipeline.ComputeShaderInfo.ImageBindingCount < textures.Length)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("Texture count exceeds the amount used by the current compute shader!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
var texturePtrs = stackalloc IntPtr[textures.Length];
|
var texturePtrs = stackalloc IntPtr[textures.Length];
|
||||||
|
|
||||||
for (var i = 0; i < textures.Length; i += 1)
|
for (var i = 0; i < textures.Length; i += 1)
|
||||||
|
@ -264,6 +307,10 @@ namespace MoonWorks.Graphics
|
||||||
uint computeParamOffset
|
uint computeParamOffset
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_DispatchCompute(
|
Refresh.Refresh_DispatchCompute(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -287,6 +334,8 @@ namespace MoonWorks.Graphics
|
||||||
Handle,
|
Handle,
|
||||||
graphicsPipeline.Handle
|
graphicsPipeline.Handle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
currentGraphicsPipeline = graphicsPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -294,6 +343,10 @@ namespace MoonWorks.Graphics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetViewport(Viewport viewport)
|
public void SetViewport(Viewport viewport)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassActive();
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_SetViewport(
|
Refresh.Refresh_SetViewport(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -306,6 +359,10 @@ namespace MoonWorks.Graphics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetScissor(Rect scissor)
|
public void SetScissor(Rect scissor)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassActive();
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_SetScissor(
|
Refresh.Refresh_SetScissor(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -400,6 +457,20 @@ namespace MoonWorks.Graphics
|
||||||
int length
|
int length
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
|
||||||
|
if (currentGraphicsPipeline.VertexShaderInfo.SamplerBindingCount == 0)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("The vertex shader of the current graphics pipeline does not take any samplers!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentGraphicsPipeline.VertexShaderInfo.SamplerBindingCount < length)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("Vertex sampler count exceeds the amount used by the vertex shader!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
var texturePtrs = stackalloc IntPtr[textureSamplerBindings.Length];
|
var texturePtrs = stackalloc IntPtr[textureSamplerBindings.Length];
|
||||||
var samplerPtrs = stackalloc IntPtr[textureSamplerBindings.Length];
|
var samplerPtrs = stackalloc IntPtr[textureSamplerBindings.Length];
|
||||||
|
|
||||||
|
@ -438,6 +509,20 @@ namespace MoonWorks.Graphics
|
||||||
int length
|
int length
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
|
||||||
|
if (currentGraphicsPipeline.FragmentShaderInfo.SamplerBindingCount == 0)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("The fragment shader of the current graphics pipeline does not take any samplers!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentGraphicsPipeline.FragmentShaderInfo.SamplerBindingCount < length)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("Fragment sampler count exceeds the amount used by the fragment shader!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
var texturePtrs = stackalloc IntPtr[textureSamplerBindings.Length];
|
var texturePtrs = stackalloc IntPtr[textureSamplerBindings.Length];
|
||||||
var samplerPtrs = stackalloc IntPtr[textureSamplerBindings.Length];
|
var samplerPtrs = stackalloc IntPtr[textureSamplerBindings.Length];
|
||||||
|
|
||||||
|
@ -485,6 +570,14 @@ namespace MoonWorks.Graphics
|
||||||
params T[] uniforms
|
params T[] uniforms
|
||||||
) where T : unmanaged
|
) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
|
||||||
|
if (currentGraphicsPipeline.VertexShaderInfo.UniformBufferSize == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("The current vertex shader does not take a uniform buffer!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
fixed (T* ptr = &uniforms[0])
|
fixed (T* ptr = &uniforms[0])
|
||||||
{
|
{
|
||||||
return Refresh.Refresh_PushVertexShaderUniforms(
|
return Refresh.Refresh_PushVertexShaderUniforms(
|
||||||
|
@ -504,6 +597,15 @@ namespace MoonWorks.Graphics
|
||||||
params T[] uniforms
|
params T[] uniforms
|
||||||
) where T : unmanaged
|
) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
|
||||||
|
if (currentGraphicsPipeline.FragmentShaderInfo.UniformBufferSize == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("The current fragment shader does not take a uniform buffer!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fixed (T* ptr = &uniforms[0])
|
fixed (T* ptr = &uniforms[0])
|
||||||
{
|
{
|
||||||
return Refresh.Refresh_PushFragmentShaderUniforms(
|
return Refresh.Refresh_PushFragmentShaderUniforms(
|
||||||
|
@ -523,6 +625,15 @@ namespace MoonWorks.Graphics
|
||||||
params T[] uniforms
|
params T[] uniforms
|
||||||
) where T : unmanaged
|
) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
|
||||||
|
if (currentComputePipeline.ComputeShaderInfo.UniformBufferSize == 0)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("The current compute shader does not take a uniform buffer!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fixed (T* ptr = &uniforms[0])
|
fixed (T* ptr = &uniforms[0])
|
||||||
{
|
{
|
||||||
return Refresh.Refresh_PushComputeShaderUniforms(
|
return Refresh.Refresh_PushComputeShaderUniforms(
|
||||||
|
@ -553,6 +664,10 @@ namespace MoonWorks.Graphics
|
||||||
uint fragmentParamOffset
|
uint fragmentParamOffset
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_DrawInstancedPrimitives(
|
Refresh.Refresh_DrawInstancedPrimitives(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -581,6 +696,10 @@ namespace MoonWorks.Graphics
|
||||||
uint fragmentParamOffset
|
uint fragmentParamOffset
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_DrawIndexedPrimitives(
|
Refresh.Refresh_DrawIndexedPrimitives(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -606,6 +725,10 @@ namespace MoonWorks.Graphics
|
||||||
uint fragmentParamOffset
|
uint fragmentParamOffset
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_DrawPrimitives(
|
Refresh.Refresh_DrawPrimitives(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -634,6 +757,10 @@ namespace MoonWorks.Graphics
|
||||||
uint fragmentParamOffset
|
uint fragmentParamOffset
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_DrawPrimitivesIndirect(
|
Refresh.Refresh_DrawPrimitivesIndirect(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -656,6 +783,9 @@ namespace MoonWorks.Graphics
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle
|
Handle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
currentGraphicsPipeline = null;
|
||||||
|
renderPassActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -704,6 +834,10 @@ namespace MoonWorks.Graphics
|
||||||
uint bufferOffsetInBytes = 0
|
uint bufferOffsetInBytes = 0
|
||||||
) where T : unmanaged
|
) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassInactive("Cannot copy during render pass!");
|
||||||
|
#endif
|
||||||
|
|
||||||
SetBufferData(
|
SetBufferData(
|
||||||
buffer,
|
buffer,
|
||||||
data,
|
data,
|
||||||
|
@ -728,6 +862,10 @@ namespace MoonWorks.Graphics
|
||||||
uint dataLengthInBytes
|
uint dataLengthInBytes
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassInactive("Cannot copy during render pass!");
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_SetBufferData(
|
Refresh.Refresh_SetBufferData(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -755,6 +893,10 @@ namespace MoonWorks.Graphics
|
||||||
uint numElements
|
uint numElements
|
||||||
) where T : unmanaged
|
) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassInactive("Cannot copy during render pass!");
|
||||||
|
#endif
|
||||||
|
|
||||||
var elementSize = sizeof(T);
|
var elementSize = sizeof(T);
|
||||||
|
|
||||||
fixed (T* ptr = &data[0])
|
fixed (T* ptr = &data[0])
|
||||||
|
@ -778,6 +920,10 @@ namespace MoonWorks.Graphics
|
||||||
uint bufferOffsetInElements,
|
uint bufferOffsetInElements,
|
||||||
uint numElements
|
uint numElements
|
||||||
) where T : unmanaged {
|
) where T : unmanaged {
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassInactive("Cannot copy during render pass!");
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_SetBufferData(
|
Refresh.Refresh_SetBufferData(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -804,6 +950,10 @@ namespace MoonWorks.Graphics
|
||||||
/// <param name="data">An array of data to copy into the texture.</param>
|
/// <param name="data">An array of data to copy into the texture.</param>
|
||||||
public unsafe void SetTextureData<T>(in TextureSlice textureSlice, T[] data) where T : unmanaged
|
public unsafe void SetTextureData<T>(in TextureSlice textureSlice, T[] data) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassInactive("Cannot copy during render pass!");
|
||||||
|
#endif
|
||||||
|
|
||||||
var size = sizeof(T);
|
var size = sizeof(T);
|
||||||
|
|
||||||
fixed (T* ptr = &data[0])
|
fixed (T* ptr = &data[0])
|
||||||
|
@ -826,6 +976,10 @@ namespace MoonWorks.Graphics
|
||||||
/// <param name="dataLengthInBytes">The amount of data to copy from the array.</param>
|
/// <param name="dataLengthInBytes">The amount of data to copy from the array.</param>
|
||||||
public void SetTextureData(in TextureSlice textureSlice, IntPtr dataPtr, uint dataLengthInBytes)
|
public void SetTextureData(in TextureSlice textureSlice, IntPtr dataPtr, uint dataLengthInBytes)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassInactive("Cannot copy during render pass!");
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_SetTextureData(
|
Refresh.Refresh_SetTextureData(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -850,6 +1004,10 @@ namespace MoonWorks.Graphics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetTextureDataYUV(Texture yTexture, Texture uTexture, Texture vTexture, IntPtr dataPtr, uint dataLengthInBytes)
|
public void SetTextureDataYUV(Texture yTexture, Texture uTexture, Texture vTexture, IntPtr dataPtr, uint dataLengthInBytes)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassInactive("Cannot copy during render pass!");
|
||||||
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_SetTextureDataYUV(
|
Refresh.Refresh_SetTextureDataYUV(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
|
@ -877,6 +1035,10 @@ namespace MoonWorks.Graphics
|
||||||
Filter filter
|
Filter filter
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassInactive("Cannot copy during render pass!");
|
||||||
|
#endif
|
||||||
|
|
||||||
var sourceRefreshTextureSlice = sourceTextureSlice.ToRefreshTextureSlice();
|
var sourceRefreshTextureSlice = sourceTextureSlice.ToRefreshTextureSlice();
|
||||||
var destRefreshTextureSlice = destinationTextureSlice.ToRefreshTextureSlice();
|
var destRefreshTextureSlice = destinationTextureSlice.ToRefreshTextureSlice();
|
||||||
|
|
||||||
|
@ -900,6 +1062,10 @@ namespace MoonWorks.Graphics
|
||||||
Buffer buffer
|
Buffer buffer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassInactive("Cannot copy during render pass!");
|
||||||
|
#endif
|
||||||
|
|
||||||
var refreshTextureSlice = textureSlice.ToRefreshTextureSlice();
|
var refreshTextureSlice = textureSlice.ToRefreshTextureSlice();
|
||||||
|
|
||||||
Refresh.Refresh_CopyTextureToBuffer(
|
Refresh.Refresh_CopyTextureToBuffer(
|
||||||
|
@ -909,5 +1075,39 @@ namespace MoonWorks.Graphics
|
||||||
buffer.Handle
|
buffer.Handle
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
private void AssertRenderPassActive(string message = "No active render pass!")
|
||||||
|
{
|
||||||
|
if (!renderPassActive)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertRenderPassInactive(string message = "Render pass is active!")
|
||||||
|
{
|
||||||
|
if (renderPassActive)
|
||||||
|
{
|
||||||
|
throw new System.InvalidCastException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertGraphicsPipelineBound(string message = "No graphics pipeline is bound!")
|
||||||
|
{
|
||||||
|
if (currentGraphicsPipeline == null)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertComputePipelineBound(string message = "No compute pipeline is bound!")
|
||||||
|
{
|
||||||
|
if (currentComputePipeline == null)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue