Implement DrawTexture functionality (#2747)

* Implement DrawTexture functionality

* Non-NVIDIA support

* Disable some features that should not affect draw texture (slow path)

* Remove space from shader source

* Match 2D engine names

* Fix resolution scale and add missing XML docs

* Disable transform feedback for draw texture fallback
This commit is contained in:
gdkchan 2021-11-10 15:37:49 -03:00 committed by GitHub
parent bc00a251dd
commit 611bec6e44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 421 additions and 14 deletions

View file

@ -319,6 +319,65 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_drawState.DrawIndexed = oldDrawIndexed;
}
/// <summary>
/// Performs a texture draw with a source texture and sampler ID, along with source
/// and destination coordinates and sizes.
/// </summary>
/// <param name="engine">3D engine where this method is being called</param>
/// <param name="argument">Method call argument</param>
public void DrawTexture(ThreedClass engine, int argument)
{
static float FixedToFloat(int fixedValue)
{
return fixedValue * (1f / 4096);
}
float dstX0 = FixedToFloat(_state.State.DrawTextureDstX);
float dstY0 = FixedToFloat(_state.State.DrawTextureDstY);
float dstWidth = FixedToFloat(_state.State.DrawTextureDstWidth);
float dstHeight = FixedToFloat(_state.State.DrawTextureDstHeight);
// TODO: Confirm behaviour on hardware.
// When this is active, the origin appears to be on the bottom.
if (_state.State.YControl.HasFlag(YControl.NegateY))
{
dstY0 -= dstHeight;
}
float dstX1 = dstX0 + dstWidth;
float dstY1 = dstY0 + dstHeight;
float srcX0 = FixedToFloat(_state.State.DrawTextureSrcX);
float srcY0 = FixedToFloat(_state.State.DrawTextureSrcY);
float srcX1 = ((float)_state.State.DrawTextureDuDx / (1UL << 32)) * dstWidth + srcX0;
float srcY1 = ((float)_state.State.DrawTextureDvDy / (1UL << 32)) * dstHeight + srcY0;
engine.UpdateState();
int textureId = _state.State.DrawTextureTextureId;
int samplerId = _state.State.DrawTextureSamplerId;
(var texture, var sampler) = _channel.TextureManager.GetGraphicsTextureAndSampler(textureId, samplerId);
srcX0 *= texture.ScaleFactor;
srcY0 *= texture.ScaleFactor;
srcX1 *= texture.ScaleFactor;
srcY1 *= texture.ScaleFactor;
float dstScale = _channel.TextureManager.RenderTargetScale;
dstX0 *= dstScale;
dstY0 *= dstScale;
dstX1 *= dstScale;
dstY1 *= dstScale;
_context.Renderer.Pipeline.DrawTexture(
texture?.HostTexture,
sampler?.HostSampler,
new Extents2DF(srcX0, srcY0, srcX1, srcY1),
new Extents2DF(dstX0, dstY0, dstX1, dstY1));
}
/// <summary>
/// Performs a indirect multi-draw, with parameters from a GPU buffer.
/// </summary>