Implement HLE macro for DrawElementsIndirect (#3748)
* Implement HLE macro for DrawElementsIndirect * Shader cache version bump * Use GL_ARB_shader_draw_parameters extension on OpenGL * Fix DrawIndexedIndirectCount on Vulkan when extension is not supported * Implement DrawIndex * Alignment * Fix some validation errors * Rename BaseIds to DrawParameters * Fix incorrect index buffer and vertex buffer size in some cases * Add HLE macros for DrawArraysInstanced and DrawElementsInstanced * Perform a regular draw when indirect data is not modified * Use non-indirect draw methods if indirect buffer was not GPU modified * Only check if draw parameters match if the shader actually uses them * Expose Macro HLE setting on GUI * Reset FirstVertex and FirstInstance after draw * Update shader cache version again since some people already tested this * PR feedback Co-authored-by: riperiperi <rhy3756547@hotmail.com>
This commit is contained in:
parent
b8de72de8f
commit
f1d1670b0b
60 changed files with 2336 additions and 277 deletions
|
@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
else
|
||||
{
|
||||
evt.Flush();
|
||||
return (memoryManager.Read<ulong>(gpuVa) != 0) ? ConditionalRenderEnabled.True : ConditionalRenderEnabled.False;
|
||||
return (memoryManager.Read<ulong>(gpuVa, true) != 0) ? ConditionalRenderEnabled.True : ConditionalRenderEnabled.False;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,8 +108,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
evt?.Flush();
|
||||
evt2?.Flush();
|
||||
|
||||
ulong x = memoryManager.Read<ulong>(gpuVa);
|
||||
ulong y = memoryManager.Read<ulong>(gpuVa + 16);
|
||||
ulong x = memoryManager.Read<ulong>(gpuVa, true);
|
||||
ulong y = memoryManager.Read<ulong>(gpuVa + 16, true);
|
||||
|
||||
return (isEqual ? x == y : x != y) ? ConditionalRenderEnabled.True : ConditionalRenderEnabled.False;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Gpu.Engine.Types;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
|
@ -9,6 +10,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
/// </summary>
|
||||
class DrawManager
|
||||
{
|
||||
// Since we don't know the index buffer size for indirect draws,
|
||||
// we must assume a minimum and maximum size and use that for buffer data update purposes.
|
||||
private const int MinIndirectIndexCount = 0x10000;
|
||||
private const int MaxIndirectIndexCount = 0x4000000;
|
||||
|
||||
private readonly GpuContext _context;
|
||||
private readonly GpuChannel _channel;
|
||||
private readonly DeviceStateWithShadow<ThreedClassState> _state;
|
||||
|
@ -28,6 +34,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
|
||||
private int _instanceIndex;
|
||||
|
||||
private const int VertexBufferFirstMethodOffset = 0x35d;
|
||||
private const int IndexBufferCountMethodOffset = 0x5f8;
|
||||
|
||||
/// <summary>
|
||||
|
@ -237,6 +244,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
_instanceIndex = 0;
|
||||
}
|
||||
|
||||
UpdateTopology(topology);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current primitive topology if needed.
|
||||
/// </summary>
|
||||
/// <param name="topology">New primitive topology</param>
|
||||
private void UpdateTopology(PrimitiveTopology topology)
|
||||
{
|
||||
if (_drawState.Topology != topology || !_topologySet)
|
||||
{
|
||||
_context.Renderer.Pipeline.SetPrimitiveTopology(topology);
|
||||
|
@ -383,28 +399,27 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a indirect multi-draw, with parameters from a GPU buffer.
|
||||
/// Performs a indexed or non-indexed draw.
|
||||
/// </summary>
|
||||
/// <param name="engine">3D engine where this method is being called</param>
|
||||
/// <param name="topology">Primitive topology</param>
|
||||
/// <param name="indirectBuffer">GPU buffer with the draw parameters, such as count, first index, etc</param>
|
||||
/// <param name="parameterBuffer">GPU buffer with the draw count</param>
|
||||
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
||||
/// <param name="stride">Distance in bytes between each element on the <paramref name="indirectBuffer"/> array</param>
|
||||
public void MultiDrawIndirectCount(
|
||||
/// <param name="count">Index count for indexed draws, vertex count for non-indexed draws</param>
|
||||
/// <param name="instanceCount">Instance count</param>
|
||||
/// <param name="firstIndex">First index on the index buffer for indexed draws, ignored for non-indexed draws</param>
|
||||
/// <param name="firstVertex">First vertex on the vertex buffer</param>
|
||||
/// <param name="firstInstance">First instance</param>
|
||||
/// <param name="indexed">True if the draw is indexed, false otherwise</param>
|
||||
public void Draw(
|
||||
ThreedClass engine,
|
||||
int indexCount,
|
||||
PrimitiveTopology topology,
|
||||
BufferRange indirectBuffer,
|
||||
BufferRange parameterBuffer,
|
||||
int maxDrawCount,
|
||||
int stride)
|
||||
int count,
|
||||
int instanceCount,
|
||||
int firstIndex,
|
||||
int firstVertex,
|
||||
int firstInstance,
|
||||
bool indexed)
|
||||
{
|
||||
engine.Write(IndexBufferCountMethodOffset * 4, indexCount);
|
||||
|
||||
_context.Renderer.Pipeline.SetPrimitiveTopology(topology);
|
||||
_drawState.Topology = topology;
|
||||
_topologySet = true;
|
||||
UpdateTopology(topology);
|
||||
|
||||
ConditionalRenderEnabled renderEnable = ConditionalRendering.GetRenderEnable(
|
||||
_context,
|
||||
|
@ -418,21 +433,133 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
return;
|
||||
}
|
||||
|
||||
_drawState.FirstIndex = _state.State.IndexBufferState.First;
|
||||
_drawState.IndexCount = indexCount;
|
||||
|
||||
engine.UpdateState();
|
||||
|
||||
if (_drawState.DrawIndexed)
|
||||
if (indexed)
|
||||
{
|
||||
_context.Renderer.Pipeline.MultiDrawIndexedIndirectCount(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||
_drawState.FirstIndex = firstIndex;
|
||||
_drawState.IndexCount = count;
|
||||
_state.State.FirstVertex = (uint)firstVertex;
|
||||
engine.ForceStateDirty(IndexBufferCountMethodOffset * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
_context.Renderer.Pipeline.MultiDrawIndirectCount(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||
_state.State.VertexBufferDrawState.First = firstVertex;
|
||||
_state.State.VertexBufferDrawState.Count = count;
|
||||
engine.ForceStateDirty(VertexBufferFirstMethodOffset * 4);
|
||||
}
|
||||
|
||||
_state.State.FirstInstance = (uint)firstInstance;
|
||||
|
||||
_drawState.DrawIndexed = indexed;
|
||||
_drawState.HasConstantBufferDrawParameters = true;
|
||||
|
||||
engine.UpdateState();
|
||||
|
||||
if (indexed)
|
||||
{
|
||||
_context.Renderer.Pipeline.DrawIndexed(count, instanceCount, firstIndex, firstVertex, firstInstance);
|
||||
_state.State.FirstVertex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_context.Renderer.Pipeline.Draw(count, instanceCount, firstVertex, firstInstance);
|
||||
}
|
||||
|
||||
_state.State.FirstInstance = 0;
|
||||
|
||||
_drawState.DrawIndexed = false;
|
||||
_drawState.HasConstantBufferDrawParameters = false;
|
||||
|
||||
if (renderEnable == ConditionalRenderEnabled.Host)
|
||||
{
|
||||
_context.Renderer.Pipeline.EndHostConditionalRendering();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a indirect draw, with parameters from a GPU buffer.
|
||||
/// </summary>
|
||||
/// <param name="engine">3D engine where this method is being called</param>
|
||||
/// <param name="topology">Primitive topology</param>
|
||||
/// <param name="indirectBufferAddress">Address of the buffer with the draw parameters, such as count, first index, etc</param>
|
||||
/// <param name="parameterBufferAddress">Address of the buffer with the draw count</param>
|
||||
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
||||
/// <param name="stride">Distance in bytes between each entry on the data pointed to by <paramref name="indirectBufferAddress"/></param>
|
||||
/// <param name="indexCount">Maximum number of indices that the draw can consume</param>
|
||||
/// <param name="drawType">Type of the indirect draw, which can be indexed or non-indexed, with or without a draw count</param>
|
||||
public void DrawIndirect(
|
||||
ThreedClass engine,
|
||||
PrimitiveTopology topology,
|
||||
ulong indirectBufferAddress,
|
||||
ulong parameterBufferAddress,
|
||||
int maxDrawCount,
|
||||
int stride,
|
||||
int indexCount,
|
||||
IndirectDrawType drawType)
|
||||
{
|
||||
UpdateTopology(topology);
|
||||
|
||||
ConditionalRenderEnabled renderEnable = ConditionalRendering.GetRenderEnable(
|
||||
_context,
|
||||
_channel.MemoryManager,
|
||||
_state.State.RenderEnableAddress,
|
||||
_state.State.RenderEnableCondition);
|
||||
|
||||
if (renderEnable == ConditionalRenderEnabled.False)
|
||||
{
|
||||
_drawState.DrawIndexed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
PhysicalMemory memory = _channel.MemoryManager.Physical;
|
||||
|
||||
bool hasCount = (drawType & IndirectDrawType.Count) != 0;
|
||||
bool indexed = (drawType & IndirectDrawType.Indexed) != 0;
|
||||
|
||||
if (indexed)
|
||||
{
|
||||
indexCount = Math.Clamp(indexCount, MinIndirectIndexCount, MaxIndirectIndexCount);
|
||||
_drawState.FirstIndex = 0;
|
||||
_drawState.IndexCount = indexCount;
|
||||
engine.ForceStateDirty(IndexBufferCountMethodOffset * 4);
|
||||
}
|
||||
|
||||
_drawState.DrawIndexed = indexed;
|
||||
_drawState.DrawIndirect = true;
|
||||
_drawState.HasConstantBufferDrawParameters = true;
|
||||
|
||||
engine.UpdateState();
|
||||
|
||||
if (hasCount)
|
||||
{
|
||||
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferAddress, (ulong)maxDrawCount * (ulong)stride);
|
||||
var parameterBuffer = memory.BufferCache.GetBufferRange(parameterBufferAddress, 4);
|
||||
|
||||
if (indexed)
|
||||
{
|
||||
_context.Renderer.Pipeline.DrawIndexedIndirectCount(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
_context.Renderer.Pipeline.DrawIndirectCount(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferAddress, (ulong)stride);
|
||||
|
||||
if (indexed)
|
||||
{
|
||||
_context.Renderer.Pipeline.DrawIndexedIndirect(indirectBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
_context.Renderer.Pipeline.DrawIndirect(indirectBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
_drawState.DrawIndexed = false;
|
||||
_drawState.DrawIndirect = false;
|
||||
_drawState.HasConstantBufferDrawParameters = false;
|
||||
|
||||
if (renderEnable == ConditionalRenderEnabled.Host)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
/// </summary>
|
||||
public bool DrawIndexed;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the next draw will be a indirect draw.
|
||||
/// </summary>
|
||||
public bool DrawIndirect;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if any of the currently used vertex shaders reads the instance ID.
|
||||
/// </summary>
|
||||
|
@ -32,6 +37,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
/// </summary>
|
||||
public bool IsAnyVbInstanced;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0.
|
||||
/// </summary>
|
||||
public bool HasConstantBufferDrawParameters;
|
||||
|
||||
/// <summary>
|
||||
/// Primitive topology for the next draw.
|
||||
/// </summary>
|
||||
|
|
38
Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs
Normal file
38
Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
{
|
||||
/// <summary>
|
||||
/// Indirect draw type, which can be indexed or non-indexed, with or without a draw count.
|
||||
/// </summary>
|
||||
enum IndirectDrawType
|
||||
{
|
||||
/// <summary>
|
||||
/// Non-indexed draw without draw count.
|
||||
/// </summary>
|
||||
DrawIndirect = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Indexed draw without draw count.
|
||||
/// </summary>
|
||||
DrawIndexedIndirect = Indexed,
|
||||
|
||||
/// <summary>
|
||||
/// Non-indexed draw with draw count.
|
||||
/// </summary>
|
||||
DrawIndirectCount = Count,
|
||||
|
||||
/// <summary>
|
||||
/// Indexed draw with draw count.
|
||||
/// </summary>
|
||||
DrawIndexedIndirectCount = Indexed | Count,
|
||||
|
||||
/// <summary>
|
||||
/// Indexed flag.
|
||||
/// </summary>
|
||||
Indexed = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// Draw count flag.
|
||||
/// </summary>
|
||||
Count = 1 << 1
|
||||
}
|
||||
}
|
|
@ -34,10 +34,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
|
||||
private ProgramPipelineState _pipeline;
|
||||
|
||||
private bool _vsUsesDrawParameters;
|
||||
private bool _vtgWritesRtLayer;
|
||||
private byte _vsClipDistancesWritten;
|
||||
|
||||
private bool _prevDrawIndexed;
|
||||
private bool _prevDrawIndirect;
|
||||
private IndexType _prevIndexType;
|
||||
private uint _prevFirstVertex;
|
||||
private bool _prevTfEnable;
|
||||
|
@ -210,7 +212,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
// of the shader for the new state.
|
||||
if (_shaderSpecState != null)
|
||||
{
|
||||
if (!_shaderSpecState.MatchesGraphics(_channel, GetPoolState(), GetGraphicsState(), false))
|
||||
if (!_shaderSpecState.MatchesGraphics(_channel, GetPoolState(), GetGraphicsState(), _vsUsesDrawParameters, false))
|
||||
{
|
||||
ForceShaderUpdate();
|
||||
}
|
||||
|
@ -237,6 +239,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
_prevDrawIndexed = _drawState.DrawIndexed;
|
||||
}
|
||||
|
||||
// Some draw parameters are used to restrict the vertex buffer size,
|
||||
// but they can't be used on indirect draws because their values are unknown in this case.
|
||||
// When switching between indirect and non-indirect draw, we need to
|
||||
// make sure the vertex buffer sizes are still correct.
|
||||
if (_drawState.DrawIndirect != _prevDrawIndirect)
|
||||
{
|
||||
_updateTracker.ForceDirty(VertexBufferStateIndex);
|
||||
}
|
||||
|
||||
// In some cases, the index type is also used to guess the
|
||||
// vertex buffer size, so we must update it if the type changed too.
|
||||
if (_drawState.DrawIndexed &&
|
||||
|
@ -938,6 +949,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
|
||||
_drawState.IsAnyVbInstanced = false;
|
||||
|
||||
bool drawIndexed = _drawState.DrawIndexed;
|
||||
bool drawIndirect = _drawState.DrawIndirect;
|
||||
|
||||
for (int index = 0; index < Constants.TotalVertexBuffers; index++)
|
||||
{
|
||||
var vertexBuffer = _state.State.VertexBufferState[index];
|
||||
|
@ -965,14 +979,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
ulong vbSize = endAddress.Pack() - address + 1;
|
||||
ulong size;
|
||||
|
||||
if (_drawState.IbStreamer.HasInlineIndexData || _drawState.DrawIndexed || stride == 0 || instanced)
|
||||
if (_drawState.IbStreamer.HasInlineIndexData || drawIndexed || stride == 0 || instanced)
|
||||
{
|
||||
// This size may be (much) larger than the real vertex buffer size.
|
||||
// Avoid calculating it this way, unless we don't have any other option.
|
||||
|
||||
size = vbSize;
|
||||
|
||||
if (stride > 0 && indexTypeSmall && _drawState.DrawIndexed && !instanced)
|
||||
if (stride > 0 && indexTypeSmall && drawIndexed && !drawIndirect && !instanced)
|
||||
{
|
||||
// If the index type is a small integer type, then we might be still able
|
||||
// to reduce the vertex buffer size based on the maximum possible index value.
|
||||
|
@ -1207,6 +1221,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
byte oldVsClipDistancesWritten = _vsClipDistancesWritten;
|
||||
|
||||
_drawState.VsUsesInstanceId = gs.Shaders[1]?.Info.UsesInstanceId ?? false;
|
||||
_vsUsesDrawParameters = gs.Shaders[1]?.Info.UsesDrawParameters ?? false;
|
||||
_vsClipDistancesWritten = gs.Shaders[1]?.Info.ClipDistancesWritten ?? 0;
|
||||
|
||||
if (oldVsClipDistancesWritten != _vsClipDistancesWritten)
|
||||
|
@ -1222,6 +1237,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
_context.Renderer.Pipeline.SetProgram(gs.HostProgram);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates bindings consumed by the shader stage on the texture and buffer managers.
|
||||
/// </summary>
|
||||
/// <param name="stage">Shader stage to have the bindings updated</param>
|
||||
/// <param name="info">Shader stage bindings info</param>
|
||||
private void UpdateStageBindings(int stage, ShaderProgramInfo info)
|
||||
{
|
||||
_currentProgramInfo[stage] = info;
|
||||
|
@ -1340,7 +1360,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
_state.State.AlphaTestEnable,
|
||||
_state.State.AlphaTestFunc,
|
||||
_state.State.AlphaTestRef,
|
||||
ref attributeTypes);
|
||||
ref attributeTypes,
|
||||
_drawState.HasConstantBufferDrawParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -497,6 +497,50 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a indexed or non-indexed draw.
|
||||
/// </summary>
|
||||
/// <param name="topology">Primitive topology</param>
|
||||
/// <param name="count">Index count for indexed draws, vertex count for non-indexed draws</param>
|
||||
/// <param name="instanceCount">Instance count</param>
|
||||
/// <param name="firstIndex">First index on the index buffer for indexed draws, ignored for non-indexed draws</param>
|
||||
/// <param name="firstVertex">First vertex on the vertex buffer</param>
|
||||
/// <param name="firstInstance">First instance</param>
|
||||
/// <param name="indexed">True if the draw is indexed, false otherwise</param>
|
||||
public void Draw(
|
||||
PrimitiveTopology topology,
|
||||
int count,
|
||||
int instanceCount,
|
||||
int firstIndex,
|
||||
int firstVertex,
|
||||
int firstInstance,
|
||||
bool indexed)
|
||||
{
|
||||
_drawManager.Draw(this, topology, count, instanceCount, firstIndex, firstVertex, firstInstance, indexed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a indirect draw, with parameters from a GPU buffer.
|
||||
/// </summary>
|
||||
/// <param name="topology">Primitive topology</param>
|
||||
/// <param name="indirectBufferAddress">Address of the buffer with the draw parameters, such as count, first index, etc</param>
|
||||
/// <param name="parameterBufferAddress">Address of the buffer with the draw count</param>
|
||||
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
||||
/// <param name="stride">Distance in bytes between each entry on the data pointed to by <paramref name="indirectBufferAddress"/></param>
|
||||
/// <param name="indexCount">Maximum number of indices that the draw can consume</param>
|
||||
/// <param name="drawType">Type of the indirect draw, which can be indexed or non-indexed, with or without a draw count</param>
|
||||
public void DrawIndirect(
|
||||
PrimitiveTopology topology,
|
||||
ulong indirectBufferAddress,
|
||||
ulong parameterBufferAddress,
|
||||
int maxDrawCount,
|
||||
int stride,
|
||||
int indexCount,
|
||||
IndirectDrawType drawType)
|
||||
{
|
||||
_drawManager.DrawIndirect(this, topology, indirectBufferAddress, parameterBufferAddress, maxDrawCount, stride, indexCount, drawType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the current color and depth-stencil buffers.
|
||||
/// Which buffers should be cleared can also specified with the arguments.
|
||||
|
@ -507,25 +551,5 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
{
|
||||
_drawManager.Clear(this, argument, layerCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a indirect multi-draw, with parameters from a GPU buffer.
|
||||
/// </summary>
|
||||
/// <param name="indexCount">Index Buffer Count</param>
|
||||
/// <param name="topology">Primitive topology</param>
|
||||
/// <param name="indirectBuffer">GPU buffer with the draw parameters, such as count, first index, etc</param>
|
||||
/// <param name="parameterBuffer">GPU buffer with the draw count</param>
|
||||
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
||||
/// <param name="stride">Distance in bytes between each element on the <paramref name="indirectBuffer"/> array</param>
|
||||
public void MultiDrawIndirectCount(
|
||||
int indexCount,
|
||||
PrimitiveTopology topology,
|
||||
BufferRange indirectBuffer,
|
||||
BufferRange parameterBuffer,
|
||||
int maxDrawCount,
|
||||
int stride)
|
||||
{
|
||||
_drawManager.MultiDrawIndirectCount(this, indexCount, topology, indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue