/// <summary> /// Clears the current color and depth-stencil buffers. /// Which buffers should be cleared is also specified on the argument. /// </summary> /// <param name="state">Current GPU state</param> /// <param name="argument">Method call argument</param> private void Clear(GpuState state, int argument) { if (!GetRenderEnable(state)) { return; } // Scissor affects clears aswell. if (state.QueryModified(MethodOffset.ScissorState)) { UpdateScissorState(state); } UpdateRenderTargetState(state, useControl: false); TextureManager.CommitGraphicsBindings(); bool clearDepth = (argument & 1) != 0; bool clearStencil = (argument & 2) != 0; uint componentMask = (uint)((argument >> 2) & 0xf); int index = (argument >> 6) & 0xf; if (componentMask != 0) { var clearColor = state.Get <ClearColors>(MethodOffset.ClearColors); ColorF color = new ColorF( clearColor.Red, clearColor.Green, clearColor.Blue, clearColor.Alpha); _context.Renderer.Pipeline.ClearRenderTargetColor(index, componentMask, color); } if (clearDepth || clearStencil) { float depthValue = state.Get <float>(MethodOffset.ClearDepthValue); int stencilValue = state.Get <int> (MethodOffset.ClearStencilValue); int stencilMask = 0; if (clearStencil) { stencilMask = state.Get <StencilTestState>(MethodOffset.StencilTestState).FrontMask; } _context.Renderer.Pipeline.ClearRenderTargetDepthStencil( depthValue, clearDepth, stencilValue, stencilMask); } UpdateRenderTargetState(state, useControl: true); }
/// <summary> /// Updates host state based on the current guest GPU state. /// </summary> /// <param name="state">Guest GPU state</param> /// <param name="firstIndex">Index of the first index buffer element used on the draw</param> /// <param name="indexCount">Number of index buffer elements used on the draw</param> private void UpdateState(GpuState state, int firstIndex, int indexCount) { 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, firstIndex, indexCount); } 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(Topology); _prevTfEnable = true; } }
/// <summary> /// Updates host state based on the current guest GPU state. /// </summary> /// <param name="state">Guest GPU state</param> private void UpdateState(GpuState state) { // 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.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.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)) { UpdatePointSizeState(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(); }
/// <summary> /// Clears the current color and depth-stencil buffers. /// Which buffers should be cleared is also specified on the argument. /// </summary> /// <param name="state">Current GPU state</param> /// <param name="argument">Method call argument</param> private void Clear(GpuState state, int argument) { ConditionalRenderEnabled renderEnable = GetRenderEnable(state); if (renderEnable == ConditionalRenderEnabled.False) { return; } // Scissor and rasterizer discard also affect clears. if (state.QueryModified(MethodOffset.ScissorState)) { UpdateScissorState(state); } if (state.QueryModified(MethodOffset.RasterizeEnable)) { UpdateRasterizerState(state); } int index = (argument >> 6) & 0xf; UpdateRenderTargetState(state, useControl: false, singleUse: index); state.Channel.TextureManager.UpdateRenderTargets(); bool clearDepth = (argument & 1) != 0; bool clearStencil = (argument & 2) != 0; uint componentMask = (uint)((argument >> 2) & 0xf); if (componentMask != 0) { var clearColor = state.Get <ClearColors>(MethodOffset.ClearColors); ColorF color = new ColorF( clearColor.Red, clearColor.Green, clearColor.Blue, clearColor.Alpha); _context.Renderer.Pipeline.ClearRenderTargetColor(index, componentMask, color); } if (clearDepth || clearStencil) { float depthValue = state.Get <float>(MethodOffset.ClearDepthValue); int stencilValue = state.Get <int> (MethodOffset.ClearStencilValue); int stencilMask = 0; if (clearStencil) { stencilMask = state.Get <StencilTestState>(MethodOffset.StencilTestState).FrontMask; } _context.Renderer.Pipeline.ClearRenderTargetDepthStencil( depthValue, clearDepth, stencilValue, stencilMask); } UpdateRenderTargetState(state, useControl: true); if (renderEnable == ConditionalRenderEnabled.Host) { _context.Renderer.Pipeline.EndHostConditionalRendering(); } }