diff --git a/plugins/GSdx/GLState.cpp b/plugins/GSdx/GLState.cpp index 39f7a7c6f1..88fbb80b35 100644 --- a/plugins/GSdx/GLState.cpp +++ b/plugins/GSdx/GLState.cpp @@ -57,6 +57,8 @@ namespace GLState { GLuint program; GLuint pipeline; + uint64 available_vram; + void Clear() { fbo = 0; viewport = GSVector2i(0, 0); @@ -93,5 +95,9 @@ namespace GLState { vs = 0; program = 0; pipeline = 0; + + // Set a max vram limit for texture allocation + // (256MB are reserved for PBO/IBO/VBO/UBO buffers) + available_vram = (4096u - 256u) * 1024u * 1024u; } } diff --git a/plugins/GSdx/GLState.h b/plugins/GSdx/GLState.h index 5203526207..69e60c342d 100644 --- a/plugins/GSdx/GLState.h +++ b/plugins/GSdx/GLState.h @@ -59,5 +59,7 @@ namespace GLState { extern GLuint program; extern GLuint pipeline; + extern uint64 available_vram; + extern void Clear(); } diff --git a/plugins/GSdx/GSTextureOGL.cpp b/plugins/GSdx/GSTextureOGL.cpp index b375e63d7b..43d59afb11 100644 --- a/plugins/GSdx/GSTextureOGL.cpp +++ b/plugins/GSdx/GSTextureOGL.cpp @@ -221,14 +221,14 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read) case GL_DEPTH32F_STENCIL8: m_int_format = GL_DEPTH_STENCIL; m_int_type = GL_FLOAT_32_UNSIGNED_INT_24_8_REV; - m_int_shift = 0; + m_int_shift = 3; // 4 bytes for depth + 4 bytes for stencil by texels break; // Backbuffer case 0: m_int_format = 0; m_int_type = 0; - m_int_shift = 0; + m_int_shift = 2; // 4 bytes by texels break; default: @@ -238,6 +238,13 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read) ASSERT(0); } + m_mem_usage = (m_size.x * m_size.y) << m_int_shift; + if (m_mem_usage > GLState::available_vram) { + throw GSDXErrorOOM(); // Still time to do a prayer ! + } else { + GLState::available_vram -= m_mem_usage; + } + // Generate & Allocate the buffer switch (m_type) { case GSTexture::Offscreen: @@ -275,6 +282,8 @@ GSTextureOGL::~GSTextureOGL() glDeleteTextures(1, &m_texture_id); + GLState::available_vram += m_mem_usage; + if (m_local_buffer) _aligned_free(m_local_buffer); } @@ -485,16 +494,5 @@ bool GSTextureOGL::Save(const string& fn, bool user_image, bool dds) uint32 GSTextureOGL::GetMemUsage() { - switch (m_type) { - case GSTexture::Offscreen: - return m_size.x * m_size.y * (4 + 4); // Texture + buffer - case GSTexture::Texture: - case GSTexture::RenderTarget: - return m_size.x * m_size.y * 4; - case GSTexture::DepthStencil: - return m_size.x * m_size.y * 8; - case GSTexture::Backbuffer: - default: - return 0; - } + return m_mem_usage; } diff --git a/plugins/GSdx/GSTextureOGL.h b/plugins/GSdx/GSTextureOGL.h index 298738a5c1..cba8601f64 100644 --- a/plugins/GSdx/GSTextureOGL.h +++ b/plugins/GSdx/GSTextureOGL.h @@ -53,12 +53,14 @@ class GSTextureOGL final : public GSTexture int m_r_w; int m_r_h; - // internal opengl format/type/alignment GLenum m_int_format; GLenum m_int_type; uint32 m_int_shift; + // Allow to track size of allocated memory + uint32 m_mem_usage; + public: explicit GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read); virtual ~GSTextureOGL();