ThreedClass.cs
1 using Ryujinx.Common.Memory; 2 using Ryujinx.Graphics.Device; 3 using Ryujinx.Graphics.GAL; 4 using Ryujinx.Graphics.Gpu.Engine.GPFifo; 5 using Ryujinx.Graphics.Gpu.Engine.InlineToMemory; 6 using Ryujinx.Graphics.Gpu.Engine.Threed.Blender; 7 using Ryujinx.Graphics.Gpu.Engine.Types; 8 using Ryujinx.Graphics.Gpu.Synchronization; 9 using Ryujinx.Memory.Range; 10 using System; 11 using System.Collections.Generic; 12 using System.Runtime.CompilerServices; 13 using System.Runtime.Intrinsics; 14 15 namespace Ryujinx.Graphics.Gpu.Engine.Threed 16 { 17 /// <summary> 18 /// Represents a 3D engine class. 19 /// </summary> 20 class ThreedClass : IDeviceState, IDisposable 21 { 22 private readonly GpuContext _context; 23 private readonly GPFifoClass _fifoClass; 24 private readonly DeviceStateWithShadow<ThreedClassState> _state; 25 26 private readonly InlineToMemoryClass _i2mClass; 27 private readonly AdvancedBlendManager _blendManager; 28 private readonly DrawManager _drawManager; 29 private readonly SemaphoreUpdater _semaphoreUpdater; 30 private readonly ConstantBufferUpdater _cbUpdater; 31 private readonly StateUpdater _stateUpdater; 32 33 private SetMmeShadowRamControlMode ShadowMode => _state.State.SetMmeShadowRamControlMode; 34 35 /// <summary> 36 /// Creates a new instance of the 3D engine class. 37 /// </summary> 38 /// <param name="context">GPU context</param> 39 /// <param name="channel">GPU channel</param> 40 public ThreedClass(GpuContext context, GpuChannel channel, GPFifoClass fifoClass) 41 { 42 _context = context; 43 _fifoClass = fifoClass; 44 _state = new DeviceStateWithShadow<ThreedClassState>(new Dictionary<string, RwCallback> 45 { 46 { nameof(ThreedClassState.LaunchDma), new RwCallback(LaunchDma, null) }, 47 { nameof(ThreedClassState.LoadInlineData), new RwCallback(LoadInlineData, null) }, 48 { nameof(ThreedClassState.SyncpointAction), new RwCallback(IncrementSyncpoint, null) }, 49 { nameof(ThreedClassState.InvalidateSamplerCacheNoWfi), new RwCallback(InvalidateSamplerCacheNoWfi, null) }, 50 { nameof(ThreedClassState.InvalidateTextureHeaderCacheNoWfi), new RwCallback(InvalidateTextureHeaderCacheNoWfi, null) }, 51 { nameof(ThreedClassState.TextureBarrier), new RwCallback(TextureBarrier, null) }, 52 { nameof(ThreedClassState.LoadBlendUcodeStart), new RwCallback(LoadBlendUcodeStart, null) }, 53 { nameof(ThreedClassState.LoadBlendUcodeInstruction), new RwCallback(LoadBlendUcodeInstruction, null) }, 54 { nameof(ThreedClassState.TextureBarrierTiled), new RwCallback(TextureBarrierTiled, null) }, 55 { nameof(ThreedClassState.DrawTextureSrcY), new RwCallback(DrawTexture, null) }, 56 { nameof(ThreedClassState.DrawVertexArrayBeginEndInstanceFirst), new RwCallback(DrawVertexArrayBeginEndInstanceFirst, null) }, 57 { nameof(ThreedClassState.DrawVertexArrayBeginEndInstanceSubsequent), new RwCallback(DrawVertexArrayBeginEndInstanceSubsequent, null) }, 58 { nameof(ThreedClassState.VbElementU8), new RwCallback(VbElementU8, null) }, 59 { nameof(ThreedClassState.VbElementU16), new RwCallback(VbElementU16, null) }, 60 { nameof(ThreedClassState.VbElementU32), new RwCallback(VbElementU32, null) }, 61 { nameof(ThreedClassState.ResetCounter), new RwCallback(ResetCounter, null) }, 62 { nameof(ThreedClassState.RenderEnableCondition), new RwCallback(null, Zero) }, 63 { nameof(ThreedClassState.DrawEnd), new RwCallback(DrawEnd, null) }, 64 { nameof(ThreedClassState.DrawBegin), new RwCallback(DrawBegin, null) }, 65 { nameof(ThreedClassState.DrawIndexBuffer32BeginEndInstanceFirst), new RwCallback(DrawIndexBuffer32BeginEndInstanceFirst, null) }, 66 { nameof(ThreedClassState.DrawIndexBuffer16BeginEndInstanceFirst), new RwCallback(DrawIndexBuffer16BeginEndInstanceFirst, null) }, 67 { nameof(ThreedClassState.DrawIndexBuffer8BeginEndInstanceFirst), new RwCallback(DrawIndexBuffer8BeginEndInstanceFirst, null) }, 68 { nameof(ThreedClassState.DrawIndexBuffer32BeginEndInstanceSubsequent), new RwCallback(DrawIndexBuffer32BeginEndInstanceSubsequent, null) }, 69 { nameof(ThreedClassState.DrawIndexBuffer16BeginEndInstanceSubsequent), new RwCallback(DrawIndexBuffer16BeginEndInstanceSubsequent, null) }, 70 { nameof(ThreedClassState.DrawIndexBuffer8BeginEndInstanceSubsequent), new RwCallback(DrawIndexBuffer8BeginEndInstanceSubsequent, null) }, 71 { nameof(ThreedClassState.IndexBufferCount), new RwCallback(SetIndexBufferCount, null) }, 72 { nameof(ThreedClassState.Clear), new RwCallback(Clear, null) }, 73 { nameof(ThreedClassState.SemaphoreControl), new RwCallback(Report, null) }, 74 { nameof(ThreedClassState.SetFalcon04), new RwCallback(SetFalcon04, null) }, 75 { nameof(ThreedClassState.UniformBufferUpdateData), new RwCallback(ConstantBufferUpdate, null) }, 76 { nameof(ThreedClassState.UniformBufferBindVertex), new RwCallback(ConstantBufferBindVertex, null) }, 77 { nameof(ThreedClassState.UniformBufferBindTessControl), new RwCallback(ConstantBufferBindTessControl, null) }, 78 { nameof(ThreedClassState.UniformBufferBindTessEvaluation), new RwCallback(ConstantBufferBindTessEvaluation, null) }, 79 { nameof(ThreedClassState.UniformBufferBindGeometry), new RwCallback(ConstantBufferBindGeometry, null) }, 80 { nameof(ThreedClassState.UniformBufferBindFragment), new RwCallback(ConstantBufferBindFragment, null) }, 81 }); 82 83 _i2mClass = new InlineToMemoryClass(context, channel, initializeState: false); 84 85 var spec = new SpecializationStateUpdater(context); 86 var drawState = new DrawState(); 87 88 _drawManager = new DrawManager(context, channel, _state, drawState, spec); 89 _blendManager = new AdvancedBlendManager(_state); 90 _semaphoreUpdater = new SemaphoreUpdater(context, channel, _state); 91 _cbUpdater = new ConstantBufferUpdater(channel, _state); 92 _stateUpdater = new StateUpdater(context, channel, _state, drawState, _blendManager, spec); 93 94 // This defaults to "always", even without any register write. 95 // Reads just return 0, regardless of what was set there. 96 _state.State.RenderEnableCondition = Condition.Always; 97 } 98 99 /// <summary> 100 /// Reads data from the class registers. 101 /// </summary> 102 /// <param name="offset">Register byte offset</param> 103 /// <returns>Data at the specified offset</returns> 104 [MethodImpl(MethodImplOptions.AggressiveInlining)] 105 public int Read(int offset) => _state.Read(offset); 106 107 /// <summary> 108 /// Writes data to the class registers. 109 /// </summary> 110 /// <param name="offset">Register byte offset</param> 111 /// <param name="data">Data to be written</param> 112 [MethodImpl(MethodImplOptions.AggressiveInlining)] 113 public void Write(int offset, int data) 114 { 115 _state.WriteWithRedundancyCheck(offset, data, out bool valueChanged); 116 117 if (valueChanged) 118 { 119 _stateUpdater.SetDirty(offset); 120 } 121 } 122 123 /// <summary> 124 /// Sets the shadow ram control value of all sub-channels. 125 /// </summary> 126 /// <param name="control">New shadow ram control value</param> 127 public void SetShadowRamControl(int control) 128 { 129 _state.State.SetMmeShadowRamControl = (uint)control; 130 } 131 132 /// <summary> 133 /// Updates current host state for all registers modified since the last call to this method. 134 /// </summary> 135 public void UpdateState() 136 { 137 _fifoClass.CreatePendingSyncs(); 138 _cbUpdater.FlushUboDirty(); 139 _stateUpdater.Update(); 140 } 141 142 /// <summary> 143 /// Updates current host state for all registers modified since the last call to this method. 144 /// </summary> 145 /// <param name="mask">Mask where each bit set indicates that the respective state group index should be checked</param> 146 public void UpdateState(ulong mask) 147 { 148 _stateUpdater.Update(mask); 149 } 150 151 /// <summary> 152 /// Updates render targets (color and depth-stencil buffers) based on current render target state. 153 /// </summary> 154 /// <param name="updateFlags">Flags indicating which render targets should be updated and how</param> 155 /// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param> 156 public void UpdateRenderTargetState(RenderTargetUpdateFlags updateFlags, int singleUse = -1) 157 { 158 _stateUpdater.UpdateRenderTargetState(updateFlags, singleUse); 159 } 160 161 /// <summary> 162 /// Updates scissor based on current render target state. 163 /// </summary> 164 public void UpdateScissorState() 165 { 166 _stateUpdater.UpdateScissorState(); 167 } 168 169 /// <summary> 170 /// Marks the entire state as dirty, forcing a full host state update before the next draw. 171 /// </summary> 172 public void ForceStateDirty() 173 { 174 _drawManager.ForceStateDirty(); 175 _stateUpdater.SetAllDirty(); 176 } 177 178 /// <summary> 179 /// Marks the specified register offset as dirty, forcing the associated state to update on the next draw. 180 /// </summary> 181 /// <param name="offset">Register offset</param> 182 public void ForceStateDirty(int offset) 183 { 184 _stateUpdater.SetDirty(offset); 185 } 186 187 /// <summary> 188 /// Marks the specified register range for a group index as dirty, forcing the associated state to update on the next draw. 189 /// </summary> 190 /// <param name="groupIndex">Index of the group to dirty</param> 191 public void ForceStateDirtyByIndex(int groupIndex) 192 { 193 _stateUpdater.ForceDirty(groupIndex); 194 } 195 196 /// <summary> 197 /// Forces the shaders to be rebound on the next draw. 198 /// </summary> 199 public void ForceShaderUpdate() 200 { 201 _stateUpdater.ForceShaderUpdate(); 202 } 203 204 /// <summary> 205 /// Create any syncs from WaitForIdle command that are currently pending. 206 /// </summary> 207 public void CreatePendingSyncs() 208 { 209 _fifoClass.CreatePendingSyncs(); 210 } 211 212 /// <summary> 213 /// Flushes any queued UBO updates. 214 /// </summary> 215 public void FlushUboDirty() 216 { 217 _cbUpdater.FlushUboDirty(); 218 } 219 220 /// <summary> 221 /// Perform any deferred draws. 222 /// </summary> 223 public void PerformDeferredDraws() 224 { 225 _drawManager.PerformDeferredDraws(this); 226 } 227 228 /// <summary> 229 /// Updates the currently bound constant buffer. 230 /// </summary> 231 /// <param name="data">Data to be written to the buffer</param> 232 public void ConstantBufferUpdate(ReadOnlySpan<int> data) 233 { 234 _cbUpdater.Update(data); 235 } 236 237 /// <summary> 238 /// Test if two 32 byte structs are equal. 239 /// </summary> 240 /// <typeparam name="T">Type of the 32-byte struct</typeparam> 241 /// <param name="lhs">First struct</param> 242 /// <param name="rhs">Second struct</param> 243 /// <returns>True if equal, false otherwise</returns> 244 [MethodImpl(MethodImplOptions.AggressiveInlining)] 245 private static bool UnsafeEquals32Byte<T>(ref T lhs, ref T rhs) where T : unmanaged 246 { 247 if (Vector256.IsHardwareAccelerated) 248 { 249 return Vector256.EqualsAll( 250 Unsafe.As<T, Vector256<uint>>(ref lhs), 251 Unsafe.As<T, Vector256<uint>>(ref rhs) 252 ); 253 } 254 else 255 { 256 ref var lhsVec = ref Unsafe.As<T, Vector128<uint>>(ref lhs); 257 ref var rhsVec = ref Unsafe.As<T, Vector128<uint>>(ref rhs); 258 259 return Vector128.EqualsAll(lhsVec, rhsVec) && 260 Vector128.EqualsAll(Unsafe.Add(ref lhsVec, 1), Unsafe.Add(ref rhsVec, 1)); 261 } 262 } 263 264 /// <summary> 265 /// Updates blend enable. Respects current shadow mode. 266 /// </summary> 267 /// <param name="masks">Blend enable</param> 268 public void UpdateBlendEnable(ref Array8<Boolean32> enable) 269 { 270 var shadow = ShadowMode; 271 ref var state = ref _state.State.BlendEnable; 272 273 if (shadow.IsReplay()) 274 { 275 enable = _state.ShadowState.BlendEnable; 276 } 277 278 if (!UnsafeEquals32Byte(ref enable, ref state)) 279 { 280 state = enable; 281 282 _stateUpdater.ForceDirty(StateUpdater.BlendStateIndex); 283 } 284 285 if (shadow.IsTrack()) 286 { 287 _state.ShadowState.BlendEnable = enable; 288 } 289 } 290 291 /// <summary> 292 /// Updates color masks. Respects current shadow mode. 293 /// </summary> 294 /// <param name="masks">Color masks</param> 295 public void UpdateColorMasks(ref Array8<RtColorMask> masks) 296 { 297 var shadow = ShadowMode; 298 ref var state = ref _state.State.RtColorMask; 299 300 if (shadow.IsReplay()) 301 { 302 masks = _state.ShadowState.RtColorMask; 303 } 304 305 if (!UnsafeEquals32Byte(ref masks, ref state)) 306 { 307 state = masks; 308 309 _stateUpdater.ForceDirty(StateUpdater.RtColorMaskIndex); 310 } 311 312 if (shadow.IsTrack()) 313 { 314 _state.ShadowState.RtColorMask = masks; 315 } 316 } 317 318 /// <summary> 319 /// Updates index buffer state for an indexed draw. Respects current shadow mode. 320 /// </summary> 321 /// <param name="addrHigh">High part of the address</param> 322 /// <param name="addrLow">Low part of the address</param> 323 /// <param name="type">Type of the binding</param> 324 public void UpdateIndexBuffer(uint addrHigh, uint addrLow, IndexType type) 325 { 326 var shadow = ShadowMode; 327 ref var state = ref _state.State.IndexBufferState; 328 329 if (shadow.IsReplay()) 330 { 331 ref var shadowState = ref _state.ShadowState.IndexBufferState; 332 addrHigh = shadowState.Address.High; 333 addrLow = shadowState.Address.Low; 334 type = shadowState.Type; 335 } 336 337 if (state.Address.High != addrHigh || state.Address.Low != addrLow || state.Type != type) 338 { 339 state.Address.High = addrHigh; 340 state.Address.Low = addrLow; 341 state.Type = type; 342 343 _stateUpdater.ForceDirty(StateUpdater.IndexBufferStateIndex); 344 } 345 346 if (shadow.IsTrack()) 347 { 348 ref var shadowState = ref _state.ShadowState.IndexBufferState; 349 shadowState.Address.High = addrHigh; 350 shadowState.Address.Low = addrLow; 351 shadowState.Type = type; 352 } 353 } 354 355 /// <summary> 356 /// Updates uniform buffer state for update or bind. Respects current shadow mode. 357 /// </summary> 358 /// <param name="size">Size of the binding</param> 359 /// <param name="addrHigh">High part of the addrsss</param> 360 /// <param name="addrLow">Low part of the address</param> 361 public void UpdateUniformBufferState(int size, uint addrHigh, uint addrLow) 362 { 363 var shadow = ShadowMode; 364 ref var state = ref _state.State.UniformBufferState; 365 366 if (shadow.IsReplay()) 367 { 368 ref var shadowState = ref _state.ShadowState.UniformBufferState; 369 size = shadowState.Size; 370 addrHigh = shadowState.Address.High; 371 addrLow = shadowState.Address.Low; 372 } 373 374 state.Size = size; 375 state.Address.High = addrHigh; 376 state.Address.Low = addrLow; 377 378 if (shadow.IsTrack()) 379 { 380 ref var shadowState = ref _state.ShadowState.UniformBufferState; 381 shadowState.Size = size; 382 shadowState.Address.High = addrHigh; 383 shadowState.Address.Low = addrLow; 384 } 385 } 386 387 /// <summary> 388 /// Updates a shader offset. Respects current shadow mode. 389 /// </summary> 390 /// <param name="index">Index of the shader to update</param> 391 /// <param name="offset">Offset to update with</param> 392 public void SetShaderOffset(int index, uint offset) 393 { 394 var shadow = ShadowMode; 395 ref var shaderState = ref _state.State.ShaderState[index]; 396 397 if (shadow.IsReplay()) 398 { 399 offset = _state.ShadowState.ShaderState[index].Offset; 400 } 401 402 if (shaderState.Offset != offset) 403 { 404 shaderState.Offset = offset; 405 406 _stateUpdater.ForceDirty(StateUpdater.ShaderStateIndex); 407 } 408 409 if (shadow.IsTrack()) 410 { 411 _state.ShadowState.ShaderState[index].Offset = offset; 412 } 413 } 414 415 /// <summary> 416 /// Updates uniform buffer state for update. Respects current shadow mode. 417 /// </summary> 418 /// <param name="ubState">Uniform buffer state</param> 419 public void UpdateUniformBufferState(UniformBufferState ubState) 420 { 421 var shadow = ShadowMode; 422 ref var state = ref _state.State.UniformBufferState; 423 424 if (shadow.IsReplay()) 425 { 426 ubState = _state.ShadowState.UniformBufferState; 427 } 428 429 state = ubState; 430 431 if (shadow.IsTrack()) 432 { 433 _state.ShadowState.UniformBufferState = ubState; 434 } 435 } 436 437 /// <summary> 438 /// Launches the Inline-to-Memory DMA copy operation. 439 /// </summary> 440 /// <param name="argument">Method call argument</param> 441 private void LaunchDma(int argument) 442 { 443 _i2mClass.LaunchDma(ref Unsafe.As<ThreedClassState, InlineToMemoryClassState>(ref _state.State), argument); 444 } 445 446 /// <summary> 447 /// Pushes a block of data to the Inline-to-Memory engine. 448 /// </summary> 449 /// <param name="data">Data to push</param> 450 public void LoadInlineData(ReadOnlySpan<int> data) 451 { 452 _i2mClass.LoadInlineData(data); 453 } 454 455 /// <summary> 456 /// Pushes a word of data to the Inline-to-Memory engine. 457 /// </summary> 458 /// <param name="argument">Method call argument</param> 459 private void LoadInlineData(int argument) 460 { 461 _i2mClass.LoadInlineData(argument); 462 } 463 464 /// <summary> 465 /// Performs an incrementation on a syncpoint. 466 /// </summary> 467 /// <param name="argument">Method call argument</param> 468 public void IncrementSyncpoint(int argument) 469 { 470 uint syncpointId = (uint)argument & 0xFFFF; 471 472 _context.AdvanceSequence(); 473 _context.CreateHostSyncIfNeeded(HostSyncFlags.StrictSyncpoint); 474 _context.Renderer.UpdateCounters(); // Poll the query counters, the game may want an updated result. 475 _context.Synchronization.IncrementSyncpoint(syncpointId); 476 } 477 478 /// <summary> 479 /// Invalidates the cache with the sampler descriptors from the sampler pool. 480 /// </summary> 481 /// <param name="argument">Method call argument (unused)</param> 482 private void InvalidateSamplerCacheNoWfi(int argument) 483 { 484 _context.AdvanceSequence(); 485 } 486 487 /// <summary> 488 /// Invalidates the cache with the texture descriptors from the texture pool. 489 /// </summary> 490 /// <param name="argument">Method call argument (unused)</param> 491 private void InvalidateTextureHeaderCacheNoWfi(int argument) 492 { 493 _context.AdvanceSequence(); 494 } 495 496 /// <summary> 497 /// Issues a texture barrier. 498 /// This waits until previous texture writes from the GPU to finish, before 499 /// performing new operations with said textures. 500 /// </summary> 501 /// <param name="argument">Method call argument (unused)</param> 502 private void TextureBarrier(int argument) 503 { 504 _context.Renderer.Pipeline.TextureBarrier(); 505 } 506 507 /// <summary> 508 /// Sets the start offset of the blend microcode in memory. 509 /// </summary> 510 /// <param name="argument">Method call argument</param> 511 private void LoadBlendUcodeStart(int argument) 512 { 513 _blendManager.LoadBlendUcodeStart(argument); 514 } 515 516 /// <summary> 517 /// Pushes one word of blend microcode. 518 /// </summary> 519 /// <param name="argument">Method call argument</param> 520 private void LoadBlendUcodeInstruction(int argument) 521 { 522 _blendManager.LoadBlendUcodeInstruction(argument); 523 } 524 525 /// <summary> 526 /// Issues a texture barrier. 527 /// This waits until previous texture writes from the GPU to finish, before 528 /// performing new operations with said textures. 529 /// This performs a per-tile wait, it is only valid if both the previous write 530 /// and current access has the same access patterns. 531 /// This may be faster than the regular barrier on tile-based rasterizers. 532 /// </summary> 533 /// <param name="argument">Method call argument (unused)</param> 534 private void TextureBarrierTiled(int argument) 535 { 536 _context.Renderer.Pipeline.TextureBarrierTiled(); 537 } 538 539 /// <summary> 540 /// Draws a texture, without needing to specify shader programs. 541 /// </summary> 542 /// <param name="argument">Method call argument</param> 543 private void DrawTexture(int argument) 544 { 545 _drawManager.DrawTexture(this, argument); 546 } 547 548 /// <summary> 549 /// Performs a non-indexed draw with the specified topology, index and count. 550 /// </summary> 551 /// <param name="argument">Method call argument</param> 552 private void DrawVertexArrayBeginEndInstanceFirst(int argument) 553 { 554 _drawManager.DrawVertexArrayBeginEndInstanceFirst(this, argument); 555 } 556 557 /// <summary> 558 /// Performs a non-indexed draw with the specified topology, index and count, 559 /// while incrementing the current instance. 560 /// </summary> 561 /// <param name="argument">Method call argument</param> 562 private void DrawVertexArrayBeginEndInstanceSubsequent(int argument) 563 { 564 _drawManager.DrawVertexArrayBeginEndInstanceSubsequent(this, argument); 565 } 566 567 /// <summary> 568 /// Pushes four 8-bit index buffer elements. 569 /// </summary> 570 /// <param name="argument">Method call argument</param> 571 private void VbElementU8(int argument) 572 { 573 _drawManager.VbElementU8(argument); 574 } 575 576 /// <summary> 577 /// Pushes two 16-bit index buffer elements. 578 /// </summary> 579 /// <param name="argument">Method call argument</param> 580 private void VbElementU16(int argument) 581 { 582 _drawManager.VbElementU16(argument); 583 } 584 585 /// <summary> 586 /// Pushes one 32-bit index buffer element. 587 /// </summary> 588 /// <param name="argument">Method call argument</param> 589 private void VbElementU32(int argument) 590 { 591 _drawManager.VbElementU32(argument); 592 } 593 594 /// <summary> 595 /// Resets the value of an internal GPU counter back to zero. 596 /// </summary> 597 /// <param name="argument">Method call argument</param> 598 private void ResetCounter(int argument) 599 { 600 _semaphoreUpdater.ResetCounter(argument); 601 } 602 603 /// <summary> 604 /// Finishes the draw call. 605 /// This draws geometry on the bound buffers based on the current GPU state. 606 /// </summary> 607 /// <param name="argument">Method call argument</param> 608 private void DrawEnd(int argument) 609 { 610 _drawManager.DrawEnd(this, argument); 611 } 612 613 /// <summary> 614 /// Starts draw. 615 /// This sets primitive type and instanced draw parameters. 616 /// </summary> 617 /// <param name="argument">Method call argument</param> 618 private void DrawBegin(int argument) 619 { 620 _drawManager.DrawBegin(this, argument); 621 } 622 623 /// <summary> 624 /// Sets the index buffer count. 625 /// This also sets internal state that indicates that the next draw is an indexed draw. 626 /// </summary> 627 /// <param name="argument">Method call argument</param> 628 private void SetIndexBufferCount(int argument) 629 { 630 _drawManager.SetIndexBufferCount(argument); 631 } 632 633 /// <summary> 634 /// Performs a indexed draw with 8-bit index buffer elements. 635 /// </summary> 636 /// <param name="argument">Method call argument</param> 637 private void DrawIndexBuffer8BeginEndInstanceFirst(int argument) 638 { 639 _drawManager.DrawIndexBuffer8BeginEndInstanceFirst(this, argument); 640 } 641 642 /// <summary> 643 /// Performs a indexed draw with 16-bit index buffer elements. 644 /// </summary> 645 /// <param name="argument">Method call argument</param> 646 private void DrawIndexBuffer16BeginEndInstanceFirst(int argument) 647 { 648 _drawManager.DrawIndexBuffer16BeginEndInstanceFirst(this, argument); 649 } 650 651 /// <summary> 652 /// Performs a indexed draw with 32-bit index buffer elements. 653 /// </summary> 654 /// <param name="argument">Method call argument</param> 655 private void DrawIndexBuffer32BeginEndInstanceFirst(int argument) 656 { 657 _drawManager.DrawIndexBuffer32BeginEndInstanceFirst(this, argument); 658 } 659 660 /// <summary> 661 /// Performs a indexed draw with 8-bit index buffer elements, 662 /// while also pre-incrementing the current instance value. 663 /// </summary> 664 /// <param name="argument">Method call argument</param> 665 private void DrawIndexBuffer8BeginEndInstanceSubsequent(int argument) 666 { 667 _drawManager.DrawIndexBuffer8BeginEndInstanceSubsequent(this, argument); 668 } 669 670 /// <summary> 671 /// Performs a indexed draw with 16-bit index buffer elements, 672 /// while also pre-incrementing the current instance value. 673 /// </summary> 674 /// <param name="argument">Method call argument</param> 675 private void DrawIndexBuffer16BeginEndInstanceSubsequent(int argument) 676 { 677 _drawManager.DrawIndexBuffer16BeginEndInstanceSubsequent(this, argument); 678 } 679 680 /// <summary> 681 /// Performs a indexed draw with 32-bit index buffer elements, 682 /// while also pre-incrementing the current instance value. 683 /// </summary> 684 /// <param name="argument">Method call argument</param> 685 private void DrawIndexBuffer32BeginEndInstanceSubsequent(int argument) 686 { 687 _drawManager.DrawIndexBuffer32BeginEndInstanceSubsequent(this, argument); 688 } 689 690 /// <summary> 691 /// Clears the current color and depth-stencil buffers. 692 /// Which buffers should be cleared is also specified on the argument. 693 /// </summary> 694 /// <param name="argument">Method call argument</param> 695 private void Clear(int argument) 696 { 697 _drawManager.Clear(this, argument); 698 } 699 700 /// <summary> 701 /// Writes a GPU counter to guest memory. 702 /// </summary> 703 /// <param name="argument">Method call argument</param> 704 private void Report(int argument) 705 { 706 _semaphoreUpdater.Report(argument); 707 } 708 709 /// <summary> 710 /// Performs high-level emulation of Falcon microcode function number "4". 711 /// </summary> 712 /// <param name="argument">Method call argument</param> 713 private void SetFalcon04(int argument) 714 { 715 _state.State.SetMmeShadowScratch[0] = 1; 716 } 717 718 /// <summary> 719 /// Updates the uniform buffer data with inline data. 720 /// </summary> 721 /// <param name="argument">New uniform buffer data word</param> 722 private void ConstantBufferUpdate(int argument) 723 { 724 _cbUpdater.Update(argument); 725 } 726 727 /// <summary> 728 /// Binds a uniform buffer for the vertex shader stage. 729 /// </summary> 730 /// <param name="argument">Method call argument</param> 731 private void ConstantBufferBindVertex(int argument) 732 { 733 _cbUpdater.BindVertex(argument); 734 } 735 736 /// <summary> 737 /// Binds a uniform buffer for the tessellation control shader stage. 738 /// </summary> 739 /// <param name="argument">Method call argument</param> 740 private void ConstantBufferBindTessControl(int argument) 741 { 742 _cbUpdater.BindTessControl(argument); 743 } 744 745 /// <summary> 746 /// Binds a uniform buffer for the tessellation evaluation shader stage. 747 /// </summary> 748 /// <param name="argument">Method call argument</param> 749 private void ConstantBufferBindTessEvaluation(int argument) 750 { 751 _cbUpdater.BindTessEvaluation(argument); 752 } 753 754 /// <summary> 755 /// Binds a uniform buffer for the geometry shader stage. 756 /// </summary> 757 /// <param name="argument">Method call argument</param> 758 private void ConstantBufferBindGeometry(int argument) 759 { 760 _cbUpdater.BindGeometry(argument); 761 } 762 763 /// <summary> 764 /// Binds a uniform buffer for the fragment shader stage. 765 /// </summary> 766 /// <param name="argument">Method call argument</param> 767 private void ConstantBufferBindFragment(int argument) 768 { 769 _cbUpdater.BindFragment(argument); 770 } 771 772 /// <summary> 773 /// Generic register read function that just returns 0. 774 /// </summary> 775 /// <returns>Zero</returns> 776 private static int Zero() 777 { 778 return 0; 779 } 780 781 /// <summary> 782 /// Performs a indexed or non-indexed draw. 783 /// </summary> 784 /// <param name="topology">Primitive topology</param> 785 /// <param name="count">Index count for indexed draws, vertex count for non-indexed draws</param> 786 /// <param name="instanceCount">Instance count</param> 787 /// <param name="firstIndex">First index on the index buffer for indexed draws, ignored for non-indexed draws</param> 788 /// <param name="firstVertex">First vertex on the vertex buffer</param> 789 /// <param name="firstInstance">First instance</param> 790 /// <param name="indexed">True if the draw is indexed, false otherwise</param> 791 public void Draw( 792 PrimitiveTopology topology, 793 int count, 794 int instanceCount, 795 int firstIndex, 796 int firstVertex, 797 int firstInstance, 798 bool indexed) 799 { 800 _drawManager.Draw(this, topology, count, instanceCount, firstIndex, firstVertex, firstInstance, indexed); 801 } 802 803 /// <summary> 804 /// Performs a indirect draw, with parameters from a GPU buffer. 805 /// </summary> 806 /// <param name="topology">Primitive topology</param> 807 /// <param name="indirectBufferRange">Memory range of the buffer with the draw parameters, such as count, first index, etc</param> 808 /// <param name="parameterBufferRange">Memory range of the buffer with the draw count</param> 809 /// <param name="maxDrawCount">Maximum number of draws that can be made</param> 810 /// <param name="stride">Distance in bytes between each entry on the data pointed to by <paramref name="indirectBufferRange"/></param> 811 /// <param name="indexCount">Maximum number of indices that the draw can consume</param> 812 /// <param name="drawType">Type of the indirect draw, which can be indexed or non-indexed, with or without a draw count</param> 813 public void DrawIndirect( 814 PrimitiveTopology topology, 815 MultiRange indirectBufferRange, 816 MultiRange parameterBufferRange, 817 int maxDrawCount, 818 int stride, 819 int indexCount, 820 IndirectDrawType drawType) 821 { 822 _drawManager.DrawIndirect(this, topology, indirectBufferRange, parameterBufferRange, maxDrawCount, stride, indexCount, drawType); 823 } 824 825 /// <summary> 826 /// Clears the current color and depth-stencil buffers. 827 /// Which buffers should be cleared can also specified with the arguments. 828 /// </summary> 829 /// <param name="argument">Method call argument</param> 830 /// <param name="layerCount">For array and 3D textures, indicates how many layers should be cleared</param> 831 public void Clear(int argument, int layerCount) 832 { 833 _drawManager.Clear(this, argument, layerCount); 834 } 835 836 protected virtual void Dispose(bool disposing) 837 { 838 if (disposing) 839 { 840 _drawManager.Dispose(); 841 } 842 } 843 844 public void Dispose() 845 { 846 Dispose(true); 847 GC.SuppressFinalize(this); 848 } 849 } 850 }