Skip to content

Commit

Permalink
Merge pull request #5901 from peppy/contextual-initialise-levels
Browse files Browse the repository at this point in the history
Avoid initialising textures when unnecessary
  • Loading branch information
smoogipoo authored Jul 7, 2023
2 parents d48d623 + fc3efca commit a08e61c
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 30 deletions.
2 changes: 1 addition & 1 deletion osu.Framework/Graphics/OpenGL/GLRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ public override IFrameBuffer CreateFrameBuffer(RenderBufferFormat[]? renderBuffe
protected override IUniformBuffer<TData> CreateUniformBuffer<TData>() => new GLUniformBuffer<TData>(this);

protected override INativeTexture CreateNativeTexture(int width, int height, bool manualMipmaps = false, TextureFilteringMode filteringMode = TextureFilteringMode.Linear,
Color4 initialisationColour = default)
Color4? initialisationColour = null)
{
All glFilteringMode;

Expand Down
24 changes: 12 additions & 12 deletions osu.Framework/Graphics/OpenGL/Textures/GLTexture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public int? MipLevel
private readonly List<RectangleI> uploadedRegions = new List<RectangleI>();

private readonly All filteringMode;
private readonly Color4 initialisationColour;
private readonly Color4? initialisationColour;

/// <summary>
/// Creates a new <see cref="GLTexture"/>.
Expand All @@ -79,8 +79,8 @@ public int? MipLevel
/// <param name="height">The height of the texture.</param>
/// <param name="manualMipmaps">Whether manual mipmaps will be uploaded to the texture. If false, the texture will compute mipmaps automatically.</param>
/// <param name="filteringMode">The filtering mode.</param>
/// <param name="initialisationColour">The colour to initialise texture levels with (in the case of sub region initial uploads).</param>
public GLTexture(GLRenderer renderer, int width, int height, bool manualMipmaps = false, All filteringMode = All.Linear, Color4 initialisationColour = default)
/// <param name="initialisationColour">The colour to initialise texture levels with (in the case of sub region initial uploads). If null, no initialisation is provided out-of-the-box.</param>
public GLTexture(GLRenderer renderer, int width, int height, bool manualMipmaps = false, All filteringMode = All.Linear, Color4? initialisationColour = null)
{
Renderer = renderer;
Width = width;
Expand Down Expand Up @@ -470,21 +470,21 @@ protected virtual void DoUpload(ITextureUpload upload, IntPtr dataPointer)

private void initializeLevel(int level, int width, int height)
{
using (var image = createBackingImage(width, height))
if (initialisationColour == null)
return;

var rgbaColour = new Rgba32(new Vector4(initialisationColour.Value.R, initialisationColour.Value.G, initialisationColour.Value.B, initialisationColour.Value.A));

using var image = initialisationColour == default
? new Image<Rgba32>(width, height)
: new Image<Rgba32>(width, height, rgbaColour);

using (var pixels = image.CreateReadOnlyPixelSpan())
{
updateMemoryUsage(level, (long)width * height * 4);
GL.TexImage2D(TextureTarget2d.Texture2D, level, TextureComponentCount.Rgba8, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte,
ref MemoryMarshal.GetReference(pixels.Span));
}
}

private Image<Rgba32> createBackingImage(int width, int height)
{
// it is faster to initialise without a background specification if transparent black is all that's required.
return initialisationColour == default
? new Image<Rgba32>(width, height)
: new Image<Rgba32>(width, height, new Rgba32(new Vector4(initialisationColour.R, initialisationColour.G, initialisationColour.B, initialisationColour.A)));
}
}
}
2 changes: 1 addition & 1 deletion osu.Framework/Graphics/Rendering/Dummy/DummyRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public IFrameBuffer CreateFrameBuffer(RenderBufferFormat[]? renderBufferFormats
=> new DummyFrameBuffer(this);

public Texture CreateTexture(int width, int height, bool manualMipmaps = false, TextureFilteringMode filteringMode = TextureFilteringMode.Linear, WrapMode wrapModeS = WrapMode.None,
WrapMode wrapModeT = WrapMode.None, Color4 initialisationColour = default)
WrapMode wrapModeT = WrapMode.None, Color4? initialisationColour = null)
=> new Texture(new DummyNativeTexture(this) { Width = width, Height = height }, wrapModeS, wrapModeT);

public Texture CreateVideoTexture(int width, int height)
Expand Down
12 changes: 10 additions & 2 deletions osu.Framework/Graphics/Rendering/IRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,18 @@ public interface IRenderer
IFrameBuffer CreateFrameBuffer(RenderBufferFormat[]? renderBufferFormats = null, TextureFilteringMode filteringMode = TextureFilteringMode.Linear);

/// <summary>
/// Creates a new texture.
/// Creates a new <see cref="Texture"/>.
/// </summary>
/// <param name="width">The width of the texture.</param>
/// <param name="height">The height of the texture.</param>
/// <param name="manualMipmaps">Whether manual mipmaps will be uploaded to the texture. If false, the texture will compute mipmaps automatically.</param>
/// <param name="filteringMode">The filtering mode.</param>
/// <param name="initialisationColour">The colour to initialise texture levels with (in the case of sub region initial uploads). If null, no initialisation is provided out-of-the-box.</param>
/// <param name="wrapModeS">The texture's horizontal wrap mode.</param>
/// <param name="wrapModeT">The texture's vertex wrap mode.</param>
/// <returns>The <see cref="Texture"/>.</returns>
Texture CreateTexture(int width, int height, bool manualMipmaps = false, TextureFilteringMode filteringMode = TextureFilteringMode.Linear, WrapMode wrapModeS = WrapMode.None,
WrapMode wrapModeT = WrapMode.None, Color4 initialisationColour = default);
WrapMode wrapModeT = WrapMode.None, Color4? initialisationColour = null);

/// <summary>
/// Creates a new video texture.
Expand Down
6 changes: 3 additions & 3 deletions osu.Framework/Graphics/Rendering/Renderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1084,10 +1084,10 @@ internal IShader GetMipmapShader()
/// <param name="height">The height of the texture.</param>
/// <param name="manualMipmaps">Whether manual mipmaps will be uploaded to the texture. If false, the texture will compute mipmaps automatically.</param>
/// <param name="filteringMode">The filtering mode.</param>
/// <param name="initialisationColour">The colour to initialise texture levels with (in the case of sub region initial uploads).</param>
/// <param name="initialisationColour">The colour to initialise texture levels with (in the case of sub region initial uploads). If null, no initialisation is provided out-of-the-box.</param>
/// <returns>The <see cref="INativeTexture"/>.</returns>
protected abstract INativeTexture CreateNativeTexture(int width, int height, bool manualMipmaps = false, TextureFilteringMode filteringMode = TextureFilteringMode.Linear,
Color4 initialisationColour = default);
Color4? initialisationColour = null);

/// <summary>
/// Creates a new <see cref="INativeTexture"/> for video sprites.
Expand All @@ -1097,7 +1097,7 @@ protected abstract INativeTexture CreateNativeTexture(int width, int height, boo
/// <returns>The video <see cref="INativeTexture"/>.</returns>
protected abstract INativeTexture CreateNativeVideoTexture(int width, int height);

public Texture CreateTexture(int width, int height, bool manualMipmaps, TextureFilteringMode filteringMode, WrapMode wrapModeS, WrapMode wrapModeT, Color4 initialisationColour)
public Texture CreateTexture(int width, int height, bool manualMipmaps, TextureFilteringMode filteringMode, WrapMode wrapModeS, WrapMode wrapModeT, Color4? initialisationColour)
=> CreateTexture(CreateNativeTexture(width, height, manualMipmaps, filteringMode, initialisationColour), wrapModeS, wrapModeT);

public Texture CreateVideoTexture(int width, int height) => CreateTexture(CreateNativeVideoTexture(width, height));
Expand Down
23 changes: 13 additions & 10 deletions osu.Framework/Graphics/Veldrid/Textures/VeldridTexture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public string Identifier
private readonly List<RectangleI> uploadedRegions = new List<RectangleI>();

private readonly SamplerFilter filteringMode;
private readonly Color4 initialisationColour;
private readonly Color4? initialisationColour;

public ulong BindCount { get; protected set; }

Expand Down Expand Up @@ -83,9 +83,9 @@ protected virtual TextureUsage Usages
/// <param name="height">The height of the texture.</param>
/// <param name="manualMipmaps">Whether manual mipmaps will be uploaded to the texture. If false, the texture will compute mipmaps automatically.</param>
/// <param name="filteringMode">The filtering mode.</param>
/// <param name="initialisationColour">The colour to initialise texture levels with (in the case of sub region initial uploads).</param>
/// <param name="initialisationColour">The colour to initialise texture levels with (in the case of sub region initial uploads). If null, no initialisation is provided out-of-the-box.</param>
public VeldridTexture(VeldridRenderer renderer, int width, int height, bool manualMipmaps = false, SamplerFilter filteringMode = SamplerFilter.MinLinear_MagLinear_MipLinear,
Color4 initialisationColour = default)
Color4? initialisationColour = null)
{
this.manualMipmaps = manualMipmaps;
this.filteringMode = filteringMode;
Expand Down Expand Up @@ -485,6 +485,7 @@ protected virtual void DoUpload(ITextureUpload upload)
if (!upload.Data.IsEmpty)
{
// ensure all mip levels up to the target level are initialised.
// generally we always upload at level 0, so this won't run.
if (upload.Level > maximumUploadedLod)
{
for (int i = maximumUploadedLod + 1; i <= upload.Level; i++)
Expand All @@ -508,20 +509,22 @@ protected virtual void DoUpload(ITextureUpload upload)

private unsafe void initialiseLevel(Texture texture, int level, int width, int height)
{
using (var image = createBackingImage(width, height))
if (initialisationColour == null)
return;

var rgbaColour = new Rgba32(new Vector4(initialisationColour.Value.R, initialisationColour.Value.G, initialisationColour.Value.B, initialisationColour.Value.A));

using var image = initialisationColour == default
? new Image<Rgba32>(width, height)
: new Image<Rgba32>(width, height, rgbaColour);

using (var pixels = image.CreateReadOnlyPixelSpan())
{
updateMemoryUsage(level, (long)width * height * sizeof(Rgba32));
Renderer.UpdateTexture(texture, 0, 0, width, height, level, pixels.Span);
}
}

private Image<Rgba32> createBackingImage(int width, int height)
{
// it is faster to initialise without a background specification if transparent black is all that's required.
return initialisationColour == default
? new Image<Rgba32>(width, height)
: new Image<Rgba32>(width, height, new Rgba32(new Vector4(initialisationColour.R, initialisationColour.G, initialisationColour.B, initialisationColour.A)));
}

// todo: should this be limited to MAX_MIPMAP_LEVELS or was that constant supposed to be for automatic mipmap generation only?
Expand Down
2 changes: 1 addition & 1 deletion osu.Framework/Graphics/Veldrid/VeldridRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ protected override IUniformBuffer<TData> CreateUniformBuffer<TData>()
=> new VeldridUniformBuffer<TData>(this);

protected override INativeTexture CreateNativeTexture(int width, int height, bool manualMipmaps = false, TextureFilteringMode filteringMode = TextureFilteringMode.Linear,
Color4 initialisationColour = default)
Color4? initialisationColour = null)
=> new VeldridTexture(this, width, height, manualMipmaps, filteringMode.ToSamplerFilter(), initialisationColour);

protected override INativeTexture CreateNativeVideoTexture(int width, int height)
Expand Down

0 comments on commit a08e61c

Please sign in to comment.