DrawTexture support

This commit is contained in:
gdk 2021-11-15 14:18:17 -03:00 committed by riperiperi
parent e9222a426a
commit 5fbfa9a9bd
3 changed files with 144 additions and 6 deletions

View file

@ -155,6 +155,20 @@ void main()
region[2] = (float)srcRegion.Y1 / src.Height;
region[3] = (float)srcRegion.Y2 / src.Height;
if (dstRegion.X1 > dstRegion.X2)
{
float temp = region[0];
region[0] = region[1];
region[1] = temp;
}
if (dstRegion.Y1 > dstRegion.Y2)
{
float temp = region[2];
region[2] = region[3];
region[3] = temp;
}
var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize);
gd.BufferManager.SetData<float>(bufferHandle, 0, region);
@ -167,8 +181,14 @@ void main()
Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1];
var rect = new Rectangle<float>(
MathF.Min(dstRegion.X1, dstRegion.X2),
MathF.Min(dstRegion.Y1, dstRegion.Y2),
MathF.Abs(dstRegion.X2 - dstRegion.X1),
MathF.Abs(dstRegion.Y2 - dstRegion.Y1));
viewports[0] = new GAL.Viewport(
new Rectangle<float>(dstRegion.X1, dstRegion.Y1, dstRegion.X2 - dstRegion.X1, dstRegion.Y2 - dstRegion.Y1),
rect,
ViewportSwizzle.PositiveX,
ViewportSwizzle.PositiveY,
ViewportSwizzle.PositiveZ,
@ -198,6 +218,76 @@ void main()
gd.BufferManager.Delete(bufferHandle);
}
public void DrawTexture(
VulkanGraphicsDevice gd,
PipelineBase pipeline,
TextureView src,
ISampler srcSampler,
Extents2DF srcRegion,
Extents2DF dstRegion)
{
const int RegionBufferSize = 16;
pipeline.SetTextureAndSampler(32, src, srcSampler);
Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)];
region[0] = srcRegion.X1 / src.Width;
region[1] = srcRegion.X2 / src.Width;
region[2] = srcRegion.Y1 / src.Height;
region[3] = srcRegion.Y2 / src.Height;
if (dstRegion.X1 > dstRegion.X2)
{
float temp = region[0];
region[0] = region[1];
region[1] = temp;
}
if (dstRegion.Y1 > dstRegion.Y2)
{
float temp = region[2];
region[2] = region[3];
region[3] = temp;
}
var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize);
gd.BufferManager.SetData<float>(bufferHandle, 0, region);
Span<BufferRange> bufferRanges = stackalloc BufferRange[1];
bufferRanges[0] = new BufferRange(bufferHandle, 0, RegionBufferSize);
pipeline.SetUniformBuffers(1, bufferRanges);
Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1];
var rect = new Rectangle<float>(
MathF.Min(dstRegion.X1, dstRegion.X2),
MathF.Min(dstRegion.Y1, dstRegion.Y2),
MathF.Abs(dstRegion.X2 - dstRegion.X1),
MathF.Abs(dstRegion.Y2 - dstRegion.Y1));
viewports[0] = new GAL.Viewport(
rect,
ViewportSwizzle.PositiveX,
ViewportSwizzle.PositiveY,
ViewportSwizzle.PositiveZ,
ViewportSwizzle.PositiveW,
0f,
1f);
Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1];
pipeline.SetProgram(_programColorBlit);
pipeline.SetViewports(0, viewports);
pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip);
pipeline.Draw(4, 1, 0, 0);
gd.BufferManager.Delete(bufferHandle);
}
public unsafe void ConvertI8ToI16(VulkanGraphicsDevice gd, CommandBufferScoped cbs, BufferHolder src, BufferHolder dst, int srcOffset, int size)
{
// TODO: Do this with a compute shader?

View file

@ -292,7 +292,50 @@ namespace Ryujinx.Graphics.Vulkan
public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
{
throw new NotImplementedException();
if (texture is TextureView srcTexture)
{
var oldCullMode = _newState.CullMode;
var oldStencilTestEnable = _newState.StencilTestEnable;
var oldDepthTestEnable = _newState.DepthTestEnable;
var oldDepthWriteEnable = _newState.DepthWriteEnable;
var oldTopology = _newState.Topology;
var oldViewports = VulkanConfiguration.UseDynamicState ? _dynamicState.Viewports : _newState.Internal.Viewports;
var oldViewportsCount = _newState.ViewportsCount;
_newState.CullMode = CullModeFlags.CullModeNone;
_newState.StencilTestEnable = false;
_newState.DepthTestEnable = false;
_newState.DepthWriteEnable = false;
SignalStateChange();
Gd.HelperShader.DrawTexture(
Gd,
this,
srcTexture,
sampler,
srcRegion,
dstRegion);
_newState.CullMode = oldCullMode;
_newState.StencilTestEnable = oldStencilTestEnable;
_newState.DepthTestEnable = oldDepthTestEnable;
_newState.DepthWriteEnable = oldDepthWriteEnable;
_newState.Topology = oldTopology;
if (VulkanConfiguration.UseDynamicState)
{
_dynamicState.Viewports = oldViewports;
_dynamicState.ViewportsCount = (int)oldViewportsCount;
_dynamicState.SetViewportsDirty();
}
else
{
_newState.Internal.Viewports = oldViewports;
}
_newState.ViewportsCount = oldViewportsCount;
SignalStateChange();
}
}
public void EndTransformFeedback()
@ -425,7 +468,7 @@ namespace Ryujinx.Graphics.Vulkan
public void SetFaceCulling(bool enable, Face face)
{
_newState.CullMode = enable ? face.Convert() : 0;
_newState.CullMode = enable ? face.Convert() : CullModeFlags.CullModeNone;
SignalStateChange();
}

View file

@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Vulkan
private uint _frontReference;
public int ViewportsCount;
private Array16<Viewport> _viewports;
public Array16<Viewport> Viewports;
private enum DirtyFlags
{
@ -70,11 +70,16 @@ namespace Ryujinx.Graphics.Vulkan
public void SetViewport(int index, Viewport viewport)
{
_viewports[index] = viewport;
Viewports[index] = viewport;
_dirty |= DirtyFlags.Viewport;
}
public void SetViewportsDirty()
{
_dirty |= DirtyFlags.Viewport;
}
public void ForceAllDirty()
{
_dirty = DirtyFlags.All;
@ -127,7 +132,7 @@ namespace Ryujinx.Graphics.Vulkan
private void RecordViewport(Vk api, CommandBuffer commandBuffer)
{
api.CmdSetViewport(commandBuffer, 0, (uint)ViewportsCount, _viewports.ToSpan());
api.CmdSetViewport(commandBuffer, 0, (uint)ViewportsCount, Viewports.ToSpan());
}
}
}