Prevent textures being created over the maximum texture dimension, fixes #3341
This commit is contained in:
parent
d91242df53
commit
dcfe55360a
|
@ -7,10 +7,13 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
{
|
||||
internal sealed class OpenGLControl : GraphicsControl
|
||||
{
|
||||
public SDL2OpenGLContext Context { get; private set; }
|
||||
private readonly Action _initGLState;
|
||||
private SDL2OpenGLContext _context;
|
||||
|
||||
public OpenGLControl()
|
||||
public OpenGLControl(Action initGLState)
|
||||
{
|
||||
_initGLState = initGLState;
|
||||
|
||||
// according to OpenTK, these are the styles we want to set
|
||||
SetStyle(ControlStyles.Opaque, true);
|
||||
SetStyle(ControlStyles.UserPaint, true);
|
||||
|
@ -41,14 +44,15 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
protected override void OnHandleCreated(EventArgs e)
|
||||
{
|
||||
base.OnHandleCreated(e);
|
||||
Context = new(Handle, 3, 2, true);
|
||||
_context = new(Handle, 3, 2, true);
|
||||
_initGLState();
|
||||
}
|
||||
|
||||
protected override void OnHandleDestroyed(EventArgs e)
|
||||
{
|
||||
base.OnHandleDestroyed(e);
|
||||
Context.Dispose();
|
||||
Context = null;
|
||||
_context.Dispose();
|
||||
_context = null;
|
||||
}
|
||||
|
||||
private void MakeContextCurrent()
|
||||
|
@ -58,13 +62,13 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
throw new ObjectDisposedException(nameof(OpenGLControl));
|
||||
}
|
||||
|
||||
if (Context is null)
|
||||
if (_context is null)
|
||||
{
|
||||
CreateControl();
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.MakeContextCurrent();
|
||||
_context.MakeContextCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,23 +80,19 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
public override void SetVsync(bool state)
|
||||
{
|
||||
MakeContextCurrent();
|
||||
Context.SetVsync(state);
|
||||
_context.SetVsync(state);
|
||||
}
|
||||
|
||||
public override void Begin()
|
||||
{
|
||||
MakeContextCurrent();
|
||||
}
|
||||
=> MakeContextCurrent();
|
||||
|
||||
public override void End()
|
||||
{
|
||||
SDL2OpenGLContext.MakeNoneCurrent();
|
||||
}
|
||||
=> SDL2OpenGLContext.MakeNoneCurrent();
|
||||
|
||||
public override void SwapBuffers()
|
||||
{
|
||||
MakeContextCurrent();
|
||||
Context.SwapBuffers();
|
||||
_context.SwapBuffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
{
|
||||
GraphicsControl ret = gl switch
|
||||
{
|
||||
IGL_OpenGL => new OpenGLControl(),
|
||||
IGL_OpenGL openGL => new OpenGLControl(openGL.InitGLState),
|
||||
IGL_D3D11 d3d11 => new D3D11Control(d3d11.CreateSwapChain),
|
||||
IGL_GDIPlus gdiPlus => new GDIPlusControl(gdiPlus.CreateControlRenderTarget),
|
||||
_ => throw new InvalidOperationException()
|
||||
|
|
|
@ -26,13 +26,14 @@ namespace BizHawk.Bizware.Graphics
|
|||
public ID3D11RasterizerState RasterizerState;
|
||||
|
||||
public FeatureLevel DeviceFeatureLevel;
|
||||
public int MaxTextureDimension;
|
||||
public bool PresentAllowTearing;
|
||||
|
||||
public D3D11RenderTarget CurRenderTarget;
|
||||
public D3D11Pipeline CurPipeline;
|
||||
|
||||
public readonly HashSet<D3D11Texture2D> Textures = new();
|
||||
public readonly HashSet<D3D11Pipeline> Pipelines = new();
|
||||
public readonly HashSet<D3D11Texture2D> Textures = [ ];
|
||||
public readonly HashSet<D3D11Pipeline> Pipelines = [ ];
|
||||
|
||||
public void CreateResources()
|
||||
{
|
||||
|
@ -99,6 +100,14 @@ namespace BizHawk.Bizware.Graphics
|
|||
|
||||
DeviceFeatureLevel = Device.FeatureLevel;
|
||||
|
||||
MaxTextureDimension = DeviceFeatureLevel switch
|
||||
{
|
||||
FeatureLevel.Level_9_1 or FeatureLevel.Level_9_2 => 2048,
|
||||
FeatureLevel.Level_9_3 => 4096,
|
||||
FeatureLevel.Level_10_0 or FeatureLevel.Level_10_1 => 8192,
|
||||
_ => ID3D11Resource.MaximumTexture2DSize,
|
||||
};
|
||||
|
||||
var rd = new RasterizerDescription
|
||||
{
|
||||
CullMode = CullMode.None,
|
||||
|
|
|
@ -182,6 +182,8 @@ namespace BizHawk.Bizware.Graphics
|
|||
_resources.Dispose();
|
||||
}
|
||||
|
||||
public int MaxTextureDimension => _resources.MaxTextureDimension;
|
||||
|
||||
public void ClearColor(Color color)
|
||||
=> Context.ClearRenderTargetView(CurRenderTarget?.RTV ?? _controlSwapChain.RTV, new(color.R, color.B, color.G, color.A));
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@ namespace BizHawk.Bizware.Graphics
|
|||
{
|
||||
}
|
||||
|
||||
// maximum bitmap size doesn't seem to be well defined... we'll just use D3D11's maximum size
|
||||
public int MaxTextureDimension => 16384;
|
||||
|
||||
internal SDGraphics GetCurrentGraphics()
|
||||
=> CurRenderTarget?.TextureGraphics ?? _controlRenderTarget.BufferedGraphics.Graphics;
|
||||
|
||||
|
|
|
@ -15,6 +15,12 @@ namespace BizHawk.Bizware.Graphics
|
|||
/// </summary>
|
||||
EDispMethod DispMethodEnum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum size any dimension of a texture may have
|
||||
/// This should be set on init, and therefore shouldn't need a graphics context active...
|
||||
/// </summary>
|
||||
int MaxTextureDimension { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a texture with the specified dimensions
|
||||
/// The texture will use a clamping address mode and nearest neighbor filtering by default
|
||||
|
|
|
@ -35,6 +35,22 @@ namespace BizHawk.Bizware.Graphics
|
|||
public void Dispose()
|
||||
=> GL.Dispose();
|
||||
|
||||
/// <summary>
|
||||
/// Should be called once the GL context is created
|
||||
/// </summary>
|
||||
public void InitGLState()
|
||||
{
|
||||
GL.GetInteger(GetPName.MaxTextureSize, out var maxTextureDimension);
|
||||
if (maxTextureDimension == 0)
|
||||
{
|
||||
throw new($"Failed to get max texture size, GL error: {GL.GetError()}");
|
||||
}
|
||||
|
||||
MaxTextureDimension = maxTextureDimension;
|
||||
}
|
||||
|
||||
public int MaxTextureDimension { get; private set; }
|
||||
|
||||
public void ClearColor(Color color)
|
||||
{
|
||||
GL.ClearColor(color);
|
||||
|
|
|
@ -304,6 +304,10 @@ namespace BizHawk.Client.Common
|
|||
if (size.Width < 1) size.Width = 1;
|
||||
if (size.Height < 1) size.Height = 1;
|
||||
|
||||
// if either of the dimensions exceed the maximum size of a texture, we need to constrain them
|
||||
size.Width = Math.Min(size.Width, _gl.MaxTextureDimension);
|
||||
size.Height = Math.Min(size.Height, _gl.MaxTextureDimension);
|
||||
|
||||
var fPadding = new FinalPresentation(size);
|
||||
chain.AddFilter(fPadding, "padding");
|
||||
fPadding.Config_PadOnly = true;
|
||||
|
@ -771,10 +775,14 @@ namespace BizHawk.Client.Common
|
|||
vw += padding.Horizontal;
|
||||
vh += padding.Vertical;
|
||||
|
||||
//in case the user requested so much padding that the dimensions are now negative, just turn it to something small.
|
||||
// in case the user requested so much padding that the dimensions are now negative, just turn it to something small.
|
||||
if (vw < 1) vw = 1;
|
||||
if (vh < 1) vh = 1;
|
||||
|
||||
// if either of the dimensions exceed the maximum size of a texture, we need to constrain them
|
||||
vw = Math.Min(vw, _gl.MaxTextureDimension);
|
||||
vh = Math.Min(vh, _gl.MaxTextureDimension);
|
||||
|
||||
BitmapBuffer bb = null;
|
||||
ITexture2D videoTexture = null;
|
||||
if (!simulate)
|
||||
|
|
|
@ -452,9 +452,22 @@ namespace BizHawk.Client.Common.Filters
|
|||
|
||||
public override void SetInputFormat(string channel, SurfaceState state)
|
||||
{
|
||||
var outputSize = state.SurfaceFormat.Size;
|
||||
outputSize.Width *= Scale;
|
||||
outputSize.Height *= Scale;
|
||||
var inputSize = state.SurfaceFormat.Size;
|
||||
var outputSize = new Size(inputSize.Width * Scale, inputSize.Height * Scale);
|
||||
var maxTexDimension = FilterProgram.GL.MaxTextureDimension;
|
||||
while (outputSize.Width > maxTexDimension || outputSize.Height > maxTexDimension)
|
||||
{
|
||||
outputSize.Width -= inputSize.Width;
|
||||
outputSize.Height -= inputSize.Height;
|
||||
Scale--;
|
||||
}
|
||||
|
||||
// this hopefully never happens
|
||||
if (outputSize.Width == 0 || outputSize.Height == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Prescale input was too large for a texture");
|
||||
}
|
||||
|
||||
var ss = new SurfaceState(new(outputSize), SurfaceDisposition.RenderTarget);
|
||||
DeclareOutput(ss, channel);
|
||||
}
|
||||
|
|
|
@ -254,8 +254,9 @@ namespace BizHawk.Client.EmuHawk
|
|||
// need to have a context active for checking renderer, will be disposed afterwards
|
||||
using (new SDL2OpenGLContext(3, 2, true))
|
||||
{
|
||||
using var testIgl = new IGL_OpenGL();
|
||||
_ = CheckRenderer(testIgl);
|
||||
using var testOpenGL = new IGL_OpenGL();
|
||||
testOpenGL.InitGLState();
|
||||
_ = CheckRenderer(testOpenGL);
|
||||
}
|
||||
|
||||
// don't return the same IGL, we don't want the test context to be part of this IGL
|
||||
|
|
Loading…
Reference in New Issue