Clamp number of mipmap levels to avoid API errors due to invalid textures (#2808)
This commit is contained in:
parent
f41687f4c1
commit
f78bcb8048
3 changed files with 40 additions and 12 deletions
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.GAL
|
namespace Ryujinx.Graphics.GAL
|
||||||
{
|
{
|
||||||
|
@ -112,6 +113,25 @@ namespace Ryujinx.Graphics.GAL
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly int GetLevelsClamped()
|
||||||
|
{
|
||||||
|
int maxSize = Width;
|
||||||
|
|
||||||
|
if (Target != Target.Texture1D &&
|
||||||
|
Target != Target.Texture1DArray)
|
||||||
|
{
|
||||||
|
maxSize = Math.Max(maxSize, Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Target == Target.Texture3D)
|
||||||
|
{
|
||||||
|
maxSize = Math.Max(maxSize, Depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxLevels = BitOperations.Log2((uint)maxSize) + 1;
|
||||||
|
return Math.Min(Levels, maxLevels);
|
||||||
|
}
|
||||||
|
|
||||||
private static int GetLevelSize(int size, int level)
|
private static int GetLevelSize(int size, int level)
|
||||||
{
|
{
|
||||||
return Math.Max(1, size >> level);
|
return Math.Max(1, size >> level);
|
||||||
|
|
|
@ -50,12 +50,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
internalFormat = (SizedInternalFormat)format.PixelInternalFormat;
|
internalFormat = (SizedInternalFormat)format.PixelInternalFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int levels = Info.GetLevelsClamped();
|
||||||
|
|
||||||
switch (Info.Target)
|
switch (Info.Target)
|
||||||
{
|
{
|
||||||
case Target.Texture1D:
|
case Target.Texture1D:
|
||||||
GL.TexStorage1D(
|
GL.TexStorage1D(
|
||||||
TextureTarget1d.Texture1D,
|
TextureTarget1d.Texture1D,
|
||||||
Info.Levels,
|
levels,
|
||||||
internalFormat,
|
internalFormat,
|
||||||
Info.Width);
|
Info.Width);
|
||||||
break;
|
break;
|
||||||
|
@ -63,7 +65,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
case Target.Texture1DArray:
|
case Target.Texture1DArray:
|
||||||
GL.TexStorage2D(
|
GL.TexStorage2D(
|
||||||
TextureTarget2d.Texture1DArray,
|
TextureTarget2d.Texture1DArray,
|
||||||
Info.Levels,
|
levels,
|
||||||
internalFormat,
|
internalFormat,
|
||||||
Info.Width,
|
Info.Width,
|
||||||
Info.Height);
|
Info.Height);
|
||||||
|
@ -72,7 +74,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
case Target.Texture2D:
|
case Target.Texture2D:
|
||||||
GL.TexStorage2D(
|
GL.TexStorage2D(
|
||||||
TextureTarget2d.Texture2D,
|
TextureTarget2d.Texture2D,
|
||||||
Info.Levels,
|
levels,
|
||||||
internalFormat,
|
internalFormat,
|
||||||
Info.Width,
|
Info.Width,
|
||||||
Info.Height);
|
Info.Height);
|
||||||
|
@ -81,7 +83,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
case Target.Texture2DArray:
|
case Target.Texture2DArray:
|
||||||
GL.TexStorage3D(
|
GL.TexStorage3D(
|
||||||
TextureTarget3d.Texture2DArray,
|
TextureTarget3d.Texture2DArray,
|
||||||
Info.Levels,
|
levels,
|
||||||
internalFormat,
|
internalFormat,
|
||||||
Info.Width,
|
Info.Width,
|
||||||
Info.Height,
|
Info.Height,
|
||||||
|
@ -112,7 +114,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
case Target.Texture3D:
|
case Target.Texture3D:
|
||||||
GL.TexStorage3D(
|
GL.TexStorage3D(
|
||||||
TextureTarget3d.Texture3D,
|
TextureTarget3d.Texture3D,
|
||||||
Info.Levels,
|
levels,
|
||||||
internalFormat,
|
internalFormat,
|
||||||
Info.Width,
|
Info.Width,
|
||||||
Info.Height,
|
Info.Height,
|
||||||
|
@ -122,7 +124,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
case Target.Cubemap:
|
case Target.Cubemap:
|
||||||
GL.TexStorage2D(
|
GL.TexStorage2D(
|
||||||
TextureTarget2d.TextureCubeMap,
|
TextureTarget2d.TextureCubeMap,
|
||||||
Info.Levels,
|
levels,
|
||||||
internalFormat,
|
internalFormat,
|
||||||
Info.Width,
|
Info.Width,
|
||||||
Info.Height);
|
Info.Height);
|
||||||
|
@ -131,7 +133,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
case Target.CubemapArray:
|
case Target.CubemapArray:
|
||||||
GL.TexStorage3D(
|
GL.TexStorage3D(
|
||||||
(TextureTarget3d)All.TextureCubeMapArray,
|
(TextureTarget3d)All.TextureCubeMapArray,
|
||||||
Info.Levels,
|
levels,
|
||||||
internalFormat,
|
internalFormat,
|
||||||
Info.Width,
|
Info.Width,
|
||||||
Info.Height,
|
Info.Height,
|
||||||
|
|
|
@ -48,13 +48,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
pixelInternalFormat = format.PixelInternalFormat;
|
pixelInternalFormat = format.PixelInternalFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int levels = Info.GetLevelsClamped();
|
||||||
|
|
||||||
GL.TextureView(
|
GL.TextureView(
|
||||||
Handle,
|
Handle,
|
||||||
target,
|
target,
|
||||||
_parent.Handle,
|
_parent.Handle,
|
||||||
pixelInternalFormat,
|
pixelInternalFormat,
|
||||||
FirstLevel,
|
FirstLevel,
|
||||||
Info.Levels,
|
levels,
|
||||||
FirstLayer,
|
FirstLayer,
|
||||||
Info.GetLayers());
|
Info.GetLayers());
|
||||||
|
|
||||||
|
@ -81,7 +83,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
|
|
||||||
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
|
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
|
||||||
|
|
||||||
int maxLevel = Info.Levels - 1;
|
int maxLevel = levels - 1;
|
||||||
|
|
||||||
if (maxLevel < 0)
|
if (maxLevel < 0)
|
||||||
{
|
{
|
||||||
|
@ -122,8 +124,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
public unsafe ReadOnlySpan<byte> GetData()
|
public unsafe ReadOnlySpan<byte> GetData()
|
||||||
{
|
{
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
int levels = Info.GetLevelsClamped();
|
||||||
|
|
||||||
for (int level = 0; level < Info.Levels; level++)
|
for (int level = 0; level < levels; level++)
|
||||||
{
|
{
|
||||||
size += Info.GetMipSize(level);
|
size += Info.GetMipSize(level);
|
||||||
}
|
}
|
||||||
|
@ -227,7 +230,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
faces = 6;
|
faces = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int level = 0; level < Info.Levels; level++)
|
int levels = Info.GetLevelsClamped();
|
||||||
|
|
||||||
|
for (int level = 0; level < levels; level++)
|
||||||
{
|
{
|
||||||
for (int face = 0; face < faces; face++)
|
for (int face = 0; face < faces; face++)
|
||||||
{
|
{
|
||||||
|
@ -465,10 +470,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
int width = Info.Width;
|
int width = Info.Width;
|
||||||
int height = Info.Height;
|
int height = Info.Height;
|
||||||
int depth = Info.Depth;
|
int depth = Info.Depth;
|
||||||
|
int levels = Info.GetLevelsClamped();
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
for (int level = 0; level < Info.Levels; level++)
|
for (int level = 0; level < levels; level++)
|
||||||
{
|
{
|
||||||
int mipSize = Info.GetMipSize(level);
|
int mipSize = Info.GetMipSize(level);
|
||||||
|
|
||||||
|
|
Reference in a new issue