/// <summary> /// Starts draw. /// This sets primitive type and instanced draw parameters. /// </summary> /// <param name="argument">Method call argument</param> public void DrawBegin(int argument) { bool incrementInstance = (argument & (1 << 26)) != 0; bool resetInstance = (argument & (1 << 27)) == 0; if (_state.State.PrimitiveTypeOverrideEnable) { PrimitiveTypeOverride typeOverride = _state.State.PrimitiveTypeOverride; DrawBegin(incrementInstance, resetInstance, typeOverride.Convert()); } else { PrimitiveType type = (PrimitiveType)(argument & 0xffff); DrawBegin(incrementInstance, resetInstance, type.Convert()); } }
/// <summary> /// Starts draw. /// This sets primitive type and instanced draw parameters. /// </summary> /// <param name="state">Current GPU state</param> /// <param name="argument">Method call argument</param> private void DrawBegin(GpuState state, int argument) { bool incrementInstance = (argument & (1 << 26)) != 0; bool resetInstance = (argument & (1 << 27)) == 0; PrimitiveType type = (PrimitiveType)(argument & 0xffff); PrimitiveTypeOverride typeOverride = state.Get <PrimitiveTypeOverride>(MethodOffset.PrimitiveTypeOverride); if (typeOverride != PrimitiveTypeOverride.Invalid) { DrawBegin(incrementInstance, resetInstance, typeOverride.Convert()); } else { DrawBegin(incrementInstance, resetInstance, type.Convert()); } }
/// <summary> /// Starts draw. /// This sets primitive type and instanced draw parameters. /// </summary> /// <param name="state">Current GPU state</param> /// <param name="argument">Method call argument</param> private void DrawBegin(GpuState state, int argument) { if ((argument & (1 << 26)) != 0) { _instanceIndex++; } else if ((argument & (1 << 27)) == 0) { PerformDeferredDraws(); _instanceIndex = 0; } PrimitiveType type = (PrimitiveType)(argument & 0xffff); _context.Renderer.Pipeline.SetPrimitiveTopology(type.Convert()); PrimitiveType = type; }
/// <summary> /// Updates host state based on the current guest GPU state. /// </summary> /// <param name="state">Guest GPU state</param> private void UpdateState(GpuState state) { bool tfEnable = state.Get <Boolean32>(MethodOffset.TfEnable); if (!tfEnable && _prevTfEnable) { _context.Renderer.Pipeline.EndTransformFeedback(); _prevTfEnable = false; } // Shaders must be the first one to be updated if modified, because // some of the other state depends on information from the currently // bound shaders. if (state.QueryModified(MethodOffset.ShaderBaseAddress, MethodOffset.ShaderState) || _forceShaderUpdate) { _forceShaderUpdate = false; UpdateShaderState(state); } if (state.QueryModified(MethodOffset.TfBufferState)) { UpdateTfBufferState(state); } if (state.QueryModified(MethodOffset.ClipDistanceEnable)) { UpdateUserClipState(state); } if (state.QueryModified(MethodOffset.RasterizeEnable)) { UpdateRasterizerState(state); } if (state.QueryModified(MethodOffset.RtColorState, MethodOffset.RtDepthStencilState, MethodOffset.RtControl, MethodOffset.RtDepthStencilSize, MethodOffset.RtDepthStencilEnable)) { UpdateRenderTargetState(state, useControl: true); } if (state.QueryModified(MethodOffset.ScissorState)) { UpdateScissorState(state); } if (state.QueryModified(MethodOffset.ViewVolumeClipControl)) { UpdateDepthClampState(state); } if (state.QueryModified(MethodOffset.AlphaTestEnable, MethodOffset.AlphaTestRef, MethodOffset.AlphaTestFunc)) { UpdateAlphaTestState(state); } if (state.QueryModified(MethodOffset.DepthTestEnable, MethodOffset.DepthWriteEnable, MethodOffset.DepthTestFunc)) { UpdateDepthTestState(state); } if (state.QueryModified(MethodOffset.DepthMode, MethodOffset.ViewportTransform, MethodOffset.ViewportExtents)) { UpdateViewportTransform(state); } if (state.QueryModified(MethodOffset.DepthBiasState, MethodOffset.DepthBiasFactor, MethodOffset.DepthBiasUnits, MethodOffset.DepthBiasClamp)) { UpdateDepthBiasState(state); } if (state.QueryModified(MethodOffset.StencilBackMasks, MethodOffset.StencilTestState, MethodOffset.StencilBackTestState)) { UpdateStencilTestState(state); } // Pools. if (state.QueryModified(MethodOffset.SamplerPoolState, MethodOffset.SamplerIndex)) { UpdateSamplerPoolState(state); } if (state.QueryModified(MethodOffset.TexturePoolState)) { UpdateTexturePoolState(state); } // Input assembler state. if (state.QueryModified(MethodOffset.VertexAttribState)) { UpdateVertexAttribState(state); } if (state.QueryModified(MethodOffset.PointSize, MethodOffset.VertexProgramPointSize, MethodOffset.PointSpriteEnable, MethodOffset.PointCoordReplace)) { UpdatePointState(state); } if (state.QueryModified(MethodOffset.PrimitiveRestartState)) { UpdatePrimitiveRestartState(state); } if (state.QueryModified(MethodOffset.IndexBufferState)) { UpdateIndexBufferState(state); } if (state.QueryModified(MethodOffset.VertexBufferDrawState, MethodOffset.VertexBufferInstanced, MethodOffset.VertexBufferState, MethodOffset.VertexBufferEndAddress)) { UpdateVertexBufferState(state); } if (state.QueryModified(MethodOffset.FaceState)) { UpdateFaceState(state); } if (state.QueryModified(MethodOffset.RtColorMaskShared, MethodOffset.RtColorMask)) { UpdateRtColorMask(state); } if (state.QueryModified(MethodOffset.BlendIndependent, MethodOffset.BlendConstant, MethodOffset.BlendStateCommon, MethodOffset.BlendEnableCommon, MethodOffset.BlendEnable, MethodOffset.BlendState)) { UpdateBlendState(state); } if (state.QueryModified(MethodOffset.LogicOpState)) { UpdateLogicOpState(state); } CommitBindings(); if (tfEnable && !_prevTfEnable) { _context.Renderer.Pipeline.BeginTransformFeedback(PrimitiveType.Convert()); _prevTfEnable = true; } }