This commit is contained in:
Soreepeong 2024-05-21 09:27:51 +09:00
parent 8c7771bf7d
commit 20717cce3d
13 changed files with 213 additions and 199 deletions

View file

@ -7,6 +7,7 @@ using Dalamud.Interface.Textures.TextureWraps.Internal;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Plugin.Services;
using Dalamud.Utility;
using Dalamud.Utility.TerraFxCom;
using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows;
@ -62,18 +63,11 @@ internal sealed partial class TextureManager
unsafe
{
var srvDesc = new D3D11_SHADER_RESOURCE_VIEW_DESC(
using var srv = this.device.CreateShaderResourceView(
tex,
D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2D);
using var srv = default(ComPtr<ID3D11ShaderResourceView>);
this.device.Get()->CreateShaderResourceView(
(ID3D11Resource*)tex.Get(),
&srvDesc,
srv.GetAddressOf())
.ThrowOnError();
new(tex.Get(), D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2D));
var desc = default(D3D11_TEXTURE2D_DESC);
tex.Get()->GetDesc(&desc);
var desc = tex.GetDesc();
var outWrap = new UnknownTextureWrap(
(IUnknown*)srv.Get(),
@ -126,15 +120,10 @@ internal sealed partial class TextureManager
TextureModificationArgs args = default,
CancellationToken cancellationToken = default)
{
using var tex2D = wrapAux.NewTexRef();
if (!args.IsCompleteSourceCopy(wrapAux.Desc))
{
using var tmp = await this.NoThrottleCreateFromExistingTextureAsync(wrapAux, args);
unsafe
{
tex2D.Swap(&tmp);
}
}
using var tex2D =
args.IsCompleteSourceCopy(wrapAux.Desc)
? wrapAux.NewTexRef()
: await this.NoThrottleCreateFromExistingTextureAsync(wrapAux, args);
cancellationToken.ThrowIfCancellationRequested();
@ -147,32 +136,29 @@ internal sealed partial class TextureManager
{
cancellationToken.ThrowIfCancellationRequested();
D3D11_TEXTURE2D_DESC desc;
tex2D.Get()->GetDesc(&desc);
var desc = tex2D.GetDesc();
using var device = default(ComPtr<ID3D11Device>);
tex2D.Get()->GetDevice(device.GetAddressOf());
using var context = default(ComPtr<ID3D11DeviceContext>);
device.Get()->GetImmediateContext(context.GetAddressOf());
using var tmpTex = default(ComPtr<ID3D11Texture2D>);
if ((desc.CPUAccessFlags & (uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ) == 0)
{
var tmpTexDesc = desc with
{
MipLevels = 1,
ArraySize = 1,
SampleDesc = new(1, 0),
Usage = D3D11_USAGE.D3D11_USAGE_STAGING,
BindFlags = 0u,
CPUAccessFlags = (uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ,
MiscFlags = 0u,
};
device.Get()->CreateTexture2D(&tmpTexDesc, null, tmpTex.GetAddressOf()).ThrowOnError();
context.Get()->CopyResource((ID3D11Resource*)tmpTex.Get(), (ID3D11Resource*)tex2D.Get());
cancellationToken.ThrowIfCancellationRequested();
}
using var tmpTex =
(desc.CPUAccessFlags & (uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ) == 0
? device.CreateTexture2D(
desc with
{
MipLevels = 1,
ArraySize = 1,
SampleDesc = new(1, 0),
Usage = D3D11_USAGE.D3D11_USAGE_STAGING,
BindFlags = 0u,
CPUAccessFlags = (uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ,
MiscFlags = 0u,
},
tex2D)
: default;
cancellationToken.ThrowIfCancellationRequested();
var mapWhat = (ID3D11Resource*)(tmpTex.IsEmpty() ? tex2D.Get() : tmpTex.Get());
@ -205,25 +191,22 @@ internal sealed partial class TextureManager
if (args.NewHeight == 0)
args = args with { NewHeight = (int)MathF.Round((args.Uv1Effective.Y - args.Uv0.Y) * wrapAux.Desc.Height) };
using var tex2DCopyTemp = default(ComPtr<ID3D11Texture2D>);
unsafe
{
var tex2DCopyTempDesc = new D3D11_TEXTURE2D_DESC
{
Width = (uint)args.NewWidth,
Height = (uint)args.NewHeight,
MipLevels = 1,
ArraySize = 1,
Format = args.Format,
SampleDesc = new(1, 0),
Usage = D3D11_USAGE.D3D11_USAGE_DEFAULT,
BindFlags = (uint)(D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE |
D3D11_BIND_FLAG.D3D11_BIND_RENDER_TARGET),
CPUAccessFlags = 0u,
MiscFlags = 0u,
};
this.device.Get()->CreateTexture2D(&tex2DCopyTempDesc, null, tex2DCopyTemp.GetAddressOf()).ThrowOnError();
}
using var tex2DCopyTemp =
this.device.CreateTexture2D(
new()
{
Width = (uint)args.NewWidth,
Height = (uint)args.NewHeight,
MipLevels = 1,
ArraySize = 1,
Format = args.Format,
SampleDesc = new(1, 0),
Usage = D3D11_USAGE.D3D11_USAGE_DEFAULT,
BindFlags = (uint)(D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE |
D3D11_BIND_FLAG.D3D11_BIND_RENDER_TARGET),
CPUAccessFlags = 0u,
MiscFlags = 0u,
});
await this.RunDuringPresent(() => DrawSourceTextureToTarget(wrapAux, args, this.SimpleDrawer, tex2DCopyTemp));

View file

@ -12,6 +12,7 @@ using Dalamud.Interface.Textures.TextureWraps.Internal;
using Dalamud.Logging.Internal;
using Dalamud.Plugin.Services;
using Dalamud.Utility;
using Dalamud.Utility.TerraFxCom;
using Lumina.Data;
using Lumina.Data.Files;
@ -24,8 +25,7 @@ namespace Dalamud.Interface.Textures.Internal;
/// <summary>Service responsible for loading and disposing ImGui texture wraps.</summary>
[ServiceManager.EarlyLoadedService]
internal sealed partial class TextureManager
: IServiceType,
IDisposable,
: IInternalDisposableService,
ITextureProvider,
ITextureSubstitutionProvider,
ITextureReadbackProvider
@ -101,7 +101,7 @@ internal sealed partial class TextureManager
}
/// <inheritdoc/>
public void Dispose()
void IInternalDisposableService.DisposeService()
{
if (this.disposing)
return;
@ -221,6 +221,53 @@ internal sealed partial class TextureManager
static T? ForceNullable<T>(T s) => s;
}
/// <inheritdoc/>
public unsafe IDalamudTextureWrap CreateEmpty(
RawImageSpecification specs,
bool cpuRead,
bool cpuWrite,
string? debugName = null)
{
if (cpuRead && cpuWrite)
throw new ArgumentException("cpuRead and cpuWrite cannot be set at the same time.");
var cpuaf = default(D3D11_CPU_ACCESS_FLAG);
if (cpuRead)
cpuaf |= D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ;
if (cpuWrite)
cpuaf |= D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE;
D3D11_USAGE usage;
if (cpuRead)
usage = D3D11_USAGE.D3D11_USAGE_STAGING;
else if (cpuWrite)
usage = D3D11_USAGE.D3D11_USAGE_DYNAMIC;
else
usage = D3D11_USAGE.D3D11_USAGE_DEFAULT;
using var texture = this.device.CreateTexture2D(
new()
{
Width = (uint)specs.Width,
Height = (uint)specs.Height,
MipLevels = 1,
ArraySize = 1,
Format = specs.Format,
SampleDesc = new(1, 0),
Usage = usage,
BindFlags = (uint)D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE,
CPUAccessFlags = (uint)cpuaf,
MiscFlags = 0,
});
using var view = this.device.CreateShaderResourceView(
texture,
new(texture, D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2D));
var wrap = new UnknownTextureWrap((IUnknown*)view.Get(), specs.Width, specs.Height, true);
this.BlameSetName(wrap, debugName ?? $"{nameof(this.CreateEmpty)}({specs})");
return wrap;
}
/// <inheritdoc/>
bool ITextureProvider.IsDxgiFormatSupported(int dxgiFormat) =>
this.IsDxgiFormatSupported((DXGI_FORMAT)dxgiFormat);

View file

@ -28,9 +28,8 @@ namespace Dalamud.Interface.Textures.Internal;
[ResolveVia<ITextureSubstitutionProvider>]
[ResolveVia<ITextureReadbackProvider>]
#pragma warning restore SA1015
internal sealed partial class TextureManagerPluginScoped
: IServiceType,
IDisposable,
internal sealed class TextureManagerPluginScoped
: IInternalDisposableService,
ITextureProvider,
ITextureSubstitutionProvider,
ITextureReadbackProvider
@ -114,7 +113,7 @@ internal sealed partial class TextureManagerPluginScoped
}
/// <inheritdoc/>
public void Dispose()
void IInternalDisposableService.DisposeService()
{
if (Interlocked.Exchange(ref this.managerTaskNullable, null) is not { } task)
return;
@ -134,6 +133,19 @@ internal sealed partial class TextureManagerPluginScoped
: $"{nameof(TextureManagerPluginScoped)}({this.plugin.Name})";
}
/// <inheritdoc/>
public IDalamudTextureWrap CreateEmpty(
RawImageSpecification specs,
bool cpuRead,
bool cpuWrite,
string? debugName = null)
{
var manager = this.ManagerOrThrow;
var textureWrap = manager.CreateEmpty(specs, cpuRead, cpuWrite, debugName);
manager.Blame(textureWrap, this.plugin);
return textureWrap;
}
/// <inheritdoc/>
public async Task<IDalamudTextureWrap> CreateFromExistingTextureAsync(
IDalamudTextureWrap wrap,

View file

@ -31,6 +31,13 @@ public record struct RawImageSpecification
this.DxgiFormat = dxgiFormat;
}
/// <summary>Initializes a new instance of the <see cref="RawImageSpecification"/> class.</summary>
/// <param name="desc">The source texture description.</param>
internal RawImageSpecification(in D3D11_TEXTURE2D_DESC desc)
: this((int)desc.Width, (int)desc.Height, (int)desc.Format)
{
}
/// <summary>Initializes a new instance of the <see cref="RawImageSpecification"/> class.</summary>
/// <param name="desc">The source texture description.</param>
/// <param name="pitch">The pitch of the raw image in bytes.</param>